Numerous improvements have been made over the original DOS 3.3C assembly source code listing!
Header Format is:
Line format is:
=== FILENAME - Description, Page #, Track/Sector @ $offset, $#### (Relocated address in high memory) ===
Addr:## ## ## L## LABEL MNEMONIC COMMENT AnnotationLegend:
Addr | Address at assemble time | ||||||||||||||
## ## ## | Opcode(s) or raw hex bytes (may be unspecified) | ||||||||||||||
L## | Line number of source file | ||||||||||||||
LABEL | All function names, variable names, branch target names, and references to Code and Data are color-coded:
Function Definition Data Definition Macro Definition Const Definition |
||||||||||||||
MNEMONIC | Assembly language instruction
Function Reference Variable Reference 0-9, A-F |
||||||||||||||
COMMENT | Official comment -- spelling mistakes and improper indentation are verbatim | ||||||||||||||
Annotation | Modern commentary by me.
|
||||||||||||||
Misc. |
|
WARNING: DOS 3.3 was written by an amateur. Reading this source code will probably make you angry at all the dumb shit it does. Look for all my *sigh* comments and HNTDAFS (How NOT to Design a File System) links. While knowing "What To Do" is important, knowing "What NOT To Do" is even more important. As they say, "Hindsight is 20/20."
DISCLAIMER: YOU MAY NOT USE APPLE'S SOURCE CODE EXCEPT FOR LEARNING else you face risking the wrath of Apple's lawyers. Since Apple has already previously released this source code I'm assuming it is OK to provide a mirror of the information since I'm not presenting anything new (well, OK, my commentary, but you get the point) that isn't already publically available.
With that "legalese" out of the way ... enjoy the read!
00001 001 SBTL "DOS3.3C w/APPEND fix, U/L case" 00002 002 LST ON,VSYM 00003 003 MSB OFF 00004 004 ORIGIN EQU $1B00 00005 005 DIAGMOD EQU 0 00006 006 DOS33B EQU 1 00007 007 ULC EQU 0 ;1=ASM with lower case patch ;Address .. Addr, Track/Sector(s) 00008 008 INCLUDE RELOCTR,,2 ; $1B00 .. $1C80, T0SA - T0SB 00009 009 INCLUDE DOSINIT,,2 ; $1C81 .. $1E80, T0SB - T0SD 00010 010 INCLUDE DOSHOOK,,2 ; $1E81 .. $1FCC, T0SD - T0SE 00011 011 INCLUDE CMDSCAN,,2 ; $1FCD .. $2192, T0SE - T1S0 00012 012 INCLUDE XOPNCLS,,2 ; $2193 .. $2330, T1S0 - T1S2 00013 013 INCLUDE XLODSAV,,2 ; $2331 .. $250F, T1S2 - T1S4 00014 014 INCLUDE XMISCMD,,2 ; $2510 .. $26A7, T1S4 - T1S5 00015 015 INCLUDE DOSGOER,,2 ; $26A8 .. $27D3, T1S5 - T1S6 00016 016 INCLUDE BLDFTAB,,2 ; $27D4 .. $2883, T1S6 - T1S7 00017 017 INCLUDE CMDTBLS,,2 ; $2884 .. $2A4E, T1S7 - T1S9 00018 018 INCLUDE FDOSENT,,2 ; $2A4F .. $2B21, T1S9 - T1SA 00019 019 INCLUDE FOPCLRW,,2 ; $2B22 .. $2CEE, T1SA - T1SB 00020 020 INCLUDE FDELCAT,,2 ; $2CEF .. $2E8D, T1SB - T1SD 00021 021 INCLUDE FMTRWIO,,2 ; $2E8E .. $2FF6, T1SD - T1SE 00022 022 INCLUDE FLOCNXB,,2 ; $2FF7 .. $31C8, T1SE - T2S0 00023 023 INCLUDE FLOCSEC,,2 ; $31C9 .. $3396, T2S0 - T2S2 00024 024 INCLUDE FVCBUFS,,2 ; $3397 .. $35FD, T2S2 - T2S4 00025 025 INLUCDE BOOTLDR,,2 ; $35FE .. $37FF, T0S0 - T0S1 00026 026 INCLUDE COREQUS,,1 ; n/a 00027 027 INCLUDE PRENIBL,,1 ; $3800 .. $3829, T0S2 00028 028 INCLUDE WRITRTN,,1 ; $382A .. $38C1, T0S2 00029 029 INCLUDE POSTNRD,,1 ; $38C2 .. $3943, T0S2 - T0S3 00030 030 INCLDUE RDADSEK,,1 ; $3944 .. $39FC, T0S3 00031 031 INCLUDE MSWAITR,,1 ; $39FD .. $3C55, T0S3 - T0S6 00032 032 INCLUDE WRITADR,,1 ; $3C56 .. $3CFF, T0S6 00033 033 INCLUDE RWTSONE,,1 ; $3D00 .. $3DAA, T0S7 00034 034 INCLUDE RWTSTWO,,1 ; $3DAB .. $3EAE, T0S7 - T0S8 00035 035 INCLUDE FORMATR,,1 ; $3EAF .. $3FC7, T0S8 - T0S9 00036 036 INCLUDE DOSPTCH,,1 ; $3FC8 .. $3FFF, T0S9
00037 001 PAGE ; === Page 110 === 00038 002 ***************************************************** 00039 003 * * 00040 004 * (C) COPYRIGHT 1978,1980,1982 APPLE COMPUTER, INC. * 00041 005 * * 00042 006 ***************************************************** 00043 007 SKP 2 00044 008 ********************************* 00045 009 * * 00046 010 * ADAPTED FOR MACRO EDASM BY * 00047 011 * JOHN ARKLEY * 00048 012 * DEC 1980 * 00049 013 * * 00050 014 ********************************* 00051 015 SKP 2 00052 016 ********************************* 00053 017 * * 00054 018 * DOS 3.3 REVISION B PATCHES * 00055 019 * INSTALLED BY MARK HOUDE * 00056 020 * JUL 1982 * 00057 021 * * 00058 022 ********************************* 00059 023 SKP 2 00060 024 ********************************* 00061 025 * * 00062 026 * DOS 3.3 REV B PATCHES VER 2 * 00063 027 * INSTALLED BY FERN BACHMAN * 00064 028 * SEP 1982 * 00065 029 * * 00066 030 ********************************* 00067 031 SKP 2 00068 032 ********************************* 00069 033 * * 00070 034 * DOS33C PATCHES (APPEND & * 00071 035 * UPPER/LOWER CASE CHECK) * 00072 036 * * 00073 037 * BY * 00074 038 * GUIL BANKS * 00075 039 * 1983 * ; Note: Fixed EOL formatting in PDF 00076 040 * * 00077 041 ********************************* 00078 042 ; 00079 043 ;EQUATES REQD TO FIND THINGS IN APPLE II 00080 044 ; 00081 045 SETVID EQU $FE93 ; Monitor: 0 Ctrl-P 00082 046 SETKBD EQU $FE89 ; Monitor: 0 Ctrl-K 00083 047 PROMPT EQU $33 ; PROMPT CHAR 00084 048 OUTSW EQU $36 ; OUTPUT VECTOR SWITCH 00085 049 INSW EQU $38 ; INPUT VECTOR SWITCH 00086 050 ZPGWRK EQU $40 ; ZERO PAGE WORK CELL 00087 051 CNUM EQU $44 ; CONVERTED NUMERIC ; 16-bit input number 00088 052 LBUFF EQU $200 ; LINE BUFFER ; Keyboard buffer of 255 chars 00089 053 MULT EQU $FB63 ; MULT ROUTINE ; -- unused, never referenced --
00090 054 INPRT EQU $FE8B ; SET IN PORT ; === Page 111 === ; *sigh* Apple 2 ROM lists INPORT = $FE8B, INPRT = $FE8D 00091 055 OUTPRT EQU $FE95 ; SET OUT PORT 00092 056 IBCHN EQU $E836 ; BASIC RUN ; Integer Basic 00093 057 IBLMEM EQU $4A ; BASIC LOW MEM ; Integer Basic 00094 058 IBHMEM EQU $4C ; INTEGER BASIC HIMEM ; Integer Basic 00095 059 IBSOP EQU $CA ; INTEGER BASIC START OF CGM ; Integer Basic CGM ??? 00096 060 IBBRK EQU $E3E3 ; BASIC BREAK ; Integer Basic 00097 061 IBGO EQU $E000 ; BASIC ENTRY POINT ; Integer Basic COLD start 00098 062 IBCONT EQU $E003 ; BASIC CONTINUE ENTRY POINT ; Integer Basic WARM start 00099 063 IBSOV EQU $CC ; BASIC START OF VARIABLES ; Integer Basic 00100 064 ASSOP EQU $67 ; AS START OF PROGRAM ; Applesoft Basic 00101 065 ASEOP EQU $AF ; AS END OF PROGRAM ; Applesoft Basic 00102 066 ASEOP2 EQU $69 ; AS END-OF PGM 2 ; Applesoft Basic 00103 067 ASHM1 EQU $73 ; AS HIGH MEM 1 ; Applesoft Basic 00104 068 ASHM2 EQU $6F ; AS HIGH MEM 2 ; Applesoft Basic 00105 069 ASRNX EQU $D6 ;AS RUN-ONLY FLAG ; Applesoft Basic 00106 070 ASONERR EQU $D8 ;AS ON-ERR GOTO FLAG ; Applesoft Basic =0067 00107 071 ASLMEM EQU ASSOP ; AS LOW MEM ; Applesoft Basic -- never referenced 00108 072 ASBRK1 EQU $D865 ; AS ROM BREAK ; Applesoft Basic 00109 073 ASBRK2 EQU $1067 ; AS RAM BREAK ; Applesoft Basic 00110 074 ASCNTU1 EQU $D43C ; ROM entry point 00111 075 ASCNTU2 EQU $C3C ; RAM entry point 00112 076 ASRSEQ1 EQU $D4F2 ; ROM entry point 00113 077 ASRSEQ2 EQU $CF2 ; RAM entry point 00114 078 AITSTL EQU $E000 ; AS 1 IB TEST LOC ; Applesoft Basic E000: JMP $F128 00115 079 ATSTV EQU $4C ; AS TEST VALUE ; Applesoft Basic 00116 080 ITSTV EQU $20 ; IB TEST VALUE ; Integer Basic 00117 081 BOOTSL EQU $2E ; BOOT FROM SLOT ; Slot from Boot 00118 082 ZPGFCB EQU $42 ; ZERO PAGE WORK CELL ; File Control Block 00119 083 MONRST EQU $FF65 ;MONITOR RESET ENTRY 00120 084 MONBRK EQU $FA59 ;MONITOR BREAK ENTRY 00121 085 IORTS EQU $FF58 ;KNOWN RTS IN MONITOR ROM 00122 086 HOME EQU $FC58 ; cls(); Clear the text screen 00123 087 PRINT EQU $FDED ; putchar(); 00124 088 GETKEY EQU $FD0C ; getchar(); 00125 089 INSDS2 EQU $F88E ; Instruction Disassembly Opcode Length 00126 090 LENGTH EQU $2F 00127 091 ZRSET EQU $3F2 ;NEW MONITOR ROM RESET VECTOR 00128 092 PWCNST EQU $3F4 ;NEW MONITOR ROM POWER UP CONSTANT 00129 093 REP 40 00130 094 * 00131 095 * 00132 096 ORG ORIGIN 00133 097 * 00134 098 * 00135 099 REP 40 00136 100 PAGE 1B00:4C 84 1D 00137 101 BEGIN JMP DBINIT ; === DOS loads @ $1B00 === 00138 102 ; ; Loaded in at $38D4 00139 103 DOSREL EQU * ; Called from File BOOTLDR, Page 12, Line #298 00140 104 ; 00141 105 ; GET RELOCATION PARMS 00142 106 ; 00143 107 DR0 EQU * 00144 108 LOC1 EQU $26 ; Monitor ROM GBASL = $26, Pointer to last HGR Byte plotted 1B03:A9 BF 00145 109 LDA #$BF ; START AT BF00 ; Top of 48K 1B05:85 41 00146 110 STA ZPGWRK+1 ; TO LOOK FOR ; ZPGWRK = MemTestAdr 1B07:A2 00 00147 111 LDX #0 ; HIGH RAM 1B09:86 40 00148 112 STX ZPGWRK 1B0B:A0 00 00149 113 DR0A LDY #0 ; APPLE TEST 00150 114 DR1B EQU * ; unused label 1B0D:A1 40 00151 115 LDA (ZPGWRK,X) 1B0F:85 26 00152 116 STA LOC1 ; LOC1 = MemTestVal
1B11:98 00153 117 DR1 TYA ; === Page 112 === 1B12:45 26 00154 118 EOR LOC1 1B14:85 26 00155 119 STA LOC1 1B16:98 00156 120 TYA 1B17:41 40 00157 121 EOR (ZPGWRK,X) 1B19:81 40 00158 122 STA (ZPGWRK,X) 1B1B:C5 26 00159 123 CMP LOC1 1B1D:D0 05 00160 124 BNE DR1A ; ↓ /rant Crappy HTML name ↓ instead of simpler \v 1B1F:C8 00161 125 INY 1B20:D0 EF 00162 126 BNE DR1 ; ↑ /rant Crappy HTML name ↑ instead of simpler \^ 1B22:F0 04 00163 127 BEQ DR2 ; BR IF TOOK ; v 00164 128 DR1A EQU * 1B24:C6 41 00165 129 DEC ZPGWRK+1 ; NOT RAM 1B26:D0 E3 00166 130 BNE DR0A ; TRY NEXT PAGE ; ^ 00167 131 ; 00168 132 DR2 EQU * 00169 133 ; 1B28:A5 41 00170 134 LDA ZPGWRK+1 ;BEGIN PATCH TO INSURE ***** ; note: '*****' is BEGIN_PATCH 1B2A:29 DF 00171 135 AND #$DF ; PROPER HIGH MEMORY CHECK. 1B2C:85 43 00172 136 STA ZPGFCB+1 ;(DOS MASTER 3.1 CONTAINS 1B2E:86 42 00173 137 STX ZPGFCB ; THIS ROUTINE STARTING AT LOCATION 1B30:A1 42 00174 138 LDA (ZPGFCB,X) ; $3540) 1B32:48 00175 139 PHA 1B33:85 26 00176 140 STA LOC1 ;SAVE TEST VALUE 1B35:98 00177 141 DR2A TYA ;(FIRST TIME Y=0) 1B36:45 26 00178 142 EOR LOC1 ;TEST EACH (ALLEDGED) MEMORY BYTE 1B38:85 26 00179 143 STA LOC1 ; 256 TIMES TO DETERMINE IF 1B3A:98 00180 144 TYA ; IT IS REALLY GOOD MEMORY AND 1B3B:41 40 00181 145 EOR (ZPGWRK,X) ; MIRRORED 8K LOWER IN RAM. 1B3D:81 42 00182 146 STA (ZPGFCB,X) 1B3F:C5 26 00183 147 CMP LOC1 ;DID IT PASS THIS TIME? 1B41:D0 09 00184 148 BNE DR2B ; BYTE NOT MIRRORED, THEN GOOD MEMORY ; *sigh* more crap code: S-L-O-W 1B43:C8 00185 149 INY ;MAYBE IT WAS COINCIDENCE ; Instead of testing *every* byte (256 times WTF!) 1B44:D0 EF 00186 150 BNE DR2A ; BRANCH UNLESS IT'S MATCHED 256 TIMES ; just test the last byte of every page 1B46:A4 43 00187 151 LDY ZPGFCB+1 ;HIMEM IS 8K LOWER THEN WAS ; Switch PLA, LDY, then BNE instead 1B48:68 00188 152 PLA ;ORIGINALLY THOUGHT! ; since ZPGFCB can never be on mem page $00 1B49:4C 51 1B 00189 153 JMP DR2C ; wastes 1 byte with JMP instead of BNE. See Line #151 1B4C:68 00190 154 DR2B PLA ; ORIGINAL HIMEM PROVED GOOD 1B4D:81 42 00191 155 STA (ZPGFCB,X) ;RESTORE BYTE ORIGINALLY MESSED WITH. 1B4F:A4 41 00192 156 LDY ZPGWRK+1 ;END OF PATCH ***** ; ***** = END_PATCH 1B51:C8 00193 157 DR2C INY ; NEW END OF DOS ; Y = $BF 1B52:8C 7D 1C 00194 158 STY NEPAGE 1B55:38 00195 159 SEC 1B56:98 00196 160 TYA 1B57:ED 7E 1C 00197 161 SBC DOSLNG ; MINUS DOS LENGTH 1B5A:8D 7C 1C 00198 162 STA NSPAGE ; IS NEW START OF DOS 1B5D:38 00199 163 SEC 1B5E:ED 7A 1C 00200 164 SBC RSPAGE ; MINUS OLD DOS START 1B61:F0 9D 00201 165 BEQ BEGIN ; (BREIF NO DELTA) ; ^ Giving the benefit of doubt; NOT misspelt: BRanch Equal If ? 1B63:8D 7F 1C 00202 166 STA DELTA ; IS DELTA 1B66:AD 7A 1C 00203 167 LDA RSPAGE ; RESET START PAGE TO NORMAL 1B69:8D 0D 1D 00204 168 STA ASTART+1 00205 169 ; 1B6C:A9 1D 00206 170 LDA #<DBINIT ; RESET PI RTN TO NORMAL ; PI = Post Init; @ boot defaults to us, our relocator: DOSREL 1B6E:8D 49 37 00207 171 STA DI3+2 1B71:A9 84 00208 172 LDA #>DBINIT 1B73:8D 48 37 00209 173 STA DI3+1 00210 174 ; 00211 175 ;RELOCATE ADR TABLES 00212 176 ;
1B76:A2 00 00213 177 LDX #0 ; === Page 113 === 1B78:86 40 00214 178 STX ZPGWRK 00215 179 DR3 EQU * 1B7A:BD 29 1C 00216 180 LDA ADRTAB+1,X ; [StartLo] If only we had an ($BC) LDY ADRTAB+1,X instruction ... 1B7D:A8 00217 181 TAY ; wastes 1 byte; ... to skip this useless instruction. 1B7E:BD 2A 1C 00218 182 LDA ADRTAB+2,X ; [StartHi] Oh wait, we do! /rhetorical Who knew! 1B81:85 41 00219 183 STA ZPGWRK+1 ; Evident code quality to come. :-/ 1B83:4C 93 1B 00220 184 JMP DR5 ; wastes 1 byte instead of BNE; skip low address ptr 00221 185 ; ; See software was bloated in the "good ol' days" too. :-( 00222 186 DR4 EQU * 1B86:18 00223 187 CLC 1B87:B1 40 00224 188 LDA (ZPGWRK),Y 1B89:6D 7F 1C 00225 189 ADC DELTA 1B8C:91 40 00226 190 STA (ZPGWRK),Y 1B8E:C8 00227 191 INY ; Line #203 1B8F:D) 02 00228 192 BNE DR5 1B91:E6 41 00229 193 INC ZPGWRK+1 1B93:C8 00230 194 DR5 INY 1B94:D0 02 00231 195 BNE DR6 1B96:E6 41 00232 196 INC ZPGWRK+1 00233 197 ; 00234 198 DR6 EQU * 1B98:A5 41 00235 199 LDA ZPGWRK+1 1B9A:DD 2C 1C 00236 200 CMP ADRTAB+4,X ; [EndHi] Crappy array offset, see comments starting on Line #286 1B9D:90 E7 00237 201 BCC DR4 1B9F:98 00238 202 TYA 1BA0:DD 2B 1C 00239 203 CMP ADRTAB+3,X ; [EndLo] 1BA3:90 E1 00240 204 BCC DR4 00241 205 ; 1BA5:8A 00242 206 TXA 1BA6:18 00243 207 CLC 1BA7:69 04 00244 208 ADC #4 ; 4 bytes per entry: {StartAdr,EndAdr} 1BA9:AA 00245 209 TAX 1BAA:EC 28 1C 00246 210 CPX ADRTAB ; Done all bytes? 1BAD:90 CB 00247 211 BCC DR3 00248 212 PAGE 00249 213 ; 00250 214 ;RELOCATE CODE 00251 215 ; 1BAF:A2 00 00252 216 LDX #0 1BB1:8E 9C 33 00253 217 DR7 STX TEMP1 00254 218 ; 1BB4:BD 5A 1C 00255 219 LDA CDETAB+1,X ; GET A START OF CODE ADR 1BB7:85 40 00256 220 STA ZPGWRK ; PUT IN ZPG 1BB9:BD 5B 1C 00257 221 LDA CDETAB+2,X 1BBC:85 41 00258 222 STA ZPGWRK+1 00259 223 ; 1BBE:A2 00 00260 224 DR8 LDX #0 ; GET OP CODE 1BC0:A1 40 00261 225 LDA (ZPGWRK,X) ; GO FIND OUT HOW LONG ; Since we don't have a linker, interesting hack of using 1BC2:20 8E F8 00262 226 JSR INSDS2 ; monitor ROM to get instruction opcode length 00263 227 ; 1BC5:A4 2F 00264 228 LDY LENGTH ; GET HOW LONG ; crappy var name -- length of what?? Oh OPCODE_LEN 1BC7:C0 02 00265 229 CPY #2 ; IF IT AIN'T ; *sigh* #3-1 is clearer since zero based 1BC9:D0 11 00266 230 BNE DR9 ; 3 THEN DON'T RELOC ; 300:A9 20 20 8E F8 A5 2F 09 30 4C ED FD 1BCB:B1 40 00267 231 LDA (ZPGWRK),Y ; GET PAGE FROM INST 1BCD:CD 7A 1C 00268 232 CMP RSPAGE ; IF PAGE < REL START 1BD0:90 0A 00269 233 BCC DR9 ; THEN IGNOR 1BD2:CD 7B 1C 00270 234 CMP REPAGE ; IF PAGE >= REL END 1BD5:B0 05 00271 235 BCS DR9 ; THEN IGNORE 1BD7:6D 7F 1C 00272 236 ADC DELTA ; ELSE ADD DELTA 1BDA:91 40 00273 237 STA (ZPGWRK),Y ; TO RELOCATE 00274 238 ; 1BDC:38 00275 239 DR9 SEC
1BDD:A5 2F 00276 240 LDA LENGTH ; ADD LENGTH ; === Page 114 === 1BDF:65 40 00277 241 ADC ZPGWRK ; TO PC 1BE1:95 40 00278 242 STA ZPGWRK 1BE3:A9 00 00279 243 LDA #0 1BE5:65 41 00280 244 ADC ZPGWRK+1 1BE7:85 41 00281 245 STA ZPGWRK+1 00282 246 ; 1BE9:AE 9C 33 00283 247 LDX TEMP1 ; CHECK FOR END 1BEC:DD 5D 1C 00284 248 CMP CDETAB+4,X ; OF CODE SEGMENT 1BEF:90 CD 00285 249 BCC DR8 ; BR NOT END 1BF1:A5 40 00286 250 LDA ZPGWRK 1BF3:DD 5C 1C 00287 251 CMP CDETAB+3,X 1BF6:90 C6 00288 252 BCC DR8 ; BR NOT END 00289 253 ; 1BF8:8A 00290 254 TXA 1BF9:18 00291 255 CLC 1BFA:69 04 00292 256 ADC #04 ; INCREMENT TABLE INDEX 1BFC:AA 00293 257 TAX 1BFD:EC 59 1C 00294 258 CPX CDETAB ; DONE 1C00:90 AF 00295 259 BCC DR7 ; BR IF NOT ; === T0SB === 00296 260 ; 00297 261 PAGE 00298 262 ; 00299 263 ;MOVE TO RELOCATED CODE 00300 264 ; 1C02:A9 3F 00301 265 LDA #<ENDOFDOS-$80 1C04:85 41 00302 266 STA ZPGWRK+1 ; ZPGWRK=FROM 1C06:AC 7D 1C 00303 267 LDY NEPAGE 1C09:88 00304 268 DEY 1C0A:84 43 00305 269 STY ZPGFCB+1 ; ZPGFCB = TOO 1C0C:A9 00 00306 270 LDA #0 ; /sarcasm If only we had a LDY #0 instruction ... 1C0E:85 40 00307 271 STA ZPGWRK 1C10:85 42 00308 272 STA ZPGFCB 1C12:A8 00309 273 TAY ; wastes 1 byte; ... to remove this one. See Line #270 00310 274 ; 1C13:B1 40 00311 275 DR10 LDA (ZPGWRK),Y ; BYTE FROM 1C15:91 42 00312 276 STA (ZPGFCB),Y ; BYTE TO 1C17:C8 00313 277 INY ; INCREMENT ; /sarcasm No shit, Sherlock 1C18:D0 F9 00314 278 BNE DR10 ; BR NOT FULL PAGE 1C1A:CE 80 1C 00315 279 DEC DPGCNT ; DECREMENT PAGE CNT 1C1D:F0 06 00316 280 BEQ DR11 ; BR IF DONE 1C1F:C6 41 00317 281 DEC ZPGWRK+1 ; INC FROM PAGE 1C21:C6 43 00318 282 DEC ZPGFCB+1 ; INC TOO PAGE 1C23:D0 EE 00319 283 BNE DR10 ; MOVE PAGE 00320 284 ; 1C25:4C 54 1E 00321 285 DR11 JMP DBVECT+3 ; DONE ; DOSINIT, Page 51 -> JMP DBINIT 00322 286 PAGE ; This is really crappy table formatting due to 2 reasons: ; 1) A redundant +1 offset is needed for "almost all"(*) offsets in code ; since the length of the array doesn't have its own label: ; ; ADRTABLEN DFB 9*4 ; Poor Solution: but better then original ; ; (*) "almost all" means all except one when the length IS checked on Line #210 ; ; 2) The start and end address are not on a single line ; with no visual indicators to tell what is the start or end address ; This makes it extremely hard to tell which addresses belong to ; which entry. I've added the array offset [#] to make the original code ; more readable. ; Better Solution: Place each entry on a single line ; along with the correct half-open range interval notation [,) ; then each block of memory to relocate becomes very crystal clear: ; ; ; [Start, End) ; ADRTAB DW SAT1 , EAT1 ; DW RUN , RUN ; DW IBVT , IBVT ; DW AS1VT, AS1VT ; ; Best Solution: Even better would be to use two labels ; offset by two bytes to simulate two struct member variables: ; ; ADRTABS DW SAT1 ; Start Address ; ADRTABE DW EAT ; End Address ; DW RUN , RUN ; DW IBVT , IBVT ; DW AS1VT, AS1VT ; ; While the second's line formatting, ADRTABE, is a little unorthodox ; using dual labels makes the array offsets obvious compared to ; the original non-descript code: ; ; LDY ADRTABS+0,X ; lo byte of start address; was LDA ADRTAB+1,X ; LDA ADRTABS+1,X ; hi byte of start address; was LDA ADRTAB+2,X ; CMP ADRTABE+1,X ; hi byte of end address; was CMP ADRTAB+4,X ; CMP ADRTABE+0,X ; lo byte of end address; was CMP ADRTAB+3,X ; 1C28:24 00323 287 ADRTAB DFB 9*4 ; magic number Really?! We can't do ADRTAB_LEN DFB ADRTAB_END - ADRTAB_START ??? 1C29:00 1D 00324 288 DW SAT1 ; [0] Start Address Table 1 in DOSINIT 1C2B:56 1D 00325 289 DW EAT1 ; End Address Table 1 ; wastes 4 bytes due to non-contiguous memory ; $1D56, $1D57 = CHAIN ; Solution would be to add our own stub of 3 bytes ; DOS_CHAIN_IB: JMP $E836 1C2D:58 1D 00326 290 DW RUN ; [1] Allowing us to remove 4 bytes from the table: end[0], start[1] 1C2F:5A 1D 00327 291 DW RUN+2 ; Further optimization would remove 10 bytes (5 entries) 1C31:64 1D 00328 292 DW IBVT+2 ; [2] Integer Basic Vector Table 1C33:66 1D 00329 293 DW IBVT+4 ; 1C35:6C 1D 00330 294 DW AS1VT ; [3] Applesoft (ROM) Vector Table 1C37:70 1D 00331 295 DW AS1VT+4 1C39:78 1D 00332 296 DW AS2VT ; [4] Applesoft (RAM) Vector Table 1C3B:7C 1D 00333 297 DW AS2VT+4 1C3D:7E 1D 00334 298 DW AS2VT+6 ; [5] Applesoft (RAM) Vetor Table 1C3F:80 1D 00335 299 DW AS2VT+8 1C41:C1 2A 00336 300 DW SAT2 ; [6] Start Address Table 2 in FDOSENT 1C43:FD 2A 00337 301 DW EAT2 1C45:E4 37 00338 302 DW BAIOB ; [7]
1C47:E8 37 00339 303 DW ADOSLD+2 ; === Page 115 === 1C49:EE 37 00340 304 DW IBDCTP ; [8] 1C4B:F0 37 00341 305 DW IBDCTP+2 1C4D:00 00 00 00 00342 306 DFB 0,0,0,0 ; wastes 12 bytes -- never referenced ! 1C51:00 00 00 00 00343 307 DFB 0,0,0,0 1C55:00 00 00 00 00344 308 DFB 0,0,0,0 00345 309 CDETAB EQU * ; 1C59:1C = v1980, 20 = v1983 1C59:20 00346 310 DFB 8*4 ; magic number Really?! We can't do CDETAB_LEN DFB CDETAB_END - CDETAB_START ??? 1C5A:84 1D 00347 311 DW SC1 ; [0] 1C5C:84 28 00348 312 DW EC1 1C5E:FD 2A 00349 313 DW SC2 ; [1] 1C60:97 33 00350 314 DW EC2 1C62:5D 36 00351 315 DW SC3 ; [2] 1C64:E0 37 00352 316 DW EC3 1C66:56 3C 00353 317 DW SWADR1 ; [3] 1C68:DF 3C 00354 318 DW EWADR1 1C6A:00 38 00355 319 DW ASC1 ; [4] 1C6C:11 3A 00356 320 DW AEC1 1C6E:69 3A 00357 321 DW PSC1 ; [5] 1C70:94 3A 00358 322 DW PEC1 1C72:00 3D 00359 323 DW ASC2 ; [6] 1C74:A8 3F 00360 324 DW AEC2 1C76:C8 3F 00361 325 DW SDP1 ; [7] Start Dos Patch 1C78:FF 3F 00362 326 DW EDP1 ; End Dos Patch 1C7A:1D 00363 327 RSPAGE DFB <START ; (Source) Relocation Start Page $1D00 1C7B:40 00364 328 REPAGE DFB <ENDOFDOS ; (Source) Relocation End+1 Page $4000, wastes 1 bytes; See AEND 00365 329 ; 1C7C:00 00366 330 NSPAGE DFB 0 1C7D:00 00367 331 NEPAGE DFB 0 00368 332 ; 1C7E:23 00369 333 DOSLNG DFB <ENDOFDOS-START 00370 334 ; 1C7F:00 00371 335 DELTA DFB 0 1C80:23 00372 336 DPGCNT DFB <ENDOFDOS-START 00373 337 PAGE
00374 001 HEREL HEREL EQU >* ; === Page 48 === $81 00375 002 REMDR REMDR EQU 256-HEREL ; DOS 3.3B bytes | $7F 1C81:FC FC FC 00376 003 ORG *+REMDR ; 1C81: FC FD FD | disk wastes 127 bytes padding to end of sector 1C84:FC FC FC FD ; 1C84:FD FC FD FC | Technically only 82 bytes ($1CD3-$1C81 = $52) are wasted 1C88:FC FC FF FC ; 1C88:FC FC FE FE | but FTAB DW *-45 (below) is sloppy code 1C8C:FD FC FC FF ; 1C8C:FC FE FC FC | Why isn't this "allocated" at run-time? 1C90:FF FC FE FD ; 1C90:FD FE FC FF | Meaning this should be placed after ALL the code. 1C94:FE FD FD FE ; 1C94:FC FD FC FC | See: Wasted Disk Space 1C98:FF FC FE FF ; 1C98:FC FF FC FF | 1C9C:FD FE FF FD ; 1C9C:FC FE FF FF | 1CA0:FC FD FD FC ; 1CA0:FF FF FD FE | 1CA4:FD FE FD FF ; 1CA4:FC FD FC FC | 1CA8:FC FE FC FC ; 1CA8:FC FC FD FC | 1CAC:FC FC FC FC ; 1CAC:FE FE FE FC | 1CB0:FD FC FC FE ; 1CB0:FD FF FC FC | 1CB4:FC FD FC FC ; 1CB4:FC FE FC FD | 1CB8:FF FC FC FE ; 1CB8:FC FC FC FE | 1CBC:FD FC FD FF ; 1CBC:FC FD FC FC | 1CC0:FC FF FD FE ; 1CC0:FC FD FC FD | 1CC4:FF FD FF FC ; 1CC4:FD FC FC FC | 1CC8:FC FD FE FF ; 1CC8:FD FD FC FE | ECLOSE, EDEL, EPOS, RWPOSN, CLOSFILE call 1CCC:FF FF FC FC ; 1CCC:FC FC FE FC | FILSRC (File Search) 1CD0:FF FF FC FE ; 1CD0:FC FD FD FC | [00] $1CD3 ($9CD3) Used by TSINIT, init @ Line #036 1CD4:FD FC FD FD ; 1CD4:FF FE FC FC | 1CD8:FE FF FD FE ; 1CD8:FC FC FD FC | 1CDC:FF FC FE FE ; 1CDC:FD FE FC FC | 1CE0:FC FD FC FD ; 1CE0:FD FC FF FC | 1CE4:FE FD FD FC ; 1CE4:FE FF FF FF | 1CE8:FD FC FF FD ; 1CE8:FD FC FE FE | See init @ BFT1, Line #041 1CEC:FC FF FC FC ; 1CEC:FC FC FE FC | [1E] $1CF1 ($9CF1): $9CA6 (buf1 ptr) 1CF0:FE FD FC FC ; 1CF0:FC FE FC FE | [20] $1CF3 ($9CF3): $9BA6 (buf2 ptr) 1CF4:FD FC FE FC : 1CF4:FC FE FE FC | [22] $1CF5 ($9CF5): $9AA6 (buf3 ptr) 1CF8:FC FD FF FC ; 1CF8:FE FE FC FC | $1CF8 Use by TSNXT 1CFC:FC FD FC FC ; 1CFC:FE FC FD FD | 00377 004 ; 00378 005 ;RELOCATION TABLES 00379 006 ; 00380 007 START EQU * 00381 008 SAT1 EQU * ; Start Address Table 1 of relocation 1D00:D3 1C 00382 009 FTAB DW *-45 ; === T0SC === $1CD3; Really?! Couldn't do FTAB DS 45, 0 1D02:81 1E 00383 010 CINA DW CHRIN 1D04:BD 1E 00384 011 COUTA DW CHROUT 1D06:75 2A 00385 012 FN1ADR DW FNAME1 1D08:93 2A 00386 013 FN2ADR DW FNAME2 1D0A:60 2A 00387 014 SVBLA DW SVBL 1D0C:00 1B 00388 015 ASTART DW BEGIN 1D0E:BB 35 00389 016 CCBADR DW CCB 00390 017 ; 00391 018 OUTSVT EQU * ; CHAR OUTPUT STATE VECTOR TABLE 1D10:EA 1E 00392 019 DW COS0-1 1D12:11 1F 00393 020 DW COS1-1 1D14:22 1F 00394 021 DW COS2-1 1D16:2E 1F 00395 022 DW COS3-1 1D18:51 1F 00396 023 DW COS4-1 1D1A:60 1F 00397 024 DW COS5-1 1D1C:70 1F 00398 025 DW COS6-1 00399 026 ;COMMAND EXECUTION TABLE 00400 027 CMDETB EQU * ; /sarcasm Yay for shitty 5 & 6 letter var names! See CMNDNTB for the commands entered by the user 1D1E:4E 25 00401 028 DW EINIT-1 ; [0] INIT Stupid 6502 design for RTS instruction forces -1 for func jump table 1D20:12 24 00402 029 DW ELOAD-1 ; [1] LOAD 1D22:96 23 00403 030 DW ESAVE-1 ; [2] SAVE 1D24:D0 24 00404 031 DW ERUN-1 ; [3] RUN 1D26:EF 24 00405 032 DW ECHAIN-1 ; [4] CHAIN 1D28:62 22 00406 033 DW EDEL-1 ; [5] DELETE 1D2A:70 22 00407 034 DW ELOCK-1 ; [6] LOCK 1D2C:74 22 00408 035 DW EUNLK-1 ; [7] UNLOCK /sarcasm Oh, noes! That 'OC' in 'unlOCk' is too much work to type! 1D2E:E9 22 00409 036 DW ECLOSE-1 ; [8] CLOSE 1D30:1A 25 00410 037 DW EREAD-1 ; [9] READ 1D32:C5 25 00411 038 DW EEXEC-1 ; [A] EXEC 1D34:0F 25 00412 039 DW EWRITE-1 ; [B] WRITE 1D36:DC 25 00413 040 DW EPOS-1 ; [C] POSITION 1D38:A2 22 00414 041 DW EOPEN-1 ; [D] OPEN 1D3A:97 22 00415 042 DW EAPND-1 ; [E] APPEND 1D3C:80 22 00416 043 DW EREN-1 ; [F] RENAME 1D3E:6D 25 00417 044 DW ECAT-1 ;[10] CATALOG 1D40:32 22 00418 045 DW EMON-1 ;[11] MON 1D42:3C 22 00419 046 DW ENOMON-1 ;[12] NOMON 1D44:28 22 00420 047 DW EPR-1 ;[13] PR# 1D46:2D 22 00421 048 DW EIN-1 ;[14] IN# 1D48:50 22 00422 049 DW EMAXF-1 ;[15] MAXFILES 1D4A:79 25 00423 050 DW EAS-1 ;[16] FP 1D4C:9D 25 00424 051 DW EINT-1 ;[17] INT 1D4E:30 23 00425 052 DW EBSV-1 ;[18] BSAVE *sigh* EBSAVE - I'm sorry, we blew our key budget for 'A' 1D50:5C 23 00426 053 DW EBLD-1 ;[19] BLOAD *sigh* EBLOAD - and also 'O'
1D52:8D 23 00427 054 DW EBRUN-1 ;[1A] BRUN === Page 49 === 1D54:7C 22 00428 055 DW EVAR-1 ;[1B] VERIFY last byte relocated in Entry [0] ADRTAB 00429 056 EAT1 EQU * ; End Address Table 1 00430 057 PAGE 00431 058 ; ; *note* Annotating [-] to mean addresss is not relocated in ADRTAB 00432 059 ;NON-RELOCATING ADRS 00433 060 ; ; Using a,b,c,d,e,f for abbreviated field names in IBASVT 00434 061 IBASVT EQU * ; ACTIVE table but waste disk space (12 bytes @ $56) storing it! 1D56:36 E8 00435 062 CHAIN DW IBCHN ;a[-] Really? Forces another table entry [1] in ADRTAB 1D58:E5 24 00436 063 RUN DW IBRUN ;b[1] Repeat after me: You **group** 1D5A:E3 E3 00437 064 BREAK DW IBBRK ;c[-] CONST data together THEN 1D5C:00 E0 00438 065 GO DW IBGO ;d[-] VARIABLE data together 1D5E:03 E0 00439 066 CONT DW IBCONT ; BASIC CONT ENTRY POINT ;e[-] You (almost) *never* interleave them 1D60:00 00 00440 067 ASEQ DW 0 ;f that just leads to data+code bloat ; *sigh* Too lazy to add a single empty ';' line seperator before IBVT ??? ; Intentionally adding an empty line as a spacer to improve readability *shock* ; ; *note* IBVT, AS1VT, and AS2VT are Read-Only (after being relocated to high mem.) 1D62:36 E8 00441 068 IBVT DW IBCHN ;a[-] Integer Basic Vector Table 1D64:E5 24 00442 069 DW IBRUN ;b[2] 1D66:E3 E3 00443 070 DW IBBRK ;c[-] 1D68:00 E0 00444 071 DW IBGO ;d[-] 1D6A:03 E0 00445 072 DW IBCONT ;e[-] 00446 073 IBVTL EQU *-IBVT ; Length = $1D6C - $1D62 = $A bytes so we don't over-write ASEQ 00447 074 ; ; /sarcasm Because it is obvious 1D6C:FC 24 00448 075 AS1VT DW ASRUN1 ;a[3] 1 = ROM, and 1D6E:FC 24 00449 076 DW ASRUN1 ;b[3] 2 = RAM, right? 1D70:65 D8 00450 077 DW ASBRK1 ;c[-] ASCNTU1 (Continue) S-C DocuMentor $D365 1D72:00 E0 00451 078 DW IBGO ;d[-] ASRSEQ1 (ResetQ???) 1D74:3C D4 00452 079 DW ASCNTU1 ;e[-] Why not IBCONT??? $E003: JMP $D43C ; Applesoft (Warm) RESTART 1D76:F2 D4 00453 080 DW ASRSEQ1 ;f[-] Applesoft FIX.LINKS 00454 081 AS1VTL EQU *-AS1VT 00455 082 ; ; Copied into IBASVT via INIT_AS_RAM, oh wait, INITC 1D78:06 25 00456 083 AS2VT DW ASRUN2 ;a[4] wastes 12 bytes on Apple ][+ or newer 1D7A:06 25 00457 084 DW ASRUN2 ;b[4] Type 2: AppleSoft in RAM Vector Table (early Apple 1 or ][ ???) 1D7C:67 10 00458 085 DW ASBRK2 ;c[-] 1D7E:84 1D 00459 086 DW DBINIT ;d[5] 1D80:3C 0C 00460 087 DW ASCNTU2 ;e Continue (Warm Restart) and R*s*E*q ??? 1D82:F2 0C 088 DW ASRSEQ2 ;f See Applesoft source Line #70 RESTART and Line #270 FIX LINKS 089 AS2VTL EQU *-AS2VT 090 PAGE 091 ; 092 ; DOS BASIC INTERPRETER - INITIAL ENTRY 093 ; 094 SC1 EQU * ; Start Relocate Code 1 095 DBINIT EQU * ; DB = Dos Basic 1D84:AD E9 37 096 LDA IBSLOT ; GET BOOT SLOT 1D87:4A 097 LSR A ; /sarcasm Gee, maybe we wouldn't even need the next comment 1D88:4A 098 LSR A ; if we used good variable names such as CUR_SLOTx16 1D89:4A 099 LSR A ; but who would want that? Isn't it obvious that 1D8A:4A 100 LSR A ; CS means Current Slot * 16 !? 1D8B:8D 6A 2A 101 STA CS ; SET AS CUURENT SLOT ; *spelling* CURRENT 1D8E:AD EA 37 102 LDA IBDRVN ; GET BOOT DRIVE NUMBER 1D91:8D 68 2A 103 STA CD ; SET AS CURRENT DRIVE 1D94:AD 00 E0 104 LDA AITSTL ; GET APPLESOFT/IB TEST ; ATSTV= $4C, E000:4C = JMP $abs; Applesoft 1D97:49 20 105 EOR #ITSTV ; IF AS THEN 1D99:D0 11 106 BNE IAS1 ; GO TO AS INIT ; 107 ; ; ELSE INIT FOR IB 1D9B:8D B6 2A 108 STA ASIBSW ; SET SW FOR IB ; magic number BASIC_TYPE_INTEGER = $00 ; 30 = $1D9E .. $1DBB ; -5 = Don't count opcodes at Lines #117,118 ; -18 = Replacement code at Line 118 Solution ; === 1D9E:A2 0A 109 LDX #IBVTL ; GET IB VT LENGTH ; wastes 7 bytes 1DA0:BD 61 1D 110 IIB1 LDA IBVT-1,X ; MOVE IB ADDR ; Problem: *sigh* due to IBVTL=$A != AS1VTL=$C 1DA3:9D 55 1D 111 STA IBASVT-1,X ; we end up with duplicate code (**9 times**, er, 3 times!) to 1DA6:CA 112 DEX ; copy the BASIC Vector Table! (An array of function pointers) 1DA7:D0 F7 113 BNE IIB1 ; 1DA9:4C BC 1D 114 JMP INITAA ; normally wastes 1 byte, BEQ INITAA; but see bigger optimization on Line #109 115 ; 116 IAS1 EQU * ; IAS1 = Init Applesoft ROM; /cynical "There will be a test"
1DAC:A9 40 117 LDA #$40 ; INDICATE ROM APPLESOFT ; === Page 50 === magic number BASIC_TYPE_APPLESOFT_ROM = $40 1DAE:8D B6 2A 118 STA ASIBSW ; Solution: ; a) Lines 117-118 should be moved after Line #103 to anticipate the common case, ; b) This is one of those rare times where we padd IBVT ; (with 2 bytes data on the end) ; to make IBVT, AS1VT, and AS2VT all the same length ; ; Table SourceOffset Instructios ; IBVT #$00 #IBVT -IBVT ; AS1VT #$0C #AS1VT-IBVT ; AS2VT #$1E #AS2VT-IBVT ; ; AA 109 TAX ; X = SourceOffset #$00 = IBVT ; 2C DB $2C ; BIT $abs to skip next instruction ; ; A2 0C IAS1 LDX #AS1VT-IBVTL ; SourceOffset $C = AS1VT 1DB1:A2 0C 119 LDX #AS1VTL ; A0 00 LDY #0 ; Y = DestOffset = BytesCopied 1DB3:BD 6B 1D 120 IAS1A LDA AS1VT-1,X ; MOVE ROM AS ADRS ; BD 62 1D 1AS1A LDA IBVT,X ; X = $0, $C, or $18 to start 1DB6:9D 55 1D 121 STA IBASVT-1,X ; 99 56 1D STA IBASVT,Y 1DB9:CA 122 DEX ; E8 INX 1DBA:D0 F7 123 BNE IAS1A ; C8 INY ; C0 0C CPY #C ; D0 F4 BNE copy 124 ; 125 INITAA EQU ; /sarcasm Hey, we need a new label inbetween INITA, and INITB 1DBC:38 126 SEC ; INDICATE INIT ; I know, let's call it crappy "INITAA" instead of DoneCopyBasicVectors 1DBD:B0 12 127 BCS INITA ; ↓ (always) (*note* Intentional next empty line spacer for readability) ; 1DBF:AD 62 2A 128 DBRST LDA ASIBSW ;GET APPLESOFT/INITGER BASIC FLAG ; *spelling* INTEGER; DBRST = DosBasicReset 1DC2:D0 04 129 BNE INITA1 ;BRANCH IF NOT INITGER BASIC ; *spelling* INTEGER 1DC4:A9 20 130 LDA #ITSTV ;GET INTIGER TEST VALUE AND GO SET ; *spelling* INTEGER 1DC6:D0 05 131 BNE INITA2 ; ROM SWITCH TO 'IB'. (BRANCH ALWAYS) 1DC8:0A 132 INITA1 ASL A ;TEST FOR ROM APPLESOFT ; $40 = Applesoft RAM 1DC9:10 05 133 BPL INITA3 ;BRANCH IF RAM VERSION ; /cynical Test time! INITA3 referes to InitApplesoftRAM or InitApplesoftROM ? 1DCB:A9 4C 134 LDA #ATSTV ;GET APPLESOFT TEST VALUE AND GO SET 1DCD:20 B2 25 135 INITA2 JSR SWTST ;GO SELECT PROPER ROM BASIC. ; more crappy naming: _which_ Switch Test 1DD0:18 136 INITA3 CLC 137 ; 138 INITA EQU * 1DD1:08 139 PHP ;SAVE INIT/RESET 1DD2:20 51 28 140 JSR MVCSW ; GO MOVE CHAR SWITCH 1DD5:A9 00 141 LDA #0 ; CLR MONITOR MODES ; MON C,I,O 1DD7:8D 5E 2A 142 STA MONMOD 143 ; 1DDA:8D 52 2A 144 STA OSTATE ; CLEAR OUTSTATE AND EXECUTE STATE ; what happened to STA ESTATE ?? 1DDD:28 145 PLP ; GET INIT/RESET 1DDE:6A 146 ROR A ; SHIFT CARRY TO MSB ; /sarcasm Gee, if only we could understand 6502 instructions, $00 = Reset, $80 = Init 1DDF:8D 51 2A 147 STA ISTATE ; SAVE INSTATE ; Frak-You Captain Obvious with a STA IN_STATE 1DE2:30 03 148 BMI INITB ; BR IF INIT 1DE4:6C 5E 1D 149 JMP (CONT) ; GO TO CONTINUE ENTRY ; No Shit, Sherlock; _what_ is the difference between CONT and GO ??? 1DE7:6C 5C 1D 150 INITB JMP (GO) ; GO TO GO ENTRY ; 151 PAGE 152 INITC EQU * ; Called by CHIN0 1DEA:0A 153 ASL A ; OF ISTATE NOT ON 1DEB:10 19 154 BPL INITD ; THEN NOT RAM AS ; 1DED:8D 62 2A 155 STA ASIBSW ; SET RAM AS 1DF0:A2 0C 156 LDX #AS2VTL ; more duplicate code, we should LDA #AS2VT-IBVT and JSR 118 Solution (make a subroutine) 1DF2:BD 77 1D 157 IAS2A LDA AS2VT-1,X ; MOVE RAM AS ADRS ; wastes 6 bytes, (9 - 3 for JSR SOLUTION.118) 1DF5:9D 55 1D 158 STA IBASVT-1,X ; When you see the same block of code your spidey sense should be tingling: 1DF8:CA 159 DEX ; Is there a way to refactor this common code? 1DF9:D0 F7 160 BNE IAS2A 1DFB:A2 1D 161 LDX #29 ; magic number better: 30-1, best: FILENAME_MAX-1 1DFD:BD 93 2A 162 IAS2B LDA FNAME2,X 1E00:9D 75 2A 163 STA FNAME1,X ; === T0SD === 1E03:CA 164 DEX 1E04:10 F7 165 BPL IAS2B 166 ; 167 INITD EQU * 1E06:AD B1 2A 168 LDA DFNFTS ; GO BUILD FILE TABS 1E09:8D 57 2A 169 STA CNFTBS ; AND SET MEM BOUNDS 1E0C:20 D4 27 170 JSR BLDFTB 1E0F:AD B3 2A 171 LDA ESTATE ; GET EXEC STATE 1E12:F0 09 172 BEQ INITZ ; BR IF NOT EXECUTE 1E14:48 173 PHA ; SVE CHAR ; *spelling* SAVE 1E15:20 9D 26 174 JSR MVEFTA ; GO MOVE EX FILE TAB ADR TO ZP 1E18:68 175 PLA 1E19:A0 00 176 LDA #0 1E1B:91 40 177 STA (ZPGWRK),Y ; Oh, we're still around? 178 INITZ EQU *
1E1D:20 5B 27 179 JSR CLRSTS ; SET IN AND OUT STATES TO ZERO ; === Page 51 === ClearStates 1E20:AD 5F 2A 180 LDA CMDNO ; IF NOT BOOT (DUPLICATED FROM LINES 4540, 4550) 1E23:D0 20 181 BNE INITF ; THEN DONE 1E25:A2 2F 182 LDX #IFBL 1E27:BD 51 1E 183 INITE LDA DBVECT,X ; MOVE RESTART VECTORS 1E2A:9D D0 03 184 STA $3D0,X ; magic number 1E2D:CA 185 DEX 1E2E:10 F7 186 BPL INITE 1E30:AD 53 1E 187 LDA DBVECT+2 ;SET RESET VECTORS FOR NEW MONITOR. ; WTF is the point of even using a table 1E33:8D F3 03 188 STA ZRSET+1 ;NOTE: THESE ARE NOT NORMALLY USED AND ; if you're just going to ignore part of it??? 1E36:49 A5 189 EOR #$A5 ; ARE ONLY SET ONCE ON BOOT ; magic number F800.S Ctrl-Reset Powered Up 1E38:8D F4 03 190 STA PWCNST ;POWER UP CONSTANT=COMPLIMENT OF HI RESET VECTOR. ; Checksum not constant 1E3B:AD 52 1E 191 LDA DBVECT+1 ;SET LOW VECTOR ADDRESS. ;[.. wastes 6 bytes due to Line #221 Clusterfrak 1E3E:8D F2 03 192 STA ZRSET ;NOW APPLE RESET WILL KEEP DOS IN I/O LOOP ; ..] 1E41:A9 06 193 LDA #6 ;INIDICATE RUN ; magic number TODO 1E43:D0 05 194 BNE INITF1 ;LOAD AND RUN THE 'HELLO' PROGRAM ; ↓ (always) 195 ; 196 INITF EQU * 1E45:AD 62 2A 197 LDA SVCMD 1E48:F0 06 198 BEQ INITG 1E4A:8d 5F 2A 199 INITF1 STA CMDNO 1E4D:4C 80 21 200 JMP CMDGO1 201 INITG EQU * 1E50:60 202 RTS 203 ; 204 IFB EQU * ; --- Copied to $3D0 --- 1E51:4C BF 1D 205 DBVECT JMP DBRST ; $3D0: JMP $9DBF DOS Warm RESET -- Really?? You couldn't put this in the SAME order 1E54:4C 84 1D 206 JMP DBINIT ; $3D3: JMP $9D84 DOS Cold RESET -- as BASIC: Cold THEN Warm ??? 1E57:4C FD 2A 207 JMP USERENT ;USER EXTERNAL ENTRY TO FILE MANAGER; $3D6: JMP $AAFD FM (File Manager) 1E5A:4C B5 37 208 JMP DISKIO ; $3D9: JMP $B7B5 RWTS (ReadWriteTrackSector) 209 CCBLDR EQU * ; $3DC: GetParamFM (A,Y = $B5BB, CCB = Command Control Block) 1E5D:AD 0F 1D 210 LDA CCBADR+1 1E60:AC 0E 1D 211 LDY CCBADR ; NOTE The labels CCBLDR and IOBLDR are never referenced anywhere. 1E63:60 212 RTS 213 IOBLDR EQU * ; $3E3: GetParamRWTS (A,Y = $B7E8, IOB = Input Output Block) 1E64:AD C2 2A 214 LDA AIOB+1 ; /sarcasm Really? You couldn't be consistent and call it IOBADR ??? 1E67:AC C1 2A 215 LDY AIOB 1E6A:60 216 RTS 1E6B:4C 51 28 217 JMP MVCSW ; $3EA: Set CIN/COUT to DOS 1E6E:EA 218 NOP ; $3ED: [.. Normally, this would be wastes 2 bytes -- NEVER used anywhere 1E6F:EA 219 NOP ; ... HOWEVER they ARE needed since they are used as padding to align the following BRK IRQ vector. ; ... Diversi-DOS has: 3ED: 4C DF BC JMP $BCDF ; ..] Thanks Tommy for the insight! 1E70:4C 59 FA 220 JMP MONBRK ; $3EF: JMP $FA59 Autostart BRK handler. ; Note: This is never directly called as the Autostart ROM reads the address at $3F0, $3F1 via $FA56: 6C F0 03 JMP (BRKV) 1E73:4C 65 FF 221 JMP MONRST ; $3F2: $9DBF,$38 Control-Reset - Why not DW DBRST, DB $#>DBRST ^ $A5 ??? Line #191 1E76:4C 58 FF 222 JMP IORTS ; $3F5: JMP $FF58 Ampersand handler 1E79:4C 65 FF 223 JMP MONRST ; $3F8: JMP $FF65 Ctrl-Y handler 1E7C:4C 65 FF 224 JMP MONRST ; $3FB: JMP $FF65 NMI handler 1E7F:65 FF 225 DW MONRST ; $3FE: dw $FF65 IRQ vector 226 IFBL EQU *-IFB-1 ; IFB_Length = $1E81 - 1E51 = $2F
001 PAGE 002 ; 003 ;CHRIN - CHAR RCVD VIA IN SWITCH 004 ; 005 CHRIN EQU * 1E81:20 D1 1E 006 JSR SVREGS ; 1E84:AD 51 2A 007 LDA ISTATE ; IF NOT DISKIN 1E87:F0 15 008 BEQ CHIN1 ; THEN BRANCH, ELSE 1E89:48 009 PHA ;SAVE ISTATE 1E8A:AD 5C 2A 010 LDA SVA 1E8D:91 28 011 STA ($28),Y ;REPLACE CURSOR ; magic number /sarcasm If only F800.S ROM defined BASL EQU $28 1E8F:68 012 PLA ;GET ISTATE AGAIN 1E90:30 03 013 BMI CHIN0 ;BRANCH IF NOT 'READ' FROM DISK 1E92:4C 26 26 014 JMP ICFD ; AND GET CHAR FROM DISK 1E95:20 EA 1D 015 CHIN0 JSR INITC 1E98:A4 24 016 LDY $24 ;GET CURSOR HORIZ ; magic number /sarcasm If only F800.S ROM defined CH EQU $24 1E9A:A9 60 017 LDA #$60 ;RESTORE A FLASHING CURSOR ; #' ' + FLASH ; INVERSE = $00..$3F, FLASH = $40..$7F, NORMAL = $80..FF 1E9C:91 28 018 STA ($28),Y ; TO PROMPT USER ; magic number 019 CHIN1 EQU * 1E9E:AD B3 2A 020 LDA ESTATE 1EA1:F0 03 021 BEQ CHIN2 1EA3:20 82 26 022 JSR NXTEXC ;RETURNS TO HERE ONLY WHEN 'EXEC' IS EXHAUSTED 023 CHIN2 EQU * 1EA6:A9 03 024 LDA #3 ; SET OUT CHAR ; magic number COS_INPUT_ECHO = 3 1EA8:8D 52 2A 025 STA OSTATE ; STATE TO INPUT ECHO 1EAB:20 BA 1F 026 JSR LDREGS 1EAE:20 BA 1E 027 JSR GETIN 1EB1:8D 5C 2A 028 STA SVA ; SAVE CHAR & INDEX 1EB4:8E 5A 2A 029 STX SVX 1EB7:4C B3 1F 030 JMP ORTN 031 ; 1EBA:6C 38 00 032 GETIN JMP (INSW) 033 ; 034 ;CHROUT - CHAR RCVD VIA OUTPUT SWITCH 035 ; 036 CHROUT EQU * 1EBD:20 D1 1E 037 JSR SVREGS ; SAVE REGS 038 ; 1EC0:AD 52 2A 039 LDA OSTATE ; GET OUT SPARE 1EC3:0A 040 ASL A 1EC4:0A 041 TAX 1EC5:BD 11 1D 042 LDA OUTSVT1+1,X ; GET ROUTINE ADR 1EC8:48 043 PHA 1EC9:BD 10 1D 044 LDA OUTSVT+1,X 1ECC:48 045 PHA 1ECD:AD 5C 2A 046 LDA SVA 1ED0:60 047 RTS ; GO TO ROUTINE 048 ; 049 ;SVREGS - SAVE REGS WHILE PROCESSING CHARS 050 ; 051 SVREGS EQU * 1ED1:8D 5C 2A 052 STA SVA ; SAVE ACU ; Captain Obvious to the rescue!
053 SVRGSA EQU * ; === Page 45 === SaveRegsA, uh, NO, SaveRegsXY, we _already_ saved A; this is why using nameA nameB are bad. 1ED4:8D 5A 2A 054 STX SVX ; SAVE X ; More crap names. Good variable naming such as SAVEX and SAVEY 1ED7:8C 5B 2A 055 STY SVY ; SAVE Y ; negates the need for these useless redundant comments. 1EDA:BA 056 TSX ;SAVE STACK POINTER 1EDB:E8 057 INX 1EDC:E8 058 INX ;ADJUST IT TO ORIGINAL 1EDD:8E 59 2A 059 STX SVSTK 1EE0:A2 03 060 LDX #3 ; SET FOR FOUR BYTE MOVE ; /sarcasm If only we could read assembly ... 1EE2:BD 53 2A 061 SVRB LDA SVOUTS,X ; MOVE SAVED OUT AND IN SW ; SVRB = SaVe Regs B, /sarcasm What, SVRGSB wasn't available??? (A. It is.) 1EE5:95 36 062 STA OUTSW,X ; TO APPLE OUT/IN SW 1EE7:CA 063 DEX 1EE8:10 F8 064 BPL SVRB 1EEA:60 065 RTS ; DONE ; Can someone please put Captain Obvious out of _our_ misery? 066 PAGE 067 ; 068 ; COS0 - 1ST CHAR OF PRINTED OUTPUT LINE 069 ;CHECK FOR CNTL-D ; "You say CNTL-D, I say CTRL-D" 070 ; ; We're both inconsistently dropping a consonant: CoNTRoL 071 COS0 EQU * 1EEB:AE B7 2A 072 LDX RSTATE ;FIRST CHECK FOR 'AFTER APSFT RELOC' 1EEE:F0 03 073 BEQ COS00 ;BRANCH IF NOT ; Really?! You couldn't use COS0A and COS0B like you do for the other states?? ; COS0 & COS00 are crap function names; they are WAY too easy to mis-read/type 1EF0:4C 78 1F 074 JMP COS7 ; wastes 3 bytes, but since $1F78-$1EF0 > $80 ; TODO We need to move COS5..COS7 before COS0; change Line #74 to BNE COS7 1EF3:AE 51 2A 075 COS00 LDX ISTATE ;IS IN STATE NOT ZERO ; I'm serious, someone please shoot Captain Obvious 1EF6:F0 08 076 BEQ COS01 ; 1EF8:C9 BF 077 CMP #'?'+$80 ; THEN IS THIS ? 1EFA:F0 75 078 BEQ COS6 ; THEN PRINT ONLY IF MONITOR 1EFC:C5 33 079 CMP PROMPT 1EFE:F0 27 080 BEQ COS2A 081 COS01 EQU * ; === T0SE === 1F00:A2 02 082 LDX #2 ; magic number 1F02:8E 52 2A 083 STX OSTATE 1F05:CD B2 2A 084 CMP CCHAR ; IF NOT CNTL-D 1F08:D0 19 085 BNE COS2 ; THEN GO TO STATE 2 1F0A:CA 086 DEX 1F0B:8E 52 2A 087 STX OSTATE ; ELSE STATE=1 1F0E:CA 088 DEX 1F0F:8E 5D 2A 089 STX LBUFD ; AND LBUFD=0 090 ; 091 ;COS1 - ACCUMULATE CMD FROM PRINTED OUTPUT 092 ; 093 COS1 EQU * 1F12:AE 5D 2A 094 LDX LBUFD ; GET LINE BUFF DISPL 1F15:9D 00 02 095 COS1A STA LBUFF,X ; PUT CHAR IN BUFF 1F18:E8 096 INX ; INCR PTR 1F19:8E FD 2A 097 STX LBUFD ; SAVE PTR 1F1C:C9 8D 098 CMP #$8D ; WAS THIS A CR ; magic number 1F1E:D0 75 099 BNE CMDRTN ; IF NOT THEN PR CHAR 100 ; 1F20:4C CD 1F 101 JMP SCNCMD ; GO SCAN COMMAND 102 ; 103 ;COS2 - PRINTED OUTPUT, NOT FIRST CHAR 104 ; 105 COS2 EQU * 1F23:C9 8D 106 CMP #$8D ; IS IT A CR ; magic number 1F25:D0 7D 107 BNE PRRTN ; BR IF NOT 1F27:A2 00 108 COS2A LDX #0 ; SET FOR POSSIBLE C-D NEXT ; C-D = Control-D magic number COS_STATE_FIRST_CONTROL_D = 0 1F29:8E 52 2A 109 STX OSTATE ; NEXT STATE 1F2C:4C A4 1F 110 JMP PRRTN ; GO PRINT CHAR ; wastes 1 byte, $1F83 - $1F2C = $57, BEQ PRRTN 111 PAGE 112 ; 113 ;COS3 - KEY IN ECHO PRINT 114 ; 115 COS3 EQU *
1F2F:A2 00 116 LDX #0 ; === Page 46 === magic number COS_STATE_0 1F31:8E 52 2A 117 STX OSTATE ; RESET OUT STATE 1F34:C9 8D 118 CMP #$8D ; IS IT CR 1F36:F0 07 119 BEQ COS3A ; IF CR THEN CMD CHECK 1F38:AD B3 2A 120 COS3B LDA ESTATE ; ELSE: IF NOT EXECUTE 1F3B:F0 67 121 BEQ PRRTN ; THEN PRINT CHAR 1F3D:D0 5E 122 BNE DRTNI ; ELSE: PRINT IF MON INPUT ; Data Return In 1F3F:48 123 COS3A PHA ;SAVE CARRAGE RETURN 1F40:38 124 SEC ;ANTICIPATE EXEC FILE INPUT. 1F41:AD B3 2A 125 LDA ESTATE ;CHECK EXEC FLAG 1F44:D0 03 126 BNE COS3C ;BR IF WAS INPUT FROM EXEC. 1F46:20 5E 26 127 JSR TSTRUN ;GO TEST FOR RUN MODE. 1F49:68 128 COS3C PLA 1F4A:90 EC 129 BCC COS3B ;IGNORE INPUT IF RUNNING. 1F4C:AE 5A 2A 130 LDX SVX ; GET LINE INDEX 1F4F:4C 15 1F 131 JMP COS1A ; TODO Can this ever be zero?? 132 ; 133 ;COS4 - DISK OUTPUT MODE 134 ; 135 COS4 EQU * 1F52:C9 8D 136 CMP #$8D ; IS IT CR 1F54:D0 05 137 BNE COS4A ; BR IF NOT CR 1F56:A9 05 138 LDA #5 ; SET STATE FOR CNTL-D 1F58:8D 52 2A 139 STA OSTATE ; EXAMINE 1F5B:20 0E 26 140 COS4A JSR OCTD ; GO OUTPUT CJHAR TO DISK ; *spelling* Char 1F5E:4C 99 1F 141 JMP DRTNO ; GO TO DATA RETURN (OUT) 142 ; 143 ;COS5 - DISK OUTPUT MODE - 1ST CHAR 144 ; 145 COS5 EQU * 1F61:CD B2 2A 146 CMP CCHAR ; IS IT CNTL D 1F64:F0 85 147 BEQ COS0 ; BR IF CNTL- D 1F66:C9 8A 148 CMP #$8A ; LINE FEED? 1F68:F0 F1 149 BEQ COS4A 1F6A:A2 04 150 LDX #4 1F6C:8E 52 2A 151 STX OSTATE ; SET NEW OUT STATE ; No Shit Sherlock, *what* is State 4 ?? 1F6F:D0 E1 152 BNE COS4 ; BR IF NOT CNTL D ; ↑ (always) wastes 2 bytes, move COS5 before COS4 and remove this branch 153 ; 154 ;COS6 - DISK INPUT ECHO 155 ; 1F71:A9 00 156 COS6 LDA #0 1F73:8D 52 2A 157 STA OSTATE ; RESET OUT STATE = 0 1F76:F0 25 158 BEQ DRTNI ; GO TO DATA IN RETURN 159 ; 160 ; COS7 - SPECIAL FOR RECOVER FROM AS ROM/RAM RELOC. 161 ; 1F78:A9 00 162 COS7 LDA #0 ; RESET RELOC STATE 1F7A:8D B7 2A 163 STA RSTATE 1F7D:20 51 28 164 JSR MVCSW ;FOR COMPATABILITY ON REENTRY 1F80:4C DC 24 165 JMP ERUN1 166 PAGE 167 ; 168 ;PRRTN - PRINT CHAR RETURN 169 ; 170 ; 171 ; CMDRTN - PRINT CHAR IF MONITOR CMBS MODE ; TODO CMBS ??? 172 ; DRTNO - PRINT CHAR IF MONITOR DATA OUT 173 ; DRTNI - PRINT CHAR IF MONITOR DATA IN 174 ; 175 CERTN EQU * 1F83:AD 00 02 176 LDA LBUFF ; CHECK FOR PRINTED COMMAND 1F86:CD B2 2A 177 CMP CCHAR 1F89:F0 0A 178 BEQ CMDRTN ; IF PC THEN NO RESET X REG
1F8B:A9 8D 179 LDA #$8D ; CARRAGE RETURN ; === Page 47 === magic number KEY_CR 1F8D:8D 00 02 180 STA LBUFF ; TO OUT BUFFER 1F90:A2 00 181 LDX #0 ; RESET TO SOL ; StartOfLine 1F92:8E 5A 2A 182 STX SVX 1F95:A9 40 183 CMDRTN LDA #MC 1F97:D0 06 184 BNE MODECK ; ↓ (always) 1F99:A9 10 185 DRTNO LDA #MO ; Data Return Out 1F9B:D0 02 186 BNE MODECK ; ↓ (always) 1F9D:A9 20 187 DRTNI LDA #MI ; Data Return In 188 ; 189 MODECK EQU * ; ModeCheck common entry 1F9F:2D 5E 2A 190 AND MONMOD ; AND WITH MODE 1FA2:F0 0F 191 BEQ ORTN ; BR IF NOT PRINT 1FA4:20 BA 1F 192 PRRNT JSR LDREGS 1FA7:20 C5 1F 193 JSR ORTN1 1FAA:8D 5C 2A 194 STA SVA ;SAVE REGISTERS 1FAD:8C 5B 2A 195 STY SVY 1FB0:8E 5A 2A 196 STX SVX 197 ; 198 ORTN EQU * 1FB3:20 51 28 199 JSR MVCSW ; GO MOVE CHAR I/O SWITCH 1FB6:AE 59 2A 200 LDX SVSTK ;RESTORE ORIGINAL STACK POINTER (YEEECH!) ; /sarcasm And yet you're still futzing with the Stack Pointer 1FB9:9A 201 TXS 202 LDREGS EQU * 1FBA:AD 5C 2A 203 LDA SVA ; ACU ; Captain Obvious SAVE_A 1FBD:AC 5B 2A 204 LDY SVY ; Y ; is working SAVE_Y 1FC0:AE 5A 2A 205 LDX SVX ; X ; overtime today SAVE_X 1FC3:38 206 SEC ;(FOR 'ESC' SCREEN FUNCTIONS) 1FC4:60 207 RTS ; BY PASS PRINT 208 ; 1FC5:6C 36 00 209 ORTN1 JMP (OUTSW) 210 ; 211 ; PRRIF - PRINT CR IF MON CMDS 212 ; 213 PRCRIF EQU * 1FC8:A9 8D 214 LDA #$8D ; ELSE PRINT CR ; magic number KEY_CR 1FCA:4C C5 1F 215 JMP ORTN1 ; wastes 1 byte; BNE ORTN1
001 PAGE 002 ; 003 ; SCNCMD - SCAN A COMMAND 004 ; 005 SCNCMD EQU * 006 DO ULC 007 LDX #0 ;Init X for lower case check 008 JSR UPRCASE ;Go check 009 ELSE 1FCD:A0 FF 010 LDY #$FF ;Set CMDNO to -1 1FCF:8C 5F 2A 011 STY CMDNO 012 FIN 1FD2:C8 013 INY ; INCR TABLE INDEX 1FD3:8C 62 2A 014 STY SVCMD 015 SC0 EQU * 1FD6:EE 5F 2A 016 INC CMDNO ; INCR CMD NO ; Thanks Captain Obvious 1FD9:A2 00 017 LDX #0 ; RESET LINE INDEX TO 0 1FDB:08 018 PHP ; SAVE EQ STATUS 1FDC:BD 00 02 019 LDA LBUFF,X ; GET 1ST LINE CHAR 1FDF:CD B2 2A 020 CMP CCHAR ; IS IT CONTROL D 1FE2:D0 01 021 BNE SC0A ; BR /IF NOT 1FE4:E8 022 INX ; INCR OVER CNTLD 1FE5:8E 5D 2A 023 SC0A STX LBUFD 024 ; 025 SC1X EQU * 1FE8:20 A4 21 026 JSR GNBC ; GET NON BLANK INPUT CHAR 1FEB:29 7F 027 AND #$7F ; MSB OF CHAR OFF 1FED:59 84 28 028 EOR CMDNTB,Y ; EOR WITH INPUT 1FF0:C8 029 INY ; INCREMENT TABLE INDEX 1FF1:0A 030 ASL A ; IF MSB OF EOR RESULT ON 1FF2:F0 02 031 BEQ SC1A ; IF RESULT NOT NOW ZERO 1FF4:68 032 PLA ; THEN INPUT DOES NOT 1FF5:08 033 PHP ; EQUAL ENTRY 1FF6:90 F0 034 SC1A BCC SC1X ; LOOP FOR END OF ENTRY 035 ; 1FF8:28 036 PLP ; IF INPUT EQUALS END ; 1FF9:F0 20 037 BEQ SYNTAX ; THEN GO SYNTAX 038 ; 1FFB:B9 84 A8 039 LDA CMDNTB,Y ; IF NEXT TABLE CHAR NOT ZERO 1FFE:D0 D6 040 BNE SC0 ; THENSCANTHE NEXT TABLE ENTRY ; /sarcasm whoneedsspacesanyways 041 CNF EQU * ; COMMAND NOT FOUND 2000:AD 00 02 042 LDA LBUFF ; LINE IS A CNOTROL-D ; *spelling* Control-D 2003:CD B2 2A 043 CMP CCHAR ; THEN THIS IS A 2006:F0 03 044 BEQ CNF1 ; POSSIBLE SYNTAX ERROR, ELSE 2008:4C A4 1F 045 JMP PRRTN ; ITS A BASIC INPUT LINE 046 CNF1 EQU * 200B:AD 01 02 047 LDA LBUFF+1 ; GET NEXT CHAR 200E:C9 8D 048 CMP #$8D ; IS IT A CR ; magic number KEY_CR 2010:D0 06 049 BNE CSERR ; BR IF CR 2012:20 5B 27 050 JSR CLRSTS ; CLEAR THE STATES 2015:4C 95 1F 051 JMP CMDRTN ; CNTL-D ONLY 052 ; 2018:4C C4 26 053 CSERR JMP ESYNTX
054 PAGE ; === Page 17 === 055 ; 056 ; SYNTAX - FIGURE OUT WHAT WE GOT HERE 057 ; 058 SYNTAX EQU * 201B:0E 5F 2A 059 ASL CMDNO 201E:AC 5F 2A 060 LDY CMDNO 2021:20 5E 26 061 JSR TSTRUN 2024:90 0C 062 BCC SYN1 2026:A9 02 063 LDA #RNONLY 2028:39 09 29 064 AND CMDSTB,Y 202B:F0 05 065 BEQ SYN1 202D:A9 0F 066 LDA #$F ; magic number ERR_NOT_DIRECT 202F:4C D2 26 067 JMP ERROR 2032:C0 06 068 SYN1 CPY #6 ; magic number TODO CMD_RUN 2034:D0 02 069 BNE SYN1A 2036:84 33 070 STY PROMPT ; CHANGE PROMPT TO INSURE APPLESOFT RUN DETECT. 2038:A9 20 071 SYN1A LDA #FN1 203A:39 09 29 072 AND CMDSTB,Y 203D:F0 61 073 BEQ SN10 203F:20 95 20 074 JSR CLRFNS 2042:08 075 PHP ; SAVE EQ STATUS 076 ; 077 SN2 EQU * 2043:20 A4 21 078 JSR GNBC ; GET NON BLANK CHAR 2046:F0 1E 079 BEQ SN6 ; BR IF CR OR COMMA 2048:0A 080 ASL A ; TEST FOR ALPHA 2049:90 05 081 BCC SN2A ; BR IF ALPHA 204B:30 03 082 BMI SN2A ; BR IF APLHA 204D:4C 00 20 083 JMP CNF ; LURCH IF NOT ALPHA 2050:6A 084 SN2A ROR A ; RESTORE BITS 2051:4C 59 20 085 JMP SN4 ; AWAY WE GO 2054:20 93 21 086 SN3 JSR GNXTC ; GO GET NEXT CHAR ; GetNextChar 2057:F0 0D 087 BEQ SN6 ; BR IF COMMA OR CR 2059:99 75 2A 088 SN4 STA FNAME1,Y ; PUT INTO FILENAME 205C:C8 089 INY ; INC FN INDEX ; Total filenames length < 60 ? 205D:C0 3C 090 CPY #60 ; ATFN CHAR LIMIT ; At Filename Character Limit TODO What triggers this? 205F:90 F3 091 BCC SN3 ; BR IF NOT 2061:20 93 21 092 SN5 JSR GNXTC ; LOOP UNTIL CR OR COMMA 2064:D0 FB 093 BNE SN5 094 ; 2066:28 095 SN6 PLP ; WAS THIS FN2 L OO ; TODO Was this filename 2 _length_ _ok_??? 2067:D0 0F 096 BNE SN7 ; BR IF IT WAS 097 ; 2069:AC 5F 2A 098 LDY CMDNO 206C:A9 10 099 LDA #FN2 206E:39 09 29 100 AND CMDSTB,Y ; IF FN2 NOT REQD THEN 2071:F0 0C 101 BEQ SN8 ; BRANCH 102 ; 2073:A0 1E 103 LDY #30 ; SET FN2 INDEX ; @filename2[0] magic number MAX_FILENAME_LEN 2075:08 104 PHP ; INDICATE FN2 SEEK 2076:D0 CB 105 BNE SN2 ; GO LOOK FOR FN2 106 ; 2078:AD 93 2A 107 SN7 LDA FNAME2 ; IF 1ST CHAR OF 207B:C9 A0 108 CMP #$A0 ; FN2 IS BLANK THEN 207D:F0 13 109 BEQ SERR1 ; SYNTAX ERROR 110 ; 207F:AD 75 2A 111 SN8 LDA FNAME1 ; IF 1ST CHAR OF 2082:C9 A0 112 CMP #$A0 ; FN1 IS NOT BLANK 2084:D0 4B 113 BNE SOPTS ; THEN GO LOOK FOR OPTIONS 114 ; 2086:AC 5F 2A 115 LDY CMDNO
2089:A9 C0 116 LDA #NPB+NPE ; IF CMD MUST HAVE FILENAME ; === Page 18 === 208B:39 09 29 117 AND CMDSTB,Y ; THEN 208E:F0 02 118 BEQ SERR1 ; THIS IS ERROR, ELSE 119 ; 2090:10 3F 120 BPL SOPTS ; ITS EXCUTABLE WITHOUT ; *spelling* Executable 121 ; 2092:4C 00 20 122 SERR1 JMP CNF 123 ; 124 CLRFNS EQU * 2095:A0 3C 125 LDY #60 ; magic number MAX_FILENAME_LEN * 2 126 CLRFNA EQU * 2097:A9 A0 127 LDA #$A0 2099:99 74 2A 128 SN1 STA FNAME1-1,Y ; CLEAR FN1, FN2 ; *sigh* instead of -1 offset, LDY #2*MAX_FILENAME_LEN-1 209C:88 129 DEY 209D:D0 FA 130 BNE SN1 209F:60 131 RTS 132 PAGE 133 SN10 EQU * ; FILE NAMES NOT REQD 20A0:8D 75 2A 134 STA FNAME1 20A3:A9 0C 135 LDA #NUM1+NUM2 ; IF NEITHER NUM1 20A5:39 09 29 136 AND CMDSTB,Y ; OR NUM2 IS REQD 20A8:F0 27 137 BEQ SOPTS ; THEN GO LOOK AT OPTIONS 138 ; 20AA:20 B9 21 139 JSR GETNUM ; GO GET NUMERICS 20AD:B0 1F 140 BCS SERR2 141 ; 20AF:A8 142 TAY ; IF HIGH DIGIT NOT 20B0:D0 17 143 BNE SERR3 ; ZERO THEN BAD 144 ; 20B2:E0 11 145 CPX #17 ; IF LOW DIGIT GT 16 20B4:B0 13 146 BCS SERR3 ; THEN BAD 147 ; 20B6:AC 5F 2A 148 LDY CMDNO 20B9:A9 08 149 LDA #NUM1 20BB:39 09 29 150 AND CMDSTB,Y ; IF WE WANT NUM2 20BE:F0 06 151 BEQ SN11 152 ; 20C0:E0 08 153 CPX #8 ; IF NUM2>1 20C2:B0 CE 154 BCS SERR1 ; THEN ERROR, ELSE 20C4:90 0B 155 BCC SOPTS ; GO SCAN OPTIONS 156 ; 157 SN11 EQU * 20C6:8A 158 TXA ; IF NUM1=0 20C7:D0 08 159 BNE SOPTS ; THEN ERROR, ELSE GET OPTIONS 160 ; 20C9:A9 02 161 SERR3 LDA #2 ;RANGE ERROR! ; magic number 20CB:4C D2 26 162 JMP ERROR 20CE:4C C4 26 163 SERR2 JMP ESYNTX ;DISK CMD SYNTAX ERROR 164 ; 165 PAGE 166 ; 167 ; SOPTS - LOOK FOR SYNTAX OPTIONS 168 ; 169 SOPTS EQU * 20D1:A9 00 170 LDA #0 20D3:8D 65 2A 171 STA INOPTS ; CLEAR INPUT OPTIONS 20D6:8D 74 2A 172 STA IMBITS 20D9:8D 66 2A 173 STA CV ;DEFAULT VOLUME=0 20DC:8D 6C 1A 174 STA CL 20DF:8D 6D 2A 175 STA CL+1 20E2:20 DC 3F 176 JSR CLRBYTE ;PATCH FOR BYTE PARAMETER (WAS STA TEMP1A) 20E5:AD 5D 2A 177 LDA LBUFD ; SET PASS 1
178 ; ; === Page 19 === 20E8:20 A4 21 179 SP1 JSR GNBC ; GO GET NON-BLANK CHAR 20EB:D0 1F 180 BNE SP2 ; BR IF NOT COMMA OR CR 20ED:C9 8D 181 CMP #$8D ; IF CHAR IS COMMA ; magic number KEY_CR 20EF:D0 F7 182 BNE SP1 ; THEN GO GET CHAR 183 ; 20F1:AE 5F 2A 184 LDX CMDNO ; OPTIONS INPUT = I 20F4:AD 65 2A 185 LDA INOPTS ; ALLOW OPTS = A 20F7:1D 0A 29 186 ORA CMDSTB+1,X ; IF (A OR I) 20FA:5D 0A 29 187 EOR CMDSTB+1,X XOR A NOT =0 THEN 20FD:D0 93 188 BNE SERR1 ; WE HAVE UNALLOWED OPTIONS 189 ; 20FE:AE 62 2A 190 LDX TEMP1A ; IF THIS IS PASS2 ; === T1S0 === 2102:F0 76 191 BEQ CMDGO ; THEN DONE, 2104:8D 63 2A 192 STA TEMP1A ; ELSE SET PASS 2107:8E 5D 2A 193 STX LBUFD ; RESTORE LBUFD AND 210A:D0 DC 194 BNE SP1 ; GO DO PASS 2 195 ; 210C:A2 0A 196 SP2 LDX #OPT1L ; COMPARE CHAR HAVE WITH 210E:DD 40 29 197 SP3 CMP OPTAB1-1,X ; CHARS IN OPT TABLE 2111:F0 F5 198 BEQ SP4 ; IF FOUND CONTINUE, 2113:CA 199 DEX 2114:D0 F8 200 BNE SP3 ; IF NOT FOUND 2116:F0 B6 201 SERR2A BEQ SERR2 ; THEN SYNTAX ERROR 202 ; 2118:BD 4A 29 203 SP4 LDA OPTAB2-1,X ; IF CORRESPONDING OP TAB 2 IS 211B:30 47 204 BMI SP8 ; MINUS THEN IT MONITOR BITS ; C,I,O were all flagged with +$80, see OPTAB2 211D:0D 65 2A 205 ORA INOPTS 2120:8D 65 2A 206 STA INOPTS 2123:CA 207 DEX 208 ; 2124:8E 64 2A 209 STX TEMP2A ; ELSE A NUMERIC MUST FOLLOW 2127:20 B9 21 210 JSR GETNUM ; FOLLOW 212A:B0 A2 211 BCS SERR2 212 ; 212C:AD 64 2A 213 LDA TEMP2A ; GET IOTION NUMBER 212F:0A 214 ASL A ; MULT BY 4 2130:0A 215 ASL A 2131:A8 216 TAY 217 ; ; Compare 16-bit cnum >= low, cnum < max 2132:A5 45 218 LDA CNUM+1 ; IF RESULT NUM HI IS ; +1 = cnum.hi; is cnum < 256 ? i.e. only 8-bit 2134:D0 09 219 BNE SP5 ; GT 0, THEN GT LOW RANGE 2136:A5 44 220 LDA CNUM ; TEST RESULT LOW ; +0 = cnum.low < 2138:D9 55 29 221 CMP OPTAB3,Y ; WITH LOW RANGE (LOW) ; +0 = OptValMin[x].Lo ? 213B:90 8C 222 BCC SERR3 ; BR IF RESULT < LR 213D:A5 45 223 LDA CNUM+1 ; +1 = cnum.hi < 213F:D9 58 29 224 SP5 CMP OPTAB3+3,Y ; +3 = OptValMax[x].Hi ? 2142:90 0B 225 BCC SP6 ; BR IF LESS 2144:D0 83 226 SERR3A BNE SERR3 ; BR IF GREATER 2146:A5 44 227 LDA CNUM 2148:D9 57 29 228 CMP OPTAB3+2,Y ; +2 = OptValMax[x].Lo 214B:90 02 229 BCC SP6 ; BR IF LESS 214D:D0 F5 230 BNE SERR3A ; BR IF GREATER 231 ; 214F:AD 63 2A 232 SP6 LDA TEMP1A ; IF PASS 1, THEN 2152:D0 94 233 BNE SP1 ; DONT STORE RESULT 2154:98 234 TYA 2155:4A 235 LSR A 2156:A8 236 TAY 237 ; 2157:A5 45 238 LDA CNUM+1 ; STORE THE RESULT 2159:99 67 2A 239 STA CUROPT+1,Y 215C:A5 44 240 LDA CNUM
215E:99 66 2A 241 STA CUROPT,Y ; === Page 20 === 2161:4C E8 20 242 SP7 JMP SP1 ; GO FOR NEXT OPT 243 ; 244 SP8 EQU * ; MONITOR REQ ; Have 'C', 'I', or 'O' 2164:48 245 PHA ; SAVE TYPE REQ 2165:A9 80 246 LDA #CIO ; SET OPTION OF CIO 2167:0D 65 2A 247 ORA INOPTS 216A:8D 65 2A 248 STA INOPTS 216D:68 249 PLA ; RESTOERE REQ 216E:29 7F 250 AND #$7F ; CLEAR CIO ; magic number Why not ~CIO ? Crappy tool (assembler)?? 2170:0D 74 2A 251 ORA IMBITS ; OR WITH PREV IMBITS 2173:8D 74 2A 252 STA IMBITS 2176:D0 E9 253 BNE SP7 ; GO FOR NEXT 254 ; 2178:F0 9C 255 BEQ SERR2A ;BRANCH ALWAYS 256 ; 217A:20 80 21 257 CMDGO JSR CMDGO1 ; CMDGO - EXECUTE COMMAND 217D:4C 83 1F 258 JMP CERTN 259 ; 260 CMDGO1 EQU * 2180:20 5B 27 261 JSR CLRSTS ; Clear States 2183:20 AE 21 262 JSR CLRCCB ; GO CLEAR CCB ; /sarcasm I never would have guessed 263 ECMD EQU * 2186:AD 5F 2A 264 LDA CMDNO ; COMMAND NO ; Think, McFly! 2189:AA 265 TAX ; IS CMD EXEC TAB INDEX ; wastes 1 byte /sarcasm If only we had LDX CMDNO on Line #264 218A:BD 1F 1D 266 LDA CMDETB+1,X ; GET CMD ADR ;[.. 218D:48 267 PHA ; ONTO STACK ; .. 218E:BD 1E 1D 268 LDA CMDETB,X ; .. 2191:48 269 PHA ; .. Classic technique of 6502 jump table, 2192:60 270 RTS ; AND GOTO COMMAND ; ..] use RTS to "call" the function pointer
001 PAGE 002 ; ; Setup: LineLength (current char offset in Line Buffer to process) 003 ; GNXTC - GET NEXT CHAR ; In : n/a 004 ; ; Out : A=char in LineBuffer, (X=LineLength if CR else X=LineLength+1) 005 GNXTC EQU * ; Z=1 if CR or COMMA, else Z=0 2193:AE 5D 2A 006 LDX LBUFD 2196:BD 00 02 007 LDA LFUFF,X ; GET NEXT CHAR AND IF ; char c = LineBuffer[ LineLength ]; 2199:C9 8D 008 CMP #$8D ; IS IT A CR ; gEqual = (c == '\r'); 219B:F0 06 009 BEQ GNXTCR ; THEN RETURN WITHOUT ; if( gEqual ) 219D:E8 010 INX ; INCR TO NEXT CHAR ; return c; 219E:8E 5D 2A 011 STX LBUFD ; LineLength++; 21A1:C9 AC 012 CMP #','+$80 ; TEST FOR COMMA ; gEqual = (c == ','); 21A3:60 013 GNXTCR RTS ; return c; 014 ; 015 ; GNBC - GET NON BLANK CHAR 016 ; 017 GNBC EQU * ; char c; 21A4:20 93 21 018 JSR GNXTC ; GO GET NEXT CHAR ; do { 21A7:F0 FA 019 BEQ GNXTCR ; BR IF COMMA OR CR ; c = GetNextChar(); 21A9:C9 A0 020 CMP #$A0 ; IS IT BLANK ; if (gEqual) break; 21AB:F0 F7 021 BEQ GNBC ; BR IF BLANK ; } while (c == ' '); 21AD:60 022 RTS ; DONE ; o7 Captain Obvious 023 ; 024 ; CLRCCB - CLEAR CCB 025 ; 026 CLRCCB EQU * 21AE:A9 00 027 LDA #0 21B0:A0 16 028 LDY #CCBLEN ; CCBLENGTH 21B2:99 BA 35 029 CLC1 STA CCB-1,Y ; CLEAR BYTE 21B5:88 030 DEY 21B6:D0 FA 031 BNE CLC1 21B8:60 032 RTS 033 PAGE 034 ; 035 ; GETNUM - CONVERT ASCII INPUT TO NUMERIC 036 ; 037 GETNUM EQU * ; cnum = atoi(); 21B9:A9 00 038 LDA #0 ; CLEAR WORK AREA 21BB:85 44 039 STA CNUM 21BD:85 45 040 STA CNUM+1 21BF:20 A4 21 041 JSR GNBC ; GetNonBlankChar() 21C2:08 042 PHP ; need to save flags since testing for hex num nukes them 21C3:C9 A4 043 CMP #$A4 ; magic number #'$'+$80 (improvement), CHAR_DOLLAR (better), or OPT_NUM_HEX (best) 21C5:F0 3C 044 BEQ HEXNUM ; ↓ $2203 21C7:28 045 PLP 21C8:4C CE 21 046 JMP GN2A ; wastes 1 byte, BMI GN2A 047 ; 21CB:20 A4 21 048 GN2 JSR GNBC ; GET NEXT NON BLANK 049 GN2A EQU * 21CE:D0 06 050 BNE GN3 ; BR NOT COMMA OR CR 21D0:A6 44 051 LDX CNUM ; X=RESULT LOW 21D2:A5 45 052 LDA CNUM+1 ; Y=RESULT HI ; *sigh* *spelling* A=Result Hi as Y isn't even used! 21D4:18 053 CLC
21D5:60 054 RTS ; DONE ; === Page 151 === o7 Captain Obvious 055 ; 21D6:38 056 GN3 SEC ; GetDigit 21D7:E9 B0 057 SBC #$B0 ; SUBTRACT ASCII 0 ; You keep using this word ASCII, it doesn't mean what you think it means., #'0'+$80 21D9:30 21 058 BMI GN4 ; BR IF NOT SUM 21DB:C9 0A 059 CMP #10 21DD:B0 1D 060 BCS GN4 ; BR IF NOT NUM 21DF:20 FE 21 061 JSR GN5 ; OLD*2 ; Test Time: 1. Describe what GN5 does without looking at the code. 21E2:65 44 062 ADC CNUM ; PLUS NEW ; 2. Describe what MUL2CNUM does. 21E4:AA 063 TAX ; n*10 = n*8 + n*2 21E5:A9 00 064 LDA #0 21E7:65 45 065 ADC CNUM+1 21E9:A8 066 TAY 21EA:20 FE 21 067 JSR GN5 ; OLD*4 21ED:20 FE 21 068 JSR GN5 ; OLD*8 21F0:8A 069 TXA ; OLD*8 + OLD*2 + NEW 21F1:65 44 070 ADC CNUM 21F3:85 44 071 STA CNUM ; =OLD*10 + NEW 21F5:98 072 TYA 21F6:65 45 073 ADC CNUM+1 21F8:85 45 074 STA CNUM+1 21FA:90 CF 075 BCC GN2 076 ; 077 GN4 EQU * 21FC:38 078 SEC 21FD:60 079 RTS ; DONE 080 GN5 EQU * 21FE:06 44 081 ASL CNUM ; CNUM * 2 2200:26 45 082 ROL CNUM+1 ; === T1S1 === 2202:60 083 RTS 084 PAGE 085 ; 086 HEXNUM EQU * 2203:28 087 PLP 088 HN0 EQU * 2204:20 A4 21 089 JSR GNBC ; GO GET CHAR 2207:F0 C5 090 BEQ GN2A ; BR IF CR OR COMMA 091 ; 2209:38 092 SEC 220A:E9 B0 093 SBC #$B0 ; CHAR - ASCII0 ; ASCII is 7-bit, not 8-bit, SBC #'0'+$80 220C:30 EE 094 BMI GN4 ; BR IF LT0 ; signed c = GetNextLineBufferChar() 220E:C9 0A 095 CMP #10 ; IS IT LT10 ; if ((c - '0') < 0) return; 2210:90 08 096 BCC HN1 ; BR IF LT ; if (c >= 10) c -= ('A' -'9'); 2212:E9 07 097 SBC #$7 ; SUB 7 FOR ASCII A ; magic number 7 = ('A' -'9') 2214:30 E6 098 BMI GN4 ; BR IF LT A 2216:C9 10 099 CMP #16 ; TEST GT 15 2218:B0 E2 100 BCS GN4 ; BR GT 15 ; A = digit = 0..F 221A:A2 04 101 HN1 LDX #4 ; CNUM <<= 4; // shift left one nibble 221C:20 FE 21 102 HN2 JSR GN5 ; OLD*16 221F:CA 103 DEX ;LOOP 4 TIMES ONLY 2220:D0 FA 104 BNE HN2 2222:05 44 105 ORA CNUM ; OR IN NEW ; CNUM += digit 2224:85 44 106 STA CNUM ; SAVE NEW 2226:4C 04 22 107 JMP HN0 ; GO FOR NEXT CHAR 108 PAGE 109 ; 110 ; EPR - EXECUTE PR# 111 ; 112 EPR EQU * ; CMDETB [13] 2229:A5 44 113 LDA CNUM ; GET PORT ; Get *slot* #, not port 222B:4C 95 FE 114 JMP OUTPRT ; GO DO IT 115 ; 116 ; EIN - EXECUTE IN#
117 ; ; === 152 === 118 EIN EQU * ; CMDETB [14] 222E:A5 44 119 LDA CNUM ; GET PORT 2230:4C 8B FE 120 JMP INPRT ; GO DO IT 121 ; 122 ; EMON - EXECUTE MONITOR CMD 123 ; 124 EMON EQU * ; CMDETB [11] 2233:AD 5E 2A 125 LDA MONMOD ; GET CURRENT BITS 2236:0D 74 2A 126 ORA IMBITS ; OR IN NEW BITS 2239:8D 5E 2A 127 STA MONMOD ; SET NEW MODE 223C:60 128 RTS 129 ; 130 ; ENOMON - EXECUTE NO MONITOR CMD 131 ; 132 ENOMON EQU * ; CMDETB [12] 223D:2C 74 2A 133 BIT IMBITS 2240:50 03 134 BVC ENM1 2242:20 C8 1F 135 JSR PRCRIF 136 ENM1 EQU * 2245:A9 70 137 LDA #$70 ; magic number 2247:4D 74 2A 138 EOR IMBITS ; INVERT INPUT BITS 224A:2D 5E 2A 139 AND MONMOD ; AND WITH CURRENT 224D:8D 5E 2A 140 STA MONMOD ; SET NEW MODE 2250:60 141 RTS 142 PAGE 143 ; 144 ; EMAXF - EXECUTE MAX FILES 145 ; 146 EMAXF EQU * ; CMDETB [15] 2251:A9 00 147 LDA #0 ; RESET EXECUTE 2253:8D B3 2A 148 STA ESTATE 2256:A5 44 149 LDA CNUM ; SAVE NEW NO FILES 2258:48 150 PHA 2259:20 16 23 151 JSR CLALL ; GO CLOSE ALL FILES 225C:68 152 PLA 225D:8D 57 2A 153 STA CNFTBS ; SET NEW NO FILE TBLS 2260:4C D4 27 154 JMP BLDFTB ; GO BUILD NEW ONES 155 ; 156 ; EDEL - DELETE A FILE 157 ; 158 EDEL EQU * ; CMDETB [5] 2263:A9 05 159 LDA #CRQDEL 2265:20 AA 22 160 JSR OPEN 2268:20 64 27 161 JSR FILSRC 226B:A0 00 162 LDY #0 ; Common Code WHY isn't this a common subroutine ZEROFILE ?? 226D:98 163 TYA ; BFT1, CLS, and the Append bug patch CLOSFILE all do the same thing! 226E:91 40 164 STA (ZPGWRK),Y ; RESET FN ; Sadly, INITD can't be re-factored. 2270:60 165 RTS ; 166 ; 167 ; ELOCK - LOCK A FILE 168 ; 169 ELOCK EQU * ; CMDETB [6] 2271:A9 07 170 LDA #CRQLCK ; SET LOCK 2273:D0 02 171 BNE ELGO ; wastes 1 byte, use DFB $2C ; BIT $abs to skip next instruction 172 ; 173 ; EUNLK - UNLOCK A FILE 174 ; 175 EUNLK EQU * ; CMDETB [7] 2275:A9 08 176 LDA #CRQUNL ; SET UNLOCK 177 ELGO EQU * ; Holy shit! Common Code for ELOCK, EUnlock, EVerify but not to rain on our parade ... 2277:20 AA 22 178 JSR OPEN ; OPEN FILE & UNLOCK ; ... Common Code Why is ELGO and LCKGO different??? 227A:4C EA 22 179 JMP ECLOSE ; CLOSE IT
180 ; ; === Page 153 181 ; EVAR - VERIFY A FILE 182 ; 183 EVAR EQU * ; CMDETB [1B] 227D:A9 0C 184 LDA #CRQVAR ; SET VARIFY ; *spelling* Damnit Jim, I wish you would VARIFY your spelling. 227F:D0 F6 185 BNE ELGO 186 PAGE 187 ; 188 ; EREN - RENAME 189 ; 190 EREN EQU * 2281:AD 08 1D 191 LDA FN2ADR ; MOVE FILE NAME2 2284:8D BD 35 192 STA CCBFN2 2287:AD 09 1D 193 LDA FN2ADR+1 228A:8D BE 35 194 STA CCBFN2+1 228D:A9 09 195 LDA CRQRNM 228F:8D 63 2A 196 STA TEMP1A ; SET RENAME 2292:20 C8 22 197 JSR EO3 ; GO OPEN AND RENAME 2295:4C EA 22 198 JMP ECLOSE ; GO CLOSE 199 ; 200 ; EAPND - OPEN FILE FOR APPEND 201 ; 202 EAPND EQU * ; CMDETB [E] 2298:20 A3 22 203 JSR EOPEN ; GO OPEN 204 AP1 EQU * 229B:20 8C 26 205 JSR RBYTE ; READ A BYTE 229E:D0 FB 206 BNE AP1 ; BR IF NOT ZERO 207 ; ; Test Time! Without looking at the code, give a summary of why 22A0:4C 71 36 208 JMP BUMPER ; GO TO PATCH FOR APPEND FIX ; a) BUMPER exists, and 209 PAGE ; b) APPEND_FIX. 210 ; 211 ; EOPEN - OPEN A FILE 212 ; 22A3:A9 00 213 EOPEN LDA #0 ;FIX TYPE MISMATCH DETECTION ; CMDETB [D] 22A5:4C D5 23 214 JMP SV1 ;(CALLS EOPN1) ; Why not JSR SV1??? EASAV, EBSV, and EBLD all do JSR SV1 22A8:A9 01 215 EOPN1 LDA #CRQOPN 216 OPEN EQU * ; Common entry point for EDEL, EUNLK, EBSV, EINIT, ECAT, and indirectly EOPEN, EPOS, 22AA:8D 63 2A 217 STA TEMP1A 22AD:AD 6C 2A 218 LDA CL ; IF NO LENGTH ENTERED 22B0:D0 0A 219 BNE EO1 ; THEN SET DEFAULT OF 1 ;↓ 22B2:AD 6D 2A 220 LDA CL+1 22B5:D0 05 221 BNE EO1 ;↓ 22B7:A9 01 222 LDA #1 22B9:8D 6C 2A 223 STA CL 224 EO1 EQU * 22BC:AD 6C 2A 225 LDA CL ; MOVE REC LENGTH 22BF:8D BD 35 226 STA CCBRLN 22C2:AD 6D 2A 227 LDA CL+1 22C5:8D BE 35 228 STA CCBRLN+1 229 EO3 EQU * 22C8:20 EA 22 230 JSR ECLOSE ; GO CLOSE IF OPEN 231 EO4 EQU * 22CB:A5 45 232 LDA CNUM+1 ; GET AVALL ENTRY ; *Spelling* Avail 22CD:D0 03 233 BNE EO5 ; BR IF ONE AVAIL 22CF:4C C8 26 234 JMP ENFA ; DONE - NO FILES AVAIL 235 EO5 EQU * 22D2:85 41 236 STA ZPGWRK+1 ; MOVE AVAIL SLOT TO ZPG 22D4:A5 44 237 LDA CNUM 22D6:85 40 238 STA ZPGWRK 239 EO6 EQU * 22D8:20 43 27 240 JSR MVFN1 ; GO MOVE FILE NAME 22DB:20 4E 27 241 JSR MVBUFP ; GO MOVE BUF PTRS 22DE:20 1A 27 242 JSR OPNSUP ; GO SET UP OPEN
22E1:AD 63 2A 243 LDA TEMP1A ; SET OPEN REQ ; === 154 === 22E4:8D BB 35 244 STA CCBREQ 22E7:4C A8 26 245 JMP DOSGO ; GO OPEN 246 PAGE 247 ; 248 ; ECLOSE - EXECUTE CLOSE FILE COMMAND 249 ; 250 ECLOSE EQU * ; CMDETB [8] 22EA:AD 75 2A 251 LDA FNAME1 22ED:C9 A0 252 CMP #$A0 ; #' '+$80 aka SPC_HI 22EF:F0 25 253 BEQ CLALL 22F1:20 64 27 254 JSR FILSRC ; GO FIND FILE 22F4:B0 3A 255 BCS CL2 ; BR IF NOT FOUND 22F6:20 FC 22 256 JSR CLOSE ; GO CLOSE 22F9:4C EA 22 257 JMP ECLOSE ; GO SEE IF ANY MORE OPEN 258 ; 259 ; CLOSE - CLOSE A FILE 260 ; 261 CLOSE EQU * 22FC:20 AF 27 262 JSR TSTEXC 22FF:D0 05 263 BNE CLX ; === T1S2 === 2301:A9 00 264 LDA #0 2303:8D B3 2A 265 STA ESTATE 266 CLX EQU * 2306:A0 00 267 LDY #0 ; CLEAR 1ST FN ; [.. wastes 2 bytes, see ZEROFILE note 2308:98 268 TYA ; CHAR TO ZERO ; .. 2309:91 40 269 STA (ZPGWRK),Y ; ..] 230B:20 4E 27 270 JSR MVBUFP ; MOVE BUFFER PTRS 230E:A9 02 271 LDA #CRQCLS ; SET CLOSE 2310:8D BB 35 272 STA CCBREQ 2313:4C A8 26 273 JMP DOSGO 274 ; 275 ; CLALL - CLOSE ALL FILES 276 ; 277 CLALL EQU * 2316:20 92 27 278 JSR TSINIT ; GO INIT FILE SEARCH 2319:D0 05 279 BNE CL1 ;↓ 280 CL0 EQU * 231B:20 9A 27 281 JSR TXNXT ; NEXT ENTRY 231E:F0 10 282 BEQ CL2 ; BR IF NO MORE 283 CL1 EQU * 2320:20 AF 27 284 JSR TXTEXC 2323:F0 F6 285 BEQ CL0 ;↑ 2325:20 AA 27 286 JSR TSTOPEN ; GO TEST OPEN 2328:F0 F1 287 BEQ CL0 ; BR NOT OPEN 232A:20 FC 22 288 JSR CLOSE ; GO CLOSE 232D:4C 16 23 289 JMP CLALL ; START OVER 2330:60 290 CL2 RTS ; DONE
001 PAGE 002 ; 003 ; EBSV - EXECUTE BINARY SAVE 004 ; 005 EBSV EQU * ; CMDETB [18] "BSAVE" 2331:A9 09 006 LDA #ADR+L ; IF A&L 2333:2D 65 2A 007 AND INOPS ; NOT GIVEN 2336:C9 09 008 CMP #ADR+L 2338:F0 03 009 BEQ EBSV1 233A:4C 00 20 010 JMP CNF ; THEN ERROR 011 EBSV1 EQU * 233D:A9 04 012 LDA #4 ; SET BINARY FILE ; magic number FILE_TYPE_BINARY EQU 4 233F:20 D5 23 013 JSR SV1 ; GO OPEN & TEST 2342:AD 73 2A 014 LDA CA+1 ; OUTPUT ADR OF BLOCK 2345:AC 72 2A 015 LDY CA 2348:20 E0 23 016 JSR SV2 234B:AD 6D 2A 017 LDA CL+1 ; GO OPEN AND TEST 234E:AC 6C 2A 018 LDY CL 2351:20 E0 23 019 JSR SV2 ; OUTPUT LENGTH 2354:AD 73 2A 020 LDA CA+1 ; GET ADR GIVEN 2357:AC 72 2A 021 LDY CA 235A:4C FF 23 022 JMP SV3 ; OUTPUT BLOCK 023 ; 024 ; EBLD - EXECUTE BINARY LOAD 025 ; 026 EBLD EQU * ; CMDETB [19] "BLOAD" 235D:20 A8 22 027 JSR EOPN1 ;(CHANGED 11/1/78 FOR TYPE MISMATCH) 028 EBLD2 EQU * ; *sigh* If only the local labels were in alphabetical order ... 2360:A9 7F 029 LDA #$7F ; magic number ~FILE_LOCK 2362:2D C2 35 030 AND CCBFUC 2365:C9 04 031 CMP #4 ; magic number FILE_TYPE_BINARY 2367:F0 03 032 BEQ EBLD3 2369:4C D0 26 033 JMP ETYP ;TYPE MISMATCH ERROR MESSAGE 034 EBLD3 EQU * 236C:A9 04 035 LDA #4 ; SET BINARY FILE ; magic number /sarcasm if only we had FILE_TYPE_BINARY EQU 4 236E:20 D5 23 036 JSR SV1 ; GO OPEN & TEST 2371:20 7A 24 037 JSR LD2 ; GO GET ADR 2374:AA 038 TAX 2375:AD 65 2A 039 LDA INOPTS 2378:29 01 040 AND #ADR ; IF ADR NOT GIVEN 237A:D0 06 041 BNE EBLD1 ; ↓ 237C:8E 72 2A 042 STX CA ; THEN USE ADR FROM FILE 237F:8C 73 2A 043 STY CA+1 044 EBLD1 EQU * 2382:20 7A 24 045 JSR LD2 ; GET LENGTH 2385:AE 72 2A 046 LDX CA ; GET GIVEN ADR 2388:AC 73 2A 047 LDY CA+1 238B:4C 71 24 048 JMP LD3 ; GO GET BLOCK ; Why is this +128 bytes away?? 049 ; 050 ; EBRUN - EXECUTE BINARY RUN 051 ; 238E:20 5D 23 052 EBRUN JSR EBLD ; CMDETB [1A] "BRUN" 2391:20 51 28 053 JSR MVCSW ; GO RESTORE CHAR I/O SW
2394:6C 72 2A 054 JMP (CA) ; GO EXEC THE STUFF ; === Page 141 === ; How Not To Design an OS ; Problem : This (indirect) JMP is why Binary programs can't use RTS to return to DOS ; Solution: The otherwise excellent 6502 has a short-Sighted design ; it lacks indirect mode: JSR ($addr): ; Regular 6502 solution requires self-modifying code. ; LDA CA ; STA GOBRUN+1 ; ** SELF-MODIFYING ! ** ; LDA CA+1 ; STA GOBRUN+2 ; ** SELF-MODIFYING ! ** ; GOBRUN JSR $0000 ; NOTE: Self-Modifying code ; JMP DBRST ; Warmstart DOS 055 PAGE 056 ; 057 ; ESAVE - EXECUTE SAVE REQUEST 058 ; 059 ESAVE EQU * 2397:AD B6 2A 060 LDA ASIBSW ; IF IB THEN 239A:F0 20 061 BEQ EIBSV ; GO TO IB SAVE 239C:A5 D6 062 LDA ASRNX ; CAN NOT DO AS SAVE WHEN RUN-ONLY PROG. 239E:10 03 063 BPL EASAV ; BRANCH IF OK TO SAVE, OTHERWISE 23A0:4C CC 26 064 JMP MFERR ; PRINT "PROGRAM TOO LARGE", THAT OUGHT TO GET 'EM. 23A3:A9 02 065 EASAV LDA #2 ; GET APPLESOFT PGM ; magic number FILE_TYPE_APPLESOFT EQU 2 23A5:20 D5 23 066 JSR SV1 ; GO OPEN AND TEST 067 ; 23A8:38 068 SEC ; BLOCK LENGTH 23A9:A5 AF 069 LDA ASEOP ; =EOP-SOP 23AB:E5 67 070 SBC ASSOP 23AD:A8 071 TAY 23AE:A5 B0 072 LDA ASEOP+1 ; single letter difference asEop 23B0:E5 68 073 SBC ASSOP+1 ; is never a good idea: asSop 23B2:20 E0 23 074 JSR SV2 ; GO OUTPUT LENGTH 075 ; 23B5:A5 68 076 LDA ASSOP+1 ; BLOCK ADR 23B7:A4 67 077 LDY ASSOP ; =SOP 23B9:4C FF 23 078 JMP SV3 ; GO OUTPUT BLOCK 079 ; 080 EIBSV EQU * 23BC:A9 01 081 LDA #1 ; SET IB PGM ; PGM = Program, magic number FILE_TYPE_INTEGER_BASIC EQU 1 23BE:20 D5 23 082 JSR SV1 ; GO OPEN AND TEST 083 ; 23C1:38 084 SEC ; BLOCK LENGTH 23C2:A5 4C 085 LDA IBHMEM ; =HIMEM-SOP 23C4:E5 CA 086 SBC IBSOP 23C6:A8 087 TAY 23C7:A5 4D 088 LDA IBHMEM+1 23C9:E5 CB 089 SBC IBSOP+1 23CB:20 E0 23 090 JSR SV2 ; GO OUTPUT LENGTH 091 ; 23CE:A5 CB 092 LDA IBSOP+1 ; BLOCK ADR 23D0:A4 CA 093 LDY IBSOP ; =SOP 23D2:4C FF 23 094 JMP SV3 ; GO OUTPUT BLOCK 095 ; 096 SV1 EQU * 097 SV1A EQU * 23D5:8D C2 35 098 STA CCBFUC ; SET PGM TYPE 23D8:48 099 PHA ; SAVE PGM TYPE 23D9:20 A8 22 100 JSR EOPN1 ; GO OPEN FILE (CHGED 11/1/78) 23DC:68 101 PLA ; GET SAVE TYPE 23DD:4C C4 27 102 JMP TSTFUC ; GO CHECK 103 ; 104 SV2 EQU * 23E0:8C C1 35 105 STY CCBBLN ; SET BLOCK LENGTH ; === HNTDAFS #5 === 23E3:8C C3 35 106 STY CCBDAT ; AND DATA BYTE ; You never store file meta-data 23E6:8D C2 35 107 STA CCBBLN+1 ; File Length 23E9:A9 04 108 LDA #CRQWR ; INDICATE WRITE ; in the file itself! 23EB:8D BB 35 109 STA CCBREQ 23EE:A9 01 110 LDA #CRNBT ; NEXT BYTE 23F0:8D BC 35 111 STA CCBRQM 23F3:20 A8 26 112 JSR DOSGO ; GO WRITE 23F6:AD C2 35 113 LDA CCBBLN+1 ; OTHER BYTE TOO 23F9:8D C3 35 114 STA CCBDAT
23FC:4C A8 26 115 JMP DOSGO ; === Page 142 === 116 ; 23FF:8C C3 35 117 SV3 STY CCBBBA ; SET BLOCK ADR 2402:8D C4 35 118 STA CCBBBA+1 2405:A9 02 119 LDA #CRMNBL ; INDICATE BLOCK I/O 2407:4C 86 36 120 JMP VPATCH ;VERIFY AFTER SAVE 240A:20 A8 26 121 GODOS JSR DOSGO ; GO DO IT 240D:4C EA 22 122 JMP ECLOSE ; CLOSE FILE 123 PAGE 2410:4C D0 26 124 NBPER NBPER JMP ERNU1 ; Not Basic Program Error called from ELD1 125 ; 126 ; ELOAD - EXECUTE LOAD REQUEST 127 ; 128 ELOAD EQU * 2413:20 16 23 129 JSR CLALL 2416:20 A8 22 130 ELOAD0 JSR EOPN1 131 ; 132 ELD1 EQU * ; *sigh* Pick a bloody consistent naming schema: ELOAD# or ELD# 2419:A9 23 133 LDA #$23 ; STRIP UNRELATED STUFF ; magic number TODO WTF do these bits mean??? 241B:2D C2 35 134 AND CCBFUC ; OUT OF FUC 241E:F0 F0 135 BEQ NBPER ; BR IF ERROR 136 ; ISOLATE IB & AS 137 ELD2 EQU * 2420:8D C2 35 138 STA CCBFUC ; SAVE IB/AS ONLY 2423:AD B6 2A 139 LDA ASISBSW ; IF IB THEN 2426:F0 28 140 BEQ EIBL ; GO TO IB LOAD ; ↓ 2428:A9 02 141 LDA #2 ; magic number FILE_TYPE_APPLESOFT EQU 2 242A:20 B1 24 142 JSR LD1 ; GO OPEN AND TEST 143 ; 242D:20 7A 24 144 JSR LD2 ; GO GET BLOCK LENGTH ; wastes 3 bytes, LD1 should fall into LD2 145 ; ; While EBLD2 (ExecBload2) calls LD2 by itself, LD1 is always followed by LD2 2430:18 146 CLC 2431:65 67 147 ADC ASSOP ; ADD BLOCK LENGTH TO SOP 2433:AA 148 TAX 2434:98 149 TYA 2435:65 68 150 ADC ASSOP+1 151 ; 2437:C5 74 152 CMP ASHM1+1 ; IF BL+SOP >= HMEM ; If Block.Length + StartOfProgram >= High Memory 2439:B0 70 153 BCS MFULL ; THEN WON'T FIT ; Memory Full 154 ; 155 EASL1 EQU * 243B:85 B0 156 STA ASEOP+1 ; SET NEW EOP ADR 243D:85 6A 157 STA ASEOP2+1 243F:86 AF 158 STX ASEOP 2441:86 69 159 STX ASEOP2 2443:A6 67 160 LDX ASSOP ; GET ADR WHERE TO LOAD 2445:A4 68 161 LDY ASSOP+1 2447:20 71 24 162 JSR LD3 ; GO LOAD 244A:20 51 28 163 JSR MVCSW ;RESTORE I/O ; TODO Why??? Did something change CIN/COUT ??? 244D:6C 60 1D 164 JMP (ASEQ) ;RELOC FOR THIS VERSION OF APPLSOFT 165 ; 166 EIBL EQU * 2450:A9 01 167 LDA #1 ; SET IB PGM ; Yup, almost 99% the same as ELD2 2452:20 B1 24 168 JSR LD1 ; GO OPEN AND TEST 169 ; 2455:20 7A 24 170 JSR LD2 ; GO GET BLOCK LENGTH ; wastes 3 bytes, see Line #141 171 ; 2458:38 172 SEC ; HMEM - BLOCK LENGTH 2459:A5 4C 173 LDA IBHMEM ; IS NEW SOP 245B:ED 60 2A 174 SBC SVBL 245E:AA 175 TAX 245F:A5 4D 176 LDA IBHMEM+1 2461:ED 61 2A 177 SBC SVBL+1
2464:90 45 178 BCC MFULL ; === Page 143 === 2466:A8 179 TAY 180 ; 2467:C4 4B 181 CPY IBLMEM+1 ; IF NEW SOP <= LMEM 2469:90 40 182 BCC MFULL 246B:F0 3E 183 BEQ MFULL 246D:84 CB 184 STY IBSOP+1 ; SET NEW SOP 246F:86 CA 185 STX IBSOP 186 LD3 EQU * 2471:8E C3 35 187 STX CCBBBA ; SET BLOCK ADDR ; Googoo, Gaga? A single underscore '_' would go a LONG way towards readability 2474:8C C4 35 188 STY CCBBBA+1 ; CCB_BBA 2477:4C 0A 24 189 JMP GODOS 190 ; 191 LD2 EQU * ; By putting this before LD1 this forces 6 byes to be wasted, see Line #143 247A:AD 0A 1D 192 LDA SVBLA ; MOVE ADR OF WHERE 247D:8D C3 35 193 STA CCBBA ; TO PUT DATA TO 2480:AD 0B 1D 194 LDA SVBLA+1 ; CCBN 2483:8D C4 35 195 STA CCBBBA+1 2486:A9 00 196 LDA #0 2488:8D C2 35 197 STA CCBBLN+1 ; READ INTO 248B:A9 02 198 LDA #2 248D:8D C1 35 199 STA CCBBLN 2490:A9 03 200 LDA #CRQRD ; READ 2492:8D BB 35 201 STA CCBREQ 2495:A9 02 202 LDA #CRMNBL ; BLOCK 2497:8D BC 35 203 STA CCBRQM 249A:20 A8 26 204 JSR DOSGO 249D:AD 61 2A 205 LDA SVBL+1 24A0:8D C2 35 206 STA CCBBLN+1 24A3:A8 207 TAY 24A4:AD 60 2A 208 LDA SVBL 24A7:8D C1 35 209 STA CCBBLN 24AA:60 210 RTS 211 ; 212 MFULL1 EQU * 24AB:20 EA 22 213 JSR ECLOSE ; GO CLOSE FILE 24AE:4C CC 26 214 JMP MFERR ; AND GIVE ERR MSG 215 LD1 EQU * 24B1:CD C2 35 216 CMP CCBFUC ; TEST TYPE 24B4:F0 1A 217 BEQ LD1C ; BR IF MATCH 24B6:AE 5F 2A 218 LDX CMDNO 24B9:8E 62 2A 219 STX SVCMD 24BC:4A 220 LSR A 24BD:F0 03 221 BEQ LD1A ; BR IF PGM IS AS 24BF:4C 9E 25 222 JMP EINT ; GO FOR INTG BASIC 223 ; 224 LD1A EQU * 24C2:A2 1D 225 LDX #29 ; SAVE FILENAME ; magic number FILENAME_MAX-1 24C4:BD 75 2A 226 LD1B LDA FNAME1,X ; INCASE IS RAM APPLESOFT 24C7:9D 93 2A 227 STA FNAME2,X 24CA:CA 228 DEX 24CB:10 F7 229 BPL LD1B 24CD:4C 7A 25 230 JMP EAS ; GO FOR AS 231 ; 24D0:60 232 LD1C RTS 233 PAGE 234 ; 235 ; ERUN - EXECUTE RUN REQUEST 236 ; 237 ERUN EQU * 24D1:AD B6 2A 238 LDA ASIBSW ; IF APPLESOFT THEN RELOC FLAG SET 24D4:F0 03 239 BEQ ERUN0 24D6:8D B7 2A 240 STA RSTATE ; INDICATE APSFT RUN
24D9:20 13 24 241 ERUN0 JSR ELOAD ; LOAD PGM ; === 144 === 24DC:20 C8 1F 242 ERUN1 JSR PRCRIF ;REENTRY POINT FOR ASFT RELOC 24DF:20 51 28 243 JSR MVCSW ; GO RESTORE CHAR I/O SW ; What keeps futzing with CIN / COUT ? Guilty Party → SVREGS 24E2:6C 58 1D 244 JMP (RUN) 245 ; 246 ; IBRUN - INT BASIC RUN 247 ; 248 IBRUN EQU * 24E5:A5 4A 249 LDA IBLMEM ; RESET START OF VARS 24E7:85 CC 250 STA IBSOV 24E9:A5 4B 251 LDA IBLMEM+1 24EB:85 CD 252 STA IBSOV+1 24ED:6C 56 1D 253 JMP (CHAIN) 254 ; 255 ; EHCAIN - EXECUTE CHAIN REQUEST ; *spelling* ECHAIN 256 ; 257 ECHAIN EQU * 24F0:20 16 24 258 JSR ELOAD0 ; LOAD PGM WITHOUT CLOSING READ FILES 24F3:20 C8 1F 259 JSR PRCRIF 24F6:20 51 28 260 JSR MVCSW ; GO RESTORE CHAR I/O SW 24F9:6C 56 1D 261 JMP (CHAIN) 24FC:20 65 D6 262 ASRUN1 JSR $D665 ; ROM ; magic number 24FF:85 33 263 STA PROMPT ;INSURES APPLESOFT RUN DETECT (A=0) ; === T1S4 === 2501:85 D8 264 STA ASONERR ;RESET APPLESOFT ONERR FLAG 2503:4C D2 D7 265 JMP $D7D2 ; magic number 2506:20 65 0E 266 ASRUN2 JSR $E65 ; RAM ; magic number AS2VT has pointer to us 2509:85 33 267 STA PROMPT ;INSURES APPLESOFT RUN DETECT (A=0) ; (dead code) wastes 10 bytes on Apple ][+ or later 250B:85 D8 268 STA ASONER ;RESET APPLESOFT ONERR FLAG ; 250D:4C D4 0F 269 JMP $FD4 ; magic number
001 PAGE 002 ; 003 ; EWRITE - WRITE CMD EXECUTE 004 ; 005 EWRITE EQU * 2510:20 26 25 006 JSR RWPOSN ; GO POSITION FILE IF REQD 2513:A9 05 007 LDA #5 ; WTF is state 5 ?? OK, COS5 And the state table transition is where again? 2515:8D 52 2A 008 STA OSTATE ; SET OSTATE=5 ; /sarcasm No Shit, Sherlock 2518:4C 83 1F 009 JMP CERTN 010 ; 011 ; EREAD - READ COMD EXECUTE 012 ; 013 EREAD EQU * 251B:20 26 25 014 JSR RWPOSN ; GO POSITION FILE IF REQD ;↓ 251E:A9 01 015 LDA #1 2520:8D 51 2A 016 STA ISTATE ; SET I STATE = DISK INPUT ; /voice="Nick Burns" See, that wasn't so hard! 2523:4C 83 1F 017 JMP CERTN ;↑ wastes 1 bytes, BNE EREAD-3 018 ; 019 ; RWPOSN - POSTION FOR READ/WRITE 020 ; 021 RWPOSN EQU * 2526:20 64 27 022 JSR FILSRC ; FIND THE FILE ;↓ 2529:90 06 023 BCC RWP1 ; BR IF FILE FOUND ;↓ 252B:20 A3 22 024 JSR EOPEN ; GO OPEN FOR KLUTZ ;↓ ??? if file doesn't exist, open it ??? 252E:4C 34 25 025 JMP RWP2 ; THEN SKIP NEXT LINE ;↓ wastes 1 byte, should be TODO 026 RWP1 EQU * 2531:20 4E 27 027 JSR MVBUFP ; MOVE BUFF POINTERS ;↓ /sarcasm WHICH way Einstein? 028 RWP2 EQU * 2534:AD 65 2A 029 LDA INOPTS ; GET IN OPTIONS 2537:29 06 030 AND #R+B ; WAS IT B OR R 2539:F0 13 031 BEQ RWPR ; BR IF NOT ;↓ Should be BEQ LD1C ;↑ 253B:A2 03 032 LDX #3 253D:BD 6E 2A 033 RWP2A LDA CR,X ; MOVE REL REC 2540:9D BD 35 034 STA CCBRRN,X ; AND REL BYTE 2543:CA 035 DEX 2544:10 F7 036 BPL RWP2A ;↑ 037 RWP3 EQU * 2546:A9 0A 038 LDA #CRQPOS ; INDICATE POISTION REQUEST ; *spelling* Position 2548:8D BB 35 039 STA CCBREQ 254B:20 A8 26 040 JSR DOSGO ;↓ [.. wastes 1 byte next instruction RTS, should be JMP 254E:60 041 RWPR RTS ; ..] 042 PAGE 043 ; 044 ; 045 ; EINIT - EXECUTE INIT COMMAND 046 ; 047 EINIT EQU * ; "INIT" -- also see FFMT 254F:A9 40 048 LDA #V ; MUST HAVE 2551:2D 65 2A 049 AND INOPTS ; VOL OPTION 2554:F0 05 050 BEQ DFVOL ;GO SET DEFAULT VOLUME=254 2556:AD 66 2A 051 LDA CV ;CAN'T SPECIFY VOL=0 2559:D0 05 052 BNE EINITA 255B:A9 FE 053 DFVOL LDA #$FE ;SET DEFAULT VOLUME NUMBER ; magic number DEFAULT_VOLUME
255D:8D 66 2A 054 STA CV ; === Page 146 === 2560:AD 0D 1D 055 EINITA LDA ASTART+1 2563:8D BC 35 056 STA CCBBSA 2566:A9 0B 057 LDA #CRQFMT 2568:20 AA 22 058 JSR OPEN 256B:4C 97 23 059 JMP ESAVE 060 ; 061 ; 062 ; ECAT - PRINT CATALOG 063 ; 064 ECAT EQU * 256E:A9 06 065 LDA #CRQDIR 2570:20 AA 22 066 JSR OPEN ; GO PRETEND OPEN 2573:AD BF 35 067 LDA CCBVOL 2576:8D 66 2A 068 STA CV 2579:60 069 RTS 070 PAGE 071 ; 072 ; EAS - EXECUTE APPLESOFT REQUEST 073 ; 074 EAS EQU * 257A:A9 4C 075 LDA #ATSTV ; GET APPLESOFT TEST VALUE 257C:20 B2 25 076 JSR SWTST ; GO SWITCH AND TEST 257F:F0 2E 077 BEQ GOINIT ; BR IF APPLESOFT 2581:A9 00 078 LDA #0 ; magic number LANGUAGE_APPLESOFT 2583:8D B6 2A 079 STA ASIBSW 080 ; 081 EAS0 EQU * 2586:A0 1E 082 LDY #30 ; magic number MAX_FILENAME_LEN-1 2588:20 97 20 083 JSR CLRFNA ; ClearFileName1 258B:A2 09 084 LDX #FASBL 258D:BD B7 2A 085 EAS1 LDA FASB-1,X ; MOVE SYSTEM FILENAME ; No, copy 2590:9D 74 2A 086 STA FNAME1-1,X 2593:CA 087 DEX 2594:D0 F7 088 BNE EAS1 089 ; 090 EAS2 EQU * 2596:A9 C0 091 LDA #$C0 ; magic number $80 + $40 2598:8D 51 2A 092 STA ISTATE ; FOR RAM APPLESOFT 259B:4C D1 24 093 JMP ERUN 094 ; 095 ; EINT - EXECUTE INTEGER REQUEST 096 ; 097 EINT EQU * 259E:A9 20 098 LDA #ITSTV ; GET IB TEST VALUE 25A0:20 B2 25 099 JSR SWTST ; GO SWITCH AND TEST 25A3:F0 05 100 BEQ GOINT ;BR IF INTIGER BASIC ; *spelling* Integer 25A5:A9 01 101 LDA #1 ;LANGUAGE NOT AVIALABLE, TOO BAD... ; *spelling* Available magic number 25A7:4C D2 26 102 JMP ERROR 25AA:A9 00 103 GOINT LDA #0 ;RESET RSTATE ; magic number 25AC:8D B7 2A 104 STA RSTATE ; FOR NON APPLESOFT PROG. 105 GOINIT EQU * 25AF:4C 84 1D 106 JMP DBINIT ; GO INIT DOS 107 SWTST EQU * 25B2:CD 00 E0 108 CMP AITSTL ; TEST CURRENT VALUE 25B5:F0 0E 109 BEQ SWTR 25B7:8D 80 C0 110 STA $C080 ; TRY SWITCH 1 ; magic number 25BA:CD 00 E0 111 CMP AITSTL ; TEST AGAIN 25BD:F0 06 112 BEQ SWTR ; BR IF NOW SAME 25BF:8D 81 C0 113 STA $C081 ; TRY SWITCH 2 ; magic number 25C2:CD 00 E0 114 CMP AITSTL ; TEST AND 25C5:60 115 SWTR RTS ; RETURN 116 ;
117 PAGE ; === Page 147 === 118 ; 119 ; EEXEC - EXECUTE EXEC CMD 120 ; 121 EEXEC EQU * ; "EXEC" 25C6:20 A3 22 122 JSR EOPEN ; OPEN FILE 25C9:AD 4F 2A 123 LDA CFTABA ; MOVE TABLE POINTERS 25CC:8D B4 2A 124 STA EFTABA 25CF:AD 50 2A 125 LDA CFTABA+1 25D2:8D B5 2A 126 STA EFTABA+1 25D5:AD 75 2A 127 LDA FNAME1 ; USE FILNAME ; *spelling* Filename 25D8:8D B3 2A 128 STA ESTATE ; SET EXSTATE NON ZERO 25DB:D0 0E 129 BNE EXP2 130 ; 131 ; 132 ; EPOS - EXECUTE POSITION 133 ; 134 EPOS EQU * ; "POSITION" 25DD:20 64 27 135 JSR FILSRC 25E0:90 06 136 BCC EXP1 25E2:20 A3 22 137 JSR EOPEN 25E5:4C EB 25 138 JMP EXP2 25E8:20 4E 27 139 EXP1 JSR MVBUFP 140 EXP2 EQU * 25EB:AD 65 2A 141 LDA INOPTS ; GET OPTIONS 25EE:29 04 142 AND #R ; TEST R 25F0:F0 1B 143 BEQ EX2 ; BR NOT R 144 ; 25F2:AD 6E 2A 145 EX0 LDA CR ; IF CR NOT ZERO 25F5:D0 08 146 BNE EX1A ; THEN DECREMENT 25F7:AE 6F 2A 147 LDX CR+1 25FA:F0 11 148 BEQ EX2 25FC:CE 6F 2A 149 DEC CR+1 25FF:CE 6E 2A 150 EX1A DEC CR 2602:20 8C 26 151 EX1 JSR RBYTE ; AND READ A RECORD 2605:F0 38 152 BEQ ICFD4 2607:C9 8D 153 CMP #$8D ; UNTIL CR ; magic number KEY_CR 2609:D0 F7 154 BNE EX1 260B:F0 E5 155 BEQ EX0 ; THEN TEST CR AGAIN 156 ; 260D:60 157 EX2 RTS 158 PAGE 159 ; 160 ; OCTD - OUTPUT A CHAR TO DISK 161 ; 162 OCTD EQU * 260E:20 5E 26 163 JSR TSTRUN ; GO TEST RUN 2611:B0 66 164 BCS ICFDB ;BRANCH IF NOT RUN MODE 2613:AD 5C 2A 165 LDA SVA ; CHAR IN SAVED ACU 2616:8D C3 35 166 STA CCBDAT ; PUT INTO CCBDATA AREA 2619:A9 04 167 LDA #CRQWR ; SET WRITE 261B:8D BB 35 168 STA CCBREQ 261E:A9 01 169 LDA #CRMNBT ; SET NEXT BYTE 2620:8D BC 35 170 STA CCBRQM 2623:4C A8 26 171 JMP DOSGO ; GO WRITE BYTE 172 ; 173 ; INCFD - INPUT A CHAR FROM DISK 174 ; 175 ICFD EQU * 2626:20 5E 26 176 JSR TSTRUN ; GO TEST RUN 2629:B0 4E 177 BCS ICFDB ;BRANCH IF NOT RUN MODE 262B:A9 06 178 LDA #6 ; SET OUT STE = 6 ; magic number 179 ICFD3 EQU *
262D:8D 52 2A 180 STA OSTATE ; TO CATCH ECHO ; === Page 148 === 2630:20 8C 26 181 JSR RBYTE 2633:D0 0F 182 BNE ICFD1 ; BR IF NOT ZERO CHAR 183 ICFD2 EQU * 2635:20 FC 22 184 JSR CLOSE 2638:A9 03 185 LDA #3 ; magic number 263A:CD 52 2A 186 CMP OSTATE 263D:F0 CE 187 BEQ EX2 188 ICFD4 EQU * 263F:A9 05 189 LDA #CREEOF 2641:4C D2 26 190 JMP ERROR ; GO TO ERROR ; /sarcasm No shit, Sherlock -- HOW did we get here? 191 ICFD1 EQU * 2644:C9 E0 192 CMP #$E0 ;CHECK FOR LOWER CASE 2646:90 02 193 BCC ICFNLC ;BRANCH IF NOT LOWER-CASE 2648:29 7F 194 AND #$7F ;STRIP HI BIT TO FOOL GETLINE 195 ICFNLC EQU * 264A:8D 5C 2A 196 STA SVA ; PUT INTO SAVED ACU 264D:AE 5A 2A 197 LDX SVX ; MUST CHECK LAST FOR LOWER CASE 2650:F0 09 198 BEQ ICFD0 ;IGNORE IF FIRST CHAR. 2652:CA 199 DEX 2653:BD 00 02 200 LDA LBUFF,X 2656:09 80 201 ORA #$80 ;RESET HI BIT 2658:9D 00 02 202 STA LBUFF,X ; EVEN THOUGH IT MAY NOT NEED IT 203 ICFD0 EQU * 265B:4C B3 1F 204 JMP ORTN ; GO RESTORE REGS AND RTS 205 ; 265E:48 206 TSTRUN PHA 265F:AD B6 2A 207 LDA ASIBSW ; GET AS/INT BASIC SWITCH 2662:F0 0E 208 BEQ TR1 ; BR IF INT 2664:A6 76 209 LDX $76 ;CHECK APPLESOFT RUN FLAG ; magic number 2666:E8 210 INX ;(NOT RUN=0 AFTER INCREMENT) 2667:F0 0D 211 BEQ NOTRUN ;IF SAYS RUNNING MAKE SURE WITH PROMPT. 2669:A6 33 212 LDX PROMPT ;TEST APPLESOFT RUNNING. 266B:E0 DD 213 CPX #']'+$80 266D:F0 07 214 BEQ NOTRUN ; BR IF NOT RUN 266F:68 215 TR0 PLA 2670:18 216 CLC ;INDICATE PROGRAM RUNNING 2671:60 217 RTS 218 TR1 EQU * 2672:A5 D9 219 LDA $D9 ; GET INT RUN FLAG ; magic number 2674:30 F9 220 BMI TR0 ; BR IF RUN 2676:68 221 NOTRUN PLA ;INDICATE PROGRAM NOT RUNNING 2677:38 222 SEC ; WITH CARRY SET. 2678:60 223 RTS 224 ; 225 ICFDB EQU * ; NOT RUN MODE 2679:20 FC 22 226 JSR CLOSE ; GO CLOSE FILE 267C:20 5B 27 227 JSR CLRSTS ; GO CLEAR STATES 267F:4C B3 1F 228 JMP ORTN ; 229 PAGE 230 ; 231 ; NXTEXC - NEXT EXECUTE CHAR 232 ; 233 NXTEXC EQU * 2682:20 9D 26 234 JSR MVEFTA 2685:20 4E 27 235 JSR MVBUFP ; GO MOVE PTRS 2688:A9 03 236 LDA #3 268A:D0 A1 237 BNE ICFD3 ; ↑ (always) 238 ; 239 ; RBYTE - READ NEXT BYTE 240 ; 241 RBYTE EQU *
268C:A9 03 242 LDA #CRQRD ; SET READ ; === Page 149 === 268E:8D BB 35 243 STA CCBREQ 2691:A9 01 244 LDA #CRMNBT ; SET NEXT BYTE 2693:8D BC 35 245 STA CCBRQM 2696:20 A8 26 246 JSR DOSGO ; GO TO DOS 2699:AD C3 35 247 LDA CCBDAT ; GET THE DATA BYTE 269C:60 248 RTS 249 MVEFTA EQU * 269D:AD B5 2A 250 LDA EFTABA+1 ; MOVE TABLE ADR 26A0:85 41 251 STA ZPGWRK+1 ; NO ZPG 26A2:AD B4 2A 252 LDA EFTABA 26A5:85 40 253 STA ZPGWRK 26A7:60 254 RTS
001 PAGE 002 ; 003 ; DOSGO - GOTO DOS 004 ; 005 DOSGO EQU * 26A8:20 06 2B 006 JSR DOSENT ; GO TO DOS 26AB:90 16 007 BCC DG3 ; BR IF NOT ERROR 008 ; 26AD:AD C5 35 009 LDA CCBSTA ;GET RETURN CODE 26B0:C9 05 010 CMP #5 ; magic number TODO 26B2:F0 03 011 BEQ YESEOF 26B4:4C 5E 36 012 JMP CLOSFILE ;NO. CLOSE & COMPLAIN 26B7:4C 92 36 013 YESEOF JMP EOFFIX ;MAYBE FIX IT UP? 26BA:EA 014 NOP ; wastes 1 byte 015 *************************** 016 * 017 * DOS 3.3 (REV B) PATCH 018 * 019 *************************** 020 DO DOS33B 26BB:20 69 3A 021 DOSGO2A JSR MOVEOF ; MOVE END OF FILE PATCH ; Called from BACK 022 ELSE 023 NOP 024 DOSGO2A NOP Why isn't this label on the previous line??? 025 NOP 026 FIN 26BE:A2 00 027 LDX #0 ; SET OTHER EIF 26C0:8E C3 35 028 STX CCBDATA 26C3:60 029 DG3 RTS 030 ; 031 PAGE 032 ; 033 ; ERROR ROUTINE 034 ; 26C4:A9 0B 035 ESYNTX LDA #CREFLK+1 ; I'd like to buy a vowel, 'A'. 26C6:D0 0A 036 BNE ERROR ; Sorry, we're fresh out. 26C8:A9 0C 037 ENFA LDA #CREFLK+2 26CA:D0 06 038 BNE ERROR ; ↓ (always) 26CC:A9 0E 039 MFERR LDA #CREFLK+4 26CE:D0 02 040 BNE ERROR ; ↓ (always) wastes 1 byte, $2C bit $abs to skip next instruction 041 ETYP EQU * 26D0:A9 0D 042 ERNU1 LDA #CREFLK+3 043 ; ; Intentional fall into ERROR 044 ERROR EQU * 26D2:8D 5C 2A 045 STA SVA ; SAVE MSG NUMBER 26D5:20 E6 3F 046 JSR CLRSTS1 ;PATCH TO CLR RSTATE TOO (WAS JSR CLRSTS) 26D8:AD B6 2A 047 LDA ASIBSW ; GET AS/IN BASIC SWITCH 26DB:F0 04 048 BEQ ERNAS ; BR IF NOT APPLESOFT 26DD:A5 D8 049 LDA ASONERR ;GET AS ERR FLAG 26DF:30 0E 050 BMI ERRTN ; BRT IF ON ERR IS GO 051 ERNAS EQU * 26E1:A2 00 052 LDX #0
26E3:20 02 27 053 JSR EMPR ; GO OUTPUT ; === Page 41 === 26E6:AE 5C 2A 054 LDX SVA ; GET SAVE MSG 26E9:20 02 27 055 JSR EMPR ; GO OUTPUT MSG 26EC:20 C8 1F 056 JSR PRCRIF ;OUTPUT A CARRIAGE RETURN AFTER MESSAGE 26EF:20 51 28 057 ERRNT JSR MVCSW ; GO MOVE CHAR I/ SW 26F2:20 5E 26 058 JSR TSTRUN 26F5:AE 5C 2A 059 LDX SVA 26F8:A9 03 060 LDA #03 ; magic number 26FA:B0 03 061 BCS ERRTN1 ;DON'T GOTO BREAK HANDLER IF NOT RUNNING 26FC:6C 5A 1D 062 JMP (BREAK) 26FF:6C 5E 1D 063 ERRTN1 JMP (CONT) ;REENTER CONT IF NOT RUN ; === T1S6 === 064 ; 065 EMPR EQU * 2702:BD 3F 2A 066 LDA EMDTB,X ; GET ITS DISPL 2705:AA 067 TAX ; INTO X 068 EMPR1 EQU * 2706:8E 63 2A 069 STX TEMP1A ; SAVE DISPL 2709:BD 71 29 070 LDA EMSG,X ; GET MSG CHAR 270C:48 071 PHA ; SAVE CHAR 270D:09 80 072 ORA #$80 ; SET MSB ON 270F:20 C5 1F 073 JSR ORTN1 ; OUTPUT CHAR 2712:AE 63 2A 074 LDX TEMP1A ; GET INDEX 2715:E8 075 INX ; INCREMENT IT 2716:68 076 PLA ; RE-LOAD CHAR 2717:10 ED 077 BPL EMPR1 ; BR IF MORE CHARS 2719:60 078 RTS ; DONE 079 PAGE 080 ; 081 ; OPNSUP - OPEN SET UP 082 ; 083 OPNSUP EQU * ; If only these were contiguous 271A:AD 66 2A 084 LDA CV ; VOLUME 271D:8D BF 35 085 STA CCBVOL ; 2720:AD 68 2A 086 LDA CD ; DRIVE 2723:8D C0 35 087 STA CCBDRV 2726:AD 6A 2A 088 LDA CS ; SLOT 2729:8D C1 35 089 STA CCBSLT 272C:AD 06 1D 090 LDA FN1ADR ; FILENAME 1 ADR 272F:8D C3 35 091 STA CCBFN1 2732:AD 07 1D 092 LDA FN1ADR+1 2735:8D C4 35 093 STA CCBFN1+1 2738:A5 40 094 LDA ZPGWRK 273A:8D 4F 2A 095 STA CFTABA 273D:A5 41 096 LDA ZPGWRK+1 273F:8D 50 2A 097 STA CFTABA+1 2742:60 098 RTS 099 ; 100 ; MVFN1 - MOVE FILE NAME 1 TO FILE PTR 101 ; 102 MVFN1 EQU * 2743:A0 1D 103 LDY #29 ; magic number MAX_FILENAME-1 2745:B9 75 2A 104 MVFN1A LDA FNAME1,Y 2748:91 40 105 STA (ZPGWRK),Y 274A:88 106 DEY 274B:10 F8 107 BPL MVFN1A 274D:60 108 RTS 109 ; 110 ; MVBUFP - MOVE BUFFER PTR TO CCB 111 ; 112 MVBUFP EQU * 274E:A0 1E 113 LDY #30 ; magic number MAX_FILENAME
2750:B1 40 114 MVBP1 LDA (ZPGWRK),Y ; === Page 42 === 2752:99 A9 35 115 STA CCBFCB-30,Y ; magic number MAX_FILENAME 2755:C8 116 INY 2756:C0 26 117 CPY #38 ; magic number MAX_FILENAME + HEADER.SIZE (See BLDFTAB) 2758:D0 F6 118 BNE MVBP1 275A:60 119 RTS 120 ; 121 ; CLRSTS - CLEAR STATES ; Which states?? Input and Ouput 122 ; 123 CLRSTS EQU * 275B:A0 00 124 LDY #0 275D:8C 51 2A 125 STY ISTATE 2760:8C 52 2A 126 STY OSTATE 2763:60 127 RTS ; Should be FLS4 SEC, RTS for FILSRC not found exit optimization 128 PAGE ; Callers: CMDGO1, CNF1, ERROR, INITZ, don't use carry. 129 ; 130 ; FILSRC - SEARCH FOR FILE NAME1 131 ; 132 FILSRC EQU * 2764:A9 00 133 LDA #0 ; CLEAR SV AVAIL 2766:85 45 134 STA CNUM+1 135 ; 2768:20 92 27 136 JSR TSINIT ; GO INIT SEARCH ; ↓ 276B:4C 73 27 137 JMP FLS1A ; wastes 1 byte, CLALL has JSR TSINIT, BNE SKIPNEXT so why JMP ??? 276E:20 9A 27 138 FLS1 JSR TSNXT ; LOOK AT NEXT 2771:F0 1D 139 BEQ FLS4 ; BR IF NO NET 140 ; 2773:20 AA 27 141 FLS1A JSR TSTOPN ; GO TEST OPEN 2776:D0 0A 142 BNE FLS2 ; BR IF OPEN 143 ; 2778:A5 40 144 LDA ZPGWRK ; SAVE AVAIL ENTRY ADR 277A:85 44 145 STA CNUM 277C:A5 41 146 LDA ZPGWRK+1 277E:85 45 147 STA CNUM+1 2780:D0 EC 148 BNE FLS1 ; GO LOOK SOME MORE 149 ; 2782:A0 1D 150 FLS2 LDY #29 ; FILE HAD 30 CHARS ; magic number MAX_FILENAME-1 2784:B1 40 151 FLS3 LDA (ZPGWRK),Y ; GET CHAR 2786:D9 75 2A 152 CMP FNAME1,Y TEST CHAR ; Missing ; for comment 2789:D0 E3 153 BNE FLS1 ; BR NOT 278B:88 154 DEY 278C:10 F6 155 BPL FLS3 ; LOOK AT 30 CHARS 278E:18 156 CLC ; FOUND 278F:60 157 RTS 158 ; 2790:38 159 FLS4 SEC ; NOT FOUND ;[.. wastes 1 byte, these 2 bytes should be moved to Line #127 2791:60 160 RTS ; DONE ; ..] 161 PAGE 162 ; 163 ; TSINIT - INITIALIZE FOR FTAB SEARCH 164 ; TSNXT - GET NEXT FTAB ENTRY 165 ; 166 TSINIT EQU * 2792:AD 00 1D 167 LDA FTAB ; GET 1ST PTR ADR 2795:AE 01 1D 168 LDX FTAB+1 2798:D0 0A 169 BNE TSST 170 TSNXT EQU * 279A:A0 25 171 LDY #37 ; GET LINK ; magic number HEADER.LINK+1 (See BLDFTB) 279C:B1 40 172 LDA (ZPGWRK),Y 279E:F0 09 173 BEQ TSR ; BR IF NO LINK 174 ; 27A0:AA 175 TAX 27A1:88 176 DEY ; HEADER.LINK+0
27A2:B1 40 177 LDA (ZPGWRK),Y ; === Page 43 === 178 TSST EQU * 27A4:86 41 179 STX ZPGWRK+1 27A6:85 40 180 STA ZPGWRK 27A8:8A 181 TXA ; SET NE CC 27A9:60 182 TSR RTS ; RTN 183 ; 184 ; TSTOPN - TST FOR OPEN FILE ; TST? Really?? You have to abbreviate the description too ?! 185 ; 186 TSTOPN EQU * 27AA:A0 00 187 LDY #0 ; GET 1ST CHAR OF FN 27AC:B1 40 188 LDA (ZPGWRK),Y 27AE:60 189 RTS 190 ; 191 ; TSTEXC - TEST CURRENT FILE FOR EXECUTE 192 ; 193 TSTEXC EQU * 27AF:AD B3 2A 194 LDA ESTATE ; IF ESTATE = 0 27B2:F0 0E 195 BEQ TXC1 ; THEN NO EXECUTE FILE 27B4:AD B4 2A 196 LDA EFTABA ; TEST CURRENT 27B7:C5 40 197 CMP ZPGWRK 27B9:D0 08 198 BNE TXC2 ; IS NOT 27BB:AD B5 2A 199 LDA EFTABA+1 27BE:C5 41 200 CMP ZPGWRK+1 27C0:F0 01 201 BEQ TXC2 ; IS 27C2:CA 202 TXC1 DEX ; IS NOT 27C3:60 203 TXC2 RTS ; DONE ; /sarcasm Thanks, Caption Obvious 204 PAGE 205 ; 206 ; TSTFUC - TEST FILE USE CODE FOR PGM 207 ; 208 TSTFUC EQU * 27C4:4D C2 35 209 EOR CCBFUC 27C7:F0 0A 210 BEQ TFUCR ; Forces TFUCR to waste 1 byte, should be BEQ TXC2 27C9:29 7F 211 AND #$7F ; magic number 27CB:F0 06 212 BEQ TFUCR ; Forces TFUCR to waste 1 byte, should be BEQ TXC2 27CD:20 EA 22 213 JSR ECLOSE ; GO CLOSE THE SOB 27D0:4C D0 26 214 JMP ERNU1 27D3:60 215 TFUCR RTS ; wastes 1 byte due to Lines #210 and #212
001 PAGE 002 ; 003 ; BLDFTB - BUILD FILE TABLES 004 ; TABLE MAP: ; $9600 = Array of File Tables 005 ; HIMEM,SOP ; $9D00 = SOP = Start of Program 006 ; SBUFF N (256) 007 ; DBUFF N (256) 008 ; FTB N (FCBLEN) ; FVCBUFS, Line #186 009 ; HEADER N (38) ; See Header Map below 010 ; . 011 ; . 012 ; SBUFF 1 013 ; DBUFF 1 014 ; FTB 1 015 ; HEADER 1 016 ; THIS PROGRAM 017 ; 018 ; HEADER MAP: 019 ; FILENAME (30) 020 ; FTB PTR (2) 021 ; DBUF PTR (2) 022 ; SBUF PTR (2) 023 ; LINK (2) 024 ; 025 BLDFTB EQU * 27D4:38 026 SEC 27D5:AD 00 1D 027 LDA FTAB ; START OF FTAB AREA ; 27D8:85 40 028 STA ZPGWRK ; IS 1ST FTB PTR ; $1D00: ptr $1CD3 27DA:AD 01 1D 029 LDA FTAB+1 ; HEADER 27DD:85 41 030 STA ZPGWRK+1 27DF:AD 57 2A 031 LDA CNFTBS ; MOVE NO FTABS ; DFNFTS default 3 buffers, INITD 27E2:8D 63 2A 032 STA TEMP1A ; TO TEMP ; fdosent, 60 033 ; 27E5:A0 00 034 BFT1 LDY #0 ; [.. wastes 2 bytes, should JSR ZEROFILE 27E7:98 035 TYA ; ... 27E8:91 40 036 STA (ZPGWRK),Y ; 1ST CHAR FN=0 ; ..] Init [00] $9CD3: 00 27EA:A0 1E 037 LDY #30 ; INC Y TO FCB PTR ; [[FTAB] + offset $1E] = $1CF1 magic number MAX_FILENAME_LEN 27EC:38 038 SEC 27ED:A5 40 039 LDA ZPGWRK ; END OF PTR HEADER 27EF:E9 2D 040 SBC #FCBLEN ; MINUS FTAB LENGTH 27F1:91 40 041 STA (ZPGWRK),Y ; IS START OF FTB ; Init [1E] $9CD3 = $9CF1: $9CA6 buf #1 ptr 27F3:48 042 PHA ; SAVE LOW ADR BYTE 27F4:A5 41 043 LDA ZPGWKR+1 27F6:E9 00 044 SBC #0 27F8:C8 045 INY 27F9:91 40 046 STA (ZPGWKR),Y ; [1F] = page 27FB:AA 047 TAX 27FC:CA 048 DEX ; FTB ADR - 256 27FD:68 049 PLA ; IS ADR DIR BUFF 27FE:48 050 PHA 27FF:C8 051 INY 2800:91 40 052 STA (ZPGWRK),Y ; SET DIR BUF PTR ; === T1S7 === [20] $9CD3 = $9BF3: $9BA6 buf #2 ptr 2802:8A 053 TXA
2803:C8 054 INY ; === Page 5 === 2804:91 40 055 STA (ZPGWRK),Y ; [21] = page 2806:AA 056 TAX 2807:CA 057 DEX ; DIR BUFF - 256 2808:68 058 PLA ; IS SBUFF ADR 2809:48 059 PHA 280A:C8 060 INY 280B:91 40 061 STA (ZPGWRK),Y ; [22] $9CD3 = $9CF5: $9AA6 280D:C8 062 INY 280E:8A 063 TXA 280F:91 40 064 STA (ZPGWRK),Y 065 ; 2811:CE 63 2A 066 DEC TEMP1A ; DECREMENT TABLE INDEX ; Init all buffers? 2814:F0 17 067 BEQ BFT2 ; COUNT AND BR IF DONE ; v 2816:AA 068 TAX 2817:68 069 PLA 2818:38 070 SEC 2819:E9 26 071 SBC #38 ; SBUFF ADR - 38 ; magic number HEADER_SIZE 281B:C8 072 INY 281C:91 40 073 STA (ZPGWRK),Y ; IF ADR OF NEXT TAB ; [24] $9CD3 = $9CF7: $9A80 281E:48 074 PHA ; WHICH GOES INTO 281F:8A 075 TXA ; LINK 2820:E9 00 076 SBC #0 2822:C8 077 INY 2823:91 40 078 STA (ZPGWRK),Y 2825:85 41 079 STA ZPGWRK+1 ; AND INTO ZPGWRK 2827:68 080 PLA ; FOR NEXT ENTRY 2828:85 40 081 STA ZPGWRK ; BUILD 282A:4C E5 27 082 JMP BFT1 ; ^ BFT1 @ $A7E4 wastes 1 byte, A = addr lo: $80 083 ; 084 BFT2 EQU * 282D:48 085 PHA 282E:A9 00 086 LDA #0 ; SET LAST LINK 2830:C8 087 INY ; TO ZERO 2831:91 40 088 STA (ZPGWRK),Y 2833:C8 089 INY 2834:91 40 090 STA (ZPGWRK),Y 091 ; 2836:AD B6 2A 092 LDA ASIBSW ; IF IB THEN GO ; Integer Basic 2839:F0 0B 093 BEQ BFTIB 094 ; 283B:68 095 PLA 283C:85 74 096 STA ASHM1+1 283E:85 70 097 STA ASHM2+1 2840:68 098 PLA 2841:85 73 099 STA ASHM1 2843:85 6F 100 STA ASHM2 2845:60 101 RTS 102 ; 103 BFTIB EQU * 2846:68 104 PLA ; SET IB 2847:85 4D 105 STA IBHMEM+1 ; UPPER MEM LIMITS 2849:85 CB 106 STA IBSOP+1 284B:68 107 PLA 284C:85 4C 108 STA IBHMEM 284E:85 CA 109 STA IBSOP 2850:60 110 RTS 111 PAGE 112 ; 113 ; MVISW - MOVE INPUT SWITCH 114 ; 115 MVCSW EQU * 2851:A5 39 116 LDA INSW+1
2853:CD 03 1D 117 CMP CINA+1 ; === Page 6 === 2856:F0 12 118 BEQ MVOSW 2858:8D 56 2A 119 STA SVINS+1 285B:A5 38 120 LDA INSW ; SAVE CHAR IN SWITCH 285D:8D 55 2A 121 STA SVINS 122 ; 2860:AD 02 1D 123 LDA CINA ; SET DFB CHAR IN ADR 2863:85 38 124 STA INSW 2865:AD 03 1D 125 LDA CINA+1 2868:85 39 126 STA INSW+1 127 ; 128 ; 129 ; MVOSW - MOVE OUTPUT SWITCH 130 ; 131 MVOSW EQU * 286A:A5 37 132 LDA OUTSW+1 286C:CD 05 1D 133 CMP COUTA+1 286F:F0 12 134 BEQ MVSRTN 2871:8D 54 2A 135 STA SVOUTS+1 2874:A5 36 136 LDA OUTSW ; SAVE CHAR OUT SWITCH 2876:8D 53 2A 137 STA SVOUTS 138 ; 2879:AD 04 1D 139 LDA COUTA ; SET DFB CHAR OUT ADR 287C:85 36 140 STA OUTSW 287E:AD 05 1D 141 LDA COUTA+1 2881:85 37 142 STA OUTSW+1 143 MVSRTN EQU * 2883:60 144 RTS
001 PAGE 002 ; ; Smart Operating System design separates 003 ; COMMAND NAME TABLE ; * Kernel 004 ; ; * Shell (Command Interpretor) 005 EC1 EQU * ; This gives each program the maximum amount of run-time memory 006 CMDNTB EQU * ; Alas, DOS is not that smart 2884:49 4E 49 D4 007 DCI "INIT" ; HNTODAOS: #1 Why is INIT listed first??? CATALOG is used far more then INIT 2888:4C 4F 41 C4 008 DCI "LOAD" ; Either sort these by: 288C:53 41 56 C5 009 DCI "SAVE" ; a) frequency of use, (best) 2890:52 55 CE 010 DCI "RUN" ; b) alphabetical (better) 2893:43 48 41 49 011 DCI "CHAIN" ; i.e. "Power Users" are more likely to use BRUN, BLOAD, BSAVE before they use DELETE 2897:CE 2898:44 45 4C 45 012 DCI "DELETE" 289C:54 C5 289E:4C 4F 43 CB 013 DCI "LOCK" 28A2:55 4E 4C 4F 014 DCI "UNLOCK" 28A6:43 CB 28A8:43 4C 4F 53 015 DCI "CLOSE" 28AC:C5 28AD:52 45 41 C4 016 DCI "READ" 28B1:45 58 45 C3 017 DCI "EXEC" ; inconsistent abbreviation: EXECUTE 28B5:57 52 49 54 018 DCI "WRITE" 28B9:C5 28BA:50 4F 53 49 019 DCI "POSITION" 28BE:54 49 4F CE 28C2:4F 50 45 CE 020 DCI "OPEN" ; Calls EOPEN 28C6:41 50 50 45 021 DCI "APPEND" 28CA:4E C4 28CC:52 45 4E 41 022 DCI "RENAME" 28D0:4D C5 28D2:43 41 54 41 023 DCI "CATALOG" ; HNTODAOS: #2 Let's slow users down forcing them type 7 characters 28D6:4C 4F C7 ; Which has a higher error rate of typos? 28D9:4D 4F CE 024 DCI "MON" ; easier to type 3 characters CAT or DIR or 7 character CATALOG ? 28DC:4E 4F 4D 4F 025 DCI "NOMON" ; /sarcasm Oh I see, we abbreviate the uncomon MONITOR but not the common CATALOG 28E0:CE 28E1:50 52 A3 026 DCI "PR#" 28E4:49 4E A3 027 DCI "IN#" 28E7:4D 41 58 46 028 DCI "MAXFILES" 28EB:49 4C 45 D3 28EF:46 D0 029 DCI "FP" 28F1:49 4E D4 030 DCI "INT" 28F4:42 53 41 56 031 DCI "BSAVE" 28F8:C5 28F9:42 4C 4F 41 032 DCI "BLOAD" 28FD:C4 28FE:42 52 55 CE 033 DCI "BRUN" ; === T1S8 === 2902:56 45 52 49 034 DCI "VERIFY" 2906:46 D9 2908:00 035 DFB 0 ; end sentinel, see TODO 036 PAGE 037 ; ; *sigh* Typical crap names; bitmask flags should be prefixed with common name: 038 ; COMMAND SYNTAX OP EQUATES FOR SYNTAX BYTE ONE ; P1_ (better) 039 ; ; PARAM1_ (best, but will concede a short name is extremely convenient) ; ;(better) 040 NPB EQU $80 ; NO PARMS OK, COMMAND GOES TO BASIC ; P1_BAS The first sign of an amateur programmer: 041 NPE EQU $40 ; NO PARMS OK, COMMAND TO EXECUTION RTN ; P1_EXC Poor variable names ; ; Having 2 variable names differ by only 1 character, ; ; such as NPE, NPB, ; or worse NUM1, NUM2 ; ; is a recipe for disaster. ; "Silient" errors (uncaught typos) are a debugging nightmare. ; Using unique names lets us minimize this error. 042 FN1 EQU $20 ; FILE NAME1 REGD ; P1_SRC 043 FN2 EQU $10 ; FILE NAME2 REQD : P1_DST 044 NUM1 EQU $08 ; NUMERIC 0-7 REGD ; P1_SLT -- WTF is the range of NUM 1 ??? Slot tells us 3-bit 045 NUM2 EQU $04 ; NUMERIC 1-10 REQD ; P1_DEC -- WTF is the range of NUM 2 ??? Decimal tells us 8-bit 046 RNONLY EQU $02 ; RUN TIME ONLY FLAG. ; P1_RUN 047 CREFLG EQU $01 ; FLAG TO INDICATE CMDS THAT MAY ; P1_CRE -- FLaG tells us nothing, ALL of these are flags! 048 ; ; Q. Why we would encode the type of paramater such as 1st or 2nd in the name? 049 ; COMMAND SYNTAX OP EQUATES FOR SYNTAX BYTE TWO ; A. It helps us to visually catch typos: 050 ; ; LDA PARAM2 051 V EQU $40 ; VOLUME ALLOWED ; CMP PARAM1_CREATE ; ← param 2 doesn‘t match param 1 above
052 D EQU $20 ; DRIVE ALLOWED ; === Page 22 === 053 S EQU $10 ; SLOT ALLOWED 054 L EQU $08 ; LENGTH ALLOWED 055 R EQU $04 ; RECORD NUMBER ALLOWED 056 B EQU $02 ; BYTE NUMBER ALLOWED 057 ADR EQU $01 ; ADDRESS ; crappy asm tools reserve A for implicit 6502 Accumulator, e.g. LSR A 058 CIO EQU $80 ; C,I, OR O ALLOWED ; CIO = FLAG_CIO = $80 = minus, See CIO, CMDSCAN, Line #204, and OPTAB2 059 ; 060 ; COMMAND SYNTAX TABLE 061 ; EACH COMMAND HAS TWO BYTE ENTRY 062 ; 063 CMDSTB EQU * ; This is another complete clusterfrak of bad formatting ; ; The second sign of an amateur programmer: ; One who doesn't understand the importance of whitespace. (Horizontal and Vertical) ; ; 1. Horizontal alignment improves readability 1000% ; 2. List the common cases, such as FN1, and V+D+S, first ; ; Notice how using a 2D grid it becomes trivial to check for typo's: ; ; FN1 +CREFLAG, V+D+S ; INIT ; FN1+NPB , V+D+S ; LOAD ; FN1+NPB +CREFLAG, V+D+S ; SAVE ; FN1+NPB , V+D+S ; RUN ; FN1 , V+D+S ; CHAIN ; FN1 , V+D+S ; DELETE ; FN1 , V+D+S ; LOCK ; FN1 , V+D+S ; UNLOCK ; FN1 +NPE , V+D+S ; CLOSE ; FN1 +RNONLY , B+R ; READ ; FN1 , V+D+S +R ; EXEC ; FN1 +RNONLY , B+R ; WRITE ; FN1 +RNONLY , R ; POSITION ; FN1 +RNONLY+CREFLAG, V+D+S +L ; OPEN ; FN1 +RNONLY , V+D+S ; APPEND ; FN1+FN2 , V+D+S ; RENAME ; NPE , V+D+S ; CATALOG ; NPE , CIO ; MONITOR ; NPE , CIO ; NO MONITOR ; NUM1 , 0 ; PR# ; NUM1 , 0 ; IN# ; NUM2 , 0 ; MAXFILES ; NPE , V+D+S ; APPLESOFT ; NPE , 0 ; INT ; FN1 +CREFLAG, V+D+S +L+ADR ; BSAVE ; FN1 , V+D+S +ADR ; BLOAD ; FN1 , V+D+S +ADR ; BRUN ; FN1 , V+D+S ; VERIFY 2909:21 70 064 DFB FN1+CREFLG,V+D+S ; INIT 290B:A0 70 065 DFB NPB+FN1,V+D+S ; LOAD 290D:A1 70 066 DFB NPB+FN1+CREFLG,V+D+S ; SAVE 290F:A0 70 067 DFB NPB+FN1,V+D+S ; RUN 2911:20 70 068 DFB FN1,V+D+S ; CHAIN 2913:20 70 069 DFB FN1,V+D+S ; DELETE 2915:20 70 070 DFB FN1,V+D+S ; LOCK 2917:20 70 071 DFB FN1,V+D+S ; UNLOCK 2919:60 00 072 DFB NPE+FN1,0 ; CLOSE 291B:22 06 073 DFB FN1+RNONLY,B+R ; READ 291D:20 74 074 DFB FN1,R+V+D+S ; EXEC 291F:22 06 075 DFB FN1+RNONLY,B+R ; WRITE 2921:22 04 076 DFB FN1+RNONLY,R ; POSITION 2923:23 78 077 DFB FN1+RNONLY+CREFLG,L+V+D+S ; OPEN 2925:22 70 078 DFB FN1+RNONLY,V+D+S ; APPEND 2927:30 70 079 DFB FN1+FN2,V+D+S ; RENAME 2929:40 70 080 DFB NPE,V+D+S ; CATALOG 292B:40 80 081 DFB NPE,CIO ; MONITOR 292D:40 80 082 DFB NPE,CIO ; NO MONITOR 292F:08 00 083 DFB NUM1,0 ; PR# 2931:08 00 084 DFB NUM1,0 ; IN# 2933:04 00 085 DFB NUM2,0 ; MAXFILES 2935:40 70 086 DFB NPE,V+D+S ; APPLESOFT 2937:40 00 087 DFB NPE,0 ; INT 2939:21 79 088 DFB FN1+CREFLG,V+D+S+ADR+L ; BSAVE 293B:20 71 089 DFB FN1,V+D+S+ADR ; BLOAD 293D:20 71 090 DFB FN1,V+D+S+ADR ; BRUN 293F:20 70 091 DFB FN1,V+D+S ; VERIFY 092 PAGE 093 ; 094 ; OPTAB - OPTIONAL PARMS SYNTAX TABLES 095 ; 096 OPTAB1 EQU * ; Problem: Keeping 2 tables in sync can lead to subtle bugs. ; Solution: It would be better to interleave OPTAB1 and OPTAB2 ; to prevent synchronization mistakes: ; MSB ON 2941:D6 C4 D3 CC 097 DFB 'V'+$80,'D'+$80,'S'+$80,'L'+$80' ; DFB 'V', V ; /sarcasm Apparently MSB ON was broken 2945:D2 C2 C1 C3 098 DFB 'R'+$80,'B'+$80,'A'+$80,'C'+$80' ; DFB 'D', D 2949:C9 CF 099 DFB 'I'+$80,'O'+$80' ; DFB 'S', S ; What's the point of compacting the lines??? 100 OPT1L EQU *-OPTAB1 ; DFB 'L', L ; You write code for HUMANS not computers. 101 MI EQU $20 ; DFB 'R', R ; TODO does MI alias FN1? See DRTNI 102 MO EQU $10 ; DFB 'B', B ; TODO does MO alias FN2? See DRTNO 103 OPTAB2 EQU * ; DFB 'A', ADR 294B:40 20 10 08 104 DFB V,D,S,L ; DFB 'C', CIO+MC ; MC was defined in FDOSENT, MC 294F:04 02 01 C0 105 DFB R,B,ADR,CIO+MC ; DFB 'I', CIO+MI ; CIO = FLAG_CIO = $80 = minus 2953:A0 90 106 DFB CIO+MI,CIO+MO ; DFB 'O', CIO+MO ; See CIO, CMDSCAN, Line #204, and OPTAB2 107 OPTAB3 EQU * ; /sarcasm Yay for more crappy table formatting and naming ; [Min, Max] ; OptValMin DW 0 ; Volume ; OptValMax DW 254 ; DW 1, 2 ; Drive ; DW 1, 7 ; Slot ; DW 1, 32767 ; Length ; DW 0, 32767 ; Record Number ; DW 0, 32767 ; Record byte number ; DW 0, $FFFF ; Address 2955:00 00 108 DW 0 ; [0] 2957:FE 00 109 DW 254 ; VOL RANGE 2959:01 00 110 DW 1 ; [1] 295B:02 00 111 DW 2 ; DRIVE RANGE 295D:01 00 112 DW 1 ; [2] 295F:07 00 113 DW 7 ; SLOT RANGE 2961:01 00 114 DW 1 ; [3] BSAVE MEM.48K,A$0,L$C000 won't work without patching DOS
2963:FF 7F 115 DW 32767 ; LENGTH RANGE ; === Page 23 === A963:FF BF to save > 32KB (48KB) 2965:00 00 116 DW 0 ; [4] 2967:FF 7F 117 DW 32767 ; REC NO RANGE 2969:00 00 118 DW 0 ; [5] 296B:FF 7F 119 DW 32767 ; REC BYTE NO RANGE 296D:00 00 120 DW 0 ; [6] 296F:FF FF 121 DW $FFFF ; ADDRESS RANGE 122 PAGE 123 ; 124 ; ERROR MESSAGE TABLES 125 ; 126 EMSG EQU * 2971:0D 07 8D 127 DFB $0D, $07, $8D ; magic number CR, BELL, CR + #$80 128 EM1 EQU *-EMSG 2974:4C 41 4E 47 129 DCI "LANGUAGE NOT AVAILABLE" 2978:55 41 47 45 297C:20 4E 4F 54 2980:20 41 56 41 2984:49 4C 41 42 130 EM2 EQU *-EMSG ; unnecessary duplicate 2988:4C C5 131 EM3 EQU *-EMSG 298A:52 41 4E 47 132 DCI "RANGE ERROR" 298E:45 20 45 52 2992:52 4F D2 133 EM4 EQU *-EMSG 2995:57 52 49 54 134 DCI "WRITE PROTECTED" 2999:45 20 50 52 299D:4F 54 45 43 29A1:54 45 C4 135 EM5 EQU *-EMSG 29A4:45 4E 44 20 136 DCI "END OF DATA" 29A8:4F 46 20 44 29AC:41 54 C1 137 EM6 EQU *-EMSG 29AF:46 49 4C 45 138 DCI "FILE NOT FOUND" 29B3:20 4E 4F 54 139 EM7 EQU *-EMSG 29B7:20 46 4F 55 29BB:4E C4 29BD:56 4F 4C 55 140 DCI "VOLUME MISMATCH" 29C1:4D 45 20 4D 29C5:49 53 4D 41 29C9:54 43 C8 141 EM8 EQU *-EMSG 29CC:49 2F 4F 20 142 DCI "I/O ERROR" 29D0:45 52 52 4F 143 EM9 EQU *-EMSG 29D4:D2 29D5:44 49 53 4B 144 DCI "DISK FULL" 29D9:20 46 55 4C 145 EM10 EQU *-EMSG 29DD:CC 29DE:46 49 4C 45 146 DCI "FILE LOCKED" 29E2:20 4C 4F 43 147 EM11 EQU *-EMSG 29E6:4B 45 C4 29E9:53 59 4E 54 148 DCI "SYNTAX ERROR" 29ED:41 58 20 45 29F1:52 52 4F D2 149 EM12 EQU *-EMSG 29F5:4E 4F 20 42 150 DCI "NO BUFFERS AVAILABLE" 29F9:55 46 46 45 29FD:52 53 20 41 ; === T1S9 === 2A01:56 41 49 4C 2A05:41 42 4C C5 151 EM13 EQU *-EMSG 2A09:46 49 4C 45 152 DCI "FILE TYPE MISMATCH" 2A0D:20 54 59 50 2A11:45 20 4D 49 2A15:53 4D 41 54 2A19:43 C8 153 EM14 EQU *-EMSG 2A1B:50 52 4F 47 154 DCI "PROGRAM TOO LARGE" 2A1F:52 41 4D 20 2A23:54 4F 4F 20 2A27:4C 41 52 47 155 ; 2A2B:C5 156 EM15 EQU *-EMSG 2A2C:4E 4F 54 20 157 DCI "NOT DIRECT COMMAND" 2A30:44 49 52 45 2A34:43 54 20 43 2A38:4F 4D 4D 41 2A3C:4E C4 2A3E:8D 158 DFB $8D ; KEY_CR 159 EMDTB EQU * ; Array of (byte) Pointers to start of each error message 2A3F:00 03 19 19 160 DFB 0,EM1,EM2,EM3 ; wastes 1 byte for redundant error message EM3 2A43:24 33 3E 4C 161 DFB EM4,EM5,EM6,EM7 2A47:5B 64 6D 78 162 DFB EM8,EM9,EM10,EM11 2A4B:84 98 AA 163 DFB EM12,EM13,EM14 2A4E:BB 164 DFB EM15
001 PAGE 002 ; 003 ; MISC BUT REQD CELLS 004 ; 2A4F:00 00 005 CFTABA DDB 0 ; CURRENT FILE TABLE POINTER ; Why Big Endian??? DW is easier to tell this is 2 bytes then DFB DDB confusions 2A51:00 006 ISTATE DFB 0 ; INPUT STATE 2A52:00 007 OSTATE DFB 0 ; OUTPUT STATE 2A53:00 00 008 SVOUTS DDB 0 ; SAVED OUT SWITCH ; Why Big Endian??? 2A55:00 00 009 SVINS DDB 0 ; SAVED IN SWITCH ; Why Big Endian??? 2A57:00 010 CNFTBS DFB 0 ; CURRENT NO FILE TABLES ; "NO" == Number 2A58:03 011 DFNFB DFB 3 ; DEFAULT NO FILE TABLES ; Does anyone actually use > 2 ? 2A59:00 012 SVSTK DFB 0 ; SAVED STACK PTR 2A5A:00 013 SVX DFB 0 ; DSAVED X REG ; *spelling* Saved 2A5B:00 014 SVY DFB 0 : SAVED Y REG 2A5C:00 015 SVA DFB 0 ; SAVED ACU 2A5D:00 016 LBUFD DFB 0 ; LINE BUFF DISPL 2A5E:00 017 MONMOD DFB 0 ; MONITOR MODE BITS 018 MC EQU $40 ; MONITOR CMDS 019 *MI EQU $20 ; MONITOR INPUT ; Moved to CMDTBLS, MI 020 *MO EQU $10 ; MONITOR OUTPUT ; Moved to CMDTBLS, MO 2A5F:00 021 CMDNO DFB $00 ; COMMAND NO IS ZERO FOR BOOT UP 2A60:00 00 022 SVBL DFB 0,0 ; SaVed Binary Length $AA60:Length of last BLOAD, BSAVE 2A62:00 023 SVCMD DFB 0 ; SaVed CoMmanD 2A63:00 024 TEMP1A DFB 0 2A64:00 025 TEMP2A DFB 0 2A65:00 026 INOPTS DFB 0 ; INPUT OPTIONS 027 CUROPT EQU * ; CURRENT OPTIONS ; /sarcasm So we can type CUR ... but too lazy to type CUR_VOL, CUR_DRV, CUR_SLT?? ; Note: OPTAB3 and CUROPT must be keep in size sync! 2A66:00 00 028 CV DW 0 ; VOLUME ; [0] normally wastes 1 byte; all numbers 16-bit, See CMDSCAN, Line #239 2A68:00 00 029 CD DW 0 ; DRIVE ; [2] normally wastes 1 byte, all numbers 16-bit, /sarcasm because DBINIT, OPNSUP 2A6A:00 00 030 CS DW 0 ; SLOT ; [4] normally wastes 1 byte, all numbers 16-bit, need 2 bytes bytes, right? 2A6C:01 00 031 CL DW 1 ; RECORD LENGTH ; [6] 2A6E:00 00 032 CR DW 0 ; RECORD NUMBER ; [8] Not Carriage Return, but Current Record. /sarcasm Obvious, right? 2A70:00 00 033 CB DW 0 ; RECORD BYTE ; [A] 2A72:00 00 034 CA DW 0 ; ADDRESS ; [C] $AA72:Address of last BLOAD 2A74:00 035 IMBITS DFB 0 ; TODO: Input Monitor Bits??? Used in EMON 036 MSB ON ; We can't DS 30-5,$A0 ??? 2A75:C8 C5 CC CC 037 FNAME1 ASC "HELLO " ; FILENAME 1" 2A79:CF A0 A0 A0 2A7D:A0 A0 A0 A0 2A81:A0 A0 A0 A0 2A85:A0 A0 A0 A0 2A89:A0 A0 A0 A0 2A8D:A0 A0 A0 A0 2A91:A0 A0 038 MSB OFF 2A93:A0 A0 A0 A0 039 FNAME2 DS 30,$A0 ;FILENAME 2 ; Too lazy to leave MSB ON, and ASC " " x30 ?? 2A97:A0 A0 A0 A0 2A9B:A0 A0 A0 A0 2A9F:A0 A0 A0 A0 2AA3:A0 A0 A0 A0 2AA7:A0 A0 A0 A0 2AAB:A0 A0 A0 A0 2AAF:A0 A0 2AB1:03 040 DFNFTS DFB 3 ; DEFAULT FILE TABLES = 3 ; INITD copies to CNFTBS 2AB2:84 041 CCHAR DFB $84 ; CONTROL CHAR ; Control-D actives DOS for next ASCII command magic number KEY_CTRL_D 2AB3:00 042 ESTATE DFB 0 ; EXECUTE STATE 2AB4:00 00 043 EFTABA DFB 0,0 ; EXECUTE FILE TABLE POINTER 2AB6:00 044 ASIBSW DFB 0 ; APPLESOFT, IB SWITCH ; 00=Integer, 40=Applesoft ROM, 80=Applesoft RAM 2AB7:00 045 RSTATE DFB 0 ; FOR APPLESOFT RUN PROGRAM AFTER RELOC 2AB8:C1 D0 D0 CC 046 FASB DFB $C1,$D0,$D0,$CC ;'APPLESOFT' WITH BIT 7 HIGH; /sarcasm If only we had MSB ON and ASC directives 2ABC:C5 D3 CF C6 047 DFB $C5,$D3,$CF,$C6 ; Binary to run if Integer active and user types FP 2AC0:D4 048 DFB $D4 049 FASBL EQU *-FASB ; Filename Length of Applesoft binary, copied in EAS0 050 PAGE 051 ; 052 ; DOS ADR TABLES (RELOCATED)
053 ; ; === Page 61 054 SAT2 EQU * ; Start Address Table ; Gee, we couldn't have put this at $1D00 to save 4 bytes in ADRTAB ?! 2AC1:E8 37 055 AIOB DW IOB ; 5-ADR IOB ; Also see BAIOB; What happened to 1 .. 4 ??? At RVT, WVT ? 2AC3:BB 33 056 AVTOC DW VTOC ; 6-ADR VTOC 2AC5:BB 34 057 AVOLDR DW VOLDIR ; 7-ADR VOLDIR 2AC7:00 40 058 AEND DW ENDOFDOS ;END OF DOS ; See REPAGE 059 ; ; File Manager 2AC9:7E 33 060 CMDVT DW GOODIO-1 ; 0-NULL ; [0] wastes 2 bytes → $B37E 2ACB:21 2B 061 DW FOPEN-1 ; 1-OPEN FILE ; [1] 2ACD:05 2C 062 DW FCLOSE-1 ; 2-CLOSE FILE ; [2] 2ACF:57 2C 063 DW FREAD-1 ; 3-READ DATA ; [3] 2AD1:6F 2C 064 DW FWRITE-1 ; 4-WRITE DATA ; [4] 2AD3:2A 2D 065 DW FDEL-1 ; 5-DELETE FILE ; [5] 2AD5:97 2D 066 DW RDIR-1 ; 6-READ DIRECTORY ; [6] /sarcasm Yay for consistent naming: FDIR 2AD7:EE 2C 067 DW FLOCK-1 ; 7-LOCK A FILE ; [7] 2AD9:F5 2C 068 DW FUNLCK-1 ; 8-UNLOCK A FILE ; [8] 2ADB:39 2C 069 DW FRNME-1 ; 9-RENAME ; [9] 2ADD:11 2D 070 DW FPOSTN-1 ; 10-POSITION A FILE ; [A] 2ADF:8D 2E 071 DW FFMT-1 ; FORMAT ; [B] 2AE1:17 2D 072 DW FVAR-1 ; VARIFY ; [C] *spelling* VERIFY 2AE3:7E 33 073 DW GOODIO-1 ; 11-SPARE ; [D] wastes 2 bytes due to fencepost error ; Uh, calling 13 "eleven" doesn't make it so. 074 ; ; See DOSENT: CCBREQ (FileManager.command) >= CRQMAX ; AAE3:00 00 ; (was 7E B3) to prove this is never called ; 0300:20 DC 03 JSR CCBLDR ; $9E5D GetCCBAdr ; $9D0E: dw $B5BB = CCB ; 0303:84 FD STY $FD ; 0305:85 FE STA $FE ; 0307:A9 0D LDA #$D ; Command = CRQMAX ; 0309:A0 00 LDY #0 ; FileManager.Command = Command ; 030B:91 FD STA ($FD),Y ; 030D:4C D6 03 JMP USERENT ; $AAFD FileManager 075 RVT EQU * ; USERENT calls FREAD 2AE5:7E 33 076 DW GOODIO-1 ; [0] wastes 2 bytes; See CRMNUL 2AE7:89 2C 077 DW RNXBYT-1 ; 1-RD NEXT BYTE ; [1] 2AE9:95 2C 078 DW NXBLK-1 ; 1-RD NEXT BLOCK ; [2] *sigh* copy-paste 2AEB:86 2C 079 DW RSPBYT-1 ; 2-RD SPECIFIC BYTE ; [3] 2AED:92 2C 080 DW RSPBLK-1 ; 3 - RD SPECIFIC BLOCK ; [4] 2AEF:7E 33 081 DW GOODIO-1 ; 4 - SPARE ; [5] wastes 2 bytes off-by-1 allocation, see CRMMAX, FREAD 082 ; 083 WVT EQU * 2AF1:7E 33 084 DW GOODIO-1 ; [0] wastes 2 bytes; Stop, please stop this stupidity 2AF3:BD 2C 085 DW WNXBYT-1 ; 1-WR NEXT BYTE ; [1] 2AF5:C9 2C 086 DW WNXBLK-1 ; WR NEXT BLOCK ; [2] *sigh* copy-paste 2AF7:BA 2C 087 DW WSPBYT-1 ; 2-WR SPECIFIC BYTE ; [3] 2AF9:C6 2C 088 DW WSPBLK-1 ; 3-WR SPECIFIC BLOCK ; [4] 2AFB:7E 33 089 DW GOODIO-1 ; 4 - SPARE ; [5] wastes 2 bytes 090 EAT2 EQU * 091 PAGE 092 ; 093 ; USERENT - DOS EXTERNAL ENTRY POINT (USER ENTRY) 094 ; ENTRY PARM: 095 ; A= HIGH ADDRESS OF CCB 096 ; Y= LOW ADDRESS OF CCB 097 ; X= 0 IF CREATE DESIRED 098 ; X> 0 IF CREATE NOT DESIRED 099 ; EXIT PARM: 100 ; CARRY CLEAR = OPERATION OK 101 ; CARRY SET = ERROR 102 ; 103 SC2 EQU * ; See: [1] CDETAB 2AFD:E0 00 104 USERENT CPX #0 ;IF X=0 THEN FILE CREATED IF NOT 2AFF:F0 02 105 BEQ USRCR ; FOUND. NOTE: FILE NOT FOUND ERROR STILL IS RETURNED ; === T1SA === 2B01:A2 02 106 LDX #2 ;INDICATE NO CREATE ALLOWED 2B03:8E 5F 2A 107 USRCR STX CMDNO ;SET UP FOR CREATE CAPIBILITY ; *spelling* CAPABILITY 108 DOSENT EQU * ; /sarcasm Is that like our potential to be cap'd or knock'd off :-) 2B06:BA 109 TSX 2B07:8E 9B 33 110 STX ENTSTK 2B0A:20 6A 2E 111 JSR CLCFCB ; GO CALCULATE FCB 2B0D:AD BB 35 112 LDA CCBREQ ; GET REQUEST 2B10:C9 0D 113 CMP #CRQMAX ; TTEST REQ RANGE ; /sarcasm South Park: Jimmy
2B12:B0 0B 114 BCS ERR2 ; BR OUT OF RANGE ; === Page 62 === A-a-n-d you still have an of-of-of-off-by-one bug allocation in array CMDVT! 2B14:0A 115 ASL A ; REQ CODE *2 2B15:AA 116 TAX 2B16:BD CA 2A 117 LDA CMDVT+1,X ; PUSH ADR ONTO STACK 2B19:48 118 PHA 2B1A:BD C9 2A 119 LDA CMDVT,X 2B1D:48 120 PHA 2B1E:60 121 DENRTS RTS 2B1F:4C 63 33 122 ERR2 JMP ERROR2
001 PAGE 002 ; 003 ; FOPEN - OPEN A FILE 004 ; 005 FOPEN EQU * 2B22:20 28 2B 006 JSR DOPEN ; ↓ 2B25:4C 7F 33 007 JMP GOODIO 008 ; 009 DOPEN EQU * 010 ; 2B28:20 DC 2B 011 JSR DCBSUP 012 ; 013 ; 2B2B:A9 01 014 LDA #1 2B2D:8D E3 35 015 STA DCBSDL+1 2B30:AE BE 35 016 LDX CCBRLN+1 ; MOVE RECORD LENGTH 2B33:AD BD 35 017 LDA CCBRLN 2B36:D0 05 018 BNE F01 2B38:E0 00 019 CPX #0 2B3A:D0 01 020 BNE F02 2B3C:E8 021 INX ; SET RL=256 2B3D:8D E8 35 022 F02 STA DCBRCL 2B40:8E E9 35 023 STX DFBRCL+1 024 ; 2B43:20 C9 31 025 JSR FNDFIL ; GO FIND FILE 2B46:90 5E 026 BCC F03 ; BR IF FOUND 027 ; 028 * CREATE FILE IF COMMAND IS SAVE, OPEN, BSAVE 029 ; 2B48:8E 9C 33 030 STX TEMP1 ; SAVE DIR. INDEX 2B4B:AE 5F 2A 031 LDX CMDNO ;TEST COMMAND FOR CREATE FLAG 2B4E:BD 09 29 032 LDA CMDSTB,X ; (BIT 0 MUST=1) 2B51:AE 9C 33 033 LDX TEMP1 ;RESTORE DIR INDEX 2B54:4A 034 LSR A ;SHIFT CREFLAG BIT TO CARRY 2B55:B0 0D 035 BCS F02B ;BRANCH ON VALID INSTR. 2B57:AD 51 2A 036 LDA ISTATE ;FIND OUT IF TRYING TO LOAD APPLESOFT 2B5A:C9 C0 037 CMP #$C0 ; magic number 2B5C:D0 03 038 BNE F02A ; NO GO 2B5E:4C 5F 33 039 JMP ERROR1 ; Which error message?? "LANGUAGE NOT AVAILABLE" 2B61:4C 73 33 040 F02A JMP ERROR6 ; PRINT "FILE NOT FOUND" MESSAGE. 2B64:A9 00 041 F02B LDA #0 ; 0001 Little Endian 2B66:9D E8 34 042 STA VDFILE+34,X ; magic number VDFILE + CAT_FILE_NUM_SEC+0 (See VDFILE) 2B69:A9 01 043 LDA #1 2B6B:9D E7 34 044 STA VDFILE+33,X ; magic number VDFILE + CAT_FILE_NUM_SEC+1 2B6E:8E 9C 33 045 STX TEMP1 ; SAVE VDIR INDEX ; Why?? wastes 2 bytes, Line #30 already saved 2B71:20 44 32 046 JSR GETSEC ; GO ALLOCATE SECTOR 2B74:AE 9C 33 047 LDX TEMP1 2B77:9D C7 34 048 STA VDFILE+1,X ; PUT SECTOR INTO VDIR ; magic number VDFILE + CAT_FILE_SECTOR 2B7A:8D D2 35 049 STA DCBFDS ; PUT SECTOR AS 1ST FILE DIR 2B7D:8D D4 35 050 STA DCBCDS ; PUT SECTOR AS CURRENT FILE DIR 051 ; 2B80:AD F1 35 052 LDA DCBATK ; GET ALLOCATED TRACK
2B83:9D C6 34 053 STA VDFILE,X ; PUT INTO VDIR ; === Page 78 === magic number VDFILE + CAT_FILE_TRACK 2B86:8D D1 35 054 STA DCBFDT ; AND AS 1ST FILE DIR ; More crappy variable names : dcbFdt 2B89:8D D3 35 055 STA DCBCDT ; AND AS CURRENT FILE DIR ; that differ by a single letter: dcbCdt 056; 2B8C:AD C2 35 057 LDA CCBFUC ; SET USE CODE 2B8F:9D C8 34 058 STA VDFILE+2,X ; INTO DIRECTORY ; magic number VDFILE + CAT_FILE_TYPE 059 ; 2B92:20 37 30 060 JSR WRVDIR ; GO WRITE VOL DIRECTORY 061 ; 2B95:20 0C 2F 062 JSR MVFCBD ; MOVE FILE DIR ADR TO ZP 2B98:20 D6 37 063 JSR CLRSEC ; GO CLEAR IT 2B9B:20 3A 2F 064 JSR WRFDGO ; GO WRITE FILE DIRECTORY 065 ; DONE CREATION 2B9E:AE 9C 33 066 LDX TEMP1 ; RE-GET INDEX ; Which index?? VDFILE offset 2BA1:A9 06 067 LDA #CREFNF 2BA3:8D C5 35 068 STA CREFNF 069 ; 070 F03 EQU * 2BA6:BD C6 34 071 LDA VDFILE,X ; MOVE FILE DIR TRACK ; magic number VDFILE + CAT_FILE_TRACK 2BA9:8D D1 35 072 STA DCBFDT 2BAC:BD C7 34 073 LDA VDFILE+1,X ; MOVE FILE DIR SECTOR ; magic number VDFILE + CAT_FILE_SECTOR 2BAF:8D D2 35 074 STA DCBFDS 2BB2:BD C8 34 075 LDA VDFILE+2,X ; 7OVE FILE USE CODE ; *spelling* Move; magic number VDFILE + CAT_FILE_TYPE 2BB5:8D C2 35 076 STA CCBFUC 2BB8:8D F6 35 077 STA DCBFUC 2BBB:BD E7 34 078 LDA VDFILE+33,X ; magic number VDFILE + CAT_FILE_NUM_SEC 2BBE:8D EE 35 079 STA DCBNSA 2BC1:BD E8 34 080 LDA VDFILE+34,X ; magic number VDFILE + CAT_FILE_NUM_SEC+1 2BC4:8D EF 35 081 STA DCBNSA+1 2BC7:8E D9 35 082 STX DCBVDI ;SAVE DIRECTORY INDEX 083 ; 2BCA:A9 FF 084 LDA #255 ; INDICATE NO SECTOR 2BCC:8D E0 35 085 STA DCBCMS ; IN MEMORY ; More crappy variable names : dcbCms 2BCF:8D E1 35 086 STA DCBCMS+1 2BD2:AD E2 33 087 LDA VTDMS ; MOVE MAX FD SECTS 2BD5:8D DA 35 088 STA DCBDMS ; TODCB ; that differ by a single letter: span class='code'>dcbDms 2BD8:18 089 CLC 2BD9:4C 5E 2F 090 JMP RDFDIR ; READ 1ST DIRECTORY RECORD ; Read inode 091 ; 092 ; 093 ; 094 ; 095 DCBSUP EQU * 2BDC:A9 00 096 LDA #0 2BDE:AA 097 TAX 2BDF:9D D1 35 098 F01 STA FCBDCB,X ; CLEAR DCB 2BE2:E8 099 INX 2BE3:E0 2D 100 CPX #DCBLEN ; Over-writes unused memory DCBSPR 2BE5:D0 F8 101 BNE F01 102 ; 2BE7:AD BF 35 103 LDA CCBVOL ; MOVE VOL 2BEA:49 FF 104 EOR #$FF ; INVERT VOL BITS ; Why?? 2BEC:8D F9 35 105 STA DCBVOL 2BEF:AD C0 35 106 LDA CCBDRV ; MOVE DRIVE 2BF2:8D F8 35 107 STA DCBDRV 2BF5:AD C1 35 108 LDA CCBSLT ; GET USER SPEC SLOT 2BF8:0A 109 ASL A ; SLOT*16 2BF9:0A 110 ASL A 2BFA:0A 111 ASL A 2BFB:0A 112 ASL A 2BFC:AA 113 TAX 114 F01A EQU * 2BFD:8E F7 35 115 STX DCBSLT
; === Page 79 === ; === T1SB === 2C00:A9 11 116 LDA #17 ;[.. wastes 5 bytes; magic number FILESYSTEM_VTOC_CAT_TRACK = $11 2C02:8D FA 35 117 STA DCBVTN ; ..] due to unitialized DCBVTN DS 1 Because this can change??? 2C05:60 118 RTS 119 PAGE 120 ; 121 ; FCLOSE - CLOSE A FILE 122 ; 123 FCLOSE EQU * 2C06:20 1D 2F 124 JSR WRSECT ; WRITE OPEN SECTOR 2C09:20 34 2F 125 JSR WRFDIR ; GO WRITE FILE DIRECTORY ; Asinine comments like this wouldn't even be needed with proper names 2C0C:20 C3 32 126 JSR FRETRK ; FREE UNUSED SECTORS ; JSR WR_FILE_DIR 2C0F:A9 02 127 LDA #IBCWTS 2C11:2D D5 35 128 AND DCBWRF 2C14:F0 21 129 BEQ FC2 130 ; 2C16:20 F7 2F 131 JSR RDVTOC 2C19:A9 00 132 LDA #0 2C1B:18 133 CLC 134 FC1 EQU * 2C1C:20 11 30 135 JSR RDVDIR ; READ VDIR ; TODO A = ??? 2C1F:38 136 SEC 2C20:CE D8 35 137 DEC DCBVDR ; TODO Why DEC ? -- Sector offset set in FNDFIL 2C23:D0 F7 138 BNE FC1 2C25:AE D9 35 139 LDX DCBVDI ; Volume Directory Index: X = file entry offset in CATALOG sector 2C28:AD EE 35 140 LDA DCBNSA ; MOVE NO SECTORS ALLOCATED ; You keep using this word move, it doesn't mean what you think it means. 2C2B:9D E7 34 141 STA VDFILE+33,X ; magic number VDFILE + CAT_FILE_NUM_SEC 2C2E:AD EF 35 142 LDA DCBNSA+1 2C31:9D E8 34 143 STA VDFILE+34,X ; magic number VDFILE + CAT_FILE_NUM_SEC 2C34:20 37 30 144 JSR WRVDIR ; WRITE VOL DIR REC ; Should be common entry point; See "wastes 3 bytes" note below 145 ; 146 ; 147 FC2 EQU * 2C37:4C 7F 33 148 JMP GOODIO ; DONE 149 PAGE 150 ; 151 * FRNAME - RENAME A FILE 152 ; 153 FRNME EQU * 2C3A:20 28 2B 154 JSR DOPEN ; GO OPEN FILE 2C3D:AD F6 35 155 LDA DCBFUC ; GET USE CODE 2C40:30 2B 156 BMI ER10 ; BR IF LOCKED 2C42:AD BD 35 157 LDA CCBFN2 ; MOVE NEW FN 2C45:85 42 158 STA ZPGFCB ; MOVE PTR TO ZPG 2C47:AD BE 35 159 LDA CCBFN2+1 2C4A:85 43 160 STA ZPGFCB+1 2C4C:AE 9C 33 161 LDX TEMP1 ; GET VDIR INDEX ; TODO Does DOPEN set this? 2C4F:20 1C 32 162 JSR MVFN ; MOVE FILE NAME 2C52:20 37 30 163 JSR WRVDIR ; GO WRITE VDIR ; [.. wastes 3 bytes: Should be JMP FC2-3 2C55:4C 7F 33 164 JMP GOODIO ; DONE RENAME ; ..] and this JMP GOODIO can be removed entirely 165 PAGE 166 ; 167 * FREAD - READ A FILE 168 ; 169 FREAD EQU * 170 ; 2C58:AD BC 35 171 LDA CCBRQM ; GET REQ MOD 2C5B:C9 05 172 CMP #CRMMAX ; TEST LIMIT 2C5D:B0 0B 173 BCS ERR3A ; BR BAD 174 ; ; Current code uses: 32 bytes ; 11 bytes $2C5F..$2C69 FREAD ; 11 bytes $2C7C..$2C86 FWRITE ; 10 bytes $2189..$2192 ECMD ; ; New code uses: 31 bytes + reloc table entries ; 4 bytes (Setup code) ; 2C5F:A2 E6 LDX #<RVT+1 ; lo byte of func table address ; 2C61:A0 2A LDY #>RVT ; hi byte of func table address ; ; ... intentional fall into CallFunc ... ; 14 bytes FREAD (Common code) ; 2C63:0A CallFunc ASL ; main entry point if A not SHL ; 2C64:86 48 SaveFunc STX IOBPL ; 2nd entry point if A is SHL ; 2C66:84 49 STY IOBPH ; ; 2C68:A8 TAY ; 2C69:B1 48 LDA (IOBPL),Y ; B9 FF FF LDA $FFFF,Y ; 2C6B:48 PHA ; 2C6C:88 DEY ; 2C6D:B1 48 LDA (IOBPL),Y ; 2C6F:48 PHA ; 2C74:60 RTS ; ; 6 bytes FWRITE ; 2C7C:A2 F1 LDX #<WVT+1 ; lo byte of func table address ; 2C7E:A0 2A LDY #>WVT ; hi byte of func table address ; 2C80:90 DF BCC CallFunc ; ; 7 bytes ECMD ; 2189:A2 1E LDX #<CMDETB+1 ; 218B:A0 1D LDY #>CMDETB ; 218D:4C 63 2C JMP SaveFunc 2C5F:0A 175 ASL A ; CODE*2 ;[.. Data*2 = Array of 16-bit Function Pointers 2C60:AA 176 TAX ; .. 2C61:BD E6 2A 177 LDA RVT+1,X ; GET READ ROUTINE ; .. 2C64:48 178 PHA ; .. old code
2C65:BD E5 2A 179 LDA RVT,X ; .. === Page 80 === 2C68:48 180 PHA ; AND ; .. 2C69:60 181 RTS ; GO TO IT ; ..] 182 ; 2C6A:4C 67 33 183 ERR3A JMP ERROR3 ; What is → CREMRE: EM3 "RANGE ERROR" 2C6D:4C 7B 33 184 ER10 JMP ERRR10 ; error#? → CREFLK: EM10 "FILE LOCKED" 185 ; ; /sarcasm Really?! Have to abbreviate 'o' in ERROR10 ??? ; ; Problem: ; FD2 has ; $2D34 BPL FD3 ; $2D36 JMP ERROR10 ; ; To remove the 3 byte jump & take advantage of existing ; code ER10 @ $2C6D JMP ERR10, ; we need to invert the branch to target ER10 ; ; $2D34 BMI ER10 ; ; But $2D36 - $2C6D = $C7 which is > $80 bytes away for BMI ; Can ER10 be safely moved closer to FD2? ; ; Solution: ; The first reference to ER10 is in FRNME @ $2C40 ; ; $2C3D LDA DCBFUC ; $2C40 BMI ER10 ; ; We need to keep ER10 within the 128 byte range of FRNME. ; ; The max branch address for FRNME is $2C42 + $80 = $2CC2 ; The min branch address for FD2 is $2D36 - $80 = $2CB6 ; ; Since the two 128-byte ranges overlap we can move ER10 ! ; The perfect spot is @ $2CBB (just after EOFIN) ; ; This is a good example of where: ; ; maximing locality ; ; can open up new opportunities for optimizing. 186 * FWRITE - WRITE A FILE 187 ; 188 FWRITE EQU * 2C70:AD F6 35 189 LDA DCBFUC ; IS FILE LOCKED 2C73:30 F8 190 BMI ER10 ; BR IF LOCKED 2C75:AD BC 35 191 LDA CCBRQM ; GET REQ MOD 2C78:C9 05 192 CMP #CRMMAX ; IN RANGE ; Off by 1 bug 2C7A:B0 EE 193 BCS ERR3A ; BR IF NOT IN RANGE ; 194 ; ; 2C7C:0A 195 ASL A ;[.. Alternative: 2C7D:AA 196 TAX ; .. (See above) 2C7E:BD F2 2A 197 LDA WVT+1,X ; GET ROUTINE ADR ; .. 2C81:48 198 PHA ; .. LDX #<WVT+1 ; lo byte of func table address 2C82:BD F1 2A 199 LDA WVT,X ; .. LDY #>WVT ; hi byte of func table address 2C85:48 200 PHA ; .. BCC CallFunc ↑ (always) 2C86:60 201 RTS ; ..] 202 PAGE 203 ; 204 * RSPBYT - READ A SPECIFIC BYTE 205 ; 206 RSPBYT EQU * 2C87:20 00 33 207 JSR LOCSEC ; GO GET REQD REL SECTOR 208 ; 209 * RNXBYT - READ NEXT BYTE 210 ; 2C8A:20 A8 2C 211 RNXBYT JSR GETBYT ; GO GET BYTE 2C8D:8D C3 35 212 STA CCBDAT ; PUT IN CCB 2C90:4C 7F 33 213 JMP GOODIO ; DONE 214 ; 215 * RSPBLK - READ A SPECIFIC BLOCK 216 ; 2C93:20 00 33 217 RSPBLCK JSR LOCSEC ; GO LOCATE REL SECTOR 218 ; 219 * RNXBLK - READ NEXT BLOCK 220 ; 221 RNXBLK EQU * 2C96:20 B5 31 222 JSR DTBLN ; GO DECR LEN (NOT RTN IF=0) 2C99:20 A8 2C 223 JSR GETBYT ; GO GET BYTE 2C9C:48 224 PHA 2C9D:20 A2 31 225 JSR MIBDA ; GO MOVE BLOCK ADR AND INCR 2CA0:A0 00 226 LDY #0 2CA2:68 227 PLA 2CA3:91 42 228 STA (ZPGFCB),Y ; SET DATA BYTE 2CA5:4C 96 2C 229 JMP RNXBLK ; GO FOR NEXT BYTE 230 ; 231 * GETBYT - GET A DATA BYTE 232 ; 233 GETBYT EQU * 2CA8:20 B6 30 234 JSR LOCNXB ; LOCATE NEXT BYTE 2CAB:B0 0B 235 BCS EOFIN ; BR IF EOF 2CAD:B1 42 236 LDA (ZPGFCB),Y ; GET DAT BYTE 2CAF:48 237 PHA ; SAVE IT ; INCBYT Should be common code for PB0 as well 2CB0:20 5B 31 238 JSR INCRRB ; INCR REC BYTE ; What is the difference between these two??? 2CB3:20 94 31 239 JSR INCSCB ; INCR SEC BYTE ; 2CB6:68 240 PLA ; GET SAVED BYTE ; Stop treating the reader like an idiot with redundant comments 2CB7:60 241 RTS ; RETURN ; All this does is just add visual noise
242 ; ; === Page 81 === 2CB8:4C 6F 33 243 EOFIN JMP ERROR5 ; GOTO EOF RTN ; CREEOF → EM5: "END OF DATA" 244 PAGE 245 ; 246 * WSPBYT - WRITE SPECIFIC BYTE 247 ; 248 WSPBYT EQU * 2CBB:20 00 33 249 JSR LOCSEC ; GO LOCATE SECTOR 250 ; 251 * WNXBYT - WRITE NEXT BYTE 252 ; 253 WNXBYT EQU * 2CBE:AD C3 35 254 LDA CCBDAT ; GET THE BYTE 2CC1:20 DA 2C 255 JSR PUTBYT ; GO WRITE BYTE 2CC4:4C 7F 33 256 JMP GOODIO ; DONE 257 ; 258 * WSPBLK - WRITE A SPECIFIC BLOCK 259 ; 260 WSPBLK EQU * 2CC7:20 00 33 261 JSR LOCSEC ; GO LOCATE SECTOR 262 ; 263 * WNXBLK - WRITE NEXT BLOCK 264 ; 265 WNXBLK EQU * 2CCA:20 A2 31 266 JSR MIBDA ; GO MOVE ADR TO ZPG AND DEC 2CCD:A0 00 267 LDY #0 2CCF:B1 42 268 LDA (ZPGFCB),Y ; GET DATA BYTE 2CD1:20 DA 2C 269 JSR PUTBYT ; GO PUT IT 2CD4:20 B5 31 270 JSR DTBLN ; GO DEC BLK LEN (NOT RTN IF = 0) 2CD7:4C CA 2C 271 JMP WNXBLK 272 ; 273 * PUTBYT - PUT OUT ONE BYTE 274 ; 275 PUTBYT EQU * 2CDA:48 276 PHA ; SAVE DATA BYTE 2CDB:20 B6 30 277 JSR LOCNXB ; GO LOCATE NEXT BYTE 278 ; 2CDE:68 279 PB0 PLA ; GET SAVED BYTE 2CDF:91 42 280 STA (ZPGFCB),Y ; PUT THE BYTE 2CE1:A9 40 281 LDA #$40 ; SET WRITE SECTOR REQD ; magic number WRITE_FLAG_SECTOR, See GNWSEC 2CE3:0D D5 35 282 ORA DCBWRF 2CE6:8D D5 35 283 STA DCBWRF 284 ; 2CE9:20 5B 31 285 JSR INCRRB ; INCR REL REC BYTE ;[.. wastes 3 bytes 2CEC:4C 94 31 286 JMP INCSCB ; INCR SECTOR BYTE ; ..] JMP INCBYT = (GETBYT+7) = Line #237
001 PAGE 002 ; 003 * FLOCK - LOCK A FILE 004 ; 2CEF:A9 80 005 FLOCK LDA #$80 ; REMEMBER LOCK ; magic number LOCK_MASK = $80 2CF1:8D 9E 33 006 STA TEMP3 ; [.. wastes 3 bytes, BNE line #12 2CF4:D0 05 007 BNE LCKGO ; ..] even better, change to DB $2C (BIT $abs) which causes to next instruction to be skipped → BIT $00A9 008 ; 009 * FUNLOCK - UNLOCK A FILE 010 ; 2CF6:A9 00 011 FUNLCK LDA #00 ; REMEMBER UNLOCK ; magic number 2CF8:8D 9E 33 012 STA TEMP3 013 ; 014 LCKGO EQU * 015 ; 2CFB:20 28 2B 016 JSR DOPEN ; GO OPEN FILE 2CFE:AE 9C 33 017 LDX TEMP1 ; === T1SC === 2D01:BD C8 34 018 LDA VDFILE+2,X ; GET FILE USE CODE ; magic number* 2D04:29 7F 019 AND #$7F ; TURN OFF LOCK ; magic number ~LOCK_MASK 2D06:0D 9E 33 020 ORA TEMP3 2D09:9D C8 34 021 STA VDFILE+2,X 2D0C:20 37 30 022 JSR WRVDIR 2D0F:4C 7F 33 023 GOGOOD JMP GOODIO 024 ; 025 * FPOSTN - POSITION A FILE 2D12:20 00 33 026 FPOSTN JSR LOCSEC ; GO POSITION 2D15:4C 7F 33 027 JMP GOODIO ; DONE 028 ; 029 ; 030 * FVAR - VARIFY A FILE ; *spelling* VERIFY 031 ; 032 FVAR EQU * 2D18:20 28 2B 033 JSR DOPEN ; OPEN FILE 2D1B:20 B6 30 034 VAR1 JSR LOCNXB ; READ A SECTOR 2D1E:B0 EF 035 BCS GOGOOD ; BR IF EOF 2D20:EE E4 35 036 INC DCBCRS ; INCREMENT SECTOR 2D23:D0 F6 037 BNE VAR1 ; Can't save > 32KB, See OPTAB3 32767 2D25:EE E5 35 038 INC DCBCRS+1 ; Therfore Current Relative Sector can never overflow to zero 2D28:4C 1B 2D 039 JMP VAR1 ; READ THIS ONE ; wastes 1 bytes BNE VAR1 040 PAGE 041 ; 042 * FDEL - DELETE A FILE 043 ; 044 FDEL EQU * 2D2B:20 28 2B 045 JSR DOPEN ; GO OPEN FILE 046 ; 2D2E:AE 9C 33 047 FD2 LDX TEMP1 ; SAVED INDEX 2D31:BD C8 34 048 LDA VDFILE+2,X ; IS FILE LOCKED ; magic number VDFILE + CAT_FILE_TYPE 2D34:10 03 049 BPL FD3 ; Should be BMI ER10 (once ER10 is moved) 2D36:4C 7B 33 050 JMP ERROR10 ; wastes 3 bytes with JMP, See ER10 optimization above 051 ; 052 FD3 EQU * 2D39:AE 9C 33 053 LDX TEMP ; GET SAVED INDEX
; === Page 56 === 2D3C:BD C6 34 054 LDA VDFILE,X ; GET DIR TRACK ; magic number VDFILE + CAT_FILE_TRACK 2D3F:8D D1 35 055 STA DCBFDT ; SET AS 1ST FD TRACK ; LC = last character 2D42:9D E6 34 056 STA VDFILE+32,X ; SAVE IN LC OF FN ; magic number VDFILE + CAT_FILE_NAME + MAX_FILENAME_LEN - 1 2D45:A9 FF 057 LDA #$FF ; DELETED FILE MARKER ; magic number FILE_TYPE_DELETED 2D47:9D C6 34 058 STA VDFILE,X ; CLEAR ENTRY ; magic number VDFILE + CAT_FILE_TRACK 2D4A:BC C7 34 059 LDY VDFILE+1,X ; GET DIR SECTOR ; magic number VDFILE + CAT_FILE_SECTOR 2D4D:8C D2 35 060 STY DCBFDS ; SET AS 1ST FD SEC 2D50:20 37 30 061 JSR WRVDIR ; GO WRITE VOLUME DIR 2D53:18 062 CLC 2D54:20 5E 2F 063 FD4 JSR RDFDIR ; GET 1ST FILE DIR SECTOR 2D57:B0 2A 064 BCS FD7 ; BR IF NO MORE 2D59:20 0C 2F 065 JSR MVFCBD ; MOVE DIR TO ZPG 2D5C:A0 0C 066 LDY #FDENT ; POINT Y TO 1ST SEC ENT 2D5E:8C 9C 33 067 FD5 STY TEMP1 ; SAVE Y ; School of Commenting on Useless Observations 2D61:B1 42 068 LDA (ZPGFCB),Y ; GET REACK ; *spelling* Track 2D63:30 0B 069 BMI FD6 ; BR IF NONE 2D65:F0 09 070 BEQ FD6 ; BR IF END OF FILE 2D67:48 071 PHA ; SAVE TRK 2D68:C8 072 INY 2D69:B1 42 073 LDA (ZPGFCB),Y ; GET SECTOR 2D6B:A8 074 TAY ; TO Y 2D6C:68 075 PLA ; GET TRK 2D6D:20 89 2D 076 JSR FDSUB ; GO FREE SECTOR ; /sarcasm What? FREESECS wasn't available??? (It is but FRESEC is used) 2D70:AC 9C 33 077 FD6 LDY TEMP1 ; GET DIR INDEX 2D73:C8 078 INY ; INCR TO NEXT INDEX 2D74:C8 079 INY 2D75:D0 E7 080 BNE FD5 ; BR NOT DONE THIS DIR 2D77:AD D3 35 081 LDA DCBCDT ; GET THIS DIR TRK 2D7A:AC D4 35 082 LDY DCBCDS ; AND SECTOR 2D7D:20 89 2D 083 JSR FDSUB ; AND GO FREE IT 2D80:38 084 SEC ; GO 2D81:B0 D1 085 BCS FD4 ; READ NEXT DIR ; ↑ (always) 086 FD7 EQU * 2D83:20 FB 2F 087 JSR WRVTOC 2D86:4C 7F 33 088 JMP GOODIO 089 ; 090 FDSUB EQU * 2D89:38 091 SEC ; SET FOR REUSE OF SEC 2D8A:20 DD 32 092 JSR FRESEC ; GO FREE SECTOR 2D8D:A9 00 093 LDA #0 ; CLEAR DCB BIT MAP 2D8F:A2 05 094 LDX #5 ; CLEAR ALL OF TRK BITMAP SO ; magic number sizeof( DCBALS=1 + DCBATK=1 + DCBABM=4 ) = 6-1 = 5 095 * ;>16 SECTORS/TRK WILL WORK ; Assumes DCBALS DCBATK DCBABM are contiguous, should be: 4 + DCBABM - DCBALS - 1 2D91:9D F0 35 096 FDS1 STA DCBALS,X ; Intentional BUFFER OVERFLOW 2D94:CA 097 DEX ; 2D95:10 FA 098 BPL FDS1 ; 2D97:60 099 RTS 100 PAGE 101 ; 102 * RDIR - PRINT DIRECTORY ; "CATALOG" 103 ; 104 RDIR EQU * 2D98:20 DC 2B 105 JSR DCBSUP 2D9B:A9 FF 106 LDA #$FF 2D9D:8D F9 35 107 STA DCBVOL 2DA0:20 F7 2F 108 JSR RDVTOC 2DA3:A9 16 109 LDA #22 ; SET 21 LINES ;[.. wastes 1 bytes, JSR NewPage 2DA5:8D 9D 33 110 STA TEMP2 ; ..] 2DA8:20 2F 2E 111 JSR PRCR ; GO PRINT ; Should be JSR PRCR2 2DAB:20 2F 2E 112 JSR PRCR ; PRINT ANOTHER CHAR ; wastes 3 bytes 2DAE:A2 0B 113 LDX #VML ; VOLUME MSG LENGTH 2DB0:BD AF 33 114 RD0 LDA VOLMES,X ; GET MSG CHAR ; \ 2DB3:20 ED FD 115 JSR PRINT ; PRINT IT ; > More stupid commenting stating the obvious 2DB6:CA 116 DEX ; DECREMENT COUNT ; /
2DB7:10 F7 117 BPL RD0 ; BR IF MORE ; === Page 57 === 118 ; 2DB9:86 45 119 STX CNUM+1 ; X=0 → CNUM+1, clear high byte for printing 2DBB:AD F6 37 120 LDA IBSMOD ; MOVE VOL NO FOR 2DBE:85 44 121 STA CNUM ; CONVERSION 2DC0:20 42 2E 122 JSR PRNUM ; GO PRINT VOL NO 123 ; 2DC3:20 2F 2E 124 JSR PRCR ; PRINT CR ; Should be JSR PRCR2 2DC6:20 2F 2E 125 JSR PRCR ; AND AGAIN ; wastes 3 bytes 126 ; 2DC9:18 127 CLC ; FIRST RECORD 128 ; 2DCA:20 11 30 129 RD1 JSR RDVDIR ; GO READ REC 2DCD:B0 5D 130 BCS RD5 2DCF:A2 00 131 LDX #0 ; SET INDEX=0 2DD1:8E 9C 33 132 RD2 STX TEMP1 ; SAVE INDEX 2DD4:BD C6 34 133 LDA VDFILE,X ; GET TRACK ; magic number VDFILE + CAT_FILE_TRACK 2DD7:F0 53 134 BEQ RD5 ; BR IF END OF DIR 2DD9:30 4A 135 BMI RD4 ; BR IF DELETED 136 ; 2DDB:A0 A0 137 LDY #$A0 ; BLANK ; KEY_SPACE 2DDD:BD C8 34 138 LDA VDFILE+2,X ; GET TYPE ; magic number VDFILE + CAT_FILE_TYPE 2DE0:10 02 139 BPL RD2A ; BR IF NOT LOCKED 2DE2:A0 AA 140 LDY #'*'+$80 ; AST ; Asterisk, KEY_ASTERISK 2DE4:98 141 RD2A TYA ; ACU = AST OR BLANK 2DE5:20 ED FD 142 JSR PRINT ; PRINT ACU ; Character Out 143 ; 2DE8:BD C8 34 144 LDA VDFILE+2,X ; GET TYPE ; magic number VDFILE + CAT_FILE_TYPE 2DEB:29 7F 145 AND #$7F ; MASK OUT MISC ; magic number FILE_LOCKED_MASK 2DED:A0 07 146 LDY #7 ; SET INDEX = 7 ; Using a bit mask instead of a enumeration is dumb 2DEF:0A 147 ASL A ;GET RID OF HI BIT ; Instead of the simple 2DF0:0A 148 RD2B ASL A ; SHIFT OUT MSB ; LDX FILE_TYPE 2DF1:B0 03 149 BCS RD2C ; BR IF TYPE BIT OUT ; LDA CHAR_FILE_TYPE,X 2DF3:88 150 DEY ; DEC INDEX ; We waste 9 bytes 2DF4:D0 FA 151 BNE RD2B ; BR IF NOT ACC BITS 152 RD2C EQU * 2DF6:B9 A7 33 153 LDA FTTAB,Y ; GET TYPE CODE 2DF9:20 ED FD 154 JSR PRINT ; PRINT IT ; o7 Captain Obvious 2DFC:A9 A0 155 LDA #$A0 ; BLANK 2DFE:20 ED FD 156 JSR PRINT ; PRINT ; === T1SD === 157 ; ; NOT File length, this is Number of Sectors Allocated 2E01:BD E7 34 158 LDA VDFILE+33,X ; MOVE FILE LENGTH ; magic number VDFILE + CAT_FILE_NUM_SEC+0 2E04:85 44 159 STA CNUM 2E06:BD E8 34 160 LDA VDFILE+34,X ; MOVE FILE LENGTH ; magic number VDFILE + CAT_FILE_NUM_SEC+1 2E09:85 45 161 STA CNUM+1 2E0B:20 42 2E 162 JSR PRNUM ; GO PRINT NUMBER 2E0E:A9 A0 163 LDA #$A0 ; BLANK 2E10:20 ED FD 164 JSR PRINT ; PRINT 165 ; 2E13:E8 166 INX 2E14:E8 167 INX 2E15:E8 168 INX 2E16:A0 1D 169 LDY #29 ; magic number MAX_FILENAME-1 2E18:BD C6 34 170 RD3 LDA VDFILE,X ; GET CHAR 2E1B:20 ED FD 171 JSR PRINT ; PRINT CHAR 2E1E:E8 172 INX 2E1F:88 173 DEY 2E20:10 F6 174 BPL RD3 ;↑ 175 RD3A EQU * 2E22:20 2F 2E 176 JSR PRCR ; GO PRINT CR 2E25:20 30 32 177 RD4 JSR VDINC ; INCR INDEX 2E28:90 A7 178 BCC RD2 ; BR IF MORE IN DIR ;↑ 2E2A:B0 9E 179 BCS RD1 ; GO READ NEXT DIR ;↑ 180 ; 2E2C:4C 7F 33 181 RD5 JMP GOODIO ; DONE ;↓
182 ; ; === Page 58 === 183 PRCR EQU * 2E2F:A9 8D 184 LDA #$8D ; CR 2E31:20 ED FD 185 JSR PRINT ; PRINTED 2E34:CE 9D 33 186 DEC TEMP2 ; DEC LINE COUNT 2E37:D0 08 187 BNE PRCR1 ; BR IF NOT ZERO 2E39:20 0C FD 188 JSR GETKEY ; WAIT FOR INPUT 2E3C:A9 15 189 LDA #21 ; RESET LINE COUNTER ; magic number NewPage, Should read Text Window Height: (WNDBTM = $23) - (WNDTOP = $22) 2E3E:8D 9D 33 190 STA TEMP2 2E41:60 191 PRCR1 RTS ; DONE 192 PAGE 193 PRNUM EQU * ; Print 16-bit CNUM as 3 decimal digits with leading zeroes 2E42:A0 02 194 LDY #2 ; 3 DIGITS 2E44:A9 00 195 PRN1 LDA #0 ; INIT DIGIT TO ZERO 2E46:48 196 PHA ; SAVE IT 197 ; 2E47:A5 44 198 PRN2 LDA CNUM ; GET NUMBER 2E49:D9 A4 33 199 CMP CVTAB,Y ; IF NUM < CVTAB ENTRY ; Crap comment: What is CVTAB??? Is digit < power of 10 2E4C:90 12 200 BCC PRN3 ; THEN DONE THIS DIGIT ;↓ 201 ; 2E4E:F9 A4 33 202 SBC CVTAB,Y ; SUBTRACT TABLE ENTRY 2E51:85 44 203 STA CNUM 2E53:A5 45 204 LDA CNUM+1 2E55:E9 00 205 SBC #0 2E57:85 45 206 STA CNUM+1 2E59:68 207 PLA ; INCREMENT DIGIT 2E5A:69 00 208 ADC #0 2E5C:48 209 PHA 2E5D:4C 47 2E 210 JMP PRN2 ; TRY AGAIN ; wastes 1 byte, A is > 0, A < $80, BNE PRN2 211 ; 212 PRN3 EQU * 2E60:68 213 PLA ; GET DIGIT 2E61:09 B0 214 ORA #$B0 ; ADD ASCII 0 ; magic number #'0'+$80 or KEY_0 2E63:20 ED FD 215 JSR PRINT ; PRINT IT ; Gee I wonder what PRINT does ... 2E66:88 216 DEY ; DECREMENT DIGIT COUNT 2E67:10 DB 217 BPL PRN1 ; BR IF MORE DIGIT 218 ; 2E69:60 219 RTS ; DONE 220 PAGE 221 ; 222 * CLCFCB - GET FCB VIA INDEX AND MOVE IT ; You keep using this word move, it doesn't mean what you think it means 223 ; 224 CLCFCB EQU * ; /sarcasm Oh I see, CLC_FB is clearer then COPY_FCB 225 ; 2E6A:20 08 2F 226 JSR MVFCBP ; MOVE FCB PTR TO ZP 2E6D:A0 00 227 LDY #0 2E6F:8C C5 35 228 STY CCBSTA 2E72:B1 42 229 CF3 LDA (ZPGFCB),Y ; MOVE FCB TO 2E74:99 D1 35 230 STA FCB,Y ; FCB WORK AREA ; $B5BB 2E77:C8 231 INY 2E78:C0 2D 232 CPY #FCBLEN 2E7A:D0 F6 233 BNE CF3 234 ; 2E7C:18 235 CLC 2E7D:60 236 RTS 237 ; 238 * RTNFCB - MOVE FCB FROM WORK AREA TO FCB 239 ; 240 RTNFCB EQU * 2E7E:20 08 2F 241 JSR MVFCBP ; MOVE FCB ADR TO ZPG 242 ;
2E81:A0 00 243 LDY #0 ; === Page 59 === 2E83:B9 D1 35 244 RF1 LDA FCB,Y 2E86:91 42 245 STA (ZPGFCB),Y 2E88:C8 246 INY 2E89:C0 2D 247 CPY #FCBLEN 2E8B:D0 F6 248 BNE RF1 2E8D:60 249 RTS
001 PAGE 002 ; 003 * FFMT - Execute Format Request ; "INIT" 004 ; 005 FFMT EQU * 2E8E:20 DC 2B 006 JSR DCBSUP ; SET UP DCB 2E91:A9 04 007 LDA #IBFMT 2E93:20 58 30 008 JSR DCBIO2 2E96:AD F9 35 009 LDA DCBVOL 2E99:49 FF 010 EOR #$FF ; TODO Is this the reason why not possible to format with Volume=0 2E9B:8D C1 33 011 STA VVOLNO 2E9E:A9 11 012 LDA #17 ; magic number LDA VDIRTK; FILESYSTEM_VTOC_CAT_TRACK 2EA0:8D EB 33 013 STA VALCA1 ; ALOCATE BYTE 1 ; *spelling* Allocate; Crappy name, should be: ALLOC_TRK 2EA3:A9 01 014 LDA #1 ; +$01 inwards to T22 2EA5:8D EC 33 015 STA VALCA2 ; ADD BYTE 2 ; Crappy name, should be: ALLOC_DIR 016 ; 2EA8:A2 38 017 LDX #VSECAL-VTOC ; Skip VTOC header 2EAA:A9 00 018 LDA #0 2EAC:9D BB 33 019 NT1 STA VTOC,X ; CLEAR SECTOR AREA ; We only care about 4 tracks set to used: T0,T1,T2,T17 2EAF:E8 020 INX 2EB0:D0 FA 021 BNE NT1 022 ; 2EB2:A2 0C 023 LDX #3*4 ; START AT TRACK 3 ; Idiotic 4 bytes/track , magic number FIRST_EMPTY_TRACK 2EB4:E0 8C 024 NT2 CPX #35*4 ; END AT TRACK 35 ; instead of 2 bytes/trk, magic number LAST_EMPTY_TRACK 2EB6:F0 14 025 BEQ NT4 2EB8:A0 03 026 LDY #3 ; 4 BYTES OF INFO 2EBA:B9 A0 33 027 NT3 LDA ALC10S,Y ; 10 SECTORS ALLOCATE ; 16 ($10) sectors used bitmask: 0=free, 1=used 2EBD:9D F3 33 028 STA VSECAL,X 2EC0:E8 029 INX 2EC1:88 030 DEY 2EC2:10 F6 031 BPL NT3 2EC4:E0 44 032 CPX #17*4 ; AT TRACK 17 ; magic number FILESYSTEM_VTOC_CAT_TRACK * ALLOC_BYTE_PER_TRACK; 2EC6:D0 EC 033 BNE NT2 2EC8:A2 48 034 LDX #18*4 ; SKIP TO 18 2ECA:D0 E8 035 BNE NT2 ; ↑ (always) 036 ; 2ECC:20 FB 2F 037 NT4 JSR WRVTOC ; WRITE NEW VTOC 038 ; 2ECF:A2 00 039 LDX #0 2ED1:8A 040 TXA 2ED2:9D BB 34 041 NT5 STA VOLDIR,X ; CLEAR VOLDIR 2ED5:E8 042 INX 2ED6:D0 FA 043 BNE NT5 044 ; 2ED8:20 45 30 045 JSR MVVDBA ; MOVE BUF PTRS 046 ; 2EDB:A9 11 047 LDA #17 ; TRACK 17 ; magic number FILESYSTEM_VTOC_CAT_TRACK = $11 2EDD:AC F0 33 048 LDY VNOSEC ; S16 2EE0:88 049 DEY ; S15 CATALOG [0] 2EE1:88 050 DEY ; S14 CATALOG [1] 2EE2:8D EC 37 051 STA IBTRK ; INTO IOB 2EE5:8D BC 34 052 NT6 STA VDLTRK ; INTO LINK 2EE8:8C BD 34 053 NT7 STY VDLSEC ;
2EEB:C8 054 INY ; === Page 74 === 2EEC:8C ED 37 055 STY IBSECT 2EEF:A9 02 056 LDA #IBCWTS 2EF1:20 58 30 057 JSR DCBIO2 2EF4:AC BD 34 058 LDY VDLSEC 2EF7:88 059 DEY ; DECREMENT SECTOR 2EF8:30 05 060 BMI NT8 ; BR LAST WRITTEN 2EFA:D0 EC 061 BNE NT7 ; BR NOT LAST 2EFC:98 062 TYA ; lAST, SET LINK TRK=0 2EFD:F0 E6 063 BEQ NT6 ;↑ 064 ; 065 NT8 EQU * 2EFF:20 C2 37 066 JSR DLDSUP ; GO SET UP FOR DOSLDR ; === T1SE === 2F02:20 4A 37 067 JSR WBOOT ; GO WRITE THE BOOT 2F05:4C 7F 33 068 JMP GOODIO ; DONE 069 PAGE 070 ; 071 * MVFCBX - MOVE FCB ADRS TO ZPGFCB 072 ; 2F08:A2 00 073 MVFCBP LDX #0 ; MOVE FCB ADR ; magic number TODO 2F0A:F0 06 074 BEQ MVF1 ;↓ 2F0C:A2 02 075 MVFCBD LDX #2 ; MOVE FCB DIR BUFF ; magic number TODO 2F0E:D0 02 076 BNE MVF1 ;↓ wastes 1 byte, $2C bit $abs 2F10:A2 04 077 MVFCBS LDX #4 ; MOVE FCB SECTOR BUFF ; magic number TODO 078 ; 079 MVF1 EQU * 2F12:BD C7 35 080 LDA CFCBAD,X ; DO THE MOVE 2F15:85 42 081 STA ZPGFCB 2F17:BD C8 35 082 LDA CFCBAD+1,X 2F1A:85 43 083 STA ZPGFCB+1 2F1C:60 084 RTS 085 ; 086 PAGE 087 ; 088 * WRSECT - WRITE CURRENT SECTOR IF REQD 089 ; 090 WRSECT EQU * 2F1D:2C D5 35 091 BIT DCBWRF ; GET WRITE REQD FLAG 2F20:70 01 092 BVS WRSGO ; BR IF WRITE SECTOR REQD ; [.. Should be: BVC WRFDIR-1 2F22:60 093 RTS ; RTS ; o7 Captain Obvious is Obvious ..] wastes 1 byte with RTS 094 ; 095 WRGO EQU * 2F23:20 E4 2F 096 JSR MVSBA ; GO MOVE SECT BUFF ADR ; MoveSectorBufferAddress 097 ; 2F26:A9 02 098 LDA #IBCWTS ; GET COMMAND 2F28:20 52 30 099 JSR DCBIO ; GO FILL IN IOB AND DO IO 100 ; 2F2B:A9 BF 101 LDA #$BF ; SET WRITE SECTOR REQD BIT OFF ; magic number $BF = 1011_1111 FLAG_W_CUR_SECTOR EQU $40; LDA ~FLAG_W_CUR_SECTOR 2F2D:2D D5 35 102 AND DCBWRF 2F30:8D D5 35 103 STA DCBWRF 2F33:60 104 RTS ; DONE 105 PAGE 106 ; 107 * WRFDIR - WRITE FILE DIRECTRY IF REQD ; *spelling* Directory 108 ; 109 WRFDIR EQU * 2F34:AD D5 35 110 LDA DCBWRF ; GET WRITE REQD FLAG 2F37:30 01 111 BMI WRFDGO ; BR IF NOT DIR REQD ;[.. Should be: BPL WRFDIR-1 2F39:60 112 RTS ; ..] wastes 1 byte with RTS 113 ; 114 WRFDGO EQU * 2F3A:20 4B 2F 115 JSR MVFDBA ; Yet another crappy name. Quick what is the difference between: MVVDBA or MVFDBA ? 116 ; ; MoveFileDirectoryBufferAddress
2F3D:A9 02 117 LDA #IBCWTS ; GET WRITE CMD ; === Page 75 === 2F3F:20 52 30 118 JSR DCBIO ; GO FILL IN IOB AND DO I/O 119 ; 2F42:a9 7F 120 LDA #$7F ; TURN WRITE DIR REQD BIT OFF ; magic number $7F = 0111_1111 FLAG_W_FIL_SECTOR EQU $80; LDA ~FLAG_W_FIL_SECTOR 2F44:2D D5 35 121 AND DCBWRF 2F47:8D D5 35 122 STA DCBWRF 2F4A:60 123 RTS 124 ; 125 * MVFDBA - MOVE FILE DIRECTORY BUFF ASDR TO IOD 126 ; 127 MVFDBA EQU * 2F4B:AD C9 35 128 LDA CFCBDR ; MOVE ADR 2F4E:8D F0 37 129 STA IBBUFP 2F51:AD CA 35 130 LDA CFCBDR+1 2F54:8D F1 37 131 STA IBBUFP+1 2F57:AE D3 35 132 LDX DCBCDT ; GET TRACK 2F5A:AC D4 35 133 LDY DCBCDS ; GET SECTOR 2F5D:60 134 RTS 135 PAGE 136 ; 137 * RDFDIR - READ FILE DIRECTORY 138 ; 139 RDFDIR EQU * 2F5E:08 140 PHP ; SAVE STATUS 2F5F:20 34 2F 141 JSR WRFDIR ; GO WRITE CURRENT DIR IF REQD 2F62:20 4B 2F 142 JSR MVFDBA ; GO MOVE DBUFF ADR TO IOB 2F65:20 0C 2F 143 JSR MVFCBD ; MOVE DBUFF ADR TO ZPG 2F68:28 144 PLP ; GET SAVED STATUS 2F69:B0 09 145 BCS RFDNXT ; BR IF RD NEXT 146 ; 2F6B:AE D1 35 147 LDX DCBFDT ; GET TRACK ;DCBFDT != DCBCDT Line #132 2F6E:AC D2 35 148 LDY DCBFDS ; GET SECTOR ;DCBFDS != DCBCDS Line #133 2F71:4C B5 2F 149 JMP RFDIO1 ; GO READ 150 ; 151 RFDNXT EQU * 2F74:A0 01 152 LDY #FDLTRK ; GET LINK TRACK 2F76:B1 42 153 LDA (ZPGFCB),Y 2F78:F0 08 154 BEQ RFDNL ; NR NO LINK ; BUG: Can't have file on T0 BPL RFDNL 2F7A:AA 155 TAX ; PUT TRACK INTO X ; o7 Captain Obvious 2F7B:C8 156 INY 2F7C:B1 42 157 LDA (ZPGFCB),Y ; GET LINK SECTOR 2F7E:A8 158 TAY ; PUT SECTOR INTO Y 2F7F:4C B5 2F 159 JMP RFDIO1 ; GO DO I/O 160 ; 161 RFDNL EQU * ; Read File Dir Next Link 2F82:AD BB 35 162 LDA CCBREQ ; THIS A WRITE 2F85:C9 04 163 CMP #CRQWR 2F87:F0 02 164 BEQ RFDNL1 ; BR IF WRITE ; ↓ TODO Should be BNE ... 2F89:38 165 SEC ; SET EOF 2F8A:60 166 RTS ; RETURN ; o7 Captain Obvious 167 ; 168 RFDNL1 EQU * 2F8B:20 44 32 169 JSR GETSEC ; GET A SECTOR 2F8E:A0 02 170 LDY #FDLSEC ; 2F90:91 42 171 STA (ZPGFCB),Y ; PUT IN LINK 2F92:48 172 PHA ; SAVE SECTOR 2F93:88 173 DEY 2F94:AD F1 35 174 LDA DCBATK ; GET TRACK 2F97:91 42 175 STA (ZPGFCB),Y ; PUT IN LINK 2F99:48 176 PHA ; SAVE TRACK 2F9A:20 3A 2F 177 JSR WRFDGO ; Go WRITE OLD DIR DEC 178 ; 2F9D:20 D6 37 179 JSR CLRSEC ; CLEAN OUT DIR
2FA0:A0 05 180 LDY #FDFRS ; SET NEW DIR SEC 1ST REL ; === Page 76 === 2FA2:Ad DE 35 181 LDA DCBDNF ; FILE SECTOR 2FA5:91 42 182 STA (ZPGFCB),Y 2FA7:C8 183 INY 2FA8:AD DF 35 184 LDA DCBDNF+1 2FAB:91 42 185 STA (ZPGFCB),Y 186 ; 2FAD:68 187 PLA ; GET SAVED TRACK 2FAE:AA 188 TAX ; INFO X 2FAF:68 189 PLA ; GET SAVED TRACK 2FB0:A8 190 TAY ; INFO Y 2FB1:A9 02 191 LDA #IBCWTS ; SET WRITE CMD 2FB3:D0 02 192 BNE RFDIO2 ; GO DO I/O 193 ; 2FB5:A9 01 194 RFDIO1 LDA #IBCRTS ; SET READ CMD 2FB7:8E D3 35 195 RFDIO2 STX DCBCDT ; SET CURR TRACK 2FBA:8C D4 35 196 STY DCBCDS ; SET CUR SECTOR 2FBD:20 52 30 197 JSR DCBIO ; GO I/O 198 ; 2FC0:A0 05 199 RDFDC LDY #FDFRS ; GET POINTER TO FIRST REL SECTOR 2FC2:B1 42 200 LDA (ZPGFCB),Y ; GET FRS ; First Relative Sector 2FC4:8D DC 35 201 STA DCBDFS ; SET INTO DCB 2FC7:18 202 CLC 2FC8:6D DA 35 203 ADC DCBDMS ; ADD MAX SECTORS 2FCB:8D DE 35 204 STA DCBDNF ; PUT INTO DCB 205 ; 2FCE:C8 206 INY ; DO SAME FOR HI BYTE 2FCF:B1 42 207 LDA (ZPGFCB),Y 2FD1:8D DD 35 208 STA DCBDFS+1 2FD4:6D DB 35 209 ADC DCBDMS+1 2FD7:8D DF 35 210 STA DCBDNF+1 211 ; 2FDA:18 212 CLC 2FDB:60 213 RTS ; DONE 214 PAGE 215 ; 216 ;RDSECT - READ A SECTOR 217 ; 218 RDSECT EQU * ; X = Track, Y = Sector 2FDC:20 E4 2F 219 JSR MVSBA ; GO MOVE SECTOR BUFFER ADR 220 ; 2FDF:A9 01 221 LDA #IBCRTS 2FE1:4C 52 30 222 JMP DCBIO ; GO DO I/O ; wastes 1 byte, BNE DCBIO ($3052 - $2FE3 = $6F < $80) 223 ; 224 ;MVSBA - MOVE SECTOR BUFFER ADR FOR I/O 225 ; 226 MVSBA EQU * 2FE4:AC CB 35 227 LDY CFCBSB ; GET SECTOR BUFF ADR 2FE7:AD CC 35 228 LDA CFCBSB+1 2FEA:8C F0 37 229 MSB1 STY IBBUFP ; SET IOB SECTOR 2FED:8D F1 37 230 STA IBBUFP+1 ; BUFF PTR 2FF0:AE D6 35 231 LDX DCBTRK ; GET TRACK 2FF3:AC D7 35 232 LDY DCBSEC ; GET SECTOR 2FF6:60 233 RTS ; RTN
001 PAGE 002 ; 003 ;RDVTOC - READ VTOC 004 ;WRVTOC - WRITE VTOC 005 ; 006 RDVTOC EQU * 2FF7:A9 01 007 LDA #IBCRTS ; READ 2FF9:D0 02 008 BNE VTIO ; wastes 1 byte, FIX: HEX 2C bit $abs 009 WRVTOC EQU * 2FFB:A9 02 010 LDA #IBCWTS ; WRITE 011 ; 2FFD:AC C3 2A 012 VTIO LDY AVTOC ; MOVE BUFF ADR 3000:8C F0 37 013 STY IBBUFP ; === T1SF === $B000 3003:AC C4 2A 014 LDY AVTOC+1 3006:8C F1 37 015 STY IBBUFP+1 016 ; 3009:AE FA 35 017 LDX DCBVTN ; GET TRACK ; $B5FA = VTN = VTOC Track Number = $11 300C:A0 00 018 LDY #0 ; VTOC Sector Number = $0 magic number FILESYSTEM_VTOC_SECTOR EQU 0 300E:4C 52 30 019 JMP DCBIO ; GO DO I/O ; wastes 1 byte, FIX: BPL DCBIO ↓ (always) 020 PAGE 021 ; 022 ;RDVDIR - READ VOLUME DIRECTOR 023 ; 024 RDVDIR EQU * 3011:08 025 PHP ; SAVE STATUS 3012:20 45 30 026 JSR MVVDBA 027 ; 3015:28 028 PLP ; GET STATUS 3016:B0 08 029 BCS RVDA ; BR IF R0 NEXT 030 ; 3018:AC BD 33 031 RVDC LDY VDIRSC ; READ 1ST SECTOR 301B:AE BC 33 032 LDX VDIRTK ; GET FIRST TRK 301E:D0 0A 033 BNE RVDGO ; GO READ ; BUG: Catalog can't be on T0, FIX: BPL RVDGO 034 ; 035 RVDA EQU * 3020:AE BC 34 036 LDX VDLTRK ; GET LINK TRACK 3023:D0 02 037 BNE RDVC ; BR IF A LINK ; BUG: Catalog can't be on T0, FIX: BPL RDVC 3025:38 038 SEC ; SET END OF DIR 3026:60 039 RTS 040 ; 3027:AC BD 34 041 RDVC LDY VDLSEC ; GET SECTOR ; Volume Directory Link Sector 042 RDVDGO EQU * 302A:8E 97 33 043 STX CVDTRK ; SET CUR TRACK 302D:8C 98 33 044 STY CVDSEC ; SET CUR SECTOR 3030:A9 01 045 LDA #IBCRTS ; GET CMD ; No shit Sherlock Q. Which command? A. ReadTrackSector 3032:20 52 30 046 JSR DCBIO ; GO DO I/O 3035:18 047 CLC 3036:60 048 RTS 049 PAGE 050 ; 051 ;WRVDIR - WRITE VOLUME DIRECTORY SECTOR 052 ; 053 WRVDIR EQU *
3037:20 45 30 054 JSR MVVDBA ; === 64 === 055 ; 303A:AE 97 33 056 LDX CVDTRK ; CURRENT TRACK 303D:AC 98 33 057 LDY CVDSEC ; CURRENT SECTOR 3040:A9 02 058 LDA #IBCWTS ; WRITE COMMAND 3042:4C 52 30 059 JMP DCBIO ; GO DO I/O ; wastes 1 byte, BNE DCBIO ↓ (always) 060 ; 061 ; MVVDBA - MOVE VOL DIR BUF ADR TO IOB 062 ; 063 MVVDBA EQU * 3045:AD C5 2A 064 LDA AVOLDR 3048:8D F0 37 065 STA IBBUFP 304B:AD C6 2A 066 LDA AVOLDR+1 304E:8D F1 37 067 STA IBBUFP+1 3051:60 068 RTS 069 PAGE 070 ; 071 ;DCBIO - DO I/O FOR A DCB ; Prologue should be: 072 ; ; LDA #IBCWTS 073 DCBIO EQU * 3052:8E EC 37 074 STX IBTRK ; TRACK ; As this is called from Page 74 and 75 3055:8C ED 37 075 STY IBSECT ; SECTOR 076 DCBIO2 EQU * 3058:8D F4 37 077 STA IBCMD ; COMMAND 305B:C9 02 078 CMP #IBCWTS 305D:D0 06 079 BNE DCBIO1 ; Read 305F:0D D5 35 080 ORA DCBWRF 3062:8D D5 35 081 STA DCBWRF 082 DCBIO1 EQU * ; *Sigh* Couldn't list DCBI01 then DCBI02?? ; *Double Sigh* Perfect example why a var shouldn't contain both I and 1. ; Better names would be: DCB_IOa DCB_IOb 3065:AD F9 35 083 LDA DCBVOL ; VOL ;[..wastes 2 bytes 3068:49 FF 084 EOR #$FF ; UNINVERT VOL BITS ; .. 0. Why was it inverted in the first place??? 306A:8D EB 37 085 STA IBVOL ; .. 1. More crappy names; Since DCB and IB are used all the time, 306D:AD F7 35 086 LDA DCBSLT ; SLOT ; .. a single letter prefix with an underscore '_' would 3070:8D E9 37 087 STA IBSLOT ; .. a) improve readability significantly, and 3073:AD F8 35 088 LDA DCBDRV ; DRIVE ; .. b) require less typing to boot 3076:8D EA 37 089 STA IBDRVN ; .. Compare and constrast the two: 3079:AD E2 35 090 LDA DCBSDL ; LENGTH ; .. D_SLOT DCBSLT 307C:8D F2 37 091 STA IBDLEN ; .. I_SLOT IBSLOT 307F:AD E3 35 092 LDA DCBSDL+1 ; .. 2. Note: Length is 16-bit 3082:8D F3 37 093 STA IBDLEN+1 ; ..] 3. Over-engineered memcpy() to marshall DCB to/from IOB ; Due to the contiguous layout (/saracasm Who knew!) ; ; [26] DCBSLT <-> [1] IBSLOT ; [27] DCBDRV <-> [2] IBDRVN ; [28] DCBVOL <-> [3] IBVOL ; ; This entire mem copy can be simplified: (18 vs 20 org. bytes) ; LDX #0 ; DCB2IOB LDA DCBSLT,X ; STA IBSLOT,X ; INX ; CPX #IBVOL-IBSLOT ; copy 3 fields (3 bytes) ; BNE DCB2IOB ; EOR #$FF ; Invert Volume ; STA IBSLOT,X ; ; If we didn't have the bad design of DCBSDL ; being not contiguous with the above 3 fields, ; ; [11] DCBSDL != [A] IBDLEN ; ; Which should be: ; ; [24] DCBSDL <-> [0] IBDLEN ; ; Then we could instead have: ; ; LDX #0 ; DCB2IOB LDA DCBSDL,X ; STA IBDLEN,X ; INX ; CPX #IBVOL-IBDLEN ; copy 4 fields (5 bytes) ; EOR #$FF ; Invert Volume ; STA IBSLOT,X ; ; Also, if we didn't have to deal with that stupid VOLUME EOR #$FF ; It could be simplified even more: (11 bytes vs 32bytes!) ; ; LDX #IBVOL-IBDLEN ; copy 4 fields (5 bytes) ; DCB2IOB LDA DCBSLT,X ; STA IBSLOT,X ; DEX ; BPL DCB2IOB ; 3085:A9 01 094 LDA #1 ; IOB TYPE ;[.. wastes 5 bytes, magic number IOB_OFFSET_TYPE 3087:8D E8 37 095 STA IBTYPE ; ..] never referenced! 096 ; 308A:AC C1 2A 097 LDY AIOB 308D:AD C2 2A 098 LDA AIOB+1 3090:20 B5 37 099 JSR DISKIO 100 ; 3093:AD F6 37 101 LDA IBSMOD ; Hack 3096:8D BF 35 102 STA CCBVOL 3099:A9 FF 103 LDA #$FF ; RESET VOL 309B:8D EB 37 104 STA IBVOL 309E:B0 01 105 BCS BADIO ; BR IF BAD 30A0:60 106 RTS ; RTN IF GOOD 107 ; 30A1:AD F5 37 108 BADIO LDA IBSTAT ; GET STATUS 30A4:A0 07 109 LDY #CREVMM 30A6:C9 20 110 CMP #IBVMME ; WAS IT VOLUME MISMATCH 30A8:F0 08 111 BEQ BD2 ; BR IF YES 30AA:A0 04 112 LDY #CREPRO 30AC:C9 10 113 CMP #IBWPER 30AE:F0 02 114 BEQ BD2 30B0:A0 08 115 LDY #CREIOE 30B2:98 116 BD2 TYA
30B3:4C 85 33 117 JMP ERRROB ; === 65 === 118 PAGE 119 ; 120 ;LOCNXB - LOCATE NEXT BYTE 121 ; 122 LOCNXB EQU * 30B6:AD E4 35 123 LDA DCBCRS ; IS THE CURRENT RELATIVE SECTOR 30B9:CD E0 35 124 CMP DCBCMS ; EQUAL TO THE CURRENT MEM SECTOR 30BC:D0 08 125 BNE LNB1 ; BR IF NOT EQ 30BE:AD E5 35 126 LDA DCBCRS+1 30C1:CD E1 35 127 CMP DCBCMS+1 30C4:F0 66 128 BEQ LNB8 ; BR IF REQD SECTOR IN MEM 129 ; 130 LNB1 EQU * ; NEED A DIFFERENT SECTOR IN MEM 30C6:20 1D 2F 131 JSR WRSECT ; GO WRITE SECTOR (IF REQD) 132 ; 30C9:AD E5 35 133 LNB2 LDA DCBCRS+1 ; IS CURRENT REL SECTORY 30CC:CD DD 35 134 CMP DCBDFS+1 ; IN CURRENT DIRECTORY (LOW LIMIT) 30CF:90 1C 135 BCC LNB4 ; BR IF IN A PREVIOUS DIR 30D1:D0 08 136 BNE LNB3 ; BR IF MAYBE IN THIS ONE 30D3:AD E4 35 137 LDA DCBCRS ; TEST LOW BYTES 30D6:CD DC 35 138 CMP DCBDFS 30D9:90 12 139 BCC LNB4 ; BR IF IN PREVIOUS DIR 140 ; 30DB:AD E5 35 141 LNB3 LDA DCBCRS+1 ; CURRENT REL SECTOR 30DE:CD DF 35 142 CMP DCBDNF+1 ; IN CURRENT DIRECTOR (HI LIMIT) 30E1:90 10 143 BCC LNB6 ; BR IF IN THIS ONE 30E3:D0 08 144 BNE LNB4 30E5:AD E4 35 145 LDA DCBCRS 30E8:CD DE 35 146 CMP DCBDNF 30EB:90 06 147 BCC LNB6 148 ;REQD SECTOR IN A NEXT DIRECTORY 30ED:20 5E 2F 149 LNB4 JSR RDFDIR 30F0:90 D7 150 BCC LNB2 30F2:60 151 RTS 152 ; 153 ; 154 LNB6 EQU * ; CALCULATE DISPL INTO DIR 30F3:38 155 SEC 30F4:AD E4 35 156 LDA DCBCRS ; 30F7:ED DC 35 157 SBC DCBDFS 30FA:0A 158 ASL A ; TIMES 2 30FB:69 0C 159 ADC #FDENT ; PLUS DISPL TO 1ST 30FD:A8 160 TAY 30FE:20 0C 2F 161 JSR MVFCBD ; MOVE DIR ADR TO ZPG 3101:B1 42 162 LDA (ZPGFCB),Y ; GET TRACK 3103:D0 0F 163 BNE LNB7 ; BR IF NOT ZERO ; should be BPL, Filesystem Design FLAW: Can't store data on Track 0 3105:AD BB 35 164 LDA CCBREQ 3108:C9 04 165 CMP #CRQWR ; WRITE! 310A:F0 02 166 BEQ LNB7A 310C:38 167 SEC 310D:60 168 RTS 310E:20 34 31 169 LNB7A JSR GNWSEC ; GO GET A NEW SECTOR ; A=C0 3111:4C 20 31 170 JMP LNBCON ;↓ wastes 1 byte 1 byte, BNE LNBCON 3114:8D D6 35 171 LNB7 STA DCBTRK ; SET TRK INTO DCB 3117:C8 172 INY 3118:B1 42 173 LDA (ZPGFCB),Y ; GET SECTOR 311A:8D D7 35 174 STA DCBSEC ; PUT INTO DCB 311D:20 DC 2F 175 JSR RDSEC ; GO READ SECTOR 3120:AD E4 35 176 LNBCON LDA DCBCRS ; MOVE CUR REL SECTOR 3123:8D E0 35 177 STA DCBCMS 3126:AD E5 35 178 LDA DCBCRS+1 ; TO CUR MEM SECTOR 3129:8D E1 35 179 STA DCBCMS+1
180 ; ; === 66 === 181 LNB8 EQU * 312C:20 10 2F 182 JSR MVFCBS ; MOVE SECTOR BUFF ADR TO ZP 312F:AC E6 35 183 LDY DCBCSB ; GET SECT BYTE 3132:18 184 CLC ; CARRY CLEAR = ALL OK 3133:60 185 RTS ; DONE 186 PAGE 187 ; 188 ; 189 GNWSEC EQU * ; NEED NEW SECTOR 3134:8C 9D 33 190 STY TEMP2 ; SAVE DIR INDEX 3137:20 44 32 191 JSR GETSEC ; GET A SECTOR 313A:AC 9D 33 192 LDY TEMP2 313D:C8 193 INY 313E:91 42 194 STA (ZPGFCB),Y ; SET NEW SECTOR 3140:8D D7 35 195 STA DCBSEC 3143:88 196 DEY 3144:AD F1 35 197 LDA DCBATK ; Allocated track? 3147:91 42 198 STA (ZPGFCB),Y ; SET NEW TRACK 3149:8D D6 35 199 STA DCBTRK 200 ; 314C:20 10 2F 201 JSR MVFCBS 314F:20 D6 37 202 JSR CLRSEC ; GO CLEAR SECTOR 203 ; 204 ; 3152:A9 C0 205 LDA #$C0 ; INDICATE BOTH ; magic number WRITE_FLAG_SECTOR | WRITE_FLAG_DIR 3154:0D D5 35 206 ORA DCBWRF ; DIR AND SECTOR ; TODO DIRECTORY or DIRECTION ??? 3157:8D D5 35 207 STA DCBWRF ; MUST BE WRITTEN 315A:60 208 RTS ; DONE ; For the love of god, WHY do you keep stating the obvious??? 209 PAGE 210 ; 211 ;INCRRB - INCREMENT RELATIVE RECORD BYTE 212 ; 213 INCRRB EQU * 315B:AE EA 35 214 LDX DCBCRR ; MOVE BYTE JUST READ OR WRITTEN 315E:8E BD 35 215 STX CCBRRN 3161:AE EB 35 216 LDX DCBCRR+1 3164:8E BE 35 217 STX CCBRRN+1 3167:AE EC 35 218 LDX DCBCRB ; X=REL BYTE (LOW) 316A:AC ED 35 219 LDY DCBCRB+1 ; Y=REL BYTE HI 316D:8E BF 35 220 STX CCBBYT 3170:8C C0 35 221 STY CCBBYT+1 3173:E8 222 INX ; INC REL BYTE (LOW) 3174:D0 01 223 BNE INCR1 ; BR IF NO CARRY 3176:C8 224 INY 225 ; 3177:CC E9 35 226 INCR1 CPY DCBRCL+1 ; REL BYTE=REC LENGTH 317A:D0 11 227 BNE INCR2 ; BR IF NOT 317C:EC E8 35 228 CPX DCBRCL 317F:D0 0C 229 BNE INCR2 3181:A2 00 230 LDX #0 3183:A0 00 231 LDY #0 ; RESET REL BYTE TO ZERO 3185:EE EA 35 232 INC DCBCRR ; AND INCR 3188:D0 03 233 BNE INCR2 ; RELATIVE RECORD 318A:EE EB 35 234 INC DCBCRR+1 235 ; 318D:8E EC 35 236 INCR2 STX DCBCRB ; SAVE NEW RELATIVE BYTE 3190:8C ED 35 237 STY DCBCRB+1 238 ; 3193:60 239 RTS 240 PAGE 241 ; 242 ;INCSCB - INCREMENT SECTOR BYTE
243 ; ; === 67 === 244 INCSCB EQU * 3194:EE E6 35 245 INC DCBCSB ; INC SECTOR BYTE 3197:D0 08 246 BNE INCS2 ; BR IF NOT FULL 3199:EE E4 35 247 INC DCBCRS ; AND INCR 319C:D0 03 248 BNE INCS2 ; RELATIVE SECTOR 319E:EE E5 35 249 INC DCBCRS+1 250 ; 251 ; 252 INCS2 EQU * 31A1:60 253 RTS 254 PAGE 255 ; 256 ;MIBDA - MOVE AND INCREMENT CCBDAT 257 ; 258 MIBDA EQU * 31A2:AC C3 35 259 LDY CCBBBA ; Y=ADR LOW 31A5:AE C4 35 260 LDX CCBBBA+1 ; X=ADR HI 31A8:84 42 261 STY ZPGFCB ; PUT ADR INTO ZPG 31AA:86 43 262 STX ZPGFCB+1 263 ; 31AC:EE C3 35 264 INC CCBBA ; INC ADR LOW 31AF:D0 03 265 BNE MIB1 ; BR IF NOT ZERO 31B1:EE C4 35 266 INC CCBBA+1 ; DONE 31B4:60 267 MIB1 RTS ; DONE 268 ; 269 ;DTBLN - DECREMENT BLONG LENGTH AND TEST ZERO 270 ; 271 DTBLN EQU * 31B5:AC C1 35 272 LDY CCBBLN ; GET LEN LOW 31B8:D0 08 273 BNE DTB1 ; BR IF NOT ZERO ; No shit Caption Obvious! 31BA:AE C2 35 274 LDX CCBBLN+1 ; GET LEN HI 31BD:F0 07 275 BEQ DTB2 ; BR IF LEN=0 31BF:CE C2 35 276 DEC CCBBLN+1 ; DEC LEN (HIGH) 31C2:CE C1 35 277 DTB1 DEC CCBBLN ; DEC LEN (LOW) 31C5:60 278 RTS ; DONE 279 ; 31C6:4C 7F 33 280 DTB2 JMP GOODIO ; FINISHED BLOCK
001 PAGE 002 ; 003 ;FNDFIL - FIND FILE NAME IN VOLUUME DIR ; *spelling* VOLUME 004 ; 005 FNDFIL EQU * 31C9:20 F7 2F 006 JSR RDVTOC ; GO GET VTOC 31CC:AD C3 35 007 LDA CCBFN ; MOVE FN PTR 31CF:85 42 008 STA ZPGFCB ; TO ZERO PAGE 31D1:AD C4 35 009 LDA CCBFN+1 31D4:85 43 010 STA ZPGFCB+1 31D6:A9 01 011 LDA #1 ; *sigh* magic number TODO 31D8:8D 9D 33 012 FF1 STA TEMP2 31DB:A9 00 013 LDA #0 31DD:8D D8 35 014 STA DCBVDR 31E0:18 015 CLC 016 FF2 EQU * 31E1:EE D8 35 017 INC DCBVDR ; 31E4:20 11 30 018 JSR RDVDIR ; GO GET VDIR SECTOR 31E7:B0 51 019 BCS FF4A ;↓ 31E9:A2 00 020 LDX #0 ; SET FOR 1ST FILE 021 ; 31EB:8E 9C 33 022 FF3 STX TEMP1 ; SAVE INDEX 31EE:BD C6 34 023 LDA VDFILE,X ; GET FILE TRK 31F1:F0 1F 024 BEQ FF6 ; BR IF LAST ENTRY ;↓ TODO NTODAFS can't store data on track 0; Should be NOP NOP 31F3:30 22 025 BMI FF7 ; BR IF DELETED ENTRY ;↓ 31F5:A0 00 026 LDY #0 ; X=X+3 31F7:E8 027 INX 31F8:E8 028 INX 31F9:E8 029 FF4 INX 31FA:B1 42 030 LDA (ZPGFCB),Y ; GET FN CHAR 31FC:DD C6 34 031 CMP VDFILE,X ; COMPARE TO ENTRY CHAR 31FF:D0 0A 032 BNE FF5 ; BR IF NOT SAME ;↓ 3201:C8 033 INY 3202:C0 1E 034 CPY #30 ; ALL 30 CHARS ; magic number FILENAME_MAX 3204:D0 F3 035 BNE FF4 ; BR IF NOT ;↑ 3206:AE 9C 33 036 LDX TEMP1 ; GET INDEX 3209:18 037 CLC ; FILE FOUND 320A:60 038 RTS ; RETURN 039 ; 040 FF5 EQU * 320B:20 30 32 041 JSR VDINC 320E:90 DB 042 BCC FF3 ;↑ 3210:B0 CF 043 BCS FF2 ;↑ 044 ; 3212:AC 9D 33 045 FF6 LDY TEMP2 ; LOOKING FOR DELETED ; *sigh* Found Last Catalog Entry 3215:D0 C1 046 BNE FF1 ; BR IF NOT (DO) ;↑ (always?) This is why you don't use crappy function names 047 ; ; that only differ by one digit 3217:AC 9D 33 048 FF7 LDY TEMP2 ; LOOKING FOR EMPTY ; *sigh* Found Deleted 321A:D0 EF 049 BNE FF5 ; BR IF NOT ;↑ (always?) 050 ; 051 MVN EQU * 321C:A0 00 052 LDY #0 ; HAVE NEW ENTRY 321E:E8 053 INX
321F:E8 054 INX ; === 69 === 3220:E8 055 FF8 INX 3221:B1 42 056 LDA (ZPGFCB),Y ; MOVE FILENAME 3223:9D C6 34 057 STA VDFILE,X 3226:C8 058 INY 3227:C0 1E 059 CPY #30 ; magic number FILENAME_MAX 3229:D0 F5 060 BNE FF8 ;↑ 061 ; 322B:AE 9C 33 062 LDX TEMP1 ; GET INDEX 322E:38 063 SEC ; TODO PASS? FAIL? 322F:60 064 RTS 065 VDINC EQU * 3230:18 066 CLC 3231:AD 9C 33 067 LDA TEMP1 ; pCatalog++; 3234:69 23 068 ADC #35 ; magic number FILENAME_ENTRY_SIZE 3236:AA 069 TAX 3237:E0 F5 070 CPX #VDFLEN 3239:60 071 RTS 072 FF4A EQU * 323A:A9 00 073 LDA #0 323C:AC 9D 33 074 LDY TEMP2 ; /cynical What? Can't do FILE_ENTRY_OFFSET = TEMP2 323F:D0 97 075 BNE FF1 ; 3241:4C 77 33 076 JMP ERROR9 ; NOT EM9: I/O ERROR, but CRENSA → "NO SECTORS AVAILABLE" 077 PAGE 078 ; 079 ;GETSEC - GET A SECTOR 080 ; 081 GETSEC EQU * 3244:AD F1 35 082 LDA DCBATK ; GET ALLOCATED TRK 3247:F0 21 083 BEQ GSS1 ; BR IF NONE ; DESIGN FLAW: Can't store file on track 0 ! 084 ; 085 GS0 EQU * 3249:CE F0 35 086 DEC DCBALS ; DECREMENT SECTOR NO 324C:30 17 087 BMI CS2 ; BR IF NO SECTORS REM 088 ; 324E:18 089 CLC 324F:A2 04 090 LDX #4 ; 4 BYTE SHIFT ; TODO magic number sizeof( DCBABM ), See: ALC10S) 3251:3E F1 35 091 GS1 ROL DCBABM-1 ; SHIFT BYTE LEFT ; ??? 3254:CA 092 DEX 3255:D0 FA 093 BNE GS1 3257:90 F0 094 BCC GS0 095 ; 3259:EE EE 35 096 INC DCBNSA 325C:D0 03 097 BNE GS1A ;↓ 325E:EE EF 35 098 INC DCBNSA+1 3261:AD F0 35 099 GS1A EQU * 3264:60 100 LDA DCBALS ; GET ALLOCATED SECTOR 101 RTS ; RETURN 102 ; 3265:A9 00 103 CS2 LDA #0 ; CLEAR ALLOCATED 3267:8D F1 35 104 STA DCBATK ; TRK 105 ; 326A:A9 00 106 GSS1 LDA #0 ; SET SEARCH STATE=0 326C:8D 9E 33 107 LDA TEMP3 326F:20 F7 2F 108 JSR RDVTOC ; GET VTOC 109 ; 110 GS2 EQU * 3272:18 111 CLC 3273:AD EB 33 112 LDA VALCA1 ; GET LAST ALLOCATED TRK 3276:6D EC 33 113 ADC VALCA2 ; AD (+1) OR (-1) 3279:F0 09 114 BEQ GS3 ; BR IF DECK TO ZERO ; TODO Can't allocate data on Track 0 327B:CD EF 33 115 CMP VNOTRK 327E:90 14 116 BCC GS5 ; BR IF NOT AT OUTER LIMIT
3280:A9 FF 117 LDA #$FF ; SET (-1) ; === Page 70 === 3282:D0 0A 118 BNE GS4 ;↓ Allways 3284:AD 9E 33 119 GS3 LDA TEMP3 ; GET SEARCH STATE 3287:D0 37 120 BNE ERR9 ; BR IF NOT ZERO 3289:A9 01 121 LDA #1 ; SET (+1) 328B:8D 9E 33 122 STA TEMP3 ; SET SEARCH SATE = 1 328E:8D EC 33 123 GS4 STA VALCA2 ; SET NEW (+1) OR (-1) 3291:18 124 CLC 3292:69 11 125 ADC #17 ; ADD VTOC TRK NO ; magic number CAT_FILE_TRACK, FILESYSTEM_VTOC_CAT_TRACK = $11 3294:8D EB 33 126 GS5 STA VALCA1 ; SET NEW LAST ALLOCATED 3297:8D F1 35 127 STA DCBATK ; PUT IN DCB 128 ; 329A:A8 129 TAY ; ALLOCATED TRACK 329B:0A 130 ASL A ; TIME 4 ; HARD-CODED 4 bytes/VTOC 329C:0A 131 ASL A 329D:A8 132 TAY ; See HNTDAFS #3 Wastes 4 bytes/track for free sector bitmap, sizeof( DCBABM ) 329E:A2 04 133 LDX #4 ; magic number VTOC_BITMAP_BYTES_PER_TRACK = sizeof(DCBABM), See: ALC10S 32A0:18 134 CLC 32A1:B9 F6 33 135 GS6 LDA VSECAL+3,Y ; MOVE BIT MAP BYTE 32A4:9D F1 35 136 STA DCBABM-1,X 32A7:F0 06 137 BEQ GS7 ; BR IF NO BITS ON 32A9:38 138 SEC ; SET HAVE SECTOR 32AA:A9 00 139 LDA #0 ; CLEAR VTOC BYTE 32AC:99 F6 33 140 STA VSECAL+3,Y 32AF:88 141 GS7 DEY 32B0:CA 142 DEX 32B1:D0 EE 143 BNE GS6 ; BR IF MORE TO MOVE 32B3:90 BD 144 BCC GS2 32B5:20 FB 2F 145 JSR WRVTOC ; GO WRITE VTOC 32B8:AD F0 33 146 LDA VNOSEC ; GET NO SECTORS 32BB:8D F0 35 147 STA DCBALS ; SET IN DCB SECTOR BYTE 32BE:D0 89 148 BNE GS0 ; GO ALLOCATED SECTOR ;↑ 32C0:4C 77 33 149 GS8 JMP ERROR9 150 PAGE 151 ; 152 ;FRETRK - FREE TRACK OF SECTORS 153 ; 154 FRETRK EQU * 32C3:AD F1 35 155 LDA DCBATK ; GET ALLOCATED TRACK 32C6:D0 01 156 BNE FT1 ; BR IF NONE ;↓ DESIGN FLAW: Can't store data on track 0, TODO 32C8:60 157 RTS 32C9:48 158 FT1 PHA 32CA:20 F7 2F 159 JSR RDVTOC ; GET VTOC 32CD:AC F0 35 160 LDY DCBALS ; GET SECTORS 32D0:68 161 PLA ; GET TRACK 32D1:18 162 CLC ; SET FREE 32D2:20 DD 32 163 JSR FRESEC ; GO FREE 32D5:A9 00 164 LDA #0 ; CLEAR ALLOCATED TRK 32D7:8D F1 35 165 STA DCBATK 32DA:4C FB 2F 166 JMP WRVTOC ; WRITE VTOC 167 ; 168 ;FRESEC - FREE A SECTOR 169 ;A=TRK, Y=SECTOR, C=ON/OFF 170 ; 171 FRESEC EQU * 32DD:A2 FC 172 FS1 LDX #252 ; 4 BYTE SHIFT ; magic number 256 - sizeof(DCBABM), See: ALC10S 32DF:7E F6 34 173 FS2 ROR DCBABM-252 ; SHIFT IN CARRY 32E2:E8 174 INX ; NEXT BYTE 32E3:D0 FA 175 BNE FS2 ; BR IF NOT DONE 32E5:C8 176 INY ; INC SECTOR NO 32E6:CC F0 33 177 CPY VNOSEC ; NORMAL 32E9:D0 F2 178 BNE FS1 ; BR IF NOT 179 ;
32EB:0A 180 ASL A ; TRACK*4 ; === Page 71 === 32EC:0A 181 ASL A 32ED:A8 182 TAY 32EE:F0 0F 183 BEQ FS4 ; See HNTDAFS #3 Wastes 4 bytes/track for free sector bitmap, sizeof( DCBABM ) 32F0:A2 04 184 LDX #4 ; magic number VTOC_BITMAP_BYTES_PER_TRACK, See: ALC10S 32F2:BD F1 35 185 FS3 LDA DCBABM-1,X ; GET BIT MAP BYTE 32F5:19 F6 33 186 ORA VSECAL+3,Y ; OR WITH VTOC BM 32F8:99 F6 33 187 STA VSECAL+3,Y 32FB:88 188 DEY 32FC:CA 189 DEX 32FD:D0 F3 190 BNE FS3 32FF:60 191 FS4 RTS ; DONE 192 PAGE 193 ; 194 ;LOCSEC - LOCATE SECTOR FOR RECORD I/O 195 ; 196 ;RELSEC = (REL REC * RECLEN + RELBYTE)/256 197 ;SECBYT = REMAINDER 198 ; 199 LOCSEC EQU * ; Proper variable names such as 3300:AD BD 35 200 LDA CCBRRN ; RELATIVE RECORD NUMBER ; === T2S2 === CCB_REL_REC_NUM 3303:8D E6 35 201 STA DCBCSB ; TO CSB FOR MULT ; Would negate the need for 3306:8D EA 35 202 STA DCBCRR ; AND CRR FOR SAVE ; 50% of comments 3309:AD BE 35 203 LDA CCBRRN+1 ; But's let abbreviate the fuck out of everything 330C:8D E4 35 204 STA DCBCRS ; Quick! What's the difference between DCBCRR and DCBCRS 330F:8D EB 35 205 STA DCBCRR+1 3312:A9 00 206 LDA #0 3314:8D E5 35 207 STA DCBCRS+1 ; HIGH CRS=0 3317:A0 10 208 LDY #16 ; 16 BIT MULT 209 ; 3319:AA 210 LS1 TAX ; SAVE MS BYTE 331A:AD E6 35 211 LDA DCBCSB 331D:4A 212 LSR A ; IF NO CARRY THEN NO PART PROD 331E:B0 03 213 BCS LS1A 3320:8A 214 TXA 3321:90 0E 215 BCC LS2 3323:18 216 LS1A CLC 3324:AD E5 35 217 LDA DCBCRS+1 ; FPORM PARTIAL PROD ; *spelling* FORM 3327:6D E8 35 218 ADC DCBRCL 332A:8D E5 35 219 STA DCBCRS+1 332D:8A 220 TXA 332E:6D E9 35 221 ADC DCBRCL+1 222 ; 3331:6A 223 LS2 ROR A ; MULT BY 2 3332:6E E5 35 224 ROR DCBCRS+1 3335:6E E4 35 225 ROR DCBCRS 3338:6E E6 35 226 ROR DCBCSB 333B:88 227 DEY ; DEC BIT COUNT 333C:D0 DB 228 BNE LS1 ; BR IF MORE BITS 229 ; 230 DO DOS33B ; Proof that the designer didn't THINK about the user and file sizes. 333E:18 231 CLC ; FOR FILE LENGTH > $7FFF BYTES ; /sarcastic What? It was too hard to realize that someone will try to do: BSAVE RAM.48K,A$0,L$C000 ??? 232 FIN ; THINK, McFLY! 333F:AD BF 35 233 LDA CCBBYT ; ADD REL BYTE RESULT 3342:8D EC 35 234 STA DCBCRB ; (SAVE REL BYTE) 3345:6D E6 35 235 ADC DCBCSB 3348:8D E6 35 236 STA DCBCSB 334B:AD C0 35 237 LDA CCBBYT+1 334E:8D ED 35 238 STA DCBCRB+1 ; (SAVE REL BYTE) 3351:6D E4 35 239 ADC DCBCRS 3354:8D E4 35 240 STA DCBCRS 241 DO DOS33B 3357:90 03 242 BCC DONTINC
3359:EE E5 35 243 INC DCBCRS+1 ; === Page 72 === 335C:60 244 DONTINC RTS 335D:00 00 245 DS 2,$00 ; wastes 2 bytes. Line 231 = 1 byte + 8 bytes keep remaining Entry Points @ same address 246 ELSE ; 9 bytes 247 LDA #0 248 ADC DCBCRS+1 249 STA DCBCRS+1 250 RTS 251 FIN 252 PAGE 335F:A9 01 253 ERROR1 LDA #CREFUN ; "FCB UNALLOCATED" - JMP'd from exactly ONE spot: F02 3361:D0 22 254 BNE ERRORA ;↓ wastes 2 bytes, above should be located at F02: LDA #CREFUN, JMP ERRORA 3363:A9 02 255 ERROR2 LDA #CRERR ; "CCB REQ RANGE ERR" - JMP'd from exactly ONE spot: ERR2 3365:D0 1E 256 BNE ERRORA ;↓ wastes 2 bytes, above should be located at ERR2: LDA #CRERR, JMP ERRORA 3367:A9 03 257 ERROR3 LDA #CREMRE ; "REQ MOD RANGE ERR" - JMP'd from exactly ONE spot: ERR3A 3369:D0 1A 258 BNE ERRORA ;↓ wastes 2 bytes, above should be located at ERR3A: LDA #CREMRE, JMP ERRORA 336B:A9 04 259 ERROR4 LDA #CREPRO ; "WRITE PROTECT" - [.. wastes 4 bytes -- never referenced! 336D:D0 16 260 BNE ERRORA ;↓ ..] 336F:A9 05 261 ERROR5 LDA #CREEOF ; "END OF FILE ON READ" - JMP'd from exactly ONE spot: EOFIN 3371:D0 12 262 BNE ERRORA ;↓ wastes 2 bytes, above should be located at EOFIN: LDA #CREEOF, JMP ERRORA 3373:A9 06 263 ERROR6 LDA #CREFNF ; "FILE NOT FOUND" - JMP'd from exactly ONE spot: F02A 3375:D0 0E 264 BNE ERRORA ;↓ wastes 2 bytes, above should be located at F02A: LDA #CREFNF, JMP ERRORA ; "VOL MIS MATCH" - What happened to error 7 ??? ; "I/O ERR" - What happened to error 8 ??? 3377:4C ED 3F 265 ERROR9 JMP ERROR9X ;MUST CLOSE ALL FILES (WAS LDA #CRENSA) ; "NO SECTORS AVAILABLE" 337A:EA 266 NOP ;↓ wastes 1 byte to keep Entry Point address unchanged 337B:A9 0A 267 ERROR10 LDA #CREFLK ; "FILE LOCKED" 337D:D0 06 268 BNE ERRORA ;↓ 337F:AD C5 35 269 GOODIO LDA CCBSTA ; Default to no change in status 3382:18 270 CLC ; CARRY=CLR ; No Shit Sherlock, Comment WHY, _not_ how; C=0 → No error 3383:90 01 271 BCC RETURN ; GO RETURN 272 ERRORA EQU * 3385:38 273 ERRORB SEC ; CARRY SET ; STOP documenting stupid shit! Instead, WHAT significance does C=1 have? → C=1 ERROR 274 RETURN EQU * 3386:08 275 PHP 3387:8D C5 35 276 STA CCBSTA ; SET STA 338A:A9 00 277 LDA #0 ;(FIX FOR APPLE SYS MONITOR $48 USED BY RWTS) 338C:85 48 278 STA $48 ;(THIS ADDED 11/1/78) ; magic number NOT ALLDONE DFB $24 SEC, but TODO 338E:20 7E 2E 279 JSR RTNFCB ; GO RTN FCB 3391:28 280 PLP ; GET STATUS 3392:AE 9B 33 281 LDX ENTSTK ; GET ENT STACK 3395:9A 282 TXS ; RESTORE STACK ; o7 Captain Obvious 3396:60 283 RTS ; DONE 284 EC2 EQU *
"Show me your code and I'll have to guess at your data (structures), Show me your data and I won't have to see your code, I'll already know it." -- Michael, paraphrasing Fred Brooks "Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won't usually need your flowcharts; they'll be obvious." -- Fred Brooks Let the complete clusterfrak of bad design commence in 3..2..1..PUFF! 001 PAGE ; This is why I partially dislike old source code: 002 ;MISC DOS WORK CELLS ; (almost) Everything has been abbreviated 003 ; ; (almost) to the point of obfuscation. 3397:00 004 CVDTRK DFB 0 ; CUR VOL DIR TRK ; i.e. 3398:00 005 CVDSEC DFB 0 ; CUR VOL DIR SECTOR ; ENT = Entry 3399:00 00 006 CURCCB DFB 0,0 ; CURRENT CCB ADR ; ALC = Allocation 339B:00 007 ENTSTK DFB 0 ; ENTRY STACK POINTER ; Why are we futzing with the stack pointer??? 339C:00 008 TEMP1 DFB 0 ; TEMP BYTE1 ; /sarcasm o7 Captain Obvious 339D:00 009 TEMP2 DFB 0 ; TEMP BYTE 2 ; *note* All the cool kids use "o7" for salute these days 339E:00 010 TEMP3 DFB 0 ; TEMP BYTE 3 ; Used by FLOCK, FUNLCK and GSS1 339F:00 011 ENTSLT DFB 0 ; BOOT SLOT SAVE 33A0:00 00 FF FF 012 ALC10S DFB 0,0,$FF,$FF ; ALLOCATION TRACK BIT MAP ; wastes 2 bytes/track free sector bitmap mask, used in NT3; See DCBABM, ; The thinking (if there even was any) was probably: ; DOS 3.2 = 13 sector ; DOS 3.3 = 16 sector ; DOS 3.4 > 16 sector -- See VNOSEC ; === HNTDAFS #1 === ; Anytime you see the word reserved or unused in a (file) format ; your spidey sense should be tingling. ; Translation: I pulled this out of my ass -- ; because I didn't actually measure what is needed!" 33A4:01 0A 64 013 CVTAB DFB 1,10,100 ; CONVERSION TABLE ; Powers of 10; sadly Applesoft's DECTBL @ $EE6C is useless :-/ 014 MSC ON ; Switch ASCII to Apple Text (high bit set) 33A7:D4 C9 C1 C2 015 FTTAB ASC "TIAB" ; FILE TYPE CONVERSTION TABLE" ; File Types You couldn't use file types that make visual hex editing easier?? ; Type Code Dumb Smart ; Applesoft Basic A 02 Ctrl-B 01 Ctrl-A ; Binary B 04 Ctrl-D 02 Ctrl-B ; c 03 ; d 04 ; e 05 ; f 06 ; g 07 ; h 08 ; Integer Basic I 01 Ctrl-A 09 Ctrl-I ; You have 3 guesses to tell which DOS uses and the first 2 don't count. 33AB:D3 D2 C1 C2 016 ASC "SRAB" ; *sigh* Really, you just had to re-use AB ?? ; === HNTDAFS #2 === ; Gee, how about using, oh I don't know: CD ; At the very least D = "user Defined" or *shock* directory: ; C = Child (directory) Parent Track/Sector, e.g. T$11S$F ; D = Directory (child), e.g. T$12S$F ; Yeah, yeah 20/20 33AF:A0 C5 CD D5 017 VOLMES ASC " EMULOV KSID" ; "DISK VOLUME " BACKWARDS ; *sigh* Micro-optimization; Not that these are bad but 33B3:CC CF D6 A0 ; /sarcasm Lets focus on a single tree, 33B7:CB D3 C9 C4 ; and completely miss the entire fraking forest! 018 MSB OFF ; Switch back to 7-bit ASCII 019 VML EQU *-VOLMES-1 ; Used by File FDELCAT, Func RDIR, Line 113 020 PAGE ; 021 ;VTOC RECORD AREA ; === VTOC === 022 VTOC EQU * ; T11S0 [offset], Right side = normal snarky commentary 33BB:04 023 VDOST DFB 4 ; DOS TYPE ; [00] wastes 1 byte -- never referenced ! ; magic number /sarcasm If only FILESYSTEM_TYPE_VTOC EQU $4 33BC:11 024 VDIRTK DFB 17 ; COLUME DIRECTORY SECTOR ; [01] *spelling* VOLUME, *sigh* TRACK not sector -- read the bloody variable name! ; Used by VTIO ; *note* This is only a copy. To change DOS while running ; F01A+4:11 → DCBVTN ; $2C01:11 → $35FA ; $AC01:11 → $B5FA 33BD:0F 025 VDIRSC DFB 15 ; VOLUME DIRECTORY SECTOR ; [02] Used by File FLOCNXB, Func RVDC, Line ?? 33BE:04 026 VDOSRN DFB 4 ; DOS RELEASE NUMBER ; [03] *sarcasm* I guess VERSION made too much sense. 33BF:00 027 DFB 0 ; SPARE ; [04] wastes 1 byte /sarcasm "Because someday these might be used ... ?" 33C0:00 028 DFB 0 ; SPARE ; [05] wastes 1 byte ಠ_ಠ Uh-huh. 33C1:FE 029 VVOLNO DFB $FE ; VOLUME NUMBER ; [06] Design for today, not someday 33C2:FC FD FF FC 030 DS 32 ; SPARE ; [07] wastes 32 bytes, WTF ! 33C6:FF FC FC FE ; Gee, here's an idea: 33CA:FF FC FD FF ; Instead of wasting space in the VTOC 33CE:FE FF FD FE ; 1) Pack our data by removing all the unused crap: 33D2:FF FD FD FD ; Total 1+1+32+8 = 42 bytes! 33D6:FF FE FD FF ; 2) Put VTOC data as first XX bytes in the T11SF CATALOG 33DA:FC FF FF FD ; 33DE:FD FC FE FE ; 33E2:7A 031 VTDMS DFB 122 ; MAX SECTORS IN A FILE DIR ; [27] *sigh* not 128 so we can BMI (Branch on Minus) ??? (Copied to DCBDMS) 33E3:FE FD FF FD 032 VSPARE DS 8 ; SPARES ; [28] wastes 8 bytes, Oh FFS already ... 33E7:FE FE FF FC 033 ; ; Who 1) designed, and 2) implemented this crap?!?! 33EB:11 034 VALCA1 DFB 17 ; ALOCATION ALGORITHM BYTE 1 ; [30] ALLOC_TRK Last allocated track TODO Cross-Ref 33EC:01 035 VALCA2 DFB 1 ; AA BYTE2 ; [31] ALLOC_DIR Direction of last track allocation -- Used by GS4 ; +1 = $01 inwards to T22, ; -1 = $FF outwards to T00. 33ED:00 036 VALCA3 DFB 0 ; AA BYTE3 ; [32] wastes 1 byte /sarcasm I really don't know what we 33EE:00 037 VALCA4 DFB 0 ; AA BYTE4 ; [33] wastes 1 byte would do without you Captain Obvious! 33EF:23 038 VNOTRK DFB 35 ; NO TRACKS ON VOL ; [34] *note* "No" = Number; To format more then 35 tracks: ; $AEFE:## ($3EFE), See: FORMATR, Line #054 33F0:10 039 VNOSEC DFB 16 ; NO SECTORS PER TRACK ; [35] Evidence that one day DOS 3.4+ might support: 33F1:00 01 040 VSECLN DW 256 ; NO. BYTES PER SECTOR ; [36] (Little) > 16 sectors/track 041 ; ; [37] (Endian) and > 256 bytes/sector. 042 VSECAL EQU * ; *note* Actual VTOC header is $F3-$BB = $38 bytes ; But we only really use: ; VVOLNO (dubious value; ProDOS users don't miss it.) ; VALCA1 ; VALCA2 ; a total of 3 bytes out of 56! ; That is ~5% usage!?!? ; wastes 70 bytes (35 tracks * 2) due to allocating 32 sectors/track! 043 ;SECTORS ALLOCATED BY BIT MAP ;struct TrackBitmap { // Bits = MSB.LSB 044 ;4 BYTES OF BITS PER TRACK ; uint8_t _f_8; //[0] Sectors: FEDCBA98 0=Used 045 ;LEFT MOST BIT REPRESENTS SECTOR ; uint8_t _7_0; //[1] Sectors: 76543210 1=Free 046 ;WHERE N=NO SECTORS PER TRACK ; uint8_t pad1; //[2] *sigh* 1 byte unused 047 ; ; uint8_t pad2; //[3] *sigh* 1 byte unused 048 ; ; } FreeSectors[ $22 ]; // Technically have room for $31 (49) tracks ;*sigh* Bytes stored : 35*4 bytes = 140 bytes ($8C) ; When we only need: 35*2 bytes = 70 bytes ($46) ;As Mike Acton says: "Solve the actual problem, ; NOT the one you think you have." 049 PAGE ;B3F3 =T00 33F3:FF 050 ORG VTOC+256 ; [38]=T00 00,00,FF,FF See HNTDAFS #3; Why not simply DS 256-VSECAL-VTOC,0 ??? 33F4:FC FC FD FC ; [3C]=T01 00,00,FF,FF Uninitialized memory is never a good idea 33F8:FE FC FC FD ; [40]=T02 00,00,FF,FF See HNTDAFS #4 33FC:FD FE FC FC ; [44]=T03 === T2S3 === disk wastes an entire sector for a single byte!? 3400:FF FC FC FD ; [48]=T04 The real kicker? VDTCDE isn't even bloody used! *facepalm* 3404:FC FD FD FC ; [4C]=T05 3408:FF FE FC FC ; [50]=T06 We then proceed to waste $C8 bytes (256-VSECAL-VTOC) 340C:FC FC FE FE ; [54]=T07 to force us to span 2 sectors with this dumb shit 3410:FC FD FC FC ; [58]=T08 instead of copying the VTOC header ($38 byte) 3414:FC FE FC FD ; [5C]=T09 into a new temporary page on init! 3418:FC FC FE FC ; [60]=T0A 341C:FC FC FE FC ; [64]=T0B === HNTDAFS #4 === 3420:FC FF FC FC ; [68]=T0C DOS reserves the entire Track 2 even though it only uses T2S0 - T2S4 !? 3424:FC FC FD FD ; [6C]=T0D 3428:FC FF FF FC ; [70]=T0E Instead of wasting yet another track T11 for meta data 342C:FE FD FE FD ; [74]=T0F 3430:FE FC FF FC ; [78]=T10 S0 = VTOC, S1-SF = CATALOG 3434:FE FF FD FC ; [7C]=T11 00,00,FF,FF 3438:FF FC FC FC ; [80]=T12 if we weren't dumb then both the 343C:FD FE FD FE ; [84]=T13 VTOC & CATALOG would reside on T2S5 - T2SF 3440:FC FC FC FF ; [88]=T14 3444:FE FC FC FD ; [8C]=T15 === HNTDAFS #3 === 3448:FC FD FF FC ; [90]=T16 DOS is unable to use Track 0 to store user files. 344C:FC FC FC FE ; [94]=T17 This means a non-bootable data disk is robbed of an additional 15 sectors! 3450:FD FC FD FC ; [98]=T18 (Boot sector would display non-bootable message) 3454:FC FC FD FC ; [9C]=T19 See File FLOCSEC, Func GETSEC, Line #83; Trk Free FRESEC, Line #183; Trk Allocation todo 3458:FD FF FC FE ; [A0]=T1A The smart thing to have done would be to 345C:FD FC FC FD ; [A4]=T1B put the VTOC and CATALOG on T0SF or T0S1 3460:FC FC FC FC ; [A8]=T1C That way both a bootable and data disk would 3464:FC FC FF FF ; [AC]=T1D get an extra 16 sectors of free disk space. 3468:FE FC FF FC ; [B0]=T1E 346C:FD FF FE FF ; [B4]=T1F The BOOTLDR would just need to move the 3470:FE FE FC FC ; [B8]=T20 disk head to track T1 and continue loading as normal. 3474:FD FC FC FC ; [BC]=T21 3478:FE FE FE FD ; [C0]=T22 (Normal last 35th accessible track) 347C:FE FD FC FE ; [C4]=T23 (Extra 36th track) 3480:FD FD FC FC ; [C8]=T24 (Extra 37th track) 3484:FE FE FC FC ; [CC]=T25 (Extra 38th track) 3488:FD FC FC FE ; [D0]=T26 (Extra 39th track) 348C:FC FC FD FC ; [D4]=T27 (Extra 40th track) 3490:FE FE FC FD ; [D8]=T28 3494:FC FC FC FC ; [DC]=T29 wastes 40 bytes [$D8..$FF] = $28 3498:FC FD FD FC ; [E0]=T2A *note* Tracks 41+ are not accessible 349C:FE FD FC FC ; [E4]=T2B on any drive that I know of. 34A0:FE FC FC FC ; [E8]=T2C That's not to say that they don't 34A4:FC FC FE FC ; [EC]=T2D exist but >basic engineering and repair 34A8:FD FD FC FF ; [F0]=T2E should tell us that accessing 34AC:FD FC FE FE ; [F4]=T2F more then 40 tracks is not possible. 34B0:FC FD FD FE ; [F8]=T30 Write for today, not "someday" 34B4:FF FD FE FF ; [FC]=T31 (Extra 50th track) 34B8:FE FF FC ; 051 ; 052 ;VOLUME DIRECTORY AREA ; 053 ; ; [--] T11SF offsets === CATALOG ===
054 VOLDIR EQU * ; ; === Page 87 === 34BB:02 055 VDTCDE DFB 2 ; VOLUME DIRECTORY TYPE CODE ; [00] wastes 1 byte -- and not even used !?!?! ; magic number /sarcasm If only FILESYSTEM_TYPE_CATALOG EQU $02 34BC:FC 056 VDLTRK DS 1 ; VD LINK TRACK ; [01] ($11) 34BD:FD 057 VDLSEC DS 1 ; VD LINK SECTOR ; [02] ($0E) 34BE:FC 058 VDNF DS 1 ; VD NUMBER FILES THIS SECTOR ; [03] wastes 1 byte -- never referenced 34BF:FC FC FE FE 059 VDSPAR DS 7 ; SPARES ; [04] wastes 7 bytes -- never referenced 34C3:FE FD FE 060 ; ; /sarcasm Glad to see this was put to good use ... NOT! 061 VDFILE EQU * ; FILE ALLOCATION AREA (7 FILES); [0B] NO, this is the _not_ the allocation; this is the *meta* data 062 ;EACH FILE: ; What can't do DSECT VDFILE *note* indented "struct FileEntry" for readability 063 ; FILE DIR TRK ; DFB CAT_FILE_TRACK ;[00] (0) inode (FILDIR) track 064 ; FILE DIR SECTOR ; DFB CAT_FILE_SECTOR ;[01] (1) inode (FILDIR) sector 065 ; FILE USE CODE ; DFB CAT_FILE_TYPE ;[02] (2) 066 ; FILE NAME (30) ; DS CAT_FILE_NAME ;[03] (3) WTF -- sizeof( FileEntry ) == 35 bytes; make it 27 067 ; FILE SECTOR COUNT (2) ; DW CAT_FILE_NUM_SEC ;[21] (33) so entire struct is 32 bytes 34C6:FF FE 068 ORG VOLDIR+256 ; wastes 256 bytes of disk space spanning two sectors *double facepalm* 34C8:FC FC FC FC 34CC:FC FE FC FD 34D0:FC FC FF FD 34D4:FC FE FC FC 34D8:FD FE FE FF 34DC:FC FE FF FD 34E0:FF FE FC FC 34E4:FE FE FD FF 34E8:FE FF FF FD 34EC:FC FE FF FC 34F0:FE FD FE FC 34F4:FE FC FF FE 34F8:FE FE FC FD 34FC:FD FE FF FC 3500:FC FC FC FC ; === T2S4 === 3504:FC FE FC FD 3508:FD FC FF FD ; /sarcasm Who cares, we have 140KB, right! 350C:FC FE FE FC 3510:FE FD FC FF 3514:FF FC FC FE 3518:FE FD FE FD 351C:FE FE FC FC 3520:FE FD FD FC 3524:FE FD FC FC 3528:FE FC FC FE 352C:FC FC FD FC 3530:FD FD FC FF 3534:FD FC FE FD 3538:FC FD FF FC 353C:FE FC FC FC 3540:FC FC FC FD 3544:FC FC FE FC 3548:FD FC FC FF 354C:FC FC FE FD 3550:FC FD FF FC 3554:FF FD FE FF 3558:FD FF FE FC 355C:FD FF FF FF 3560:FC FC FE FC 3564:FC FF FF FC 3568:FC FD FC FE 356C:FC FC FC FC 3570:FC FE FC FC 3574:FD FD FC FC 3578:FE FC FD FC 357C:FC FE FE FC 3580:FC FC FC FC 3584:FF FC FC FC 3588:FC FD FD FC 358C:FF FC FC FE 3590:FF FC FD FF 3594:FC FF FD FE 3598:FF FD FD FD 359C:FF FE FD FF 35A0:FC FF FD FD 35A4:FD FC FE FC 35A8:FC FF FE FC 35AC:FC FE FC FC 35B0:FE FC FD FD 35B4:FC FF FD FC 35B8:FE FC FC 069 VDEND EQU * 070 VDLEN EQU *-VOLDIR ; VDEND - VOLDIR = $35BB - $34BB = 256 071 VDFLEN EQU *-VDFIL ; VDEND - VDFIL = $35BB - $34C6 = $F5 072 ; 073 PAGE 074 ; 075 ;COMMAND CONTROL BLOCK (CCB) 076 ; 077 CCB EQU * ;$B5BB CCB Buffer; FM = File Manager 35BB:FF 078 CCBREQ DS 1 ; USER REQUEST BYTE ; [0] FM_Command = 0, See GetCCBAdr aka CCBLDR 079 CRQNUL EQU 0 ; 0-NO REQUEST ; WTF!!! NO ONE will ever call DOS's NOP!!! 080 CRQOPN EQU 1 ; 1-OPEN FILE ; Crap abbreviations: CMD_FILE_OPEN 081 CRQCLS EQU 2 ; 2-CLOSE FILE ; CMD_FILE_CLOSE 082 CRQRD EQU 3 ; 3-READ DATA ; CMD_FILE_READ 083 CRQWR EQU 4 ; WRITE DATA ; What happened to 4? CMD_FILE_WRITE 084 CRQDEL EQU 5 ; 5-DELETE FILE ; CMD_FILE_DELETE 085 CRQDIR EQU 6 ; 6-READ DIRECTORY ; CMD_DIR_READ 086 CRQLCK EQU 7 ; 7-LOCK FILE ; CMD_FILE_LOCK 087 CRQUNL EQU 8 ; 8-UNLOCK FILE ; CMD_FILE_UNLOCK 088 CRQRNM EQU 9 ; 9-RENAME ; CMD_FILE_RENAME 089 CRQPOS EQU 10 ; 10-POSITION FILE ; CMD_FILE_SEEK 090 CRQFMT EQU 11 ; 11-FORMAT ; CMD_DISK_FORMAT 091 CRQVAR EQU 12 ; 12 - VERIFY ; Really? CMD_DISK_VERIFY 092 CRQMAX EQU 13 ; ; You couldn't be consistent with first 11? 093 ; 094 CCBBSA EQU * ; FORMAT - BOOT START ADR PAG 35BC:FF 095 CCBRQM DS 1 ; RREQUEST MODIFIER BYTE ; [1] FM_RequestMod = 1 (SubCommand) *spelling* RREQUEST. RRReally?? 096 CRMNUL EQU 0 ; NO MODIFIER ; And this serves what purpose again ??? 097 CRMNBT EQU 1 ; R/W - 1 - NEXTBYTE 098 CRMNBL EQU 2 ; R/W - 2 - NEXTBLOCK 099 CRMSBT EQU 3 ; R/W - 3 - SPECIFCBYTE 100 CRMSBL EQU 4 ; R/W - 4 - SPECIFIC BLOCK 101 CRMMAX EQU 5 102 ; 103 CCBRRN EQU * ; I/O - RELATIVE RECORD NUMBER ; Relative Record Number, see LOCSEC 104 CCBFN2 EQU * ; RENAME - FILE NAME 2 PTR ; Address of FileNameDst 35BD:FC FC 105 CCBRLN DS 2 ; OPEN - RECORD LENGTH ; [2] FM_RelRecordNum 106 ; 107 CCBBYT EQU * ; I/O - RELATIVE BYTE NO (2 BYTES) 35BF:FD 108 CCBVOL DS 1 ; OPEN - VOL NO. ; [4] FM_Volume 35C0:FC 109 CCBDRV DS 1 ; OPEN - DRIVE ; [5] FM_Drive 110 ; 111 CCBBLN EQU * ; I/O - BLOCK LENGTH (2 BYTES) ; FM_BLockLength 35C1:FE 112 CCBSLT DS 1 ; OPEN - SLOT NO ; [6] FM_Slot 35C2:FE 113 CCBFUC DS 1 ; OPEN - FILE USE CODE ; [7] FM_FileUseCode (File Type), See TSTFUC, FRNME 114 ; 115 CCBFN1 EQU * ; OPEN, DELETE, LOCK, UNLOCK, RENAME - FILENAME
116 CCBBBA EQU * ; BLOCKK I/O - BLOCK BUFFER PTR ; === Page 88 === *spelling* BLOCK, OKKK 35C3:FE FC 117 CCBDAT DS 2 ; BYTE I/O - DATA BYTE ; [8] 118 ; 35C5:FF 119 CCBSTA DS 1 ; RESULT STATUS ; [A] Return Code 120 CREFUN EQU 1 ; FCB UNALLOCATED ; See: ERROR1 121 CRERR EQU 2 ; CCB REQ RANGE ERR ; See: ERROR2 122 CREMRE EQU 3 ; REQ MOD RANGE ERR ; See: ERROR3 123 CREPRO EQU 4 ; WRITE PROTECT ; See: ERROR4 124 CREEOF EQU 5 ; END OF FILE ON READ ; See: ERROR5 125 CREFNF EQU 6 ; FILE NOT FOUND ; See: ERROR6 126 CREVMM EQU 7 ; VOL MIS MATCH 127 CREIOE EQU 8 ; I/O ERR 128 CRENSA EQU 9 ; NO SECTORS AVAILABLE ; See: ERROR9 129 CREFLK EQU 10 ; FILE LOCKED ; See: ERROR10 130 ; 35C6:FC 131 CCBSM DDS 1 ; STATUS MODIFIER ; [B] FM_WASTED1 wastes 1 byte; never used! Can't remove since middle of struct. 35C7:FF FC 132 CCBFCB DDS 2 ; FCB PTR ; [C] FM_FCB_PTR 35C9:FF FF 133 CCBDBP DDS 2 ; DIR BUF PTR ; [E] FM_DIR_PTR 35CB:FE FC 134 CCBSBP DDS 2 ; SECTOR BUF PTR ;[10] FM_SEC_PTR 35CD:FE FC FD FF 135 CCBSPR DDS 4 ; SPARE ;[12] FM_WASTED2 wastes 4 bytes /sarcasm Someday, someday. 136 CCBLEN EQU *-CCB ; CCB LENGTH ;$16 137 CFCBAD EQU CCBFCB 138 CFCBDR EQU CCBDBP 139 CFCBSB EQU CCBSBP 140 PAGE 141 ; 142 ;FILE CONTROL BLOCK (FCB) DEFINITION 143 ;DCB - FILE DATA CONTROL BLOCK 144 ; 145 FCB EQU * 146 ; 147 ;DATA CONTROL BLOCK 148 ; 149 FCBDCB EQU * 35D1:FF 150 DCBFDT DS 1 ; 1ST FILE DIRECTORY TRACK ; [00] 35D2:FD 151 DCBFDS DS 1 ; 1ST FILE DIRECTORY SECTOR ; [01] 35D3:FD 152 DCBCDT DS 1 ; CURRENT FILE DIRECTORY TRACK ; [02] 35D4:FE 153 DCBCDS DS 1 ; CURRENT FILE DIRECTORY SECTOR ; [03] 35D5:FC 154 DCBWRF DS 1 ; WRITE REQD FLAG ; [04] 155 ;$80=WRITE FILE DIR 156 ;$40=WRITE SECTOR DIR 35D6:FC 157 DCBTRK DS 1 ; SECTOR TRACK ADR ; [05] 35D7:FC 158 DCBSEC DS 1 ; SECTOR ADR ; [06] 35D8:FC 159 DCBVDR DS 1 ; VOL DIR REC ; [07] DEC by FC1 35D9:FC 160 DCBVDI DS 1 ; VOL DIR INDEX ; [08] FNDFIL: X = File entry offset in CATALOG sector, FOPEN, FCLOSE 35DA:FE FD 161 DCBDMS DS 2 ; MAX NO DIRECTORY SECTORS ; [09] 35DC:FD FF 162 DCBDFS DS 2 ; CURRENT DIR 1ST REL SECTOR ; [0B] 35DE:FE FC 163 DCBDNF DS 2 ; REL SECTOR OF NXT DIR ; [0D] 35E0:FE FC 164 DCBCMS DS 2 ; SECTOR CURRENTLY IN MEMORY ; [0F] 35E2:FC FC 165 DCBSDL DS 2 ; SECTOR DATA LENGTH ; [11] 35E4:FF FC 166 DCBCRS DS 2 ; CURRENT RELATIVE SECTOR ; [13] See FVAR 35E6:FC FE 167 DCBCSB DS 2 ; CURRENT SECTOR BYTE ; [15] 35E8:FE FC 168 DCBRCL DS 2 ; RECORD LENGTH ; [17] 35EA:FE FC 169 DCBCRR DS 2 ; CURRENT RELATIVE REC ; [19] 35EC:FC FC 170 DCBCRB DS 2 ; CURRENT RELATIVE BYTE ; [1B] 35EE:FF FC 171 DCBNSA DS 2 ; NO SECTORS ALLOCATED ; [1D] Number of Sectors Allocated 172 ; 35F0:FC 173 DCBALS DS 1 ; ALLOCATION SECTOR BYTE ; [1F] 35F1:FC 174 DCBATK DS 1 ; ALLOCATION TRACK ; [20] 35F2:FE FC FC FF 175 DCBABM DS 4 ; ALLOCATION TRACK SECTOR BIT MAP;[21] wastes 2 bytes, See FS3 and Line #184 176 ; 35F6:FD 177 DCBFUC DS 1 ; FILE USE CODE ; [25] 35F7:FE 178 DCBSLT DS 1 ; SLOT NUMBER ; [26]
35F8:FC 179 DCBDRV DS 1 ; DRIVE NUMBER ; [27] === Page 89 === 35F9:FC 180 DCBVOL DS 1 ; VOLUME DRIVER ; [28] 35FA:FD 181 DCBVTN DS 1 ; VTOC TRACK NUMBER ; [29] Why isn't this DFB 17?? See F01A 182 ; 35FB:FC FC FF 183 DCBSPR DS 3 ; SPARES ; [2A] wastes 3 bytes, Zeroed via DCBSUP, *unused* 184 ; 185 DCBLEN EQU *-FCBDCB ; DCB LENGTH ; $2D = $35FE - $35D1 = $002D, used in exactly 1 place DCBSUP 186 FCBLEN EQU *-FCB ; FCB LENGTH ; $2D = $35FE - $35D1 = $002D 187 ;
001 SBTL '16-SECTOR DOS BOOT' 002 HERE3L EQU >* ; $FE End of FVCBUFS = $35FD, * = $35FE 003 REMDR3 EQU 256-HERE3L ; $02 Remainder 2 bytes for page alignment 35FE:FD FC 004 ORG *+REMDR3 ; $3600 wastes 2 bytes to page align BOOTLDR 005 TRK0LDR EQU * 006 DO >TRK0LDR ; Low byte of address controls if macro is on/off 007 ??? ;DELIBERATE ERROR IF NOT AT PAGE BOUNDARY 008 FIN 009 *************************** 010 * * 011 * 16-SECTOR DOS BOOTSTRAP * 012 * * 013 * RICK AURICCHIO * 014 * 10/10/79 * 015 * * 016 *************************** 017 * * 018 * THIS PROGRAM RESIDES IN * 019 * TRACK 0,SECTOR 0 OF A * 020 * DOS DISKETTE. ITS SOLE * 021 * PURPOSE IS TO READ THE * 022 * DOS LOADER PROGRAM IN * 023 * FROM TRACK 0, SECTORS * 024 * 1-9. CONTROL IS THEN * 025 * TRANSFERRED TO THAT * 026 * PROGRAM. * 027 * * 028 * NOTE: THE DOS LOADER * 029 * CONTAINS THE ENTIRE * 030 * SET OF 16-SECTOR CORE * 031 * ROUTINES; THOSE CORE * 032 * ROUTINES ARE USED TO * 033 * LOAD THE REST OF THE * 034 * DOS IMAGE INTO MEMORY. * 035 * * 036 *************************** 037 POINTA EQU $26 ;BUFFER POINTER 038 BSLOT EQU $2B ;BOOT BSLOT 039 BSECTR EQU $3D ;LAST BSECTR READ 040 BTEMP EQU $3E ;ADDRESS BTEMP 041 BRETRY EQU $5C ;OFFSET TO READER 042 * 043 MONINIT EQU $FB2F ;MONINIT SCREEN 044 BHERE3 EQU >* ; unused $00, TRK0LDR already used to test page alignment. 045 BOOTCNT EQU $800+BHERE3 ; unused but used as placeholder for P6 ROM 3600:01 046 DFB 01 ; We could store $10 here to have the P6 PROM read 16 sectors but nah, 047 PAGE ; let's waste $839-$801 = $38 (56) bytes instead! 3601:A5 27 048 LDA POINTA+1 ;WHERE DID BSECTR GET LOADED? ;[.. wastes 56 bytes; Get memory page of last load 3603:C9 09 049 CMP #09 ; (AT 0800)? ; .. 3605:D0 18 050 BNE READNEXT ;=>NO. WE'RE LOADING SOMETHING ; .. 051 * WE'VE BEEN BOOTED. SET UP ; .. 052 * PARAMS FOR BOOT PROM SO ; ..
053 * THAT WE'LL READ IN TRACK 0, ; .. === Page 9 === 054 * BSECTRS 00-09. ; .. 3607:A5 2B 055 LDA BSLOT ;GET BOOT SLOT ; .. 3609:4A 056 LSR A ;CONVERT TO CX00 ; .. 360A:4A 057 LSR A ; .. 360B:4A 058 LSR A ; .. 360C:4A 059 LSR A ; .. 360D:09 C0 060 ORA #$C0 ; .. 360F:85 3F 061 STA BTEMP+1 ; .. magic number IO_SLOT_PAGE EQU $C0 3611:A9 5C 062 LDA #BRETRY ; PROM ROUTINE OFFSET ; .. 3613:85 3E 063 STA BTEMP ; .. 3615:18 064 CLC ;BUMP LOAD ADDRESS UP TO ; .. 3616:AD FE 08 065 LDA LOADADDR+1 ; LAST PAGE SO WE ; .. 3619:6D FF 08 066 ADC BGRPGC ; CAN LOAD 'EM BACKWARDS ; .. 361C:8D FE 08 067 STA LOADADDR+1 ; .. 068 * READ IN ANOTHER BSECTR FROM ; .. 069 * TRACK ZERO... ; .. 361F:AE FF 08 070 READNEXT LDX BGRPGC ; .. 3622:30 15 071 BMI GOLOADER ;=>ALL DONE...EXECUTE IT! ; .. 3624:BD 4D 08 072 LDA TABLE,X ;GET PHYSICAL BSECTR NUMBER ; .. /sarcasm Real original name there guys. WTF does TABLE refer to??? 3627:85 3D 073 STA BSECTR ; AND SET FOR BOOT PROM READ ; .. You couldn't call it LOGSECTR for LOGical SECToR?? 3629:CE FF 08 074 DEC BGRPGC ;ONE LESS BELL TO ANSWER... ; .. 362C:AD FE 08 075 LDA LOADADDR+1 ;GET LOAD ADDRESS ; .. 362F:85 27 076 STA POINTA+1 ; FOR BSECTR READ ; .. 3631:CE FE 08 077 DEC LOADADDR+1 ;MOVE LOAD ADDRESS DOWN A PAGE ; .. 3634:A6 2B 078 LDX BSLO ;RESTORE BSLOT NUMBER ; .. 3636:6C 3E 00 079 JMP (BTEMP) ;READ MORE OF TRACK 0 ; ..] 3639:EE FE 08 080 GOLOADER INC LOADADDR+1 ;ENTRY AT SECOND PAGE 363C:EE FE 08 081 INC LOADADDR+1 363F:20 89 FE 082 JSR SETKBD ;CLEAR IN#X 3642:20 93 FE 083 JSR SETVID ; AND PR#X 3645:20 2F FB 084 JSR MONINIT ;MONINIT THE SCREEN PARAMS 3648:A6 2B 085 LDX BSLOT ;PASS BSLOT NBR TO LOADER 364A:6C FD 08 086 JMP (LOADADDR) ;OFF TO LOOADER! ; *spelling* Loader 087 * TABLE OF PHYSICAL BSECTR NUMBERS 088 * WHICH CORRESPOND TO THE LOGICAL 089 * BSECTRS 0-F ON TRACK ZERO... 090 BHERE2 EQU >* ; $4D low byte (modern assemblers use > as high byte meaning) 091 TABLE EQU $800+BHERE2 ; $084D Our native address is $3600 but also loaded at $0800 ; ; This is one time where you don't want to compact lines ; Problem: Compare & contrast this clusterfrak 364D:00 0D 0B 092 DFB $00,13,11 ;00->00,01->13,02->11 ; WHY is this grouped in triplets??? *sigh* inconsistent $00 code 3650:09 07 05 093 DFB 09,07,05 ;03->09,04->07;05->05 ; We have a sector interleave of two! *sigh* inconsistent: ; comment 3653:03 01 0E 094 DFB 03,01,14 ;06->03,07->01,08->14 ; The last line having an even number 3656:0C 0A 08 095 DFB 12,10,08 ;09->12,10->10,11->08 ; of terms wasn't your first clue!?! 3659:06 04 02 0F 096 DFB 06,04,02,15 ;12->6,13->04,14->02,15->15 ; *sigh* inconsistent 6 comment ; Solution: ; LOG_TO_PHYS EQU * ; DFB $0 ; [0] 0 ; DFB $D ; [1] 13 ; DFB $B ; [2] 11 ; DFB $9 ; [3] 9 ; DFB $7 ; [4] 7 ; DFB $5 ; [5] 5 ; DFB $3 ; [6] 3 ; DFB $1 ; [7] 1 ; DFB $E ; [8] 14 ; DFB $C ; [9] 12 ; DFB $A ; [A] 10 ; DFB $8 ; [B] 8 ; DFB $6 ; [C] 6 ; DFB $4 ; [D] 4 ; DFB $2 ; [E] 2 ; DFB $F ; [F] 15 097 PAGE 098 REP 40 ; alias for **************************************** 099 * APPEND BUG PATCHES 100 **************************** 101 SC3 EQU * 365D:00 102 EOFFLAG DFB 0 103 CLOSFILE EQU * 365E:20 64 27 104 JSR FILSRC ;FILE BUFFER FOUND? 3661:B0 08 105 BCS NOTFOUND ;=> NO, SO SKIP IT. 3663:A9 00 106 LDA #0 ;YES, CLOSE IT ;magic number 3665:A8 107 TAY 3666:8D 5D 36 108 STA EOFFLAG 3669:91 40 109 STA (ZPGWRK),Y ;RIGHT NOW 366B:AD C5 35 110 NOTFOUND LDA CCBSTA ;ORIGINAL INSTRUCTION 366E:4C D2 26 111 JMP ERROR ;BACK TO ERROR HANDLER 112 **************************** 113 BUMPER EQU * 3671:AD 5D 36 114 LDA EOFFLAG ;SHOULD WE? 3674:F0 08 115 BEQ GOBACK ;=> NO
3676:EE BD 35 116 INC CCBRRN ;BUMP CCB RECORD NUMBER ; === Page 10 === 3679:D0 03 117 BNE GOBACK 367B:EE BE 35 118 INC CCBRRN+1 ;TO GET TO NEXT SECTOR 367E:A9 00 119 GOBACK LDA #0 3680:8D 5D 36 120 STA EOFFLAG ;TURN FLAG OFF ; Note: Code here can be used to tell the version of DOS 3.3: DOS 3.3A AUG 1980, DOS 3.3B JAN 1983, or DOS 3.3C 1983 ! ; Oh look, we have lowercase support for when CapsLock is on the Apple //e! 4C 46 25 JMP FIXIT2 ; DOS 3.3A AUG 1980 4C 46 25 → JMP $A546 4C 84 3A JMP FIXIT2 ; DOS 3.3B JAN 1983 4C 84 3A → JMP $BA84 -- see Line #144 in MSWAITR below-- 3683:4C B3 36 121 JMP FIXIT2 ;Go to FIXIT2 as exit ;↓ DOS 3.3C ??? 1983 4C B3 36 → JMP $B6B3 Page 36, D/001B80:8D 5D 36 4C B3 36 122 REP 40 123 VPATCH EQU * 3686:8D BC 35 124 STA CCBRQM ;ORIGINAL INSTRUCTION 3689:20 A8 26 125 JSR DOSGO ;GO SAVE 368C:20 EA 22 126 JSR ECLOSE ;CLOSE THE FILE 368F:4C 7D 22 127 JMP EVAR ;GO VERIFY IT AFTER SAVE 128 **************************** 129 EOFFIX EQU * 3692:A0 13 130 LDY #$13 ;PEEK INTO THE FCB: IF ; magic number FCB_CUR_REL_SEC 3694:B1 42 131 CHKFILE LDA (ZPGFCB),Y ;DCBCRS,DCBCSB ARE ZEROS, 3696:D0 14 132 BNE FIXIT ; THEN WE HAVE EMPTY FILE 3698:C8 133 INY 3699:C0 17 134 CPY #$17 ; magic number FCB_REC_LEN 369B:D0 F7 135 BNE CHKFILE 369D:A0 19 136 LDY #$19 ; magic number FCB_CUR_REL_REC 369F:B1 42 137 MOVE LDA (ZPGFCB),Y ; DCBCRR,DCBCRB 36A1:99 A4 35 138 STA CCBRRN-$19,Y;INTO CCBRRN,CCBBYT ; magic number FCB_CUR_REL_REC 36A4:C8 139 INY 36A5:C0 1D 140 CPY #$1D ; magic number FCB_NUM_SEC_ALLOC 36A7:D0 F6 141 BNE MOVE 36A9:4C BB 26 142 BACK JMP DOSGO2A ;NOW LET APPEND CONTINUE 143 FIXIT EQU * 36AC:A2 FF 144 LDX #$FF ;SET FLAG SO APPEND WILL ; magic number FLAG_EOF_SEC_BOUNDARY EQU $0 36AE:8E 5D 36 145 STX EOFFLAG ;KNOW TO CROSS SECTOR BOUNDARY 36B1:D0 F6 146 BNE BACK ;ALWAYS TAKEN ; ↑ 147 PAGE 148 REP 40 149 * END OF BOOT PAGE DATA SETUP 150 REP 40 151 * 152 * FIXIT2 was developed to fix the wrap around ; Note: This is NOT at this address in DOS 3.3A 1980 or DOSB 3.3B 1983 153 * problem APPEND has when trying to APPEND to ; In DOS 3.3B it was located at $3A84 (see line 121 above) 154 * a sequential file which is > 255 sectors in length. 155 * 156 * Fix by 157 * 158 * Fern Bachman 159 * Guil Banks 160 * September 28, 1982 161 * 162 * Fix to fix added to correctly APPEND to a SECTOR 163 * 255 bytes in length 164 * 165 * by 166 * Guil Banks 167 * July 11, 1983 168 * 169 REP 30 170 SKP 1 171 FIXIT2 EQU * 36B3:AD BD 35 172 LDA CCBRLN ;Current record length lo 36B6:8D E6 35 173 STA DCBCSB ;Current sector byte 36B9:8D EA 35 174 STA DCBCRR ;Current relative record 36BC:AD Be 35 175 LDA CCBRLN+1 ;Do hi as well 36BF:8D E7 35 176 STA DCBCSB+1 36C2:8D EB 35 177 STA DCBCRR+1 36C5:8D E4 35 178 STA DCBCRS ;Set current relative sector
36C8:BA 179 TSX ; === Page 11 === 36C9:8E 9B 33 180 STX ENTSTK 36CC:4C 7F 33 181 JMP GOODIO 182 SKP 2 183 REP 30 184 * 185 * Upper/Lower case patch 186 * for DOS 3.3C and BASIC 187 * 188 * by 189 * Guil Banks 190 * Mark Houde 191 * 192 REP 10 193 * 194 * This routine converts all characters 195 * that are not between quotes to 196 * upper case and returns them to the 197 * input buffer ($200). This works with 198 * DOS, Integer & Applesoft. 199 * 200 * Upon entry - 201 * 202 * X Reg = 0 203 * 204 * Upon exit - 205 * 206 * Y Reg = $FF 207 * ACCUM = $8D 208 * X Reg = unknown 209 * 210 REP 30 211 DO ULC 212 UPRCASE EQU * 213 LUP1 LDA LBUFF,X ;Get a char 214 CMP #'"+$80 ;Is it a quote? 215 BNE CHK4UC ;=> if not 216 LUP2 INX ;Bump to next char 217 LDA LBUFF,X ;Get it 218 CMP #'"+$80 ;Closing quote? 219 BEQ NEXTCHR ;=> if so 220 CMP #$8D ;End of Line? ; magic number KEY_CR 221 BNE LUP2 ;=> if not 222 ULFINI LDY #$FF ;Do what DOS wants 223 STY CMDNO 224 RTS ; & exit 225 CHK4UC EQU * 226 CMP #$E0 ;Upper case? 227 BCC CHK4CR ;=> if not 228 AND #$DF ;Make upper case 229 STA LBUFF,X ; & restore 230 CHK4CR CMP #$8D,X ;End of input? ; magic number KEY_CR 231 BEQ ULFINI ;=> if so 232 NEXTCHR INX ;Bump to next char 233 BNE LUP1 ;=> always ; ↑ No, not always, 256 times 234 FIN ; Patch incomplete! Where is the RTS??? Called from SCNCMD 235 SKP 1 236 BHERE1 EQU >* 36CF:00 237 DS $FD-BHERE1,0 ;[.. wastes 46 bytes ($36FD - $36CF = $2E) ; .. ; === DOS 3.3A JAN 1980 EASTER EGG === secret message @ 36D0 ($B6D0): "B01-00" 36D0:00 00 00 00 ; .. PRBYTE EQU $FDDA Print A as 2 hex digits 36D4:00 00 00 00 ; .. 36D0:20 58 FC JSR HOME 36D8:00 00 00 00 ; .. 36D3:A9 C2 LDA #'B'+$80 36DC:00 00 00 00 ; .. 36D5:20 ED FD JSR COUT 36E0:00 00 00 00 ; .. 36D8:A9 01 LDA #$01 36E4:00 00 00 00 ; .. 36DA:20 DA FD JSR PRBYTE 36E8:00 00 00 00 ; .. 36DD:A9 AD LDA #'-'+$80 36EC:00 00 00 00 ; .. 36DF:20 ED FD JSR COUT 36F0:00 00 00 00 ; .. 36E2:A9 00 LDA #$00 36F4:00 00 00 00 ; .. 36E4:20 DA FD JSR PRBYTE Really?? Wastes 1 byte with JSR/RTS 36F8:00 00 00 00 ; .. 36E7:60 RTS instead of JMP 36FC:00 ; ..] === DOS 3.3 EASTER EGG === 238 * LOAD ADDRESS FOR CODE (PG BDY) 239 * ENTRY AFTER BOOT IS AT LOADADDR+256 (SECOND PAGE LOADED) 240 * 241 BHERE4 EQU >* ; $FD
242 LOADADDR EQU $800+BHERE4 ; $08FD === Page 12 === 36FD:00 243 DFB 0 36FE:36 244 GRSPG DFB <TRK0LDR ;CONTAINS PAGE#-1 OF TRK 0, SEC 1 LOAD ADDRESS 245 * LAST LOGICAL BSECTOR TO READ STARTING AT $00 246 BHERE5 EQU >* ; $FF 247 BGRPGC EQU $800+BHERE5 ; $08FF 36FF:09 248 GRPGC DFB <ENDOFDOS-TRK0LDR-$100 249 ******************** 250 PAGE 251 DOSLODR EQU * ; $3700 252 DO >DOSLODR 253 ??? ;ERROR IF NOT ON PAGE BOUNDARY 254 FIN 255 REP 40 256 * FAST BOOT AT 2:1 INTERLEAVE ; "You keep using this word fast, 257 * FOR 16-SECTOR DISKETTES ; it doesn't mean what you think it means." 258 REP 40 ; Copy ][+ has a FAST boot via 4&4 encoding, not 6&2 encoding. 3700:8E E9 37 259 STX IBSLOT ; SET BOOT SLOT ; === T0S1 === 3703:8E F7 37 260 STX IBPSLT ; SET PREVIOUS SLOT 3706:A9 01 261 LDA #1 ; SET PREV DRIVE ; Assumes boot was from drive 1; Sadly there is no hardware support to tell which drive is currently active. 3708:8D F8 37 262 STA IBPDRV ; More crappy names differing by a single letter: 370B:8D EA 37 263 STA IBDRVN ; IBPDRV IB_PRV_DRV 264 ; ; IBDRVN IB_CUR_DRV 370E:AD E0 37 265 LDA NDPGS ; COPY NO PAGES TO GET 3711:8D E1 37 266 STA BRWCNT 3714:A9 02 267 LDA #2 3716:8D EC 37 268 STA IBTRK ; SET TRACK 0 ; Uhm, T2S4, not T0S4 3719:A9 04 269 LDA #4 ;ENDING SECTOR OF DOS IMAGE 371B:8D ED 37 270 STA IBSECT ;TO IOB 371E:AC E7 37 271 LDY ADOSLD+1 ;END PAGE OF DOS IMAGE 3721:88 272 DEY ;IS ONE LESS THAN 3722:8C F1 37 273 STY IBBUFP+1 ;START OF DOSLDR+BOOT 274 ; 3725:A9 01 275 LDA #IBCRTS ; SET READ 3727:8D F4 37 276 STA IBCMD ; So it IS possible to use symbolic names instead of magic numbers! /s See Line #313 277 ; 372A:8A 278 TXA ; SET PREV TRACK = 0 372B:4A 279 LSR A 372C:4A 280 LSR A 372D:4A 281 LSR A 372E:4A 282 LSR A 372F:AA 283 TAX ; The 40x24 text screen has "memory holes" that are NOT displayed 3730:A9 00 284 LDA #0 ; reserved for each Slot 1..7 as "scratchpad" or temp vars 3732:9D F8 04 285 STA $4F8,X ; magic number /sarcasm What, DRV2TRK wasn't available??? 3735:9D 78 04 286 STA $478,X ; magic number /sarcasm What, DRV1TRK wasn't available??? 3738:20 93 37 287 JSR BOOTIO ; GO READ DOS 288 ; 289 ;DOSINT - INITIALIZE DOS ; /sarcasm Couldn't afford extra 'i' in "dosinIt" 290 ; 291 DOSINT EQU * ; Ironically in Boot Loader, not Dos Init 373B:A2 FF 292 LDX #$FF 373D:9A 293 TXS 373E:8E EB 37 294 STX IBVOL 3741:4C C8 3F 295 JMP RCPATCH ; Should be JSR RCPATCH to prevent stupid JMP RCBACK 3744:20 89 FE 296 RCBACK JSR SETKBD 297 ; 3747:4C 03 1B 298 DI3 JMP DOSREL ; GO TO POST INIT ROUTINE ; Relocate DOS to high mem DOS 3.3 1980: JMP $1B03 299 PAGE 300 WBOOT EQU * ; Write Boot; part of the INIT process 374A:AD E7 37 301 LDA ADOSLD+1 374D:38 302 SEC 374E:ED F1 37 303 SBC IBBUFP+1
3751:8D E1 37 304 STA BRWCNT ;COMPUT PAGE COUNT ; === Page 13 === *spelling* Compute 3754:AD E7 37 305 LDA ADOSLD+1 3757:8D F1 37 306 STA IBBUFP+1 ;BUFFER=LAST PAGE OF RWTS 375A:CE F1 37 307 DEC IBBUFP+1 375D:A9 02 308 LDA #2 ; magic number TODO sizeof( PROGRAM ) / 16 375F:8D EC 37 309 STA IBTRK ;ENDING TRACK 3762:A9 04 310 LDA #4 3764:8D ED 37 311 STA IBSECT ;ENDING SECTOR 3767:A9 02 312 LDA #2 ; magic number Why not IBCWTS ??? 3769:8D F4 37 313 STA IBCMD ;COMMAND = WRITE 376C:20 93 37 314 JSR BOOTIO ;WRITE DOS IMAGE TRK 2, SEC 4 315 * ;BACKWARDS TO TRK 0,SEC C 376F:AD E7 37 316 LDA ADOSLD+1 3772:8D FE 36 317 STA GRSPG ;BOOTSTRAP LOAD ADDRESS 3775:18 318 CLC 3776:69 09 319 ADC #9 3778:8D F1 37 320 STA IBBUFP+1 ;BUFFER ADDRESS OF END OF BOOT 377B:A9 0A 321 LDA #10 377D:8D E1 37 322 STA BRWCNT ;SECTOR COUNT TO WRITE ; /sarcasm If only NUM_SEC_WRITE 3780:38 323 SEC 3781:E9 01 324 SBC #1 3783:8D FF 36 325 STA GRPGC ;BOOT LAST SECTOR # 3786:8D ED 37 326 STA IBSECT ;START AT END OF RWTS&BOOT 3789:20 93 37 327 JSR BOOTIO ;AND WRITE DOWN TO ZERO 378C:60 328 RTS 378D:00 00 00 00 329 DS 6,0 ;FILL WITH BRKS ; wastes 6 bytes -- WHY ??? 3791:00 00 330 PAGE 331 BOOTIO EQU * 3793:AD E5 37 332 LDA BAIOB+1 ; wastes 3 bytes; BAIOB → IOB, JSR IOBLDR loads AIOB → IOB 3796:AC E4 37 333 LDY BAIOB 3799:20 B5 37 334 JSR DISKIO 335 ; 379C:AC ED 37 336 LDY IBSECT ; GET SECTOR 379F:88 337 DEY ; DECREMENT TO NEXT ; Stupid Commenting - stop treating the reader as a moron 37A0:10 07 338 BPL BIO1 ;AT END OF TRACK? ; See now this is a useful comment in contradistinction to the one above 37A2:A0 0F 339 LDY #15 ;SET TO SECTOR 15 ; as it tells us WHY we are branching 37A4:EA 340 NOP ; [.. wastes 2 bytes 37A5:EA 341 NOP ; ..] 37A6:CE EC 37 342 DEC IBTRK 37A9:8C ED 37 343 BI01 STY IBSECT ; SET NEXT SECTOR 344 ; 37AC:CE F1 37 345 DEC IBBUFP+1 ; DECREMENT BUFFER POINTER 37AF:CE E1 37 346 DEC BRWCNT ; DECREMENT PAGE COUNTER 37B2:D0 DF 347 BNE BOOTIO ; BR IF NOT DONE 37B4:60 348 RTS 349 ; 350 PAGE 37B5:08 351 DISKIO PHP ;SAVE INTERUPT STATUS ; *spelling* Interrupt 37B6:78 352 SEI ;INHIBIT INTERUPT WHILE ; *spelling* Interrupt 37B7:20 00 3D 353 JSR RWTS ; ACCESSING DISK 37BA:B0 03 354 BCS DSKERR ;MUST PASS BACK CARRY FLAG & INTERUPT ; *spelling* Interrupt 37BC:28 355 PLP 37BD:18 356 CLC 37BE:60 357 RTS 37BF:28 358 DISKERR PLP ;CARRY SET MEANS ERROR 37C0:38 359 SEC 37C1:60 360 RTS 37C2:AD BC 35 361 DLDSUP LDA CCBBSA ;SET UP FOR DOS LOADER 37C5:8D F1 37 362 STA IBBUFP+1 ;START ADDRESS 37C8:A9 00 363 LDA #0 37CA:8D F0 37 364 STA IBBUFP 37CD:AD F9 35 365 LDA DCBVOL ;INVERT VOLUME NUMBER
37D0:49 FF 366 EOR #$FF ; === Page 14 === 37D2:8D EB 37 367 STA IBVOL 37D5:60 368 RTS 369 ; 37D6:A9 00 370 CLRSEC LDA #0 ;CLEAR SECTOR 37D8:A8 371 TAY 37D9:91 42 372 CS1 STA (ZPGFCB),Y 37DB:C8 373 INY 37DC:D0 FB 374 BNE CS1 37DE:60 375 RTS 37DF:00 376 BRK ; wastes 1 byte -- Why??? 377 EC3 EQU * 37E0:1B 378 NDPGS DFB <TRK0LDR-BEGIN ;CALC #PAGES IN DOS WITHOUT RWTS 37E1:00 379 BRWCNT DFB 0 ;WRK CTR FOR BOOTIO 37E2:0A 380 DFB $0A ;[.. wastes 2 bytes -- never used! 37E3:1B 381 DFB $1B ; ..] 37E4:E8 37 382 BAIOB DW IOB ; BAIOB and AIOB both point to IOB 37E6:00 36 383 ADOSLD DW TRK0LDR 384 PAGE 385 ; 386 IOB - INPUT / OUTPUT CONTROL BLOCK 387 ;THE IOB IS USED FOR THE INTERFACE 388 ;BETWEEN DOS AND THE DISK I/O ROUTINES 389 ; 390 IOB EQU * ; Descriptive Names 37E8:01 391 IBTYPE DFB 1 ; IOB TYPE CODE ; [0] IOB_OFFSET_TYPE wastes 1 bytes, hard-coded to 1 in FLOCNXB, Line #95 ! 37E9:60 392 IBSLOT DFB 6*16 ; CONTROLELR SLOT NO. ; [1] IOB_OFFSET_SLOT 37EA:01 393 IBDRVN DFB 1 ; DRIVE NUMBER ; [2] IOB_OFFSET_DRV_NUM 37EB:00 394 IBVOL DFB $00 ; VOLUME NUMBER ; [3] IOB_OFFSET_VOL 37EC:00 395 IBTRK DFB 0 ; TRACK NUMBER ; [4] IOB_OFFSET_TRK 37ED:00 396 IBSECT DFB 0 ; SECTOR NUMBER ; [5] IOB_OFFSET_SEC 37EE:FB 37 397 IBDCTP DW DCT ; [6] IOB_OFFSET_DCT Why is the Device Characteristics Table 37F0:00 00 398 IBBUFP DW 0 ; POINTER TO BUFFER ; [8] IOB_OFFSET_BUF even exposed to the caller??? 37F2:00 01 399 IBDLEN DW 256 ; DATA LENGTH ; [A] IOB_OFFSET_LEN These values never change! 37F4:00 400 IBCMD DFB 0 ; COMMAND ; [C] IOB_OFFSET_CMD 401 IBCNUL EQU 0 ; 0-NULL COMMAND ; Stop with the shitty API already! 402 IBCRTS EQU 1 ; 1-READ TRACK, SECTOR ; IB_CMD_R And it is important these be bit flags why again? 403 IBCWTS EQU 2 ; 2-WRITE TRACK,SECTOR ; IB_CMD_W 404 IBFMT EQU 4 ; 4-FORMAT DISK ; IB_CMD_FORMAT 405 IBBOOT EQU 8 ; 8-WRITE BOOT ; IB_CMD_X_BOOT 37F5:00 406 IBSTAT DFB 0 ; STATUS ; [D] IOB_OFFSET_STATUS 407 IBRERR EQU $80 ; READ ERR ; IB_ERR_R Interleaving const and struct types 408 IBDERR EQU $40 ; DRIVE ERR ; IB_ERR_DRV makes for extremely poor readability 409 IBVMME EQU $20 ; VOLUME MISMATCH ; IB_ERR_VOL 410 IBWPER EQU $10 ; WRITE PROTECT ERROR ; IB_ERR_W 37F6:00 411 IBSMOD DFB 0 ; STATUS MODIFIER BYTE ; [E] IOB_OFFSET_MOD 37F7:60 412 IBPSLT DFB 6*16 ; PREVIOUS SLOT ; [F] IOB_OFFSET_PREV_SLOT Why isn't this set at boot ??? 37F8:01 413 IBPDRV DFB 1 ; PREVIOUS DRIVE ;[10] IOB_OFFSET_PREV_DRV 37F9:00 00 414 IBSPAR DS 2,0 ; IOB SPARES ;[11] wastes 2 bytes 37FB:00 01 EF D8 415 DCT DFB 0,1,$EF,$D8 ; ; magic number More crappy formatting, values defined in RWTSONE ; Put these values on one per line for readability like this: ; DCT_TYPE DFB 0 ; Device Type, $0 = Disk II ; DCT_PHASES DFB 1 ; Phases per Track ; DCT_MOTOR DW $D8EF ; Motor on time in 100 microseconds 37FF:00 416 DS 1,0 ; FILL IN 3700 PAGE ; wastes 1 byte 417 PAGE 418 ; 419 ; FILE DIRECTORY DEFINITION ; META-DATA: FTOC = array of Track/Sectors belonging to a file 420 ; ; Note: The brain dead Track/Sector is equivalent to Unix i-nodes 421 DSECT ; ProDOS switched to BlockIndex 422 FILDIR EQU * ;T12SF HNTDAFS #6; Really?, couldn't call it FILEDIR???, 423 FDUCDE DS 1 ; FILE USE CODE ; [00] wastes 1 byte -- never referenced! I presume FILESYSTEM_TYPE_FILE EQU $1 424 FDLTRK DS 1 ; LINK TO NEXT DIR TRACK ; [01] e.g. $12 ($00 = none), see RFDNXT 425 FDLSEC DS 1 ; LINK TO NEXT DIR SECTOR ; [02] e.g. $0E ($00 = none) 426 FDNSA DS 1 ; NO SECTORS ALLOCATED ; [03] wastes 1 byte -- never referenced! 427 FDLSDL DS 1 ; LAST SECTOR DATA LENGTH ; [04] wastes 1 byte -- never referenced! 428 FDFRS DS 2 ; 1ST RELATIVE SECTOR IN THIS DIR ; [05] read by RFDNL1 and RDFDC in FMTRWIO
429 FDSPAR DS 5 ; SPARES ; [07] === Page 15 === -- never referenced! 430 ; ; wastes 5 bytes on disk for EVERY catalog sector! 431 FDENT DS 1 ; START OF FILE ENTRIES (122) ; [0C] 432 FDTRK EQU 0 ; TRACK 433 FDSEC EQU 1 ; SECTOR 434 ; 435 FDLAST EQU FILDIR+256 ; $3900 ($B900) -- never referenced 436 DEND
001 SBTL '16-SECTOR CORE ROUTINES' 002 *************************** 003 * * 004 * DISC-II * 005 * 16-SECTOR FORMAT * 006 * READ AND WRITE * 007 * SUBROUTINES * 008 * * 009 *************************** 010 * * 011 * * 012 * COPYRIGHT 1979 * 013 * APPLE COMPUTER INC. * 014 * * 015 * ALL RIGHTS RESERVED * 016 * * 017 *************************** 018 * * 019 * MAR 18, 1979 * 020 * WOZ * 021 * * 022 *************************** 023 ASC1 EQU * ;TELL RELOCATOR WHERE CORE STARTS 024 PAGE 025 *************************** 026 * * 027 * CRITICAL TIMING * 028 * REQUIRES PAGE BOUND * 029 * CONSIDERATIONS FOR * 030 * CODE AND DATA * 031 * * 032 * -----CODE----- * 033 * * 034 * VIRTUALLY THE ENTIRE * 035 * 'WRITE16' ROUTINE * 036 * MUST NOT CROSS * 037 * PAGE BOUNDARIES. * 038 * * 039 * THE WRITE16, READ16 * 040 * AND RDADR16 SUBRS * 041 * WHICH MUST NOT CROSS * 042 * PAGE BOUNDARIES ARE * 043 * NOTED IN COMMENTS. * 044 * * 045 * -----DATA----- * 046 * * 047 * NBUF1 AND NBUF2 ARE * 048 * 256-BYTE AND 86-BYTE * 049 * NIBL BUFFERS IN RAM. * 050 * BOTH MUST BEGIN ON * 051 * PAGE BOUNDARIES. * 052 * * 053 * NIBLIZING TABLE 'NIBL' *
054 * (64 BYTES) MAPS 6-BIT * ; === Page 25 === 055 * NIBLS INTO VALID 7-BIT * 056 * NIBLS. THIS TABLE * 057 * MUST NOT CROSS A PAGE * 058 * BOUNDARY. * 059 * * 060 * DENIBLIZING TABLE * 061 * 'DNIBL' MAPS 7-BIT * 062 * NIBLS INTO 6-BIT * 063 * NIBLS. IT MUST BEGIN * 064 * ON A PAGE BOUNDARY, * 065 * BUT ONLY DNIBL,$96 TO * 066 * DNIBL,$FF ARE USED. * 067 * * 068 *************************** 069 PAGE 070 *************************** 071 * * 072 * EQUATES * 073 * * 074 *************************** 075 * * 076 * ----PRENIBL16---- * 077 * AND POSTNB16 * 078 * (16-SECTOR FORMAT) * 079 * * 080 *************************** 081 BUF EQU $3E TWO BYTE POINTER. 082 * 083 * POINTS TO 256-BYTE 084 * USER BUFFER ANYWHERE 085 * IN MEMORY. PRENIBL16 086 * CONVERTS USER DATA 087 * (IN BUF) INTO 6-BIT 088 * NIBLS 00ABCDEF IN 089 * NBUF1 AND NBUF2 PRIOR 090 * TO 'WRITE'. POSTNBL16 091 * CONVERTS 6-BIT NIBLS 092 * 00ABCDEF BACK TO USER 093 * DATA IN BUF AFTER 'READ'. 094 * 095 T0 EQU $26 TEMP FOR POSTNBL16 096 ************************ 097 * * 098 * ----RDADR16---- * 099 * * 100 ************************ 101 COUNT EQU $26 'MUST FIND' COUNT. 102 LAST EQU $26 'ODD BIT' NIBLS. 103 CSUM EQU $27 CHECKSUM BYTE. 104 CSSTV EQU $2C FOUR BYTES, ; Read forward, stored in backwards order due to RDA5 105 * CHECKSUM, SECTOR, TRACK, AND VOLUME. 106 * 107 ************************ 108 * * 109 * ---WRITE16--- * 110 * * 111 * USES NBUF1, NBUF2, * 112 * AND 64-BYTE TABLE * 113 * 'NIBL'. * 114 * * 115 ************************ 116 WTEMP EQU $26 TEMP FOR DATA AT NBUF2,0.
117 SLOTZ EQU $27 SLOTNUM IN Z-PAG LOC. ; === Page 26 === 118 SLOTABS EQU $678 SLOTNUM IN NON-ZPAG LOC. 119 * 120 ************************ 121 * * 122 * ----READ16----- * 123 * (16-SECTOR FORMAT) * 124 * * 125 * USES NBUF1,NBUF2. * 126 * USES LAST 106 BYTES * 127 * OF A DATA PAGE FOR * 128 * SIGNIFICANT BYTES * 129 * OF DNIBL16 TABLE. * 130 * * 131 ************************ 132 IDX EQU $26 INDEX INTO (BUF). 133 * 134 ************************ 135 * * 136 * ---- SEEK ---- * 137 * * 138 ************************ 139 TRKCNT EQU $26 HALFTRKS MOVED COUNT. 140 PRIOR EQU $27 PRIOR HALFTRACK. 141 TRKN EQU $2A DESIRED TRACK. 142 SLOTTEMP EQU $2B SLOT NUM TIMES $10. 143 CRKTRK EQU $478 CURRENT TRACK ON ENTRY. ; "Current Track" Drive 1, Why is this defined AGAIN? DRV1TRK 144 * 145 ************************ 146 * * 147 * ---- MSWAIT ---- * 148 * * 149 ************************ 150 MONTIMEL EQU $46 MOTON-ON TIME 151 MONTIMEH EQU $47 COUNTERS. 152 * 153 ************************ 154 * * 155 * ---- WRADR16 ---- * 156 * * 157 ************************ 158 AA EQU $3E ;TIMING CONSTANT ; *sigh* Really people you couldn't pick any other variable name?!, See: DSKFORM 159 NSECT EQU $3F ;SECTOR NUMBER 160 NVOL EQU $41 ;VOLUME NUMBER 161 TRK EQU $44* ;TRACK NUMBER 162 * 163 ************************ 164 * * 165 * DEVICE ADDRESS * 166 * ASSIGNMENTS * 167 * * ; See ONTABLE, and OFFTABLE 168 ************************ ; Typical B.A.D. (Beneath Apple Dos) shenanigans (Page 6-3): 169 PHASEOFF EQU $C080 STEPPER PHASE OFF. ; "The timing between accesses to these locations is 170 PHASEON EQU $C081 STEPPER PHASE ON. ; critical, making this a non-trivial exercise." WHICH IS??? 171 Q6L EQU $C08C Q7L,Q6L=READ ; *sigh* /sarcasm Riiight, because it is _obvious_ what Q7L & Q7H 172 Q6H EQU $C08D Q7L,Q6H=SENSE WPROT ; do -- but let's keep copy/paste these shitty non-descript names! 173 Q7L EQU $C08E Q7H,Q6L=WRITE ; DRIVE_MODE_R 174 Q7H EQU $C08F Q7H,Q6H=WRITE STORE ; DRIVE_MODE_W
001 SBTL '16-SECTOR PRENIBLIZE' 002 **************************** 003 * * 004 * PRENIBLIZE SUBR * 005 * (16-SECTOR FORMAT) * 006 * * 007 **************************** 008 * * 009 * CONVERTS 256 BYTES OF * 010 * USER DATA IN (BUF),0 * 011 * TO (BUF),255 INTO 342 * 012 * 6-BIT NIBLS (00ABCDEF) * 013 * IN NBUF1 AND NBUF2. * 014 * * 015 * ---- ON ENTRY ---- * 016 * * 017 * BUF IS 2-BYTE POINTER * 018 * TO 256 BYTES OF USER * 019 * DATA. * 020 * * 021 * ---- ON EXIT ----- * 022 * * 023 * A-REG UNCERTAIN. * 024 * X-REG HOLDS $FF. * 025 * Y-REG HOLDS $FF. * 026 * CARRY SET. * 027 * * 028 * NBUF1 AND NBUF2 CONTAIN * 029 * 6-BIT NIBLS OF FORM * 030 * 00ABCDEF. * 031 * * 032 **************************** 3800:A2 00 033 PRENIB16 LDX #$0 ;START NBUF2 INDEX. CHANGED BY WOZ 3802:A0 02 034 LDY #2 ;START USER BUF INDEX. CHANGED BY WOZ. 3804:88 035 PRENIB1 DEY ;NEXT USER BYTE. 3805:B1 3E 036 LDA (BUF),Y 3807:4A 037 LSR A ;SHIFT TWO BITS OF 3808:3E 00 3C 038 ROL NBUF2,X ;CURRENT USER BYTE 380B:4A 039 LSR A ;INTO CURRENT NBUF2 380C:3E 00 3C 040 ROL NBUF2,X ;BYTE. 380F:99 00 3B 041 STA NBUF1,Y ;(6 BITS LEFT). 3812:E8 042 INX ;FROM 0 TO $55. 3813:E0 56 043 CPX #$56 3815:90 ED 044 BCC PRENIB1 ;BR IF NO WRAPAROUND. 3817:A2 00 045 LDX #0 ;RESET NBUF2 INDEX. 3819:98 046 TYA ;USER BUF INDEX. 381A:D0 E8 047 BNE PRENIB1 ;(DONE IF ZERO) 381C:A2 55 048 LDX #$55 ;NBUF2 IDX $55 TO 0. 381E:BD 00 3C 049 PRENIB2 LDA NBUF2,X 3821:29 3F 050 AND #$3F ;STRIP EACH BYTE 3823:9D 00 3C 051 STA NBUF2,X ;OF NBUF2 TO 6 BITS. 3826:CA 052 DEX
3827:10 F5 053 BPL PRENIB2 ;LOOP UNTIL X NEG. ; === Page 105 === 3829:60 054 RTS ;RETURN. ; o7 Captain Obvious
001 SBTL '16-SECTOR WRITE' 002 ************************ 003 * * 004 * WRITE SUBR * 005 * (16-SECTOR FORMAT) * 006 * * 007 ************************ 008 * * 009 * WRITES DATA FROM * 010 * NBUF1 AND NBUF2 * 011 * CONVERTING 6-BIT * 012 * TO 7-BIT NIBLS * 013 * VIA 'NIBL' TABLE. * 014 * * 015 * FIRST NBUF2, * 016 * HIGH TO LOW. * 017 * THEN NBUF1, * 018 * LOW TO HIGH. * 019 * * 020 * ---- ON ENTRY ---- * 021 * * 022 * X-REG: SLOTNUM * 023 * TIMES $10. * 024 * * 025 * NBUF1 AND NBUF2 * 026 * HOLD NIBLS FROM * 027 * PRENIBL SUBR. * 028 * (00ABCDEF) * 029 * * 030 * ---- ON EXIT ----- * 031 * * 032 * CARRY SET IF ERROR. * 033 * (W PROT VIOLATION) * 034 * * 035 * IF NO ERROR: * 036 * * 037 * A-REG UNCERTAIN. * 038 * X-REG UNCHANGED. * 039 * Y-REG HOLDS $00. * 040 * CARRY CLEAR. * 041 * * 042 * SLOTABS, SLOTZ, * 043 * AND WTEMP USED. * 044 * * 045 * ---- ASSUMES ---- * 046 * * 047 * 1 USEC CYCLE TIME * 048 * * 049 ************************ 382A:38 050 WRITE16 SEC ;ANTICIPATE WPROT ERR. ; === Reloc @ $B82A === 382B:86 27 051 STX SLOTZ ;FOR ZERO PAGE ACCESS. 382D:8E 78 06 052 STX SLOTABS ;FOR NON-ZERO PAGE. 3830:BD 8D C0 053 LDA Q6H,X
3833:BD 8E C0 054 LDA Q7L,X ;SENSE WPROT FLAG. ; === Page 138 === 3836:30 7C 055 BMI WEXIT ;IF HIGH, THEN ERR. ; v 3838:AD 00 3C 056 LDA NBUF2 383B:85 26 057 STA WTEMP ;FOR ZERO-PAGE ACCESS. 383D:A9 FF 058 LDA #$FF ;SYNC DATA 383F:9D 8F C0 059 STA Q7H,X ;(5) WRITE 1ST NIBL. 3842:1D 8C C0 060 ORA Q6L,X ;(4) 3845:48 061 PHA ;(3) 3846:68 062 PLA ;(4) CRITICAL TIMING! 3847:EA 063 NOP ;(2) 3848:A0 04 064 LDY #4 ;(2) FOR 5 NIBLS. 384A:48 065 WSYNC PHA ;(3) EXACT TIMING ; --- Sync FF --- 384B:68 066 PLA ;(4) EXACT TIMING 384C:20 B9 38 067 JSR WNIBL7 ;(13,9,6) WRITE SYNC 384F:88 068 DEY ;(2) 3850:D0 F8 069 BNE WSYNC ;(2*) MUST NOT CROSS PAGE! ; ^ 3852:A9 D5 070 LDA #$D5 ;(2) 1ST DATA MARK. ; --- Data Header D5 AA AD --- 3854:20 B8 38 071 JSR WNIBL9 ;(15,9,6) 3857:A9 AA 072 LDA #$AA ;(2) 2ND DATA MARK. 3859:20 B8 38 073 JSR WNIBL9 ;(15,9,6) 385C:A9 AD 074 LDA #$AD ;(2) 3RD DATA MARK. 385E:20 B8 38 075 JSR WNIBL9 ;(15,9,6) 3861:98 076 TYA ;(2) CLEAR CHECKSUM 3862:A0 56 077 LDY #$56 ;(2) NBUF2 INDEX. 3864:D0 03 078 BNE WDATA1 ;(3) ALWAYS. NO PAGE CROSS!! ; v 3866:B9 00 3C 079 WDATA0 LDA NBUF2,Y ;(4) PRIOR 6-BIT NIBL. 3869:59 FF 3B 080 WDATA1 EOR NBUF2-1,Y ;(5) XOR WITH CURRENT. 081 * (NBUF2 MUST BE ON PAGE BOUNDARY FOR TIMING!!) 386C:AA 082 TAX ;(2) INDEX To 7-BIT NIBL 386D:BD 29 3A 083 LDA NIBL,X ;(4) MUST NOT CROSS PAGE! 3870:A6 27 084 LDX SLOTZ ;(3) CRITICAL TIMING! 3872:9D 8D C0 085 STA Q6H,X ;(5) WRITE NIBL. 3875:BD 8C C0 086 LDA Q6L,X ;(4) 3878:88 087 DEY ;(2) NEXT NIBL. 3879:D0 EB 088 BNE WDATA0 ;(2*) MUST NOT CROSS PAGE! ; ^ 387B:A5 26 089 LDA WTEMP ;(3) PRIOR NIBL FROM BUF6. 387D:EA 090 NOP ;(2) CRITICAL TIMING. 387E:59 00 3B 091 WDATA2 EOR NBUF1,Y ;(5) XOR WITH CURRENT. 3881:AA 092 TAX ;(2) 3882:BD 29 3A 093 LDA NIBL,X ;(4) 3885:AE 78 06 094 LDX SLOTABS ;(4) TIMING CRITICAL 3888:9D 8D C0 095 STA Q6H,X ;(5) WRITE NIBL. 388B:BD 8C C0 096 LDA Q6L,X ;(4) 388E:B9 00 3B 097 LDA NBUF1,Y ;(4) PRIOR 6-BIT NIBL. 3891:C8 098 INY ;(2)NEXT NBUF1 NIBL. 3892:D0 EA 099 BNE WDATA2 ;(2*) MUST NOT CROSS PAGE! ; ^ 3894:AA 100 TAX ;(2) 3895:BD 29 3A 101 LDA NIBL,X ;(4) INDEX TO 7-BIT NIBL 3898:A6 27 102 LDX SLOTZ ;(3) 389A:20 BB 38 103 JSR WNIBL ;(6,9,6) WRITE CHKSUM 389D:A9 DE 104 LDA #$DE ;(2) DM4, BIT SLIP MARK. ; magic number TODO 389F:20 B8 38 105 JSR WNIBL9 ;(15,9,6) WRITE IT. 38A2:A9 AA 106 LDA #$AA ;(2) DM5, BIT SLIP MARK. 38A4:20 B8 38 107 JSR WNIBL9 ;(15,9,6) WRITE IT. 38A7:A9 EB 108 LDA #$EB ;(2) DM6, BIT SLIP MARK. 38A9:20 B8 38 109 JSR WNIBL9 ;(15,9,6) WRITE IT. 38AC:A9 FF 110 LDA #$FF ;(2) TURN-OFF BYTE. 38AE:20 B8 38 111 JSR WNIBL9 ;(15,9,9) WRITE IT. ; TODO: 15,9,6?? 38B1:BD 8E C0 112 LDA Q7L,X ;OUT OF WRITE MODE. 38B4:BD 8C C0 113 WEXIT LDA Q6L,X ;TO READ MODE. 38B7:60 114 RTS ;RETURN FROM WRITE. 115 ***************************** 116 * *
117 * 7-BIT NIBL WRITE SUBRS * ; === WRITRTN, Page 139 === 118 * * 119 * A-REG OR'D PRIOR EXIT * 120 * CARRY CLEARED * 121 * * 122 ***************************** 38B8:18 123 WNIBL9 CLC ; (2) 9 CYCLES, THEN WRITE. 38B9:48 124 WNIBL7 PHA ; (3) 7 CYCLES, THEN WRITE. 38BA:68 125 PLA ; (4) 38BB:9D 8D C0 126 WNIBL STA Q6H,X ; (5) NIBL WRITE SUB. 38BE:1D 8C C0 127 ORA Q6L,X ; (4) CLOBBERS ACC, NOT CARRY 38C1:60 128 RTS
001 SBTL '16-SECTOR POSTNIBLIZE' 002 *************************** 003 * * 004 * POSTNIBLIZE SUBR * 005 * 16-SECTOR FORMAT * 006 * * 007 *************************** 008 * * 009 * CONVERTS 6-BIT NIBLS * 010 * OF FORM 00ABCDEF IN * 011 * NBUF1 AND NBUF2 INTO * 012 * 256 BYTES OF USER * 013 * DATA IN BUF. * 014 * * 015 * ---- ON ENTRY ---- * 016 * * 017 * X-REG: HOLDS SLOTNUM * 018 * TIMES $10. * 019 * * 020 * BUF IS 2-BYTE POINTER * 021 * TO 256 BYTES OF USER * 022 * DATA TO BE CONVERTED * 023 * TO 6-BIT NIBLS IN * 024 * NBUF1 AND NBUF2 * 025 * PRIOR TO WRITE. * 026 * * 027 * T0 CONTAINS BYTE COUNT * 028 * CODE0 = 256 BYTES * 029 * CODE1 = 1 BYTE * 030 * CODE2 = 2 BYTER * 031 * * 032 * CODE 255=255 BYTES * 033 * * 034 * ---- ON EXIT ----- * 035 * * 036 * A-REG UNCERTAIN. * 037 * Y-REG SAME AS T0. * 038 * X-REG UNCERTAIN. * 039 * CARRY SET. * 040 * * 041 * 6-BIT NIBLS OF FORM * 042 * 00ABCDEF IN NBUF1 * 043 * AND NBUF2. * 044 * (342 NIBLS) * 045 *************************** 38C2:A0 00 046 POSTNB16 LDY #$0 ; USER DATA BUF IDX. ; T0S2 TODO 38C4:A2 56 047 POST1 LDX #$56 ; INIT NBUF2 INDEX. 38C6:CA 048 POST2 DEX ; NBUF IDX $55 TO $0 38C7:30 FB 049 BMI POST1 ; WRAPAROUND IF NEG. ;↑ 38C9:B9 00 3B 050 LDA NBUF1,Y 38CC:5E 00 3C 051 LSR NBUF2,X ; SHIFT 2 BITS FROM 38CF:2A 052 ROL A ; CURRENT NBUF2 NIBL 38D0:5E 00 3C 053 LSR NBUF2,X ; INTO CURRENT NBUF1
38D3:2A 054 ROL A NIBL. ; === Page 102 === 38D4:91 3E 055 STA (BUF),Y BYTE OF USER DATA. 38D6:C8 056 INY NEXT USER BYTE. 38D7:C4 26 057 CPY T0 DONE IF EQUAL T0. 38D9:D0 EB 058 BNE POST2 ; ^ 38DB:60 059 RTS RETURN. 060 SBTL '16-SECTOR READ' 061 ************************** 062 * * 063 * READ SUBROUTINE * 043 * (16-SECTOR FORMAT) * 065 * * 066 ************************** 067 * * 068 * READS 6-BIT NIBLS * 069 * (00ABCDEF) INTO * 070 * NBUF1 and NBUF2 * 071 * CONVERTING 7-BIT * 072 * NIBLS TO 7-BIT * 073 * VIA 'DNIBL' TABLE * 074 * * 075 * FIRST READS NBUF2 * 076 * HIGH TO LOW * 077 * THEN READS NBUF1 * 078 * LOW TO HIGH * 079 * * 080 * ---- ON ENTRY ---- * 081 * * 082 * X-REG: SLOTNUM * 083 * TIMES $10. * 084 * * 085 * READ MODE (Q6L, Q7L) * 086 * * 087 * ---- ON EXIT ----- * 088 * * 089 * CARRY SET IF ERROR * 090 * * 091 * IF NO ERROR: * 092 * A-REG HOLDS $AA. * 093 * X-REG UNCHANGED. * 094 * Y-REG HOLDS $00. * 095 * CARRY CLEAR. * 096 * * 097 * NBUF1 AND NBUF2 * 098 * HOLD 6-BIT NIBLS * 099 * (00ABCDEF) * 100 * * 101 * USES TEMP 'IDX'. * 102 * * 103 * ---- CAUTION ----- * 104 * * 105 * OBSERVE * 106 * 'NO PAGE CROSS' * 107 * WARNIGNS ON * 108 * SOME BRANCHES!! * 109 * * 110 * ---- ASSUMES ---- * 111 * * 112 * 1 USEC CYCLE TIME * 113 * * 114 ************************** 38DC:A0 20 115 READ16 LDY #$20 'MUST FIND' COUNT. 38DE:88 116 RSYNC DEY IF CAN'T FIND MARKS
38DF:F0 61 117 BEQ RDERR ;THEN EXIT WITH CARRY SET ; === Page 103 === 38E1:BD 8C C0 118 READ1 LDA Q6L,X READ NIBL. 38E4:10 FB 119 BPL READ1 *** NO PAGE CROSS! *** 38E6:49 D5 120 RSYNC1 EOR #$D5 DATA MARK 1? 38E8:D0 F4 121 BNE RSYNC LOOP IF NOT. 38EA:EA 122 NOP DELAY BETWEEN NIBLS. 38EB:BD 8C C0 123 READ2 LDA Q6L,X 38EE:10 FB 124 BPL READ2 *** NO PAGE CROSS! *** 38F0:C9 AA 125 CMP #$AA DATA MARK 2? 38F2:D0 F2 126 BNE RSYNC1 (IF NOT, IS IT DM1?) ; NUM_6N2_NIBBLES = 342 38F4:A0 56 127 LDY #$56 INIT NBUF2 INDEX ; magic number NUM_6N2_NIBBLES - 256 128 * (ADDED NIBL DELAY) 38F6:BD 8C C0 129 READ3 LDA Q6L,X 38F9:10 FB 130 BPL READ3 *** NO PAGE CROSS! *** 38FB:C9 AD 131 CMP #$AD DATA MARK 3? 38FD:D0 E7 132 BNE RSYNC1 133 * (CARRY SET IF DM3!) ; And this imporant why?? 38FF:A9 00 134 LDA #$00 INIT CHECKSUM 3901:88 135 RDATA1 DEY 3902:84 26 136 STY IDX 3904:BC 8C C0 137 READ4 LDY Q6L,X 3907:10 FB 138 BPL READ4 *** NO PAGE CROSS! *** 3909:59 00 3A 139 EOR DNIBL,Y XOR 6-BIT NIBL. 390C:A4 26 140 LDY IDX 390E:99 00 3C 141 STA NBUF2,Y STORE IN NBUF2 PAGE. 3911:D0 EE 142 BNE RDATA1 TAKEN IF Y-REG NONZERO. 3913:84 26 143 RDATA2 STY IDX 3915:BC 8C C0 144 READ5 LDY Q6L,X 3918:10 FB 145 BPL READ5 *** NO PAGE CROSS! *** 391A:59 00 3A 146 EOR DNIBL,Y XOR 6-BIT NIBL. 391D:A4 26 147 LDY IDX 391F:99 00 3B 148 STA NBUF1,Y STORE IN NBUF1 PAGE. 3922:C8 149 INY 3923:D0 EE 150 BNE RDATA2 3925:BC 8C C0 151 READ6 LDY Q6L,X READ 7-BIT CSUM NIBL. 3928:10 FB 152 BPL READ6 *** NO PAGE CROSS! *** 392A:D9 00 3A 153 CMP DNIBL,Y IF LAST NBUF1 NIBL NOT 392D:D0 13 154 BNE RDERR EQUAL CHKSUM NIBL THEN ERR. 392F:BD 8C C0 155 READ7 LDA Q6L,X 3932:10 FB 156 BPL READ7 *** NO PAGE CROSS! *** 3934:C9 DE 157 CMP #$DE FIRST BIT SLIP MARK? 3936:D0 0A 158 BNE RDERR (ERR IF NOT) 3938:EA 159 NOP DELAY BETWEEN NIBLS. 3939:BD 8C C0 160 READ8 LDA Q6L,X 393C:10 FB 161 BPL READ8 *** NO PAGE CROSS! *** 393E:C9 AA 162 CMP #$AA SECOND BIT SLIP MARK? 3940:F0 5C 163 BEQ RDEXIT (DONE IF IT IS) 3942:38 164 RDERR SEC INDICATE 'ERROR EXIT'. 3943:60 165 RTS FROM READ16 OR RDADR16.
001 SBTL '16-SECTOR READ ADDRESS' 002 **************************** 003 * * 004 * READ ADDRESS FIELD * 005 * SUBROUTINE * 006 * (16-SECTOR FORMAT) * 007 * * 008 **************************** 009 * * 010 * READS VOLUME, TRACK * 011 * AND SECTOR * 012 * * 013 * ---- ON ENTRY ---- * 014 * * 015 * XREG: SLOTNUM TIMES $10 * 016 * * 017 * READ MODE (Q6L, Q7L) * 018 * * 019 * ---- ON EXIT ----- * 020 * * 021 * CARRY SET IF ERROR. * 022 * * 023 * IF NO ERROR: * 024 * A-REG HOLDS $AA. * 025 * Y-REG HOLDS $00. * 026 * X-REG UNCHANGED. * 027 * CARRY CLEAR. * 028 * * 029 * CSSTV HOLDS CHKSUM, * 030 * SECTOR, TRACK, AND * 031 * VOLUME READ. * 032 * * 033 * USES TEMPS COUNT, * 034 * LAST, CSUM, AND * 035 * 4 BYTES AT CSSTV. * 036 * * 037 * ---- EXPECTS ---- * 038 * * 039 * ORIGINAL 10-SECTOR * 040 * NORMAL DENSITY NIBLS * 041 * (4-BIT), ODD BITS, * 042 * THEN EVEN. * 043 * * 044 * ---- CAUTION ---- * 045 * * 046 * OBSERVE * 047 * 'NO PAGE CROSS' * 048 * WARNINGS ON * 049 * SOME BRANCHES!! * 050 * * 051 * ---- ASSUMES ---- * 052 * * 053 * 1 USEC CYCLE TIME *
054 * * ; === Page 107 === 055 **************************** 3944:A0 FC 056 RDADR16 LDY #$FC 3946:84 26 057 STY COUNT 'MUST FIND' COUNT. 3948:C8 058 RDASYN INY 3949:D0 04 059 BNE RDA1 LOW ORER OF COUNT. 394B:E6 26 060 INC COUNT (2K NIBLS TO FIND) 394D:F0 F3 061 BEQ RDERR (ADR MARK, ELSE ERR) 394F:BD 8C C0 062 RDA1 LDA Q6L,X READ NIBL. 3952:10 FB 063 BPL RDA1 *** NO PAGE CROSS! *** 3954:C9 D5 064 RDASN1 CMP #$D5 ADR MARK 1? ; magic number DISK_ADR_PROLOG_1 EQU #$D5 3956:D0 F0 065 BNE RDASYN (LOOP IF NOT) 3958:EA 066 NOP ADDED NIBL DELAY. 3959:BD 8C C0 067 RDA2 LDA Q6L,X 395C:10 FB 068 BPL RDA2 *** NO PAGE CROSS! *** 395E:C9 AA 069 CMP #$AA ADR MARK 2? ; magic number DISK_ADR_PROLOG_2 EQU #$AA 3960:D0 F2 070 BNE RDASN1 (IF NOT, IS IT AM1?) 3962:A0 03 071 LDY #$3 INDEX FOR 4-BYTE READ. ; Technically, we read 8 disk nibbles &rarrow; 4 memory bytes 072 * (ADDED NIBL DELAY) 3964:BD 8C C0 073 RDA3 LDA Q6L,X 3967:10 FB 074 BPL RDA3 *** NO PAGE CROSS! *** 3969:C9 96 075 CMP #$96 ADR MARK 3? ; magic number DISK_ADR_PROLOG_3 EQU #$96 396B:D0 E7 076 BNE RDASN1 (IF NOT, IS IT AM1?) 077 * (LEAVES CARRY SET!) ; C=1, And this important WHY? Carry becomes Bit 0 of 4&4 Checksum odd nibble, Line #082 396D:A9 00 078 LDA #$0 INIT CHECKSUM. 396F:85 27 079 RDAFLD STA CSUM 3971:BD 8C C0 080 RDA4 LDA Q6L,X READ 'ODD BIT' NIBL. ; Technically, read odd bits 3974:10 FB 081 BPL RDA4 *** NO PAGE CROSS! *** ; A=1a1c1e1g 3976:2A 082 ROL A ;ALIGN ODD BITS, '1' into LSB. ; A=a1c1e1gC, and C stays set 3977:85 26 083 STA LAST 3979:BD 8C C0 084 RDA5 LDA Q6L,X READ 'EVEN BIT' NIBL. ; Technically, read even bits 397C:10 FB 085 BPL RDA5 *** NO PAGE CROSS! *** ; A=1b1d1f1h 397E:25 26 086 AND LAST MERGE ODD AND EVEN BITS ; &=a1c1e1g1 3980:99 2C 00 087 STA CSSTV,Y STORE DATA BYTE. ; A=abcdefgh, Store bytes in reverse order due to Y counting down 3983:45 27 088 EOR CSUM XOR CHECKSUM 3985:88 089 DEY 3986:10 E7 090 BPL RDAFLD LOOP ON 4 DATA BYTES. 3988:A8 091 TAY IF FINAL CHECKSUM 3989:D0 B7 092 BNE RDERR NONZERO, THEN ERROR. 398B:BD 8C C0 093 RDA6 LDA Q6L,X FIRST BIT-SLIP NIBL. 398E:10 FB 094 BPL RDA6 *** NO PAGE CROSS! *** 3990:C9 DE 095 CMP #$DE ; magic number DISK_ADR_EPILOG_1 EQU #$DE 3992:D0 AE 096 BNE RDERR ERROR IF NONMATCH. 3994:EA 097 NOP DELAY BETWEEN NIBLS. 3995:BD 8C C0 098 RDA7 LDA Q6L,X SECOND BIT-SLIP NIBL. 3998:10 FB 099 BPL RDA7 *** NO PAGE CROSS! *** 399A:C9 AA 100 CMP #$AA ; magic number DISK_ADR_EPILOG_2 EQU #$AA 399C:D0 A4 101 BNE RDERR ERROR IF NONMATCH. ; Uh, what happened to checking the last disk nibble!?!?! DISK_ADR_EPILOG_3 EQU #$EB 399E:18 102 RDEXIT CLC CLEAR CARRY ON ; This probably deserves a "No shit, Sherlock" 399F:60 103 RTS NORMAL READ EXITS. ; Brilliant hardware engineers tend to clutter up code with useless trivial comments. :-/ 104 SBTL '16-SECTOR SEEK' 105 ************************** 106 * * 107 * FAST SEEK SUBROUTINE * ; A fast seek is completely useless 108 * * ; if READING forces extra disk spins due to buffer bloat 109 ************************** 110 * * 111 * ---- ON ENTRY ---- * 112 * * 113 * X-REG HOLDS SLOTNUM * 114 * TIMES $10. * 115 * * 116 * A-REG HOLDS DESIRED *
117 * HALFTRACK, * ; === Page 108 === 118 * (SINGLE PHASE) * 119 * * 120 * CURTRK HOLDS CURRENT * 121 * HALFTRACK. * 122 * * 123 * ---- ON EXIT ----- * 124 * * 125 * A-REG UNCERTAIN. * 126 * Y-REG UNCERTAIN. * 127 * X-REG UNCERTAIN. * 128 * * 129 * CURTRK AND TRKN HOLD * 130 * FINAL HALFTRACK. * 131 * * 132 * PRIOR HOLDS PRIOR * 133 * HALFTRACK IF SEEK * 134 * WAS REQUIRED. * 135 * * 136 * MONTIMEL AND MONTIMEH * 137 * ARE INCREMENTED BY * 138 * THE NUMBER OF * 139 * 100 USEC QUANTUMS * 140 * REQUIRED BY SEEK * 141 * FOR MOTOR ON TIME * 142 * OVERLAP. * 143 * * 144 * --- VARIABLES USED --- * 145 * * 146 * CURTRK, TRKN, COUNT, * 147 * PRIOR, SLOTTEMP * 148 * MONTIMEL, MONTIMEH * 149 * * 150 ************************** 39A0:86 2B 151 SEEK STX SLOTTEMP ;SAVE X-REG 39A2:85 2A 152 STA TRKN ;SAVE TARGET TRACK 39A4:CD 78 04 153 CMP CURTRK ON DESIRED TRACK? ; 39A7:F0 53 154 BEQ SEEKRTS ;YES, RETURN 39A9:A9 00 155 LDA #$0 39AB:85 26 156 STA TRKCNT ;HALFTRACK COUNT. 39AD:AD 78 04 157 SEEK2 LDA CURTRK ;SAVE CURTRK FOR 39B0:85 27 158 STA PRIOR ; DELAYED TURNOFF. 39B2:38 159 SEC 39B3:E5 2A 160 SBC TRKN ;DELTA-TRACKS. 39B5:F0 33 161 BEQ SEEKEND ;BR IF CURTRK=DESTINATION 39B7:B0 07 162 BCS OUT (MOVE OUT, NOT IN) 39B9:49 FF 163 EOR #$FF CALC TRKS TO GO 39BB:EE 78 04 164 INC CURTRK INCR CURRENT TRACK (IN). 39BE:90 05 165 BCC MINTST (ALWAYS TAKEN) 39C0:69 FE 166 OUT ADC #$FE CALC TRKS TO GO. 39C2:CE 78 04 167 DEC CURTRK DECR CURRENT TRACK (OUT). 39C5:C5 26 168 MINTST CMP TRKCNT ; crappy abbreviation: Min Test 39C7:90 02 169 BCC MAXTST AND 'TRKS MOVED'. 39C9:A5 26 170 LDA TRKCNT ; crappy abbreviation: Max Test 39CB:C9 0C 171 MAXTST CMP #$C ; magic number ON_TIME_SIZE EQU $C, or even OFFTABLE - ONTABLE 39CD:B0 01 172 BCS STEP2 ;IF TRKCNT>$B LEAVE Y ALONE (Y=$B). 39CF:A8 173 STEP TAY ;ELSE SET ACCELERATION INDEX IN Y 174 STEP2 EQU * 39D0:38 175 SEC ;CARRY SET=PHASE ON 39D1:20 EE 39 176 JSR SETPHASE ;PHASE ON 39D4:B9 11 3A 177 LDA ONTABLE,Y FOR 'ONTIME'. 39D7:20 00 3A 178 JSR MSWAIT (100 USEC INTERVALS) 179 *
39DA:A5 27 180 LDA PRIOR ; === Page 109 === 39DC:18 181 CLC ;CARRY CLEAR=PHASE OFF 39DD:20 F1 39 182 JSR CLRPHASE ;PHASE OFF 39E0:B9 1D 3A 183 LDA OFFTABLE,Y THEN WAIT 'OFFTIME'. 39E3:20 00 3A 184 JSR MSWAIT (100 USEC INTERVALS) 39E6:E6 26 185 INC TRKCNT 'TRACKS MOVED' COUNT. 39E8:D0 C3 186 BNE SEEK2 (ALWAYS TAKEN) 187 * 188 SEEKEND EQU * 39EA:20 00 3A 189 JSR MSWAIT ;A=0: WAIT 25 MS SETTLE 39ED:18 190 CLC 191 * 192 * TURN HEAD STEPPER PHASE ON/OFF 193 * 194 SETPHASE EQU * 39EE:AD 78 04 195 LDA CURTRK ;GET CURRENT PHASE 196 CLRPHASE EQU * 39F1:29 03 197 AND #3 ;MASK FOR 1 OF 4 PHASES 39F3:2A 198 ROL A ;DOUBLE FOR PHASE INDEX 39F4:05 2B 199 ORA SLOTTEMP 39F6:AA 200 TAX 39F7:BD 80 C0 201 LDA PHASEOFF,X ;FLIP THE PHASE 39FA:A6 2B 202 LDX SLOTTEMP ;RESTORE X-REG 39FC:60 203 SEEKRTS RTS ;AND RETURN ; /sarcasm I don't know what we would do without you Captain Obvious!
001 SBTL '16-SECTOR MSWAIT' 002 ************************** 003 * MSWAIT SUBROUTINE * 004 ************************** 005 * * 006 * DELAYS A SPECIFIED * 007 * NUMBER OF 100 USEC * 008 * INTERVALS FOR MOTOR * 009 * ON TIMING. * 010 * * 011 * ---- ON ENTRY ---- * 012 * A-REG: HOLDS NUMBER * 013 * OF 100 USEC * 014 * INTERVALS TO * 015 * DELAY. * 016 * * 017 * ---- ON EXIT ----- * 018 * A-REG: HOLDS $00. * 019 * X-REG: HOLDS $00. * 020 * Y-REG: UNCHANGED. * 021 * CARRY: SET. * 022 * * 023 * MONTIMEL, MONTIMEH * 024 * ARE INCREMENTED ONCE * 025 * PER 100 USEC INTERVAL* 026 * FOR MOTON ON TIMING. * 027 * ---- ASSUMES ---- * 028 * 1 USEC CYCLE TIME * 029 ************************** 39FD:00 00 00 030 DS 3,0 ;AVOID PAGE BOUNDARY CROSSING...; T0S3 @ $FC wastes 3 bytes 3A00:A2 11 031 MSWAIT LDX #$11 ; === T0S4 === *sigh* Typical bloated code ... 3A02:CA 032 MSW1 DEX DELAY 86 USEC. ; ... should just adjust algorithm timing instead! 3A03:D0 FD 033 BNE MSW1 3A05:E6 46 034 INC MONTIMEL 3A07:D0 02 035 BNE MSW2 ; DOUBLE-BYTE 3A09:E6 47 036 INC MONTIMEH INCREMENT. 3A0B:38 037 MSW2 SEC 3A0C:E9 01 038 SBC #$1 DONE 'N' INTERVALS? 3A0E:D0 F0 039 BNE MSWAIT (A-REG COUNTS) 3A10:60 040 RTS 041 AEC1 EQU * ;TELL RELOCATOR WHERE CORE ENDS 042 ************************** 043 * PHASE ON-, OFF-TIME * 044 * TABLES IN 100-USEC * 045 * INTERVALS. (SEEK) * 046 ************************** 3A11:01 30 28 047 ONTABLE DFB 1,$30,$28 ; See RDADSEK, Page 108, Line #TODO 3A14:24 20 1E 048 DFB $24,$20,$1E 3A17:1D 1C 1C 049 DFB $1D,$1C,$1C 3A1A:1C 1C 1C 050 DFB $1C,$1C,$1C 3A1D:70 2C 26 051 OFFTABLE DFB $70,$2C,$26 ; See RDADSEK Page 109, Line #183 3A20:22 1F 1E 052 DFB $22,$1F,$1E 3A23:1D 1C 1C 053 DFB $1D,$1C,$1C
3A26:1C 1C 1C 054 DFB $1C,$1C,$1C ; === Page 98 === 055 SBTL '16-SECTOR NYBBLE TABLES' 056 *************************** 057 * * 058 * 6-BIT TO 7-BIT * 059 * NIBL CONVERSION TABLE * 060 * * 061 *************************** 062 * * 063 * CODES WITH MORE THAN * 064 * ONE PAIR OF ADJACENT * 065 * ZEROES OR WITH NO * 066 * ADJACENT ONES (EXCEPT * 067 * B7) ARE EXCLUDED. * 068 * * 069 * THIS TABLE MAY *NOT* * 070 * CROSS A PAGE BOUNDARY! * 071 * * 072 *************************** 3A29:96 97 9A 073 NIBL DFB $96,$97,$9A ; /sarcasm, Gee if only 3A2C:9B 9D 9E 074 DFB $9B,$9D,$9E ; there was a HEX pseudo-mnemonic 3A2F:9F A6 A7 075 DFB $9F,$A6,$A7 ; so we could group these in 4 bytes ... 3A32:AB AC AD 076 DFB $AB,$AC,$AD ; ... maybe one day. :) 3A35:AE AF B2 077 DFB $AE,$AF,$B2 ; NOTE: Also see NIBL and PD2 3A38:B3 B4 B5 078 DFB $B3,$B4,$B5 3A3B:B6 B7 B9 079 DFB $B6,$B7,$B9 3A3E:BA BB BC 080 DFB $BA,$BB,$BC 3A41:BD BE BF 081 DFB $BD,$BE,$BF 3A44:CB CD CE 082 DFB $CB,$CD,$CE 3A47:CF D3 D6 083 DFB $CF,$D3,$D6 3A4A:D7 D9 DA 084 DFB $D7,$D9,$DA 3A4D:DB DC DD 085 DFB $DB,$DC,$DD 3A50:DE DF E5 086 DFB $DE,$DF,$E5 3A53:E6 E7 E9 087 DFB $E6,$E7,$E9 3A56:EA EB EC 088 DFB $EA,$EB,$EC 3A59:ED EE EF 089 DFB $ED,$EE,$EF 3A5C:F2 F3 F4 090 DFB $F2,$F3,$F4 3A5F:F5 F6 F7 091 DFB $F5,$F6,$F7 3A62:F9 FA FB 092 DFB $F9,$FA,$FB 3A65:FC FD FE 093 DFB $FC,$FD,$FE 3A68:FF 094 DFB $FF 095 PAGE 096 *************************** 097 * 7-BIT TO 6-BIT * 098 * 'DENIBLIZE' TABL * 099 * (16-SECTOR FORMAT) * 100 * * 101 * VALID CODES * 102 * $96 TO $FF ONLY. * 103 * * 104 * * 105 * CODES WITH MORE THAN * 106 * ONE PAIR OF ADJACENT * 107 * ZEROES OR WITH NO * 108 * ADJACENT ONES (EXCEPT * 109 * BIT 7) ARE EXCLUDED. * 110 * * 111 * THIS TABLE *MUST* BE * 112 * ALIGNED AT THE END OF * 113 * A PAGE IN MEMORY!!! * 114 *************************** 115 XP EQU <* ;CURRENT PAGE ADDRESS 116 DNIBL EQU 256*XP ;DNIBL TABLE PAGE ; See READ4
117 PAGE ; === Page 99 === 118 *********************************************** 119 * 120 * GHOST APPEND BUG PATCH BY 121 * BILL GRIMM 122 * 123 *********************************************** 124 PSC1 EQU * ;Tell relocater where to start 125 MOVEOF EQU * ; Called from DOSGO2A 3A69:AE 5F 2A 126 LDX CMDNO ; GET CMD NUMBER 3A6C:E0 1C 127 CPX #$1C ; APPEND COMMAND? ; magic number TODO 3A6E:F0 05 128 BEQ GOON ; YES, RETURN TO CALLING ROUTINE 3A70:A2 00 129 LDX #$00 ; NO, THEN CLEAR X ; Aye, Aye, Captain Obvious 3A72:8E 5D 36 130 STX EOFFLAG ; CLEAR EOF FLAG 3A75:60 131 GOON RTS 132 SKP 4 133 *********************************************** 134 * 135 * TURN Apple //e 80 COLUMN CARD 136 * OFF & INIT APPLE 137 * 138 *********************************************** 139 OFF80 EQU * 3A76:A9 FF 140 LDA #$FF 3A78:8D FB 04 141 STA $4FB ; CLEARS FUNNY 80 COL STUFF ; magic number TEXT screen hole TODO 3A7B:8D 0C C0 142 STA $C00C ; TURNS 80 COL OFF 3A7E:8D 0E C0 143 STA $C00E ; TURN OFF ALT CHAR SET ; /sarcasm If only we could define symbols ... 3A81:4C 2F FB 144 JMP $FB2F ; MONITOR INIT ROUTINE ; Oh wait! We already have MONINIT in BOOTLDR ; === DOS 3.3B 1983 ONLY === ; Called from GOBACK+5 = $3683 ; Note: "Apple II DOS 3.3 C Source Code Listing" has the old DOS 3.3B TEMPY.pretty on Page 128 ; DOS 3.3C shows this got relocated to $36B3 via the hex dump "DOS33C.OBJ" D/001B80: on Page 36 FIXIT2 EQU * LDA CCBBYT ;3A84:AD BD 35 STA DCBCSB ;3A87:8D E6 35 STA DCBCRR ;3A8A:8D EA 35 TSX ;3A8D:BA STX ENTSTK ;3A8E:8E 9B 33 JMP GOODIO ;3A91:4C 7F 33 ; === DOS 3.3B 1983 === 145 PAGE 146 PEC1 EQU * ;Tell relocater where to stop ; See CDETAB, RELOCTR, Page 115 147 PD1 EQU >* 148 PD2 EQU $96-PD1 ; $96 - $84 = $12 3A84:00 00 00 00 149 DS PD2,0 ;Must pad to $XX96 ; [.. *wastes* 18 bytes 3A88:00 00 00 00 ; .. No, no, no! 3A8C:00 00 00 00 ; .. Negative array index OFFSETS like the P6 PROM uses 3A90:00 00 00 00 ; .. 3A94:00 00 ; ..] 3A96:00 01 98 150 DFB $00,$01,$98 ; 96 97 -- *sigh* And the comment that this is the 3A99:99 02 03 151 DFB $99,$02,$03 ; -- 9A 9B 64 disk nibbles of 6&2 Read Table 3A9C:9C 04 05 152 DFB $9C,$04,$05 ; -- 9D 9E is where again? Comments people, comments! 3A9F:06 A0 A1 153 DFB $06,$A0,$A1 ; 9F -- -- Hey, after annotating 154 pages 3AA2:A2 A3 A4 154 DFB $A2,$A3,$A4 ; -- -- -- you would be grumpy too. :-) 3AA5:A5 07 08 155 DFB $A5,$07,$08 ; -- A6 A7 3AA8:A8 A9 AA 156 DFB $A8,$A9,$AA ; -- -- !! (!! Technically AA is a valid disk nibble) 3AAB:09 0A 0B 157 DFB $09,$0A,$0B ; AB AC AD but it reserved for a 3 byte header id 3AAE:0C 0D B0 158 DFB $0C,$0D,$B0 ; AE AF -- Typical DOS 3.3 B-L-O-A-T 3AB1:B1 0E 0F 159 DFB $B1,$0E,$0F ; -- B2 B3 One reserved byte D5 could be used for T/S header. HEAD = 8EAD i.e. D5 8E, or D5 8E AD 3AB4:10 11 12 160 DFB $10,$11,$12 ; B4 B5 B6 One reserved byte D5 could be used for Data header. DATA = DA1A i.e. D5 DA, or D5 DA 1A 3AB7:13 B8 14 161 DFB $13,$B8,$14 ; B7 -- B9 But since we have 66 valid disk nibbles reservering two for meta-data is OK. 3ABA:15 16 17 162 DFB $15,$16,$17 ; BA BB BC But we could pack more data on a track the more disk nibbles we use. i.e. 19 sectors/track. 3ABD:18 19 1A 163 DFB $18,$19,$1A ; BD BE BF 3AC0:C0 C1 C2 164 DFB $C0,$C1,$C2 ; -- -- -- [.. *wastes* 11 bytes (unused) 3AC3:C3 C4 C5 165 DFB $C3,$C4,$C5 ; -- -- -- .. /sarcasm But who cares, we have 48K right!? 3AC6:C6 C7 C8 166 DFB $C6,$C7,$C8 ; -- -- -- .. This is why DOS takes seconds longer to boot. 3AC9:C9 CA 1B 167 DFB $C9,$CA,$1B ; -- -- CB ..] 3ACC:CC 1C 1D 168 DFB $CC,$1C,$1D ; -- CD CE *sigh* This entire table can be compactly 3ACF:1E D0 D1 169 DFB $1E,$D0,$D1 ; CF -- -- represented with 8 lines instead of 36 lines 3AD2:D2 1F D4 170 DFB $D2,$1F,$D4 ; -- D3 -- If only we had a HEX pseudo-mnemonic ... 3AD5:D5 20 21 171 DFB $D5,$20,$21 ; @@ D6 D7 (@@ Technically D5 is valid but is reserved too) 3AD8:D8 22 23 172 DFB $D8,$22,$23 ; -- D9 DA x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF 3ADB:24 25 26 173 DFB $24,$25,$26 ; DB DC DD 9x:-- -- -- -- -- -- 00 01 -- -- 02 03 -- 04 05 06 3ADE:27 28 E0 174 DFB $27,$28,$E0 ; DE DF -- Ax:-- -- -- -- -- -- 07 08 -- -- !! 09 0A 0B 0C 0D 3AE1:E1 E2 E3 175 DFB $E1,$E2,$E3 ; -- -- -- Bx:-- -- 0E 0F 10 11 12 13 -- 14 15 16 17 18 19 1A 3AE4:E4 29 2A 176 DFB $E4,$29,$2A ; -- E5 E6 Cx:-- -- -- -- -- -- -- -- -- -- -- 1B -- 1C 1D 1E 3AE7:2B E8 2C 177 DFB $2B,$E8,$2C ; E7 -- E9 Dx:-- -- -- 1F -- @@ 20 21 -- 22 23 24 25 26 27 28 3AEA:2D 2E 2F 178 DFB $2D,$2E,$2F ; EA EB EC Ex:-- -- -- -- -- 29 2A 2B -- 2C 2D 2E 2F 30 31 32 3AED:30 31 32 179 DFB $30,$31,$32 ; ED EE EF Fx:-- -- 33 34 35 36 37 38 -- 39 3A 3B 3C 3D 3E 3F
3AF0:F0 F1 33 180 DFB $F0,$F1,$33 ; -- -- F2 === Page 100 === 3AF3:34 35 36 181 DFB $34,$35,$36 ; F3 F4 F5 3AF6:37 38 F8 182 DFB $37,$38,$F8 ; F6 F7 -- 3AF9:39 3A 3B 183 DFB $39,$3A,$3B ; F9 FA FB 3AFC:3C 3D 3E 184 DFB $3C,$3D,$3E ; FC FD FE 3AFF:3F 185 DFB $3F ; FF 186 PAGE 187 *************************** 188 * * 189 * NYBBLE BUFFERS * 190 * * 191 * NBUF1 (256 BYTES) MUST * 192 * BE ALIGNED ON A PAGE * 193 * BOUNDARY. * 194 * * 195 * NBUF2 (86 BYTES) MUST * ; Incorrect: NBUF2 must _not_ cross 196 * BE ALIGNED ON A PAGE * ; a page boundary. Technically, it can be 197 * BOUNDARY. * ; anywhere *within* the page as long as the 198 * * ; code at WRITRTN, Line #>80 is fixed up. 199 *************************** ; 200 * ; 3B00:00 00 00 00 201 NBUF1 DS 256,0 ;NBUF1 ; === T0S5 === disk sector wasted with zeroes 3B04:00 00 00 00 ; *sigh* Let's waste an *entire* sector 3B08:00 00 00 00 ; with 342 disk nibbles of raw $96 nibbles 3B0C:00 00 00 00 ; PLUS the time decoding it 3B10:00 00 00 00 ; when _9 bytes_ would do 3B14:00 00 00 00 ; the job 3B18:00 00 00 00 ; 3B1C:00 00 00 00 ; LDA #0 3B20:00 00 00 00 ; TAY 3B24:00 00 00 00 ;.1 STA NBUF1,Y 3B28:00 00 00 00 ; INY 3B2C:00 00 00 00 ; BNE .1 3B30:00 00 00 00 ; 3B34:00 00 00 00 ; This data should at $3F00 ($BF00) 3B38:00 00 00 00 3B3C:00 00 00 00 3B40:00 00 00 00 3B44:00 00 00 00 3B48:00 00 00 00 3B4C:00 00 00 00 3B50:00 00 00 00 3B54:00 00 00 00 3B58:00 00 00 00 3B5C:00 00 00 00 3B60:00 00 00 00 3B64:00 00 00 00 3B68:00 00 00 00 3B6C:00 00 00 00 3B70:00 00 00 00 3B74:00 00 00 00 3B78:00 00 00 00 3B7C:00 00 00 00 3B80:00 00 00 00 3B84:00 00 00 00 3B88:00 00 00 00 3B8C:00 00 00 00 3B90:00 00 00 00 3B94:00 00 00 00 3B98:00 00 00 00 3B9C:00 00 00 00 3BA0:00 00 00 00 3BA4:00 00 00 00 3BA8:00 00 00 00 3BAC:00 00 00 00 3BB0:00 00 00 00 3BB4:00 00 00 00 3BB8:00 00 00 00 3BBC:00 00 00 00 3BC0:00 00 00 00 3BC4:00 00 00 00 3BC8:00 00 00 00 3BCC:00 00 00 00 3BD0:00 00 00 00 3BD4:00 00 00 00 3BD8:00 00 00 00 3BDC:00 00 00 00 3BE0:00 00 00 00 3BE4:00 00 00 00 3BE8:00 00 00 00 3BEC:00 00 00 00 3BF0:00 00 00 00 3BF4:00 00 00 00 3BF8:00 00 00 00 3BFC:00 00 00 00 3C00:00 00 00 00 202 NBUF2 DS 86,0 ;NBUF2 ; === T0S6 === disk sector wasted bytes 3C04:00 00 00 00 ; *sigh* more wasted disk space 3C08:00 00 00 00 ; pack code THEN data 3C0C:00 00 00 00 ; as interleaving it just 3C10:00 00 00 00 ; wastes memory 3C14:00 00 00 00 3C18:00 00 00 00 3C1C:00 00 00 00 3C20:00 00 00 00 3C24:00 00 00 00 3C28:00 00 00 00 3C2C:00 00 00 00 3C30:00 00 00 00 3C34:00 00 00 00 3C38:00 00 00 00 3C3C:00 00 00 00 3C40:00 00 00 00 3C44:00 00 00 00 3C48:00 00 00 00 3C4C:00 00 00 00 3C50:00 00 00 00 3C54:00 00
001 SBTL '16-SECTOR WRITE ADDRESS' 002 ******************************** 003 * * 004 * WRITE ADR FIELD SUBROUTINE * ; Writes Disk Nibbles: 005 * (16-SECTOR FORMAT) * ; FF FF FF .. FF (Y sync bytes) 006 * WRITES SPECIFIED NUMBER OF * ; D5 AA 96 007 * 40-USEC (10-BIT) SELF-SYNC * ; VOL VOL 4&4 008 * NIBLS, ADR FIELDS 16-SECTOR * ; TRK TRK 4&4 009 * START MARKS ($D5,$AA,$96), * ; SEC SEC 4&4 010 * BODY (VOLUME, TRACK, SECTOR,* ; CRC CRC 4&4 011 * CHECKSUM), END FIELD MARKS, * ; DE EA EB 012 * AND THE WRITE TURN-OFF NIBL.* 013 * * 014 ******************************** 015 * * 016 * ------- ON ENTRY ------- * 017 * * 018 * THE LOCATIONS VOLUME, TRK, * ; Technically NVOL not VOLUME 019 * AND NSECT MUST CONTAIN THE * ; See, programmers wrote out-of-date comments even back then! /s 020 * DESIRED VOLUME, TRACK, AND * ; 021 * SECTOR VALUES DESIRED. * ; NVOL @ $41 Volume 022 * * ; TRK @ $44 Track 023 * THE PROPER DRIVE MUST BE * ; NSECT @ $3F Sector 024 * ENABLED AND UP TO SPEED IN * ; 025 * READ MODE (Q7L, Q6L). * ; Not documented: AA 026 * * ; 027 * X-REG CONTAINS SLOTNUM * ; Zero-Page $3E *must* contain #$AA 028 * TIMES 16. * ; for 3 cycle timing. See Line #086 029 * * 030 * Y-REG CONTAINS NUMBER OF * 031 * SELF SYNC NIBLS DESIRED * 032 * MINUS 1. * 033 * (0 FOR 256 NIBLS) * 034 * * 035 ******************************** 036 * * 037 * ------- CAUTION -------- * 038 * * 039 * 1 USEC CYCLE * 040 * * 041 ******************************** 042 * * 043 * ------- CAUTION -------- * 044 * * 045 * MOST OF THIS CODE IS TIME * 046 * CRITICAL. OBSERVE ALL * 047 * 'NO PAGE CROSS!' WARNINGS * 048 * ON BRANCHES * 049 * * 050 ******************************** 051 SWADR1 EQU * ;TELL RELOCATOR WHERE TO BEGIN 052 ******************************* 3C56:38 053 WADR16 SEC ANTICIPATE WR PROT ERR.
3C57:BD 8D C0 054 LDA Q6H,X INTO 'WR PROT SENSE' MODE. ; === Page 135 === 3C5A:BD 8E C0 055 LDA Q7L,X SENSE IT (NEG=PROTECTED) 3C5D:30 5E 056 BMI WADRTS ERR EXIT IF PROTECTED. 3C5F:A9 FF 057 LDA #$FF SELF-SYNC NIBL. ; 40 µ seconds to write any SYNC nibble 3C61:9D 8F C0 058 STA Q7H,X WRITE FRIST NIBL. ; = 0 [ 0] 3C64:DD 8C C0 059 CMP Q6L,X (4) BACK TO WRITE MODE. ; + 4 [ 4] 3C67:48 060 PHA (3) FOR DELAY ; + 3 [ 7] 3C68:68 061 PLA (4) ; + 4 [11] 3C69:20 C3 3C 062 WSYNC1 JSR WADRTS1 (12) FOR 40-USEC NIBLS. ; +12 [23] JSR=+6, <----------------+ 3C6C:20 C3 3C 063 JSR WADRTS1 (12) ; +12 [35] RTS=+6 | 3C6F:9D 8D C0 064 STA Q6H,X (5) WRITE NIBL. ; + 5 [40] ========> 0 [ 0] | 3C72:DD 8C C0 065 CMP Q6L,X (4) (BACK TO WRITE MODE) ; + 4 [ 4] | 3C75:EA 066 NOP (2) FOR DELAY. ; + 2 [ 6] | 3C76:88 067 DEY (2) NEXT OF 'N' NIBLS. ; + 2 [ 8] | 3C77:D0 F0 068 BNE WSYNC1 (3) *** NO PAGE CROSS! *** ; + 2 [10] BEQ <== + 3 [11] --> BNE ^ ; 32 µ seconds write DATA nibble 3C79:A9 D5 069 LDA #$D5 (2) ADR MARK 1. ; + 2 [12] magic number DISK_ADR_PROLOG_1 EQU #$D5 3C7B:20 D5 3C 070 JSR WNIBLB2 (15,9,6) WRITE IT. ; +24 [10] <-- JSR=6, WNIBLB2=9, WRNIBL=15 3C7E:A9 AA 071 LDA #$AA (2) ADR MARK 2. ; + 2 [12] magic number DISK_ADR_PROLOG_2 EQU #$AA 3C80:20 D5 3C 072 JSR WNIBLB2 (15,9,6) WRITE IT. ; +24 [10] 3C83:A9 96 073 LDA #$96 (2) 16-SECTOR ADR MARK 3. ; + 2 [10] magic number DISK_ADR_PROLOG_3 EQU #$96 3C85:20 D5 3C 074 JSR WNIBLB2 (15,9,6) WRITE IT. ; +24 [10] 3C88:A5 41 075 LDA NVOL (3) ; + 3 [13] 3C8A:20 C4 3C 076 JSR WBYTE (14,9,6) WRITE NVOL (ODD, THEN EVEN, BITS.) ; JSR=6 3C8D:A5 44 077 LDA TRK (3) WRITE TRACK NUMBER. ; 3C8F:20 C4 3C 078 JSR WBYTE (14,9,6) ODD, THEN EVEN, BITS) ; 3C92:A5 3F 079 LDA NSECT (3) WRITE SECTOR NUMBER. ; 3C94:20 C4 3C 080 JSR WBYTE (14,9,6) (ODD, THEN EVEN, BITS) ; 3C97:A5 41 081 LDA NVOL (3) ; 3C99:45 44 082 EOR TRK (3) FORM ADR FIELD CHECKSUM. ; 3C9B:45 3F 083 EOR NSECT (3) ; 3C9D:48 084 PHA (3) SAVE FOR EVEN BITS. ; 3C9E:4A 085 LSR A (2) ALIGHN ODD BITS. ; *spelling* "ALIGN" Poorly written assemblers explicitly need the implicit A register 3C9F:05 3E 086 ORA AA (3) SET CLOCK BITS. ; This is a shitty variable name: AA; call it WRITE_NIB_AA, see DSKFORM, Line #020, 087 * (PRECISE TIMING, 32 CYCLES PER NIBL) 3CA1:9D 8D C0 088 STA Q6H,X (5) WRITE CHECKSUM ODD BITS. ; 3CA4:BD 8C C0 089 LDA Q6L,X (4) BACK TO WRITE MODE. ; 3CA7:68 090 PLA (4) RECOVER FOR EVEN BITS. ; 3CA8:09 AA 091 ORA #$AA (2) SET CLOCK BITS. ; 3CAA:20 D4 3C 092 JSR WNIBLA (17,9,6) WRITE THEM. ; 3CAD:A9 DE 093 LDA #$DE (2) END MARK 1. ; magic number DISK_ADR_EPILOG_1 EQU #$DE 3CAF:20 D5 3C 094 JSR WNIBLB2 (15,9,6) WRITE IT. ; 3CB2:A9 AA 095 LDA #$AA (2) END MARK 2. ; magic number DISK_ADR_EPILOG_2 EQU #$AA 3CB4:20 D5 3C 096 JSR WNIBLB2 (15,9,6) WRITE IT. ; 3CB7:A9 EB 097 LDA #$EB (2) END MARK 3. ; magic number DISK_ADR_EPILOG_3 EQU #$EB 3CB9:20 D5 3C 098 JSR WNIBLB2 (15,9,6) 'WRITE TURN-OFF' ; 3CBC:18 099 CLC INDICATE NO WR PROT ERR. 3CBD:BD 8E C0 100 WADRTS LDA Q7L,X OUT OF WRITE MODE. ; TODO: used elsewhere? 3CC0:BD 8C C0 101 LDA Q6L,X TO READ MODE. ; These are shit function names -- they give no clue when they should be called! 3CC3:60 102 WADRTS1 RTS RETURN ; should be called WAIT_6 3CC4:48 103 WBYTE PHA (3) PRESERVE FOR EVEN BITS. ;+3 [22] should be called WRITE13_2NIB_22, JSR when cycles=13 3CC5:4A 104 LSR A (2) ALIGN ODD BITS. ;+2 [25] 3CC6:05 3E 105 ORA AA (3) SET CLOCK BITS. ;+3 [27] 3CC8:9D 8D C0 106 STA Q6H,X (5) WRITE NIBL. ;+5 [32] See: WRNIBL 3CCB:DD 8C C0 107 CMP Q6L,X (4) ;=4 [ 4] 3CCE:68 108 PLA (4) RECOVER FOR EVEN BITS. ;+4 [ 8] 3CCF:EA 109 NOP (2) ;+2 [10] 3CD0:EA 110 NOP (2) FOR DELAY. ;+2 [12] 3CD1:EA 111 NOP (2) ;+2 [14] 3CD2:09 AA 112 ORA #$AA (2) SET CLOCK BITS. ;+2 [16] 3CD4:EA 113 WNIBLA NOP (2) (17,9,6) ENTRY. ;+2 [18] Should be called WRITE12_1nib_18, JSR when cycles=12 3CD5:EA 114 WNIBLB2 NOP (2) (15,9,6) ENTRY. ;+2 [20] should be called WRITE14_1nib_20, JSR when cycles=14 3CD6:48 115 PHA (3) FOR ;+3 [23]
3CD7:68 116 PLA (4) DELAY. ;+4 [27] === Page 136 === 3CD8:9D 8D C0 117 WRNIBL STA Q6H,X (5) WRITE NIBL. ;+5 [32] Should be called WRITE21_1nib_27, JSR when cycles=21 3CDB:DD 8C C0 118 CMP Q6L,X (4) ;=4 [ 4] -- WRNIBL unused, never referenced -- 3CDE:60 119 RTS (6) RETURN ;+6 [10] 120 EWADR1 EQU * ;TELL RELOCTR WHERE TO STOP 121 XP2 EQU <*+255 ;H.O. ADDRESS NEXT PAGE ; Other page align macros BHERE1 use: 122 XP2H EQU 256*XP2 ;NOW AS 16-BITS ; DS $100-EWADR1 3CDF:00 123 DS XP2H-*,0 ;PAD OUT TO PAGE BOUNDARY.. ; *wastes* 33 bytes! 3CE0:00 00 00 00 3CE4:00 00 00 00 3CE8:00 00 00 00 3CEC:00 00 00 00 3CF0:00 00 00 00 3CF4:00 00 00 00 3CF8:00 00 00 00 3CFC:00 00 00 00
001 STBL '16-SECTOR RWTS' 002 **************************** 003 * DISK II * 004 * READ/WRITE TRACK-SECTOR * ; The famous RWTS 005 * * ; Technically it should be called RWSWT since it only supports: 006 * COPYRIGHT 1978 BY * ; Read Sector (RS) 007 * APPLE COMPUTER, INC. * ; Write Sector (WS) 008 * * ; Write Track (WT) 009 * ALL RIGHTS RESERVED * 010 * * 011 * R. WIGGINTON * 012 * * 013 * MODIFIED: 07/13/79 * 014 * R. AURICCHIO * 015 * ADDED WAIT-SEEK WHEN * 016 * POWERING-UP MOTOR. * 017 * * 018 * MODIFIED: 10/25/79 * 019 * R. AURICCHIO * 020 * ADDED DIAGMODE DISPLAYS * 021 * FOR ACTIVITY ANALYSIS. * 022 **************************** 023 ASC2 EQU * ;TELL RELOCTR WHERE RWTS BEGINS 024 ********************************* 025 MOTOROFF EQU $C088 026 MOTORON EQU $C089 027 DRV1EN EQU $C08A 028 DRV2EN EQU $C08B 029 ****************************** 030 * STATE MACHINE CONTROLS 031 * Q6 Q7 FUNCTION 032 * -- -- -------- 033 * LO LO READ 034 * HI LO SENSE WRITE PROTECT 035 * LO HI WRITE 036 * HI HI WRITE LOAD 037 ****************************** 038 DRV1TRK EQU $478 ; Text screen hole 039 DRV2TRK EQU $4F8 ; Text screen hole 040 IOBPL EQU $48 ; 041 IOBPH EQU $49 ; 042 SLOT EQU $5F8 ;HOLDS SLOT NUM USED ; 043 PTRSDEST EQU $3C ; 044 DEVCTBL EQU PTRSDEST ; $3C is pointer to Device Characteristics Table. See DCT 045 DRIVNO EQU $35 ; [0] Device Type -- never used -- 046 MONTIME EQU $46 ; [1] Phases Per Track 047 SECT EQU CSSTV+1 ; $2D [2] Motor On Delay Low -- never used -- 048 TRACK EQU CSSTV+2 ; $2E [3] Motor On Delay High 049 VOLUME EQU CSSTV+3 ; $2F 050 MAXSEEKS EQU 4 ;MAX FOR SEEKCNT ; 051 SEEKCNT EQU $4F8 ;# RESEEKS BEFORE RECALIBRATE ; Text screen hole, recycled with DRV2TRK 052 RETRYCNT EQU $578 ; Text screen hole 053 RECALCNT EQU $6F8 ;# RECALIBRATES -1 ; Text screen hole
054 PAGE ; === Page 117 === 055 LST OFF 056 DO DIAGMODE 057 * 058 * DIAGMODE EQUATES... 059 * 060 SP EQU $A0 ;SPACE (INDICATOR OFF) 061 TD EQU 4 ;DISPL BETWEEN CHARS 062 TC1 EQU $1E ;^ - RWTS ACTIVE 063 TL1 EQU $07D0 ; VTAB 24: HTAB 1 064 TC2 EQU $0D ;M - MOTOR STARTUP 065 TL2 EQU TL1+TD 066 TC3 EQU $13 ;S - SEEK IN PROGRESS 067 TL3 EQU TL2+TD 068 TC4 EQU $01 ;A - READING ADDRESS 069 TL4 EQU TL3+TD 070 TC5 EQU $0C ;L - NOT DESIRED SECTOR (LATENCY) 071 TL5 EQU TL4+1 072 TC6 EQU $05 ;E - ADDRESS ERROR 073 TL6 EQU TL5+1 074 TC7 EQU $10 ;P - PRENIBBILIZING 075 TL7 EQU TL4+TD 076 TC8 EQU $17 ;W - WRITING 077 TL8 EQU TL7+TD 078 TC9 EQU $12 ;R - READING 079 TL9 EQU TL8+TD 080 TC10 EQU $05 ;E - READ ERROR 081 TL10 EQU TL9+TD 082 TC11 EQU $0F ;O - POSTNIBBLIZING 083 TL11 EQU TL10+TD 084 * 085 SCOUNT EQU $2FE ;SECTORS-ACCESSED COUNT 086 LCOUNT EQU $2FF ;LATENCY COUNT 087 TL12 EQU TL11+TD ;LATENCY POSITION 088 PAGE 089 FIN 090 LST ON 091 ************************** 092 * * 093 * READ/WRITE A * 094 * TRACK AND SECTOR * 095 * * 096 ************************** 097 * * 098 * ENTER WITH A & Y * 099 * REGISTERS POINTING TO * 100 * THE I/O CONTROL BLOCK * 101 * (THE 'IOB'). INSIDE * 102 * THE IOB: * 103 * * 104 * IBTYPE: IOB TYPE CODE * 105 * (SHOULD BE A 01) * 106 * * 107 * IBSLOT: CONTROLLER SLOT* 108 * NUMBER FOR THIS * 109 * ACCESS. * 110 * * 111 * IBDRVN: DRIVE NUMBER * 112 * FOR THIS ACCESS * 113 * * 114 * IBVOL: EXPECTED VOLUME * 115 * NUMBER. NOTE THAT * 116 * VOLUME 00 MATCHES *
117 * ANY VOLUME NUMBER * ; === Page 118 === 118 * * 119 * IBTRK: TRACK TO USE * 120 * THIS ACCESS * 121 * * 122 * IBSECT: SECTOR NUMBER * 123 * TO USE THIS TIME * 124 * * 125 * IBDCTP: POINTER TO THE * 126 * DEVICE CHARACTER-* ; Really? You HAD to indent the line and force an artificial word break when it fits?? 127 * ISTICS TABLE. * 128 * * 129 * IBBUFP: POINTER TO THE * 130 * PLACE THE DATA IS* 131 * OR SHOULD BE. * 132 * * 133 * IBDLEN: AMOUNT OF DATA * 134 * INBYTESTOBE * 135 * PROCESSED. * 136 * * 137 * IBCMD: COMMAND CODE: * 138 * 0-> NULL COMMAND * ; And this null command serves what purpose??? 139 * 1-> READ SECTOR * ; RWTS_CMD_READ_SEC = 1 140 * 2-> WRITE SECTOR * ; RWTS_CMD_WRITE_SEC = 2 141 * 4-> FORMAT DISK * ; RWTS_CMD_FORMAT = 4 142 * 143 * IBSTAT: ERROR CODE: * 144 * 0-> NO ERROR * 145 * $10-> WRITE PROTECT * 146 * $20-> VOLUME ERROR * 147 * $40-> DRIVE ERROR * 148 * $80-> READ ERROR * 149 * 150 * IBSMOD: LOCATION TO * 151 * RETURN THE VOLUME* 152 * NUMBER ACTUALLY * 153 * FOUND. * 154 * * 155 * IOBPSN: PREVIOUS SLOT * 156 * NUMBER USED LAST * ; Why isn't the first word aligned with the colon??? 157 * ACCESS. * 158 * * 159 * IOBPDN: PREVIOUS DRIVE * 160 * NUMBER USED LAST * 161 * ACCESS. * 162 * * 163 ************************** 164 * * 165 * DEVICE CHARACTERISTICS * 166 * TABLE DESCRIPTION: * 167 * * 168 * DEVICE TYPE CODE * ; B7FB: [0] Device Type -- never used -- 169 * (ZERO FOR DISK II) * 170 * * 171 * NUMBER OF PHASES PER * ; B7FC: [1] Device Phases Per Track, See MYSEEK 172 * TRACK (TWO FOR DISK II)* 173 * * 174 * MOTOR ON TIME IN 100 * ; B7FD: [2] Motor On Delay Low -- never used -- 175 * MICROSECOND INTERVALS * ; B7FE: [3] Motor On Delay High -> MONTIME+1, See Line #250 176 * COMPLEMENTED. ($D8EF * ; Lies, only $D8 is used. 177 * FOR DISK II) * 178 * * 179 **************************
180 PAGE ; === Page 119 === 3D00:84 48 181 RWTS STY IOBPL ;UPON ENTRY, A&Y POINT AT THE 3D02:85 49 182 STA IOBPH ;I/O CONTROL BLOCK (IOB) 183 LST OFF 184 DO DIAGMODE 185 LDY #TC1 ;SAY WE'RE ACTIVE 186 STY TL1 187 FIN 188 LST ON 3D04:A0 02 189 LDY #2 ;SET RECALIBRATE ; magic number RWTS_RECALIBRATE = $2 3D06:8C F8 06 190 STY RECALCNT ; COUNT ; Text screen hole! 3D09:A0 04 191 LDY #MAXSEEKS ;SET RESEEK 3D0B:8C F8 04 192 STY SEEKCNT ; COUNT ; Another text screen hole. WTF! 33 bytes above on page $3C / $BC! 3D0E:A0 01 193 LDY #1 ;GET SLOT # FOR THIS OPERATION ; magic number IOB_OFFSET_SLOT 3D10:B1 48 194 LDA (IOBPL),Y 3D12:AA 195 TAX 3D13:A0 0F 196 LDY #$0F ;DID HE CHANGE SLOTS? ; magic number IOB_OFFSET_PREV_SLOT 3D15:D1 48 197 CMP (IOBPL),Y 3D17:F0 1B 198 BEQ SAMESLOT ;IF HE DIDN'T, GOOD FOR HIM! 199 * 200 * NOW ARE USING A DIFFERENT SLOT. 201 * NOW WAIT FOR THIS DRIVE TO TURN OFF 202 * TO SENSE MOTOR NOT SPINNING, DATA FROM DISK MUST 203 * BE THE SAME FOR AT LEAST 96 MICROSECONDS 3D19:8A 204 TXA ;SAVE NEW SLOT # 3D1A:48 205 PHA 3D1B:B1 48 206 LDA (IOBPL),Y ;GET 'OLD SLOT NUMBER' 3D1D:AA 207 TAX 3D1E:68 208 PLA 3D1F:48 209 PHA ;PUT BACK ON STACK 3D20:91 48 210 STA (IOBPL),Y ;SAVE 'NEW SLOT NUMBER' 3D22:BD 8E C0 211 LDA Q7L,X ;GO INTO READ MODE 3D25:A0 08 212 STILLON LDY #$08 ;TO BE SURE, DATA MUST REMAIN 3D27:BD 8C C0 213 LDA Q6L,X ;STABLE FOR 96 MICROSECONDS 3D2A:DD 8C C0 214 NOTSURE CMP Q6L,X ;DATA STILL CHANGING? 3D2D:D0 F6 215 BNE STILLON ;IF SO, STILL SPINNING 3D2F:88 216 DEY 3D30:D0 F8 217 BNE NOTSURE ;STABLE LONG ENOUGH? IF NOT, LOOP 218 * 219 * PREVIOUS SLOT'S DRIVE NOW OFF... 220 * 3D32:68 221 PLA ;RESTORE NEW SLOT # 3D33:AA 222 TAX 223 * 224 * NOW CHECK IF THE MOTOR IS ON, THEN START IT 225 * 3D34:BD 8E C0 226 SAMESLOT LDA Q7L,X ;MAKE SURE IN READ MODE 3D37:BD 8C C0 227 LDA Q6L,X 3D3A:A0 08 228 LDY #8 ;WE MAY HAFTA CHECK SEVERAL TIMES TO BE SURE ; magic number RWTS_MIN_NIBBLES_DELTA = $8 229 CHKIFON EQU * 3D3C:BD 8C C0 230 LDA Q6L,X ;GET THE DATA 3D3F:48 231 PHA ;DELAY FOR DISK DATA TO CHANGE 3D40:68 232 PLA 3D41:48 233 PHA 3D42:68 234 PLA 3D43:8E F8 05 235 STA SLOT ; Text Screen Hole 3D46:DD 8C C0 236 CMP Q6L,X ;CHECK RUNNING HERE 3D49:D0 03 237 BNE ITISON ;=>IT'S ON... 3D4B:88 238 DEY ;MAYBE WE DIDN'T CATCH IT 3D4C:D0 EE 239 BNE CHKIFON ; SO WE'LL TRY AGAIN 240 * 241 ITISON EQU *
3D4E:08 242 PHP ;SAVE TEST RESULTS ; === Page 120 === 3D4F:BD 89 C0 243 LDA MOTORON,X ;TURN ON MOTOR REGARDLESS 3D52:A0 06 244 LDY #6 ;MOVE OUT ALL POINTERS INTO ZPAGE ; magic number IOB_OFFSET_DCT 3D54:B1 48 245 PTRMOV LDA (IOBPL),Y ; [6] 37EE..37EF -> $ [0] 003C IOB_DCT 3D56:99 36 00 246 STA PTRSDEST-6,Y ; magic number IOB_OFFSET_DCT [8] 37F0..37F1 -> $ [2] 003D IOB_BUF 3D59:C8 247 INY 3D5A:C0 0A 248 CPY #$0A ;MOVED ALL POINTERS? ; magic number IOB_OFFSET_LEN 3D5C:D0 F6 249 BNE PTRMOV 3D5E:A0 03 250 LDY #3 ;SET UP THE ; magic number DCT_MOTOR+1 3D60:B1 3C 251 LDA (DEVCTBL),Y ; MOTOR-ON TIME ; 3D62:85 47 252 STA MONTIME+1 ; BUG: Motor On Time Low is never stored to MONTIME! 3D64:A0 02 253 LDY #2 ;NOW GET PARAMS ; magic number IOB_OFFSET_DRV_NUM 3D66:B1 48 254 LDA (IOBPL),Y ;DETERMINE DRIVE ONE OR TWO 3D68:A0 10 255 LDY #$10 ;SAME DRIVE USED BEFORE? ; magic number IOB_OFFSET_PREV_DRV 3D6A:D1 48 256 CMP (IOBPL),Y 3D6C:F0 06 257 BEQ OK ;IF SO, DON'T NECESSARILY WAIT FOR MOTOR 3D6E:91 48 258 STA (IOBPL),Y ;NOW USING THIS DRIVE 3D70:28 259 PLP ;TELL HIM MOTOR WAS OFF 3D71:A0 00 260 LDY #$00 ;SET ZERO FLAG ; 6502 doesn't have a CLZ or SEZ instruction 3D73:08 261 PHP 3D74:6A 262 OK ROR A ;BY GOING INTO THE CARRY 3D75:90 05 263 BCC SD1 ;SELECT DRIVE 2 ! 3D77:BD 8A C0 264 LDA DRV1EN,X ;ASSUME DRIVE 1 TO HIT 3D7A:B0 03 265 BCS DRVSEL ;IF WRONG, ENABLE DRIVE 2 INSTEAD 3D7C:BD 8B C0 266 SD1 LDA DRV2EN,X 267 DRVSEL EQU * 3D7F:66 35 268 ROR DRIVNO ;SAVE SELECTED DRIVE 269 * 270 * DRIVE SELECTED. IF MOTORING-UP, 271 * WAIT BEFORE SEEKING... 272 * 3D81:28 273 PLP ;WAS THE MOTOR 3D82:08 274 PHP ; PREVIOUSLY OFF? 3D83:D0 0B 275 BNE NOWAIT ;=>NO, FORGET WAITING. 3D85:A0 07 276 LDY #7 ;YES, DELAY 150 MS 3D87:20 00 3A 277 SEEKW JSR MSWAIT 3D8A:88 278 DEY 3D8B:D0 FA 279 BNE SEEKW 3D8D:AE F8 05 280 LDX SLOT ;RESTORE SLOT NUMBER 281 * 282 NOWAIT EQU * 283 * 284 * SEEK TO DESIRED TRACK... 285 * 3D90:A0 04 286 LDY #4 ;SET TO IOBTRK ; magic number IOB_OFFSET_TRK 3D92:B1 48 287 LDA (IOBPL),Y ;GET DESIRED TRACK 3D94:20 5A 3E 288 JSR MYSEEK ;SEEK! 289 * 290 * SEE IF MOTOR WAS ALREADY SPINNING. 291 * 3D97:28 292 PLP 3D98:D0 11 293 BNE TRYTRK 294 * 295 * WAIT FOR MOTOR SPEED TO COME UP. 296 * 297 LST OFF 298 DO DIAGMODE 299 LDY #TC2 300 STY TL2 301 LDY #0 302 STY SCOUNT 303 STY LCOUNT
304 LDY #SP ;SHUT OFF THE ; === Page 121 === 305 STY TL12 ; LATENCY INDICATOR 306 FIN 307 LST ON 3D9A:A4 47 308 LDY MONTIME+1 ;IF MOTORTIME IS POSITIVE, 3D9C:10 0D 309 BPL MOTORUP ; THEN SEEK WASTED ENUFF TIME FOR US 3D9E:A0 12 310 MOTOF LDY #$12 ;DELAY 100 USEC PER COUNT 3DA0:88 311 CONWAIT DEY 3DA1:D0 FD 312 BNE CONWAIT 3DA3:E6 46 313 INC MONTIME ; NOTE: MONTIME is never written to so this is a full 256 counter 3DA5:D0 F7 314 BNE MOTOF 3DA7:E6 47 315 INC MONTIME+1 3DA9:D0 F3 316 BNE MOTOF ;COUNT UP TO $0000 317 MOTORUP EQU * 318 LST OFF 319 DO DIAGMODE 320 LDY #SP ;SAY 'MOTOR RUNNING' 321 STY TL2 322 FIN 323 LST ON
001 * 002 * DISK IS NOW UP TO SPEED: READ IT! 003 * NOW CHECK: IF IT IS NOT THE FORMAT DISK COMMAND, 004 * LOCATE THE CORRECT SECTOR FOR THIS OPERATION. 005 * 006 TRYTRK EQU * 3DAB:A0 0C 007 LDY #$0C ; magic number IOB_OFFSET_CMD = $C 3DAD:B1 48 008 LDA (IOBPL),Y ;GET COMMAND CODE # 3DAF:F0 5A 009 BEQ GALLDONE ;IF NULL COMMAND, GO HOME TO BED. ;↓ 3DB1:C9 04 010 CMP #$04 ;FORMAT THE DISK? ; magic number RWTS_CMD_FORMAT = $4 *sigh* 3DB3:F0 58 011 BEQ FORMDSK ;ALLRIGHT,ALLRIGHT, I WILL... ; If only the IBCMD commands were an enum instead of a dumb bitmask, see RWTS_CMD_* 3DB5:6A 012 ROR A ;SET CARRY=1 FOR READ, 0 FOR WRITE 3DB6:08 013 PHP ;AND SAVE THAT 3DB7:B0 03 014 BCS TRYTRK2 ;MUST PRENIBBLE FOR WRITE. 015 LST OFF 016 DO DIAGMOD 017 LDY #TC17 ;SAY 'PRENIBBLIZING' 018 STY TL7 019 FIN 020 LST ON 3DB9:20 00 38 021 JSR PRENIB16 022 LST OFF 023 DO DIAGMOD 024 LDY #SP ;PRENIB FINISHED 025 STY TL7 026 FIN 027 LST ON 3DBC:A0 30 028 TRYTRK2 LDY #$30 ;ONLY 48 RETRIES OF ANY KIND. 3DBE:8C 78 05 029 STY RETRYCNT 3DC1:AE F8 05 030 TRYADR LDX SLOT ;GET SLOT NUM INTO X-REG 031 LST OFF 032 DO DIAGMOD 033 LDA #TC4 ;SAY 'READING ADDRESS' 034 STA TL4 035 LDA #SP ;SAY 'NO ADDRESS ERROR' (YET) 036 STA TL6 037 FIN 038 LST ON 3DC4:20 44 39 039 JSR RDADR16 ;READ NEXT ADDRESS FIELD ; ^ 040 LST OFF 041 DO DIAGMOD 042 LDA #SP ;ADDRESS-READ DONE 043 STA TL4 044 FIN 045 LST ON 3DC7:90 24 046 BCC RDRIGHT ;IF READ IT RIGHT, HURRAH! ; v 047 LST OFF 048 DO DIAGMOD 049 LDA #TC6 ;ADDRESS-READ DONE 050 STA TL4 051 FIN 052 LST ON 3DC9:CE 78 05 053 TRYADR2 DEC RETRYCNT ;ANOTHER MISTAEK!! ; *spelling* Oh, the **irony**
3DCC:10 F3 054 BPL TRYADR ; WELL, LET IT GO THIS TIME.. ; === page 123 === 055 * 056 * RRRRRECALIBRATE !!!! 057 * 058 RECAL EQU * 3DCE:AD 78 04 059 LDA CURTRK 3DD1:48 060 PHA ;SAVE TRACK WE REALLY WANT ; /sarcasm Nice to read VNOTRK * 2 phases/track 3DD2:A9 60 061 LDA #$60 ;RECALIBRATE ALL OVER AGAIN! ; /sarcasm Yeah ... let's bang the user's drive head against 3DD4:20 95 3E 062 JSR SETTRK ;PRETEND TO BE ON TRACK 96 ; the case -- that will make it work and won't cause 3DD7:CE F8 06 063 DEC RECALCCNT ;ONCE TOO MANY?? ; any head alignment problems over time ... NOT! 3DDA:F0 28 064 BEQ DRVERR ;TRIED TO RECALIBRATE TOO MANY TIMES, ERROR! ; v 3DDC:A9 04 065 LDA #MAXSEEKS ;RESET THE 3DDE:8D F8 04 066 STA SEEKCNT ; SEEK COUNTER 3DE1:A9 00 067 LDA #$00 3DE3:20 5A 3E 068 JSR MYSEEK ;MOVE TO TRACK 00 ; v 3DE6:68 069 PLA 3DE7:20 5A 3E 070 RESEEK JSR MYSEEK ;GO TO CORRECT TRACK THIS TIME! 3DEA:4C BC 3D 071 JMP TRYTRK2 ;LOOP BACK, TRY AGAIN ON THIS TRACK 072 * 073 * HAVE NOW READ 074 * MAKE SURE THIS IS THE TRACK, SECTOR, AND VOLUME DESIRED. 075 * 3DED:A4 2E 076 RDRIGHT LDY TRACK ;ON THE RIGHT TRACK? 3DEF:CC 78 04 077 CPY CURTRK 3DF2:F0 1C 078 BEQ RTTRK ;IF SO, GOOD ;↓ 079 * NO, DRIVE WAS ON A DIFFERENT TRACK. TRY 080 * RESEEKING/RECALIBRATING FROM THIS TRACK 3DF4:AD 78 04 081 LDA CURTRK ;PRESERVE DESTINATION TRACK 3DF7:48 082 PHA 3DF8:98 083 TYA 3DF9:20 95 3E 084 JSR SETTRK 3DFC:68 085 PLA 3DFD:CE F8 04 086 DEC SEKCNT ;SHOULD WE RESEEK? 3E00:D0 E5 087 BNE RESEEK ;=>YES, RESEEK ;↑ === T0S8 === 3E02:F0 CA 088 BEQ RECAL ;=>NO, RECALIBRATE! ;↑ 089 **** 3E04:68 090 DRVERR PLA ;REMOVE CURTRK 3E05:A9 40 091 LDA #IBDERR ;BAD DRIVE ERROR 3E07:28 092 JMPTO1 PLP 3E08:4C 48 3E 093 JMP HNDLERR 3E0B:F0 39 094 GALLDONE BEQ ALLDONE ;↓ 3E0D:4C AF 3E 095 FORMDSK JMP DSKFORM ;=>GO TO IT! ;↓ WhyTF is FormatDisk in the middle here??? 096 * 097 * DRIVE IS ON RIGHT TRACK, CHECK VOLUME MISMATCH 098 * 3E10:A0 03 099 RTTRK LDY #3 ;IS THE RIGHT DISK IN? ; magic number IOB_OFFSET_VOL = $03 3E12:B1 48 100 LDA (IOBPL),Y ;GET DESIRED VOLUM 3E14:48 101 PHA ;PRESERVE DESIRED VOLUME# 3E15:A5 2F 102 LDA VOLUME ;GET ACTUAL VOLUME HERE 3E17:A0 0E 103 LDY #$0E ;TELL OPSYS WHAT VOLUME WAS THERE ; magic number IOB_OFFSET_MOD = $E 3E19:91 48 104 STA (IOBPL),Y 3E1B:68 105 PLA ;GET DESIRED VOLUME BACK 3E1C:F0 08 106 BEQ CORRECTVOL ;DESIRED VOLUME 00 MATCHES ALL. ;↓ 3E1E:C5 2F 107 CMP VOLUME 3E20:F0 04 108 BEQ CORRECTVOL ;YUP, IT WAS RIGHT! ;↓ 3E22:A9 20 109 LDA #IBVMME ;HE SWITCHED DISCS! 3E24:D0 E1 110 BNE JMPTO1 ;ALWAYS TAKEN ;↑ 111 CORRECTVOL EQU * 3E26:A0 05 112 LDY #5 ; magic number IOB_OFFSET_SECTOR = $5 3E28:B1 48 113 LDA (IOBPL),Y ; TO ALLOW FOR INTERLEAVE 3E2A:A8 114 TAY 3E2B:B9 B8 3F 115 LDA INTRLEAV,Y ;COMPUTE PHYSICAL SECTOR ; DOS Sector Interleave/Skew Mapping
3E2E:C5 2D 116 CMP SECT ;DID WE GET THE SECTOR? ; === Page 124 === 117 LST OFF 118 DO DIAGMOD 119 BEQ GOTSECT ;=>WE FOUND IT! 120 LDA #TC5 ;SAY 'LATENCY' 121 STA TL5 122 LDA SCOUNT ;ARE WE WAITING FOR FIRST SECTOR? 123 BEQ NOLAT ;=>YES, LATENCY UNPREDICTABLE ANYWAY 124 INC LCOUNT ;NO, COUNT SECTORS MISSED 125 NOLAT EQU * 126 JMP TRYADR2 ;NOW..GET CORRECT SECTOR.. 127 ELSE 128 LST ON 3E30:D0 97 129 BNE TRYADR2 ;NO, KEEP TRYING. ;↑ 130 FIN 131 * 132 * HOORAY! WE GOT THE RIGHT SECTOR! 133 * 134 GOTSECT EQU * 135 LST OFF 136 DO DIAGMOD 137 LDA #SP ;SAY 'NO LATENCY' 138 STA TL5 139 INC SCOUNT ;BUMP 'SECTORS-ACCESSED' COUNT 140 FIN 141 LST ON 3E32:28 142 PLP 3E33:90 1C 143 BCC WRIT ;CARRY WAS SET FOR READ OPERATION. ;↓ 144 LST OFF 145 DO DIAGMOD 146 LDA #TC9 ;SAY 'READING' 147 STA TL9 148 LDA #SP ;SAY 'NO READ ERROR' (YET) 149 STA TL10 150 FIN 151 LST ON 3E35:20 DC 38 152 JSR READ16 ;CLEARED FOR WRITE 153 LST OFF 154 DO DIAGMOD 155 LDA #SP ;READ FINISHED 156 STA TL9 157 FIN 158 LST ON 3E38:08 159 PHP ;SAVE STATUS OF READ OPERATION 160 LST OFF 161 DO DIAGMOD 162 BCC GOODREAD ;NO ERROR 163 LDA #TC10 ;SAY 'READ ERROR' 164 STA TL10 165 JMP TRYADR2 ;RETRY ON ERROR 166 * 167 GOODREAD EQU * 168 ELSE 169 LST ON 3E39:B0 8E 170 BCS TRYADR2 ;CARRY SET UPON RETURN IF BAD READ ;↑ 171 FIN 3E3B:28 172 PLP ;CAREFUL OF STACK 3E3C:A2 00 173 LDX #0 ;SET TO POSTNIBLIZE 3E3E:86 26 174 STX T0 ; All 256 BYTES OF THE SECTOR 175 LST OFF 176 DO DIAGMOD 177 LDA #TC11 ;SAY 'POSTINIBBLIZING' ;POST_IN_NIBBLIZING 178 STA TL11
179 FIN ; === Page 125 === 180 LST ON 3E40:20 C2 38 181 JSR POSTNB16 ;DECODE INTO REAL WORLD DATA 182 LST OFF 183 DO DIAGMOD 184 LDA #SP ;POSTNIB COMPLETED 185 STA TL11 186 FIN 187 LST ON 3E43:AE F8 05 188 LDX SLOT ;RESTORE SLOTNUM INTO X ; I never would have guessed ... 3E46:18 189 ALLDONE CLC 3E47:24 190 DFB $24 ;SKIP OVER NEXT BYTE WITH BIT OPCODE ; BIT $zp 3E48:38 191 HNDLERR SEC ;INDICATE AN ERROR 3E49:A0 0D 192 LDY #$0D ;GIVE HIM ERROR# ; magic number IOB_OFFSET_ERROR = $D 3E4B:91 48 193 STA (IOBPL),Y 3E4D:BD 88 C0 194 LDA MOTOROFF,X ; TURN IT OFF... 195 LST OFF 196 DO DIAGMOD 197 * AVERAGE LATENCY = LCOUNT/SCOUNT 198 LDA LCOUNT ; GET TOTAL LATENCY 199 LDY #0 ; CLEAR QUOTIENT 200 DIVIDE EQU * 201 CMP SCOUNT ; DONE? 202 BCC PRTLAT ; =>YES.PRINT IT 203 SBC SCOUNT ; REMOVE SCOUNT 204 INY ; INCREMENT QUOTIENT 205 BNE DIVIDE 206 * 207 PRTLAT TYA ; Print Latency 208 AND #$0F ; MAX LATENCY=15 209 ORA #$B0 ; MAKE ASCII ; NO, this is make Apple Text; ASCII = $00..$7F 210 CMP #$BA ; IS IT A-F 211 BCC PRTL2 ;=>NO 212 ADC #6 ;ADD 7 (INCLUDES CARRY) 213 PRTL2 STA TL12 ;STUFF LATENCY COUNT 214 LDA #SP ; SAY 'RWTS NOT ACTIVE' 215 STA TL1 216 FIN 217 LST ON 3E50:60 218 RTS 219 WRIT EQU * 220 LST OFF 221 DO DIAGMOD 222 LDA #TC8 ; SAY 'WRITING' 223 STA TL8 224 FIN 225 LST ON 3E51:20 2A 38 226 JSR WRITE16 ;WRITE NYBBLES NOW ; ^ WRITRTN, page 137 227 LST OFF 228 DO DIAGMOD 229 LDA #SP ;WRITE FINISHED 230 STA TL8 231 FIN 232 LST ON 3E54:90 F0 233 BCC ALLDONE ;IF NO ERRORS. 3E56:A9 10 234 LDA #IBWPER ;DISK IS WRITE PROTECTED!! 3E58:B0 EE 235 BCS HNDLERR ;ALWAYS TAKEN 236 * 237 * THIS IS THE 'SEEK' ROUTINE 238 * SEEKS TRACK 'N' IN SLOT #X/$10 239 * IF DRIVNO IS NEGATIVE, ON DRIVE 1 240 * IF DRIVNO IS POSITIVE, ON DRIVE 2 241 *
3E5A:48 242 MYSEEK PHA ; AND PRESERVE A-REGISTER ; === Page 126 === Uhm, OK, Captain Obvious 243 LST OFF 244 DO DIAGMOD 245 LDA #TC3 ;SAY 'SEEKING' 246 STA TL3 247 FIN 248 LST ON 3E5B:A0 01 249 LDY #$01 ;IS THIS A TWO-PHASE DISC? ; magic number DCT_OFFSET_TYPE = $1 3E5D:B1 3C 250 LDA (DEVCTBL),Y 3E5F:6A 251 ROR A ;GET # OF PHASES INTO CARRY 3E60:68 252 PLA 3E61:90 08 253 BCC MYSEEK2 ;IF ONE PHASE PER TRACK 3E63:0A 254 ASL A 3E64:20 6B 3E 255 JSR MYSEEK2 3E67:4E 78 04 256 LDA CURTRK ;DIVIDE BACK DOWN 257 LST OFF 258 DO DIAGMOD 259 LDA #SP 260 STA TL3 ;SEEK DONE 261 FIN 262 LST ON 3E6A:60 263 RTS 3E6B:85 2A 264 MYSEEK2 STA TRKN ;SAVE DESTINATION TRACK(*2) ; 3E6D:20 8E 3E 265 JSR XTOY ;SET Y=SLOT# 3E70:B9 78 04 266 LDA DRV1TRK,Y 3E73:24 35 267 BIT DRIVNO 3E75:30 03 268 BMI WASD0 ;IS MINUS, ON DRIVE ZERO 3E77:B9 F8 04 269 LDA DRV2TRK,Y 3E7A:8D 78 04 270 WASD0 STA CURTRK ;THIS IS WHERE I AM ; Going to resist cheap shot here 3E7D:A5 2A 271 LDA TRKN ;AND WHERE I'M GOING TO ; But I will point out crappy var names and better ones: 3E7F:24 35 272 BIT DRIVNO ;NOW UPDATE SLOT DEPENDENT ; SRC_TRK 3E81:30 05 273 BMI ISDRV1 ;LOCATIONS WITH TRACK ; DST_TRK 3E83:99 F8 04 274 STA DRV2TRK,Y ;INFORMATION 3E86:10 03 275 BPL GOSEEK ;ALWAYS TAKEN 3E88:99 78 04 276 ISDRV1 STA DRV1TRK,Y 3E8B:4C A0 39 277 GOSEEK JMP SEEK ;GO THERE! 3E8E:8A 278 XTOY TXA 3E8F:4A 279 LSR A 3E90:4A 280 LSR A 3E91:4A 281 LSR A 3E92:4A 282 LSR A 3E93:A8 283 TAY 3E94:60 284 RTS 285 * 286 * THIS SUBROUTINE SETS THE SLOT DEPENDENT TRACK 287 * LOCATION. 288 * 3E95:48 289 SETTRK PHA ;PRESERVE DESTINATION TRACK 3E96:A0 02 290 LDY #$02 ; magic number IOB_OFFSET_DRIVE = $2 3E98:B1 48 291 LDA (IOBPL),Y 3E9A:6A 292 ROR A ;GET DRIVE # INTO CARRY 3E9B:66 35 293 ROR DRIVNO ;INTO (DRIVNO) 3E9D:20 8E 3E 294 JSR XTOY ;SET UP Y-REG 3EA0:68 295 PLA 3EA1:0A 296 ASL A ;ASSUME TRACK IS HELD*2 3EA2:24 35 297 SETTRK2 BIT DRIVNO ; unused label 3EA4:30 05 298 BMI ONDRV1 ;IF ON DRIVE 1(1), DRIVNO MINUS 3EA6:99 F8 04 299 STA DRV2TRK,Y 3EA9:10 03 300 BPL SETRTS 3EAB:99 78 04 301 ONDRV1 STA DRV1TRK,Y 3EAE:60 302 SETRTS RTS
001 SBTL '16-SECTOR FORMATTER' 002 **************************** 003 * * 004 * FORMAT DISK AND RETURN * 005 * * 006 **************************** 007 * 008 * EQUATES FOR FORMATTER 009 * 010 NSYNC EQU $45 ;NUM GAP SELF-SYNC NIBLS ; No, not the 90's band 011 * 012 REP 40 013 DSKFORM EQU * 014 DO DIAGMOD ;ELIMINATE FMTR FROM DIAG ASSEMBLY 015 LST OFF 016 ELSE 3EAF:A0 03 017 LDY #3 ; magic number IOB_OFFSET_VOL = $3 3EB1:B1 48 018 LDA (IOBPL),Y VOLUME NUMBER IN IOB. 3EB3:85 41 019 STA NVOL FOR FORMATTER. 3EB5:A9 AA 020 LDA #$AA SET Z-PAG LOC TO $AA FOR ; *sigh* Because AA is so descriptive ... WTF does AA stand for to a new reader?!?! 3EB7:85 3E 021 STA AA TIME DEPENDENT REFERENCES. ; Call it WRITE_NIB_AA; see WADR16, Lines #086, #105 3EB9:A0 56 022 LDY #$56 ; magic number 3EBB:A9 00 023 LDA #0 3EBD:85 44 024 STA TRK TRACK NUMBER, 0 TO 34 3EBF:99 FF 3B 025 CLRNBUF2 STA NBUF2-1,Y CLEAR NBUFS TO WRITE 3EC2:88 026 DEY ZERO SECTORS 3EC3:D0 FA 027 BNE CLRNBUF2 3EC5:99 00 3B 028 CLRNBUF1 STA NBUF1,Y 3EC8:88 029 DEY 3EC9:D0 FA 030 BNE CLRNBUF1 ; 3ECB:A9 50 031 LDA #$50 ; magic number TODO FORMAT_LAST_TRACK EQU 40*2 ; *2 = 2 phases/track 3ECD:20 95 3E 032 JSR SETTRK FAKE LIKE ON TRACK 80. 3ED0:A9 28 033 LDA #$28 ; magic number TODO FORMAT_SECTOR_GAP EQU 40 3ED2:85 45 034 STA NSYNC BEGIN WITH 40 SELF-SYNC NIBLS. 3ED4:A5 44 035 FORMTRK LDA TRK 3ED6:20 5A 3E 036 JSR MYSEEK GOTO NEXT TRACK. 3ED9:20 0D 3F 037 JSR WTRACK16 WRITE AND VERIFY TRACK. 3EDC:A9 08 038 FORMERR1 LDA #8 'UNABLE TO FORMAT' ERR CODE. ; magic number TODO 3EDE:B0 24 039 BCS FORMERR CONTINUE IF NO ERROR. 3EE0:A9 30 040 LDA #$30 UP TO 48 SECTOR RETRIES ; *sigh* Why _this_ value? magic number TODO FORMAT_MAX_RETRY EQU 48 3EE2:8D 78 05 041 STA RETRYCNT TO FIND SECTOR 0. ; Also, why not in decimal?? 3EE5:38 042 FINDS0 SEC ANTICIPATE 'UNABLE TO FORMAT' 3EE6:CE 78 05 043 DEC RETRYCNT DONE 48 RETRIES? 3EE9:F0 19 044 BEQ FORMERR IF SO, 'UNABLE TO FORMAT' ERR. 3EEB:20 44 39 045 JSR RDADR16 ;READ ADR FIELD. ; *sigh* Inconsistent comment meta character 3EEE:B0 F5 046 BCS FINDS0 RETRY IF ERR. 3EF0:A5 2D 047 LDA SECT CHECK SECTOR THAT WAS READ. 3EF2:D0 F1 048 BNE FINDS0 CONTINUE SEARCHING IF NOT SECT 0. 3EF4:20 DC 38 049 JSR READ16 ;NOW READ DATA FIELD. ; *sigh* Make up your mother falcon mind! Always use ; or not! 3EF7:B0 EC 050 BCS FINDS0 CONTINUE SEARCH IF ERR. 051 * (NOW POSITIONED PROPERLY FOR NEXT TRACK) ; Unknown if leading space after '*' should be 1 space, 1 tab, etc?? 3EF9:E6 44 052 INC TRK INCREMENT TRACK NUMBER. ; /sarcasm Gee, George what does this do? 3EFB:A5 44 053 LDA TRK ; Code documents WHAT, Comments document WHY
3EFD:C9 23 054 CMP #$23 CONTINUE IF LESS THEN 35 ; === Page 83 === magic number DISK_MAX_TRACK or at least VNOTRK 3EFF:90 D3 055 BCC FORMTRK ; === T0S9 === 3F01:18 056 CLC CLEAR CARRY TO INDICATE 'NO ERR';[.. JMP ALLDONE 3F02:90 05 057 BCC FORMDONE ELSE TURN OFF MOTOR AND RETURN ; .. 3F04:A0 0D 058 FORMERR LDY #$0D ; .. JMP HNDLERR magic number IOB_OFFSET_ERR = $D 3F06:91 48 059 STA (IOBPL),Y RETURN ERROR CODE. ; .. wastes remaining 6 bytes. 3F08:38 060 SEC SET CARRY TO INDICATE ERR. ; .. We could invert the return value, 3F09:BD 88 C0 061 FORMDONE LDA MOTOROFF,X ; TURN MOTOR OFF. ; .. but there is a better optimization 3F0C:60 062 RTS ; AND RETURN. ; .. using the two JMPs above to reach common code in RWTSTWO ] 063 PAGE 064 ****************************** 065 * * 066 * WRITE TRACK SUBROUTINE * 067 * * 068 ****************************** 3F0D:A9 00 069 WTRACK16 LDA #0 3F0F:85 3F 070 STA NSECT SECTOR NUMBER, 0 to 15. 3F11:A0 80 071 LDY #128 ;128 NIBS PRIOR SECTOR 0 3F13:D0 02 072 BNE WSECT0 ; TO INSURE NO BLANK SPOT BETW 15 & 0 3F15:A4 45 073 WSECT LDY NSYNC CURRENT NUM OF GAP SELF-SYNC NIBLS. 074 WSECT0 EQU * 3F17:20 56 3C 075 JSR WADR16 WRITE GAP AND ADR FIELD. 3F1A:B0 6B 076 BCS WEXIT2 ERR IF WRITE PROTECTED. 3F1C:20 2A 38 077 JSR WRITE16 ;WRITE SECTOR FROM NBUF1, NBUF2 3F1F:B0 66 078 BCS WEXIT2 ERR IF WRITE PROTECTED. 3F21:E6 3F 079 INC NSECT NEXT OF 16 SECTORS. 3F23:A5 3F 080 LDA NSECT 3F25:C9 10 081 CMP #$10 ; What's the point of VNOSEC in VTOC then?!?! 3F27:90 EC 082 BCC WSECT CONTINUE IF NOT DONE. 083 PAGE 084 ***************************** 085 * * 086 * VERIFY ROUTINE * 087 * * 088 * VERIFIES THAT THE FIRST * 089 * SECTOR ENCOUNTERED IS * 090 * SECTOR 0, AND THAT ALL * 091 * 16 SECTORS ARE READABLE * 092 * WITH MINIMAL RETRIES. * 093 * (2 REVOLUTIONS MAXIMUM) * 094 * * 095 * IF FIRST SECTOR IS NOT * 096 * SECTOR 0 THEN THE * 097 * CURRENT NUMBER OF SELF- * 098 * SYNC NIBLS IS DECR'D BY * 099 * 1 (IF ALREADY LESS THAN * 100 * 16) OR BY 2. THEN SECTOR * 101 * 15 IS LOCATED SO AS TO * 102 * POSITION THE NEW TRACK * 103 * REWRITE. * 104 * * 105 * IF UNABLE TO READ ANY * 106 * SECTOR THEN THE ENTIRE * 107 * TRACK IS REWRITTEN. * 108 * * 109 * AFTER VERIFYING TRACK 0, * 110 * THE NUMBER OF SELF-SYNC * 111 * NIBLS, NSYNC, IS DECR'D * 112 * BY 2 (IF STILL 16 OR * 113 * GREATER). * 114 * * 115 *****************************
116 PAGE ; === Page 84 === 3F29:A0 0F 117 VTRACK LDY #$F ; magic number TODO 3F2B:84 3F 118 STY NSECT SET 16 BYTES OF 3F2D:A9 30 119 LDA #$30 SECTOR FOUND TABLE 3F2F:8D 78 05 120 STA RETRYCNT TO $30 (MARK THEM). ; TEXT HOLE TODO XREF with other screen holes 3F32:99 A8 3F 121 CLRFOUND STA FOUND,Y 3F35:88 122 DEY 3F36:10 FA 123 BPl CLRFOUND 3F38:A4 45 124 LDY NSYNC 3F3A:20 87 3F 125 S0DELAY JSR WEXIT2 3F3D:20 87 3F 126 JSR WEXIT2 (12) EXPECTED TO INSURE 3F40:20 87 3F 127 JSR WEXIT2 (12) PROPER GAP PRIOR SECTOR 0. 3F43:48 128 PHA (3) 3F44:68 129 PLA (4) 3F45:EA 130 NOP (2) 3F46:88 131 DEY (2) 3F47:D0 F1 132 DEY S0DELAY (3) 3F49:20 44 39 133 JSR RDADR16 ;READ NEXT ADDRESS FIELD. 3F4C:B0 23 134 BCS S15LOC ERR, LOCATE SECT 15 AND REWRITE TRK. 3F4E:A5 2D 135 LDA SECT WAS IT SECTOR 0? 3F50:F0 15 136 BEQ VDATA YES, NOW VERIFY DATA FIELD. 3F52:A9 10 137 LDA #$10 ;↓ magic number TODO 3F54:C5 45 138 CMP NSYNC DECR NSYNC BY 1 IF LESS THAN 3F56:A5 45 139 LDA NSYNC 16, BY 2 IF NOT LESS. 3F58:E9 01 140 SBC #1 3F5A:85 45 141 STA NSYNC 3F5C:C9 05 142 CMP #5 IF LESS THAN 5, UNRECOVERABLE 3F5E:B0 11 143 BCS S15LOC ERR, ELSE REWRITE AFTER DATA FLD 15. 3F60:38 144 VERR SEC DRIVE EXTREMELY FAST OR 3F61:60 145 RTS OTHER SEVERE ERROR. 3F62:20 44 39 146 VSECT JSR RDADR16 ;READ AN ADDRESS FIELD. 3F65:B0 05 147 BCS VERR1 RETRY IF ERR. ;↓ 3F67:20 DC 38 148 VDATA JSR READ16 ;READ DATA FIELD. 3F6A:90 1C 149 BCC SECTOK (GOOD) ;↓ 3F6C:CE 78 05 150 VERR1 DEC RETRYCNT NEXT OF 48 SECTOR TRIES. 3F6F:D0 F1 151 BNE VSECT (KEEP TRYING) ;↑ 3F71:20 44 39 152 S15LOC JSR RDADR16 ;READ ADDRESS FIELD. ;↑ 3F74:B0 0B 153 BCS NOTS15 ERR, TRY UP TO 128 TIMES. ;↓ 3F76:A5 2D 154 LDA SECT SECTOR THAT WAS READ. 3F78:C9 0F 155 CMP #$F SECTOR 15? ; magic number VERIFY_REREAD_LAST_SEC 3F7A:D0 05 156 BNE NOTS15 NO, CONTINUE SEARCHING. ;↓ 3F7C:20 DC 38 157 JSR READ16 ;READ DATA FIELD. ; Why isn't this called READDATAHDR ??? 3F7F:90 8C 158 BCC WRITE TRACK FROM HERE IF NO ERR. ;↑ Read 16 what? Oh, Read 16 Sector Data Field 3F81:CE 78 05 159 NOTS15 DEC RETRYCNT $FF TO $7F, 128 TRIES. 3F84:D0 EB 160 BNE S15LOC TRY FOR SECT 15 AGAIN. ;↑ 3F86:38 161 SEC SET CARRY TO INDICATE VERIFY ERR. 3F87:60 162 WEXIT2 RTS AND RETURN TO FORMATTER. 3F88:A4 2D 163 SECTOK LDY SECT THIS IS SECTOR READ. 3F8A:B9 A8 3F 164 LDA FOUND,Y ALREADY FOUND? 3F8D:30 DD 165 BMI VERR1 YES, IGNORE IT. 3F8F:A9 FF 166 LDA #$FF ; magic number FLAG_SECTOR_FOUND = 1 3F91:99 A8 3F 167 STA FOUND,Y INDICATE THIS SECT NOW FOUND. 3F94:C6 3F 168 DEC NSECT FOUND 16 SECTORS? 3F96:10 CA 169 BPL VSECT NO, LOOK FOR NEXT. 3F98:A5 44 170 LDA TRK 3F9A:D0 0A 171 BNE WEXIT1 IF TRACK 0 AND NSYNC > 16 ; 3F9C:A5 45 172 LDA NSYNC (NUM GAP SYNC NIBLS) 3F9E:C9 10 173 CMP #$10 THEN SUBTRACT 2 FROM NSYNC 3FA0:90 E5 174 BCC WEXIT2 TO AVOID RETRIES ON LATER TRKS. 3FA2:C6 45 175 DEC NSYNC 3FA4:C6 45 176 DEC NSYNC 3FA6:18 177 WEXIT1 CLC INDICATE NO ERROR. 3FA7:60 178 RTS RETURN.
179 ****************************** ; === Page 85 === 180 AEC2 EQU * ;TELL RELOCTR WHERE RWTS ENDS 181 ****************************** 3FA8:00 00 00 00 182 FOUND DFB 0,0,0,0 'SECTOR FOUND' TABLE ;[.. wastes 16 bytes -- these are always cleared before used CLRFOUND, See: SECTOK 3FAC:00 00 00 00 183 DFB 0,0,0,0 ; .. TODO DOS 3.3 1980 has these as $FF 3FB0:00 00 00 00 184 DFB 0,0,0,0 ; .. 3FB4:00 00 00 00 185 DFB 0,0,0,0 ; ..] 186 FIN ; Macro started waaay back on Line #014, DSKFORM 187 LST ON 188 REP 40 189 * THIS TABLE IS USED TO TRANSLATE 190 * LOGICAL (REQUESTED) SECTOR NUMBER 191 * TO PHYSICAL SECTOR NUMBER. THE 192 * DISKETTE IS FORMATTED WITH ALL 193 * SECTORS IN MONOTONICALLY INCREASING ; MONOTONICALLY INCREASING ORDER 194 * ORDER. THE TRANSLATION WILL ALLOW ; Yup, math classes were just as boring back then too. 195 * TIME BETWEEN SECTORS FOR READS. 196 * 197 REP 40 198 * 199 * NOTE: THE CURRENT IMPLEMENTATION OF DOS 200 * USUALLY ACCESSES SECTORS IN DECREASING 201 * ORDER ON A TRACK. THUS WE WILL 202 * TRANSLATE IN REVERSE ORDER... 203 * 204 * THE INTERLEAVE IS THEN 9:1 ; TODO: Verify this is optimal for reading 205 * ; sectors in normal F,E,D,..,2,1,0 access pattern order 206 * NOTE: WE MAP LOGICAL SECTOR 0 207 * INTO PHYSICAL SECTOR 0 SO THAT 208 * WRITING OF BOOT DURING 'INIT' 209 * IS CORRECT FOR SECTOR ZERO. 210 * 211 INTRLEAV EQU * ; *sigh* 3FB8:00 0D 0B 09 212 DFB $00,$0D,$0B,$09 ; /sarcasm Here's a novel concept ... 3FBC:07 05 03 01 213 DFB $07,$05,$03,$01 ; How about *formatting* the sectors in the correct 3FC0:0E 0C 0A 08 214 DFB $0E,$0C,$0A,$08 ; order on the disk in the first place so we don't even 3FC4:06 04 02 0F 215 DFB $06,$04,$02,$0F ; need to waste memory with this table at all !
001 SBTL "DOS PATCHES" 002 ******************************** 003 * 004 * DOS 3.2 PATCHES BY DICK HUSTON 005 * 006 ******************************** 007 * AFTER THE FACT PATCHES 008 * CLRBYTE CALLED FROM DOS2 LABEL SOPTS +7 LINES 009 * CLRSTS1 CALLED FROM DOS3 LABEL ERROR +2 LINES 010 * ERROR9X CALLED FROM DOS5 LABEL ERROR9* 011 * 012 * 013 REP 40 014 * 015 * DOS 3.3 REVISION B PATCH 016 * 017 REP 40 018 ***************************** 019 SDP1 EQU * ; Start Dos Patch 020 RCPATCH EQU * ; "Called" from BOOTLDR, Func DOSINT, Line 295 3FC8:20 93 FE 021 JSR SETVID 3FCB:AD 81 C0 022 LDA $C081 ; magic number If only ROMIN = $C081 for Language Card (LC) 3FCE:AD 81 C0 023 LDA $C081 ; magic number 1st read = read ROM, 2nd read = write enable LC Bank 2 3FD1:A9 00 024 LDA #0 3FD3:8D 00 E0 025 STA $E000 ; magic number *sigh* Forces Language Card to reload 026 DO DOS33B 3FD6:20 76 3A 027 JSR OFF80 3FD9:4C 44 37 028 JMP RCBACK ; wastes 2 bytes Why not RTS ??? 029 ELSE 030 JMP RCBACK 031 DS 3,0 032 FIN 033 ***************************** 3FDC:8D 63 2A 034 CLRBYTE STA TEMP1A ; Called from SOPTS, Page 18, Line 176 3FDF:8D 70 2A 035 STA CB ;SET TYPE PARAM DEFAUTL=0 ; *spelling* DEFAULT 3FE2:8D 71 2A 036 STA CB+1 3FE5:60 037 RTS 038 SKP 4 3FE6:20 5B 27 039 CLRSTS1 JSR CLRSTS ; TODO Clear ??? 3FE9:8C B7 2A 040 STY RSTATE ;PREVENTS FOREVER 'FILE NOT FOUND' 3FEC:60 041 RTS ; IN APPLESOFT 042 ***************************** 3FED:20 7E 2E 043 ERROR9X JSR RTNFCB 3FF0:AE 9B 33 044 LDX ENTSTK ;GET STACK 3FF3:9A 045 TXS ;MESSY MESSY MESSY 3FF4:20 16 23 046 JSR CLALL ;GO CLOSE EVERYBODY 3FF7:BA 047 TSX 3FF8:8E 9B 33 048 STX ENTSTK ;RESTORE SAVE STK 3FFB:A9 09 049 LDA #9 ; magic number LDA #CRENSA 3FFD:4C 85 33 050 JMP ERRORA ;AND BACK 051 ***************************** 052 ENDP1 EQU *-1 ; END OF DOS PATCHES FOR RELOCTR 053 ENDOFDOS EQU *
054 DO ENDOFDOS-$4000 ; === Page 53 === 055 FAIL 2,'DOS LENGTH NOT CORRECT' 056 FIN
Total LOC (Lines of Code): | 6,442 |
Number of Source assembly files: | 29 |
Average LOC per source file: | 222 |
Total Spelling mistakes: | ? |
Total Equates: | ? |
Total Functions: | ? |
Total Variables: | ? |
Total Functions referenced (*) | ? |
Total Variables referenced (*) | ? |
Total Magic Numbers: | ? |
Total Wasted bytes (run-time memory): | 160 |
Total Wasted sectors: | 14 |
(*) Note: Includes commentary references to functions and variables.
RELOCTR ; $1B00 .. $1C80, T0SA - T0SB DOSINIT ; $1C81 .. $1E80, T0SB - T0SD DOSHOOK ; $1E81 .. $1FCC, T0SD - T0SE CMDSCAN ; $1FCD .. $2192, T0SE - T1S0 XOPNCLS ; $2193 .. $2330, T1S0 - T1S2 XLODSAV ; $2331 .. $250F, T1S2 - T1S4 XMISCMD ; $2510 .. $26A7, T1S4 - T1S5 DOSGOER ; $26A8 .. $27D3, T1S5 - T1S6 BLDFTAB ; $27D4 .. $2883, T1S6 - T1S7 CMDTBLS ; $2884 .. $2A4E, T1S7 - T1S9 FDOSENT ; $2A4F .. $2B21, T1S9 - T1SA FOPCLRW ; $2B22 .. $2CEE, T1SA - T1SB FDELCAT ; $2CEF .. $2E8D, T1SB - T1SD FMTRWIO ; $2E8E .. $2FF6, T1SD - T1SE FLOCNXB ; $2FF7 .. $31C8, T1SE - T2S0 FLOCSEC ; $31C9 .. $3396, T2S0 - T2S2 FVCBUFS ; $3397 .. $35FD, T2S2 - T2S4 BOOTLDR ; $35FE .. $37FF, T0S0 - T0S1 COREQUS ; n/a PRENIBL ; $3800 .. $3829, T0S2 WRITRTN ; $382A .. $38C1, T0S2 POSTNRD ; $38C2 .. $3943, T0S2 - T0S3 RDADSEK ; $3944 .. $39FC, T0S3 MSWAITR ; $39FD .. $3C55, T0S3 - T0S6 WRITADR ; $3C56 .. $3CFF, T0S6 RWTSONE ; $3D00 .. $3DAA, T0S7 RWTSTWO ; $3DAB .. $3EAE, T0S7 - T0S8 FORMATR ; $3EAF .. $3FC7, T0S8 - T0S9 DOSPTCH ; $3FC8 .. $3FFF, T0S9
1B00:4C 84 1D A9 BF 85 41 A2 |L..)?.A"| T0SA, RELOCTR, $1B00 .. $1CFF, T0SA - T0SB 1B08:00 86 40 A0 00 A1 40 85 |..@ .!@.| 1B10:26 98 45 26 85 26 98 41 |&.E&.&.A| 1B18:40 81 40 C5 26 D0 05 C8 |@.@E&P.H| 1B20:D0 EF F0 04 C6 41 D0 E3 |Pop.FAPc| 1B28:A5 41 29 DF 85 43 86 42 |%A)_.C.B| 1B30:A1 42 48 85 26 98 45 26 |!BH.&.E&| 1B38:85 26 98 41 40 81 42 C5 |.&.A@.BE| 1B40:26 D0 09 C8 D0 EF A4 43 |&P.HPo$C| 1B48:68 4C 51 1B 68 81 42 A4 |hLQ.h.B$| 1B50:41 C8 8C 7D 1C 38 98 ED |AH.}.8.m| 1B58:7E 1C 8D 7C 1C 38 ED 7A |~..|.8mz| 1B60:1C F0 9D 8D 7F 1C AD 7A |.p....-z| 1B68:1C 8D 0D 1D A9 1D 8D 49 |....)..I| 1B70:37 A9 84 8D 48 37 A2 00 |7)..H7".| 1B78:86 40 BD 29 1C A8 BD 2A |.@=).(=*| 1B80:1C 85 41 4C 93 1B 18 B1 |..AL...1| 1B88:40 6D 7F 1C 91 40 C8 D0 |@m...@HP| 1B90:02 E6 41 C8 D0 02 E6 41 |.fAHP.fA| 1B98:A5 41 DD 2C 1C 90 E7 98 |%A],..g.| 1BA0:DD 2B 1C 90 E1 8A 18 69 |]+..a..i| 1BA8:04 AA EC 28 1C 90 CB A2 |.*l(..K"| 1BB0:00 8E 9C 33 BD 5A 1C 85 |...3=Z..| 1BB8:40 BD 5B 1C 85 41 A2 00 |@=[..A".| 1BC0:A1 40 20 8E F8 A4 2F C0 |!@ .x$/@| 1BC8:02 D0 11 B1 40 CD 7A 1C |.P.1@Mz.| 1BD0:90 0A CD 7B 1C B0 05 6D |..M{.0.m| 1BD8:7F 1C 91 40 38 A5 2F 65 |...@8%/e| 1BE0:40 85 40 A9 00 65 41 85 |@.@).eA.| 1BE8:41 AE 9C 33 DD 5D 1C 90 |A..3]]..| 1BF0:CD A5 40 DD 5C 1C 90 C6 |M%@]\..F| 1BF8:8A 18 69 04 AA EC 59 1C |..i.*lY.| 1C00:90 AF A9 3F 85 41 AC 7D |./)?.A,}| T0SB 1C08:1C 88 84 43 A9 00 85 40 |...C)..@| 1C10:85 42 A8 B1 40 91 42 C8 |.B(1@.BH| 1C18:D0 F9 CE 80 1C F0 06 C6 |PyN..p.F| 1C20:41 C6 43 D0 EE 4C 54 1E |AFCPnLT.| 1C28:24 00 1D 56 1D 58 1D 5A |$..V.X.Z| 1C30:1D 64 1D 66 1D 6C 1D 70 |.d.f.l.p| 1C38:1D 78 1D 7C 1D 7E 1D 80 |.x.|.~..| 1C40:1D C1 2A FD 2A E4 37 E8 |.A*}*d7h| 1C48:37 EE 37 F0 37 00 00 00 |7n7p7...| 1C50:00 00 00 00 00 00 00 00 |........| 1C58:00 20 84 1D 84 28 FD 2A |. ...(}*| 1C60:97 33 5D 36 E0 37 56 3C |.3]6`7V<| 1C68:DF 3C 00 38 11 3A 69 3A |_<.8.:i:| 1C70:84 3A 00 3D A8 3F C8 3F |.:.=(?H?| 1C78:FF 3F 1D 40 00 00 23 00 |.?.@..#.| 1C80:23 FC FC FC FC FC FC FD |#||||||}| DOSINIT, $1C81 .. $1E80, T0SB - T0SD 1C88:FC FC FF FC FD FC FC FF |||.|}||.| 1C90:FF FC FE FD FE FD FD FE |.|~}~}}~| 1C98:FF FC FE FF FD FE FF FD |.|~.}~.}| 1CA0:FC FD FD FC FD FE FD FF ||}}|}~}.| 1CA8:FC FE FC FC FC FC FC FC ||~||||||| 1CB0:FD FC FC FE FC FD FC FC |}||~|}||| 1CB8:FF FC FC FE FD FC FD FF |.||~}|}.| 1CC0:FC FF FD FE FF FD FF FC ||.}~.}.|| 1CC8:FC FD FE FF FF FF FC FC ||}~...||| 1CD0:FF FF FC FE FD FC FD FD |..|~}|}}| 1CD8:FE FF FD FE FF FC FE FE |~.}~.|~~| 1CE0:FC FD FC FD FE FD FD FC ||}|}~}}|| 1CE8:FD FC FF FD FC FF FC FC |}|.}|.||| 1CF0:FE FD FC FC FD FC FE FC |~}||}|~|| 1CF8:FC FD FF FC FC FD FC FC ||}.||}||| 1D00:D3 1C 81 1E BD 1E 75 2A |S...=.u*| T0SC 1D08:93 2A 60 2A 00 1B BB 35 |.*`*..;5| 1D10:EA 1E 11 1F 22 1F 2E 1F |j..."...| 1D18:51 1F 60 1F 70 1F 4E 25 |Q.`.p.N%| 1D20:12 24 96 23 D0 24 EF 24 |.$.#P$o$| 1D28:62 22 70 22 74 22 E9 22 |b"p"t"i"| 1D30:1A 25 C5 25 0F 25 DC 25 |.%E%.%\%| 1D38:A2 22 97 22 80 22 6D 25 |""."."m%| 1D40:32 22 3C 22 28 22 2D 22 |2"<"("-"| 1D48:50 22 79 25 9D 25 30 23 |P"y%.%0#| 1D50:5C 23 8D 23 7C 22 36 E8 |\#.#|"6h| 1D58:E5 24 E3 E3 00 E0 03 E0 |e$cc.`.`| 1D60:00 00 36 E8 E5 24 E3 E3 |..6he$cc| 1D68:00 E0 03 E0 FC 24 FC 24 |.`.`|$|$| 1D70:65 D8 00 E0 3C D4 F2 D4 |eX.`<TrT| 1D78:06 25 06 25 67 10 84 1D |.%.%g...| 1D80:3C 0C F2 0C AD E9 37 4A |<.r.-i7J| 1D88:4A 4A 4A 8D 6A 2A AD EA |JJJ.j*-j| 1D90:37 8D 68 2A AD 00 E0 49 |7.h*-.`I| 1D98:20 D0 11 8D B6 2A A2 0A | P..6*".| 1DA0:BD 61 1D 9D 55 1D CA D0 |=a..U.JP| 1DA8:F7 4C BC 1D A9 40 8D B6 |wL<.)@.6| 1DB0:2A A2 0C BD 6B 1D 9D 55 |*".=k..U| 1DB8:1D CA D0 F7 38 B0 12 AD |.JPw80.-| 1DC0:B6 2A D0 04 A9 20 D0 05 |6*P.) P.| 1DC8:0A 10 05 A9 4C 20 B2 25 |...)L 2%| 1DD0:18 08 20 51 28 A9 00 8D |.. Q()..| 1DD8:5E 2A 8D 52 2A 28 6A 8D |^*.R*(j.| 1DE0:51 2A 30 03 6C 5E 1D 6C |Q*0.l^.l| 1DE8:5C 1D 0A 10 19 8D B6 2A |\.....6*| 1DF0:A2 0C BD 77 1D 9D 55 1D |".=w..U.| 1DF8:CA D0 F7 A2 1D BD 93 2A |JPw".=.*| 1E00:9D 75 2A CA 10 F7 AD B1 |.u*J.w-1| T0SD 1E08:2A 8D 57 2A 20 D4 27 AD |*.W* T'-| 1E10:B3 2A F0 09 48 20 9D 26 |3*p.H .&| 1E18:68 A0 00 91 40 20 5B 27 |h ..@ ['| 1E20:AD 5F 2A D0 20 A2 2F BD |-_*P "/=| 1E28:51 1E 9D D0 03 CA 10 F7 |Q..P.J.w| 1E30:AD 53 1E 8D F3 03 49 A5 |-S..s.I%| 1E38:8D F4 03 AD 52 1E 8D F2 |.t.-R..r| 1E40:03 A9 06 D0 05 AD 62 2A |.).P.-b*| 1E48:F0 06 8D 5F 2A 4C 80 21 |p.._*L.!| 1E50:60 4C BF 1D 4C 84 1D 4C |`L?.L..L| 1E58:FD 2A 4C B5 37 AD 0F 1D |}*L57-..| 1E60:AC 0E 1D 60 AD C2 2A AC |,..`-B*,| 1E68:C1 2A 60 4C 51 28 EA EA |A*`LQ(jj| 1E70:4C 59 FA 4C 65 FF 4C 58 |LYzLe.LX| 1E78:FF 4C 65 FF 4C 65 FF 65 |.Le.Le.e| 1E80:FF 20 D1 1E AD 51 2A F0 |. Q.-Q*p| DOSHOOK, $1E81 - $1FCC, T0SD - T0SE 1E88:15 48 AD 5C 2A 91 28 68 |.H-\*.(h| 1E90:30 03 4C 26 26 20 EA 1D |0.L&& j.| 1E98:A4 24 A9 60 91 28 AD B3 |$$)`.(-3| 1EA0:2A F0 03 20 82 26 A9 03 |*p. .&).| 1EA8:8D 52 2A 20 BA 1F 20 BA |.R* :. :| 1EB0:1E 8D 5C 2A 8E 5A 2A 4C |..\*.Z*L| 1EB8:B3 1F 6C 38 00 20 D1 1E |3.l8. Q.| 1EC0:AD 52 2A 0A AA BD 11 1D |-R*.*=..| 1EC8:48 BD 10 1D 48 AD 5C 2A |H=..H-\*| 1ED0:60 8D 5C 2A 8E 5A 2A 8C |`.\*.Z*.| 1ED8:5B 2A BA E8 E8 8E 59 2A |[*:hh.Y*| 1EE0:A2 03 BD 53 2A 95 36 CA |".=S*.6J| 1EE8:10 F8 60 AE B7 2A F0 03 |.x`.7*p.| 1EF0:4C 78 1F AE 51 2A F0 08 |Lx..Q*p.| 1EF8:C9 BF F0 75 C5 33 F0 27 |I?puE3p'| 1F00:A2 02 8E 52 2A CD B2 2A |"..R*M2*| T0SE 1F08:D0 19 CA 8E 52 2A CA 8E |P.J.R*J.| 1F10:5D 2A AE 5D 2A 9D 00 02 |]*.]*...| 1F18:E8 8E 5D 2A C9 8D D0 75 |h.]*I.Pu| 1F20:4C CD 1F C9 8D D0 7D A2 |LM.I.P}"| 1F28:00 8E 52 2A 4C A4 1F A2 |..R*L$."| 1F30:00 8E 52 2A C9 8D F0 07 |..R*I.p.| 1F38:AD B3 2A F0 67 D0 5E 48 |-3*pgP^H| 1F40:38 AD B3 2A D0 03 20 5E |8-3*P. ^| 1F48:26 68 90 EC AE 5A 2A 4C |&h.l.Z*L| 1F50:15 1F C9 8D D0 05 A9 05 |..I.P.).| 1F58:8D 52 2A 20 0E 26 4C 99 |.R* .&L.| 1F60:1F CD B2 2A F0 85 C9 8A |.M2*p.I.| 1F68:F0 F1 A2 04 8E 52 2A D0 |pq"..R*P| 1F70:E1 A9 00 8D 52 2A F0 25 |a)..R*p%| 1F78:A9 00 8D B7 2A 20 51 28 |)..7* Q(| 1F80:4C DC 24 AD 00 02 CD B2 |L\$-..M2| 1F88:2A F0 0A A9 8D 8D 00 02 |*p.)....| 1F90:A2 00 8E 5A 2A A9 40 D0 |"..Z*)@P| 1F98:06 A9 10 D0 02 A9 20 2D |.).P.) -| 1FA0:5E 2A F0 0F 20 BA 1F 20 |^*p. :. | 1FA8:C5 1F 8D 5C 2A 8C 5B 2A |E..\*.[*| 1FB0:8E 5A 2A 20 51 28 AE 59 |.Z* Q(.Y| 1FB8:2A 9A AD 5C 2A AC 5B 2A |*.-\*,[*| 1FC0:AE 5A 2A 38 60 6C 36 00 |.Z*8`l6.| 1FC8:A9 8D 4C C5 1F A0 FF 8C |).LE. ..| CMDSCAN, $1FCD .. $2192, T0SE - T1S0 1FD0:5F 2A C8 8C 62 2A EE 5F |_*H.b*n_| 1FD8:2A A2 00 08 BD 00 02 CD |*"..=..M| 1FE0:B2 2A D0 01 E8 8E 5D 2A |2*P.h.]*| 1FE8:20 A4 21 29 7F 59 84 28 | $!).Y.(| 1FF0:C8 0A F0 02 68 08 90 F0 |H.p.h..p| 1FF8:28 F0 20 B9 84 28 D0 D6 |(p 9.(PV| 2000:AD 00 02 CD B2 2A F0 03 |-..M2*p.| T0SF 2008:4C A4 1F AD 01 02 C9 8D |L$.-..I.| 2010:D0 06 20 5B 27 4C 95 1F |P. ['L..| 2018:4C C4 26 0E 5F 2A AC 5F |LD&._*,_| 2020:2A 20 5E 26 90 0C A9 02 |* ^&..).| 2028:39 09 29 F0 05 A9 0F 4C |9.)p.).L| 2030:D2 26 C0 06 D0 02 84 33 |R&@.P..3| 2038:A9 20 39 09 29 F0 61 20 |) 9.)pa | 2040:95 20 08 20 A4 21 F0 1E |. . $!p.| 2048:0A 90 05 30 03 4C 00 20 |...0.L. | 2050:6A 4C 59 20 20 93 21 F0 |jLY .!p| 2058:0D 99 75 2A C8 C0 3C 90 |..u*H@<.| 2060:F3 20 93 21 D0 FB 28 D0 |s .!P{(P| 2068:0F AC 5F 2A A9 10 39 09 |.,_*).9.| 2070:29 F0 0C A0 1E 08 D0 CB |)p. ..PK| 2078:AD 93 2A C9 A0 F0 13 AD |-.*I p.-| 2080:75 2A C9 A0 D0 4B AC 5F |u*I PK,_| 2088:2A A9 C0 39 09 29 F0 02 |*)@9.)p.| 2090:10 3F 4C 00 20 A0 3C A9 |.?L. <)| 2098:A0 99 74 2A 88 D0 FA 60 | .t*.Pz`| 20A0:8D 75 2A A9 0C 39 09 29 |.u*).9.)| 20A8:F0 27 20 B9 21 B0 1F A8 |p' 9!0.(| 20B0:D0 17 E0 11 B0 13 AC 5F |P.`.0.,_| 20B8:2A A9 08 39 09 29 F0 06 |*).9.)p.| 20C0:E0 08 B0 CE 90 0B 8A D0 |`.0N...P| 20C8:08 A9 02 4C D2 26 4C C4 |.).LR&LD| 20D0:26 A9 00 8D 65 2A 8D 74 |&)..e*.t| 20D8:2A 8D 66 2A 8D 6C 2A 8D |*.f*.l*.| 20E0:6D 2A 20 DC 3F AD 5D 2A |m* \?-]*| 20E8:20 A4 21 D0 1F C9 8D D0 | $!P.I.P| 20F0:F7 AE 5F 2A AD 65 2A 1D |w._*-e*.| 20F8:0A 29 5D 0A 29 D0 93 AE |.)].)P..| 2100:63 2A F0 76 8D 63 2A 8E |c*pv.c*.| T1S0 2108:5D 2A D0 DC A2 0A DD 40 |]*P\".]@| 2110:29 F0 05 CA D0 F8 F0 B6 |)p.JPxp6| 2118:BD 4A 29 30 47 0D 65 2A |=J)0G.e*| 2120:8D 65 2A CA 8E 64 2A 20 |.e*J.d* | 2128:B9 21 B0 A2 AD 64 2A 0A |9!0"-d*.| 2130:0A A8 A5 45 D0 09 A5 44 |.(%EP.%D| 2138:D9 55 29 90 8C A5 45 D9 |YU)..%EY| 2140:58 29 90 0B D0 83 A5 44 |X)..P.%D| 2148:D9 57 29 90 02 D0 F5 AD |YW)..Pu-| 2150:63 2A D0 94 98 4A A8 A5 |c*P..J(%| 2158:45 99 67 2A A5 44 99 66 |E.g*%D.f| 2160:2A 4C E8 20 48 A9 80 0D |*Lh H)..| 2168:65 2A 8D 65 2A 68 29 7F |e*.e*h).| 2170:0D 74 2A 8D 74 2A D0 E9 |.t*.t*Pi| 2178:F0 9C 20 80 21 4C 83 1F |p. .!L..| 2180:20 5B 27 20 AE 21 AD 5F | [' .!-_| 2188:2A AA BD 1F 1D 48 BD 1E |**=..H=.| 2190:1D 48 60 AE 5D 2A BD 00 |.H`.]*=.| XOPNCLS, $2193 .. $2330, T1S0 - T1S2 2198:02 C9 8D F0 06 E8 8E 5D |.I.p.h.]| 21A0:2A C9 AC 60 20 93 21 F0 |*I,` .!p| 21A8:FA C9 A0 F0 F7 60 A9 00 |zI pw`).| 21B0:A0 16 99 BA 35 88 D0 FA | ..:5.Pz| 21B8:60 A9 00 85 44 85 45 20 |`)..D.E | 21C0:A4 21 08 C9 A4 F0 3C 28 |$!.I$p<(| 21C8:4C CE 21 20 A4 21 D0 06 |LN! $!P.| 21D0:A6 44 A5 45 18 60 38 E9 |&D%E.`8i| 21D8:B0 30 21 C9 0A B0 1D 20 |00!I.0. | 21E0:FE 21 65 44 AA A9 00 65 |~!eD*).e| 21E8:45 A8 20 FE 21 20 FE 21 |E( ~! ~!| 21F0:8A 65 44 85 44 98 65 45 |.eD.D.eE| 21F8:85 45 90 CF 38 60 06 44 |.E.O8`.D| 2200:26 45 60 28 20 A4 21 F0 |&E`( $!p| T1S1 2208:C5 38 E9 B0 30 EE C9 0A |E8i00nI.| 2210:90 08 E9 07 30 E6 C9 10 |..i.0fI.| 2218:B0 E2 A2 04 20 FE 21 CA |0b". ~!J| 2220:D0 FA 05 44 85 44 4C 04 |Pz.D.DL.| 2228:22 A5 44 4C 95 FE A5 44 |"%DL.~%D| 2230:4C 8B FE AD 5E 2A 0D 74 |L.~-^*.t| 2238:2A 8D 5E 2A 60 2C 74 2A |*.^*`,t*| 2240:50 03 20 C8 1F A9 70 4D |P. H.)pM| 2248:74 2A 2D 5E 2A 8D 5E 2A |t*-^*.^*| 2250:60 A9 00 8D B3 2A A5 44 |`)..3*%D| 2258:48 20 16 23 68 8D 57 2A |H .#h.W*| 2260:4C D4 27 A9 05 20 AA 22 |LT'). *"| 2268:20 64 27 A0 00 98 91 40 | d' ...@| 2270:60 A9 07 D0 02 A9 08 20 |`).P.). | 2278:AA 22 4C EA 22 A9 0C D0 |*"Lj").P| 2280:F6 AD 08 1D 8D BD 35 AD |v-...=5-| 2288:09 1D 8D BE 35 A9 09 8D |...>5)..| 2290:63 2A 20 C8 22 4C EA 22 |c* H"Lj"| 2298:20 A3 22 20 8C 26 D0 FB | #" .&P{| 22A0:4C 71 36 A9 00 4C D5 23 |Lq6).LU#| 22A8:A9 01 8D 63 2A AD 6C 2A |)..c*-l*| 22B0:D0 0A AD 6D 2A D0 05 A9 |P.-m*P.)| 22B8:01 8D 6C 2A AD 6C 2A 8D |..l*-l*.| 22C0:BD 35 AD 6D 2A 8D BE 35 |=5-m*.>5| 22C8:20 EA 22 A5 45 D0 03 4C | j"%EP.L| 22D0:C8 26 85 41 A5 44 85 40 |H&.A%D.@| 22D8:20 43 27 20 4E 27 20 1A | C' N' .| 22E0:27 AD 63 2A 8D BB 35 4C |'-c*.;5L| 22E8:A8 26 AD 75 2A C9 A0 F0 |(&-u*I p| 22F0:25 20 64 27 B0 3A 20 FC |% d'0: || 22F8:22 4C EA 22 20 AF 27 D0 |"Lj" /'P| 2300:05 A9 00 8D B3 2A A0 00 |.)..3* .| T1S2 2308:98 91 40 20 4E 27 A9 02 |..@ N').| 2310:8D BB 35 4C A8 26 20 92 |.;5L(& .| 2318:27 D0 05 20 9A 27 F0 10 |'P. .'p.| 2320:20 AF 27 F0 F6 20 AA 27 | /'pv *'| 2328:F0 F1 20 FC 22 4C 16 23 |pq |"L.#| 2330:60 A9 09 2D 65 2A C9 09 |`).-e*I.| XLODSAV, $2331 .. $250F, T1S2 - T1S4 2338:F0 03 4C 00 20 A9 04 20 |p.L. ). | 2340:D5 23 AD 73 2A AC 72 2A |U#-s*,r*| 2348:20 E0 23 AD 6D 2A AC 6C | `#-m*,l| 2350:2A 20 E0 23 AD 73 2A AC |* `#-s*,| 2358:72 2A 4C FF 23 20 A8 22 |r*L.# ("| 2360:A9 7F 2D C2 35 C9 04 F0 |).-B5I.p| 2368:03 4C D0 26 A9 04 20 D5 |.LP&). U| 2370:23 20 7A 24 AA AD 65 2A |# z$*-e*| 2378:29 01 D0 06 8E 72 2A 8C |).P..r*.| 2380:73 2A 20 7A 24 AE 72 2A |s* z$.r*| 2388:AC 73 2A 4C 71 24 20 5D |,s*Lq$ ]| 2390:23 20 51 28 6C 72 2A AD |# Q(lr*-| 2398:B6 2A F0 20 A5 D6 10 03 |6*p %V..| 23A0:4C CC 26 A9 02 20 D5 23 |LL&). U#| 23A8:38 A5 AF E5 67 A8 A5 B0 |8%/eg(%0| 23B0:E5 68 20 E0 23 A5 68 A4 |eh `#%h$| 23B8:67 4C FF 23 A9 01 20 D5 |gL.#). U| 23C0:23 38 A5 4C E5 CA A8 A5 |#8%LeJ(%| 23C8:4D E5 CB 20 E0 23 A5 CB |MeK `#%K| 23D0:A4 CA 4C FF 23 8D C2 35 |$JL.#.B5| 23D8:48 20 A8 22 68 4C C4 27 |H ("hLD'| 23E0:8C C1 35 8C C3 35 8D C2 |.A5.C5.B| 23E8:35 A9 04 8D BB 35 A9 01 |5)..;5).| 23F0:8D BC 35 20 A8 26 AD C2 |.<5 (&-B| 23F8:35 8D C3 35 4C A8 26 8C |5.C5L(&.| 2400:C3 35 8D C4 35 A9 02 4C |C5.D5).L| T1S3 2408:86 36 20 A8 26 4C EA 22 |.6 (&Lj"| 2410:4C D0 26 20 16 23 20 A8 |LP& .# (| 2418:22 A9 23 2D C2 35 F0 F0 |")#-B5pp| 2420:8D C2 35 AD B6 2A F0 28 |.B5-6*p(| 2428:A9 02 20 B1 24 20 7A 24 |). 1$ z$| 2430:18 65 67 AA 98 65 68 C5 |.eg*.ehE| 2438:74 B0 70 85 B0 85 6A 86 |t0p.0.j.| 2440:AF 86 69 A6 67 A4 68 20 |/.i&g$h | 2448:71 24 20 51 28 6C 60 1D |q$ Q(l`.| 2450:A9 01 20 B1 24 20 7A 24 |). 1$ z$| 2458:38 A5 4C ED 60 2A AA A5 |8%Lm`**%| 2460:4D ED 61 2A 90 45 A8 C4 |Mma*.E(D| 2468:4B 90 40 F0 3E 84 CB 86 |K.@p>.K.| 2470:CA 8E C3 35 8C C4 35 4C |J.C5.D5L| 2478:0A 24 AD 0A 1D 8D C3 35 |.$-...C5| 2480:AD 0B 1D 8D C4 35 A9 00 |-...D5).| 2488:8D C2 35 A9 02 8D C1 35 |.B5)..A5| 2490:A9 03 8D BB 35 A9 02 8D |)..;5)..| 2498:BC 35 20 A8 26 AD 61 2A |<5 (&-a*| 24A0:8D C2 35 A8 AD 60 2A 8D |.B5(-`*.| 24A8:C1 35 60 20 EA 22 4C CC |A5` j"LL| 24B0:26 CD C2 35 F0 1A AE 5F |&MB5p.._| 24B8:2A 8E 62 2A 4A F0 03 4C |*.b*Jp.L| 24C0:9E 25 A2 1D BD 75 2A 9D |.%".=u*.| 24C8:93 2A CA 10 F7 4C 7A 25 |.*J.wLz%| 24D0:60 AD B6 2A F0 03 8D B7 |`-6*p..7| 24D8:2A 20 13 24 20 C8 1F 20 |* .$ H. | 24E0:51 28 6C 58 1D A5 4A 85 |Q(lX.%J.| 24E8:CC A5 4B 85 CD 6C 56 1D |L%K.MlV.| 24F0:20 16 24 20 C8 1F 20 51 | .$ H. Q| 24F8:28 6C 56 1D 20 65 D6 85 |(lV. eV.| 2500:33 85 D8 4C D2 D7 20 65 |3.XLRW e| T1S4 2508:0E 85 33 85 D8 4C D4 0F |..3.XLT.| 2510:20 26 25 A9 05 8D 52 2A | &%)..R*| XMISCMD, $2510 .. $26A7, T1S4 - T1S5 2518:4C 83 1F 20 26 25 A9 01 |L.. &%).| 2520:8D 51 2A 4C 83 1F 20 64 |.Q*L.. d| 2528:27 90 06 20 A3 22 4C 34 |'.. #"L4| 2530:25 20 4E 27 AD 65 2A 29 |% N'-e*)| 2538:06 F0 13 A2 03 BD 6E 2A |.p.".=n*| 2540:9D BD 35 CA 10 F7 A9 0A |.=5J.w).| 2548:8D BB 35 20 A8 26 60 A9 |.;5 (&`)| 2550:40 2D 65 2A F0 05 AD 66 |@-e*p.-f| 2558:2A D0 05 A9 FE 8D 66 2A |*P.)~.f*| 2560:AD 0D 1D 8D BC 35 A9 0B |-...<5).| 2568:20 AA 22 4C 97 23 A9 06 | *"L.#).| 2570:20 AA 22 AD BF 35 8D 66 | *"-?5.f| 2578:2A 60 A9 4C 20 B2 25 F0 |*`)L 2%p| 2580:2E A9 00 8D B6 2A A0 1E |.)..6* .| 2588:20 97 20 A2 09 BD B7 2A | . ".=7*| 2590:9D 74 2A CA D0 F7 A9 C0 |.t*JPw)@| 2598:8D 51 2A 4C D1 24 A9 20 |.Q*LQ$) | 25A0:20 B2 25 F0 05 A9 01 4C | 2%p.).L| 25A8:D2 26 A9 00 8D B7 2A 4C |R&)..7*L| 25B0:84 1D CD 00 E0 F0 0E 8D |..M.`p..| 25B8:80 C0 CD 00 E0 F0 06 8D |.@M.`p..| 25C0:81 C0 CD 00 E0 60 20 A3 |.@M.`` #| 25C8:22 AD 4F 2A 8D B4 2A AD |"-O*.4*-| 25D0:50 2A 8D B5 2A AD 75 2A |P*.5*-u*| 25D8:8D B3 2A D0 0E 20 64 27 |.3*P. d'| 25E0:90 06 20 A3 22 4C EB 25 |.. #"Lk%| 25E8:20 4E 27 AD 65 2A 29 04 | N'-e*).| 25F0:F0 1B AD 6E 2A D0 08 AE |p.-n*P..| 25F8:6F 2A F0 11 CE 6F 2A CE |o*p.No*N| 2600:6E 2A 20 8C 26 F0 38 C9 |n* .&p8I| T1S5 2608:8D D0 F7 F0 E5 60 20 5E |.Pwpe` ^| 2610:26 B0 66 AD 5C 2A 8D C3 |&0f-\*.C| 2618:35 A9 04 8D BB 35 A9 01 |5)..;5).| 2620:8D BC 35 4C A8 26 20 5E |.<5L(& ^| 2628:26 B0 4E A9 06 8D 52 2A |&0N)..R*| 2630:20 8C 26 D0 0F 20 FC 22 | .&P. |"| 2638:A9 03 CD 52 2A F0 CE A9 |).MR*pN)| 2640:05 4C D2 26 C9 E0 90 02 |.LR&I`..| 2648:29 7F 8D 5C 2A AE 5A 2A |)..\*.Z*| 2650:F0 09 CA BD 00 02 09 80 |p.J=....| 2658:9D 00 02 4C B3 1F 48 AD |...L3.H-| 2660:B6 2A F0 0E A6 76 E8 F0 |6*p.&vhp| 2668:0D A6 33 E0 DD F0 07 68 |.&3`]p.h| 2670:18 60 A5 D9 30 F9 68 38 |.`%Y0yh8| 2678:60 20 FC 22 20 5B 27 4C |` |" ['L| 2680:B3 1F 20 9D 26 20 4E 27 |3. .& N'| 2688:A9 03 D0 A1 A9 03 8D BB |).P!)..;| 2690:35 A9 01 8D BC 35 20 A8 |5)..<5 (| 2698:26 AD C3 35 60 AD B5 2A |&-C5`-5*| 26A0:85 41 AD B4 2A 85 40 60 |.A-4*.@`| 26A8:20 06 2B 90 16 AD C5 35 | .+..-E5| DOSGOER, $26A8 .. $27D3, T1S5 - T1S6 26B0:C9 05 F0 03 4C 5E 36 4C |I.p.L^6L| 26B8:92 36 EA 20 69 3A A2 00 |.6j i:".| 26C0:8E C3 35 60 A9 0B D0 0A |.C5`).P.| 26C8:A9 0C D0 06 A9 0E D0 02 |).P.).P.| 26D0:A9 0D 8D 5C 2A 20 E6 3F |)..\* f?| 26D8:AD B6 2A F0 04 A5 D8 30 |-6*p.%X0| 26E0:0E A2 00 20 02 27 AE 5C |.". .'.\| 26E8:2A 20 02 27 20 C8 1F 20 |* .' H. | 26F0:51 28 20 5E 26 AE 5C 2A |Q( ^&.\*| 26F8:A9 03 B0 03 6C 5A 1D 6C |).0.lZ.l| 2700:5E 1D BD 3F 2A AA 8E 63 |^.=?**.c| T1S6 2708:2A BD 71 29 48 09 80 20 |*=q)H.. | 2710:C5 1F AE 63 2A E8 68 10 |E..c*hh.| 2718:ED 60 AD 66 2A 8D BF 35 |m`-f*.?5| 2720:AD 68 2A 8D C0 35 AD 6A |-h*.@5-j| 2728:2A 8D C1 35 AD 06 1D 8D |*.A5-...| 2730:C3 35 AD 07 1D 8D C4 35 |C5-...D5| 2738:A5 40 8D 4F 2A A5 41 8D |%@.O*%A.| 2740:50 2A 60 A0 1D B9 75 2A |P*` .9u*| 2748:91 40 88 10 F8 60 A0 1E |.@..x` .| 2750:B1 40 99 A9 35 C8 C0 26 |1@.)5H@&| 2758:D0 F6 60 A0 00 8C 51 2A |Pv` ..Q*| 2760:8C 52 2A 60 A9 00 85 45 |.R*`)..E| 2768:20 92 27 4C 73 27 20 9A | .'Ls' .| 2770:27 F0 1D 20 AA 27 D0 0A |'p. *'P.| 2778:A5 40 85 44 A5 41 85 45 |%@.D%A.E| 2780:D0 EC A0 1D B1 40 D9 75 |Pl .1@Yu| 2788:2A D0 E3 88 10 F6 18 60 |*Pc..v.`| 2790:38 60 AD 00 1D AE 01 1D |8`-.....| 2798:D0 0A A0 25 B1 40 F0 09 |P. %1@p.| 27A0:AA 88 B1 40 86 41 85 40 |*.1@.A.@| 27A8:8A 60 A0 00 B1 40 60 AD |.` .1@`-| 27B0:B3 2A F0 0E AD B4 2A C5 |3*p.-4*E| 27B8:40 D0 08 AD B5 2A C5 41 |@P.-5*EA| 27C0:F0 01 CA 60 4D C2 35 F0 |p.J`MB5p| 27C8:0A 29 7F F0 06 20 EA 22 |.).p. j"| 27D0:4C D0 26 60 38 AD 00 1D |LP&`8-..| BLDFTAB, $27D4 .. $2883, T1S6 - T1S7 27D8:85 40 AD 01 1D 85 41 AD |.@-...A-| 27E0:57 2A 8D 63 2A A0 00 98 |W*.c* ..| 27E8:91 40 A0 1E 38 A5 40 E9 |.@ .8%@i| 27F0:2D 91 40 48 A5 41 E9 00 |-.@H%Ai.| 27F8:C8 91 40 AA CA 68 48 C8 |H.@*JhHH| 2800:91 40 8A C8 91 40 AA CA |.@.H.@*J| T1S7 2808:68 48 C8 91 40 C8 8A 91 |hHH.@H..| 2810:40 CE 63 2A F0 17 AA 68 |@Nc*p.*h| 2818:38 E9 26 C8 91 40 48 8A |8i&H.@H.| 2820:E9 00 C8 91 40 85 41 68 |i.H.@.Ah| 2828:85 40 4C E5 27 48 A9 00 |.@Le'H).| 2830:C8 91 40 C8 91 40 AD B6 |H.@H.@-6| 2838:2A F0 0B 68 85 74 85 70 |*p.h.t.p| 2840:68 85 73 85 6F 60 68 85 |h.s.o`h.| 2848:4D 85 CB 68 85 4C 85 CA |M.Kh.L.J| 2850:60 A5 39 CD 03 1D F0 12 |`%9M..p.| 2858:8D 56 2A A5 38 8D 55 2A |.V*%8.U*| 2860:AD 02 1D 85 38 AD 03 1D |-...8-..| 2868:85 39 A5 37 CD 05 1D F0 |.9%7M..p| 2870:12 8D 54 2A A5 36 8D 53 |..T*%6.S| 2878:2A AD 04 1D 85 36 AD 05 |*-...6-.| 2880:1D 85 37 60 49 4E 49 D4 |..7`INIT| CMDTBLS, $2884 .. $2A4E, T1S7 - T1S9 2888:4C 4F 41 C4 53 41 56 C5 |LOADSAVE| 2890:52 55 CE 43 48 41 49 CE |RUNCHAIN| 2898:44 45 4C 45 54 C5 4C 4F |DELETELO| 28A0:43 CB 55 4E 4C 4F 43 CB |CKUNLOCK| 28A8:43 4C 4F 53 C5 52 45 41 |CLOSEREA| 28B0:C4 45 58 45 C3 57 52 49 |DEXECWRI| 28B8:54 C5 50 4F 53 49 54 49 |TEPOSITI| 28C0:4F CE 4F 50 45 CE 41 50 |ONOPENAP| 28C8:50 45 4E C4 52 45 4E 41 |PENDRENA| 28D0:4D C5 43 41 54 41 4C 4F |MECATALO| 28D8:C7 4D 4F CE 4E 4F 4D 4F |GMONNOMO| 28E0:CE 50 52 A3 49 4E A3 4D |NPR#IN#M| 28E8:41 58 46 49 4C 45 D3 46 |AXFILESF| 28F0:D0 49 4E D4 42 53 41 56 |PINTBSAV| 28F8:C5 42 4C 4F 41 C4 42 52 |EBLOADBR| 2900:55 CE 56 45 52 49 46 D9 |UNVERIFY| T1S8 2908:00 21 70 A0 70 A1 70 A0 |.!p p!p | 2910:70 20 70 20 70 20 70 20 |p p p p | 2918:70 60 00 22 06 20 74 22 |p`.". t"| 2920:06 22 04 23 78 22 70 30 |.".#x"p0| 2928:70 40 70 40 80 40 80 08 |p@p@.@..| 2930:00 08 00 04 00 40 70 40 |.....@p@| 2938:00 21 79 20 71 20 71 20 |.!y q q | 2940:70 D6 C4 D3 CC D2 C2 C1 |pVDSLRBA| 2948:C3 C9 CF 40 20 10 08 04 |CIO@ ...| 2950:02 01 C0 A0 90 00 00 FE |..@ ...~| 2958:00 01 00 02 00 01 00 07 |........| 2960:00 01 00 FF 7F 00 00 FF |........| 2968:7F 00 00 FF 7F 00 00 FF |........| 2970:FF 0D 07 8D 4C 41 4E 47 |....LANG| 2978:55 41 47 45 20 4E 4F 54 |UAGE NOT| 2980:20 41 56 41 49 4C 41 42 | AVAILAB| 2988:4C C5 52 41 4E 47 45 20 |LERANGE | 2990:45 52 52 4F D2 57 52 49 |ERRORWRI| 2998:54 45 20 50 52 4F 54 45 |TE PROTE| 29A0:43 54 45 C4 45 4E 44 20 |CTEDEND | 29A8:4F 46 20 44 41 54 C1 46 |OF DATAF| 29B0:49 4C 45 20 4E 4F 54 20 |ILE NOT | 29B8:46 4F 55 4E C4 56 4F 4C |FOUNDVOL| 29C0:55 4D 45 20 4D 49 53 4D |UME MISM| 29C8:41 54 43 C8 49 2F 4F 20 |ATCHI/O | 29D0:45 52 52 4F D2 44 49 53 |ERRORDIS| 29D8:4B 20 46 55 4C CC 46 49 |K FULLFI| 29E0:4C 45 20 4C 4F 43 4B 45 |LE LOCKE| 29E8:C4 53 59 4E 54 41 58 20 |DSYNTAX | 29F0:45 52 52 4F D2 4E 4F 20 |ERRORNO | 29F8:42 55 46 46 45 52 53 20 |BUFFERS | 2A00:41 56 41 49 4C 41 42 4C |AVAILABL| T1S9 2A08:C5 46 49 4C 45 20 54 59 |EFILE TY| 2A10:50 45 20 4D 49 53 4D 41 |PE MISMA| 2A18:54 43 C8 50 52 4F 47 52 |TCHPROGR| 2A20:41 4D 20 54 4F 4F 20 4C |AM TOO L| 2A28:41 52 47 C5 4E 4F 54 20 |ARGENOT | 2A30:44 49 52 45 43 54 20 43 |DIRECT C| 2A38:4F 4D 4D 41 4E C4 8D 00 |OMMAND..| 2A40:03 19 19 24 33 3E 4C 5B |...$3>L[| 2A48:64 6D 78 84 98 AA BB 00 |dmx..*;.| FDOSENT, $2A4F .. $2B21, T1S9 - T1SA 2A50:00 00 00 00 00 00 00 00 |........| 2A58:03 00 00 00 00 00 00 00 |........| 2A60:00 00 00 00 00 00 00 00 |........| 2A68:00 00 00 00 01 00 00 00 |........| 2A70:00 00 00 00 00 C8 C5 CC |.....HEL| 2A78:CC CF A0 A0 A0 A0 A0 A0 |LO | 2A80:A0 A0 A0 A0 A0 A0 A0 A0 | | 2A88:A0 A0 A0 A0 A0 A0 A0 A0 | | 2A90:A0 A0 A0 A0 A0 A0 A0 A0 | | 2A98:A0 A0 A0 A0 A0 A0 A0 A0 | | 2AA0:A0 A0 A0 A0 A0 A0 A0 A0 | | 2AA8:A0 A0 A0 A0 A0 A0 A0 A0 | | 2AB0:A0 03 84 00 00 00 00 00 | .......| 2AB8:C1 D0 D0 CC C5 D3 CF C6 |APPLESOF| 2AC0:D4 E8 37 BB 33 BB 34 00 |Th7;3;4.| 2AC8:40 7E 33 21 2B 05 2C 57 |@~3!+.,W| 2AD0:2C 6F 2C 2A 2D 97 2D EE |,o,*-.-n| 2AD8:2C F5 2C 39 2C 11 2D 8D |,u,9,.-.| 2AE0:2E 17 2D 7E 33 7E 33 89 |..-~3~3.| 2AE8:2C 95 2C 86 2C 92 2C 7E |,.,.,.,~| 2AF0:33 7E 33 BD 2C C9 2C BA |3~3=,I,:| 2AF8:2C C6 2C 7E 33 E0 00 F0 |,F,~3`.p| 2B00:02 A2 02 8E 5F 2A BA 8E |.".._*:.| T1SA 2B08:9B 33 20 6A 2E AD BB 35 |.3 j.-;5| 2B10:C9 0D B0 0B 0A AA BD CA |I.0..*=J| 2B18:2A 48 BD C9 2A 48 60 4C |*H=I*H`L| 2B20:63 33 20 28 2B 4C 7F 33 |c3 (+L.3| FOPCLRW, $2B22 .. $2CEE, T1SA - T1SB 2B28:20 DC 2B A9 01 8D E3 35 | \+)..c5| 2B30:AE BE 35 AD BD 35 D0 05 |.>5-=5P.| 2B38:E0 00 D0 01 E8 8D E8 35 |`.P.h.h5| 2B40:8E E9 35 20 C9 31 90 5E |.i5 I1.^| 2B48:8E 9C 33 AE 5F 2A BD 09 |..3._*=.| 2B50:29 AE 9C 33 4A B0 0D AD |)..3J0.-| 2B58:51 2A C9 C0 D0 03 4C 5F |Q*I@P.L_| 2B60:33 4C 73 33 A9 00 9D E8 |3Ls3)..h| 2B68:34 A9 01 9D E7 34 8E 9C |4)..g4..| 2B70:33 20 44 32 AE 9C 33 9D |3 D2..3.| 2B78:C7 34 8D D2 35 8D D4 35 |G4.R5.T5| 2B80:AD F1 35 9D C6 34 8D D1 |-q5.F4.Q| 2B88:35 8D D3 35 AD C2 35 9D |5.S5-B5.| 2B90:C8 34 20 37 30 20 0C 2F |H4 70 ./| 2B98:20 D6 37 20 3A 2F AE 9C | V7 :/..| 2BA0:33 A9 06 8D C5 35 BD C6 |3)..E5=F| 2BA8:34 8D D1 35 BD C7 34 8D |4.Q5=G4.| 2BB0:D2 35 BD C8 34 8D C2 35 |R5=H4.B5| 2BB8:8D F6 35 BD E7 34 8D EE |.v5=g4.n| 2BC0:35 BD E8 34 8D EF 35 8E |5=h4.o5.| 2BC8:D9 35 A9 FF 8D E0 35 8D |Y5)..`5.| 2BD0:E1 35 AD E2 33 8D DA 35 |a5-b3.Z5| 2BD8:18 4C 5E 2F A9 00 AA 9D |.L^/).*.| 2BE0:D1 35 E8 E0 2D D0 F8 AD |Q5h`-Px-| 2BE8:BF 35 49 FF 8D F9 35 AD |?5I..y5-| 2BF0:C0 35 8D F8 35 AD C1 35 |@5.x5-A5| 2BF8:0A 0A 0A 0A AA 8E F7 35 |....*.w5| 2C00:A9 11 8D FA 35 60 20 1D |)..z5` .| T1SB 2C08:2F 20 34 2F 20 C3 32 A9 |/ 4/ C2)| 2C10:02 2D D5 35 F0 21 20 F7 |.-U5p! w| 2C18:2F A9 00 18 20 11 30 38 |/).. .08| 2C20:CE D8 35 D0 F7 AE D9 35 |NX5Pw.Y5| 2C28:AD EE 35 9D E7 34 AD EF |-n5.g4-o| 2C30:35 9D E8 34 20 37 30 4C |5.h4 70L| 2C38:7F 33 20 28 2B AD F6 35 |.3 (+-v5| 2C40:30 2B AD BD 35 85 42 AD |0+-=5.B-| 2C48:BE 35 85 43 AE 9C 33 20 |>5.C..3 | 2C50:1C 32 20 37 30 4C 7F 33 |.2 70L.3| 2C58:AD BC 35 C9 05 B0 0B 0A |-<5I.0..| 2C60:AA BD E6 2A 48 BD E5 2A |*=f*H=e*| 2C68:48 60 4C 67 33 4C 7B 33 |H`Lg3L{3| 2C70:AD F6 35 30 F8 AD BC 35 |-v50x-<5| 2C78:C9 05 B0 EE 0A AA BD F2 |I.0n.*=r| 2C80:2A 48 BD F1 2A 48 60 20 |*H=q*H` | 2C88:00 33 20 A8 2C 8D C3 35 |.3 (,.C5| 2C90:4C 7F 33 20 00 33 20 B5 |L.3 .3 5| 2C98:31 20 A8 2C 48 20 A2 31 |1 (,H "1| 2CA0:A0 00 68 91 42 4C 96 2C | .h.BL.,| 2CA8:20 B6 30 B0 0B B1 42 48 | 600.1BH| 2CB0:20 5B 31 20 94 31 68 60 | [1 .1h`| 2CB8:4C 6F 33 20 00 33 AD C3 |Lo3 .3-C| 2CC0:35 20 DA 2C 4C 7F 33 20 |5 Z,L.3 | 2CC8:00 33 20 A2 31 A0 00 B1 |.3 "1 .1| 2CD0:42 20 DA 2C 20 B5 31 4C |B Z, 51L| 2CD8:CA 2C 48 20 B6 30 68 91 |J,H 60h.| 2CE0:42 A9 40 0D D5 35 8D D5 |B)@.U5.U| 2CE8:35 20 5B 31 4C 94 31 A9 |5 [1L.1)| FDELCAT, $2CEF .. $2E8D, T1SB - T1SD 2CF0:80 8D 9E 33 D0 05 A9 00 |...3P.).| 2CF8:8D 9E 33 20 28 2B AE 9C |..3 (+..| 2D00:33 BD C8 34 29 7F 0D 9E |3=H4)...| T1SC 2D08:33 9D C8 34 20 37 30 4C |3.H4 70L| 2D10:7F 33 20 00 33 4C 7F 33 |.3 .3L.3| 2D18:20 28 2B 20 B6 30 B0 EF | (+ 600o| 2D20:EE E4 35 D0 F6 EE E5 35 |nd5Pvne5| 2D28:4C 1B 2D 20 28 2B AE 9C |L.- (+..| 2D30:33 BD C8 34 10 03 4C 7B |3=H4..L{| 2D38:33 AE 9C 33 BD C6 34 8D |3..3=F4.| 2D40:D1 35 9D E6 34 A9 FF 9D |Q5.f4)..| 2D48:C6 34 BC C7 34 8C D2 35 |F4<G4.R5| 2D50:20 37 30 18 20 5E 2F B0 | 70. ^/0| 2D58:2A 20 0C 2F A0 0C 8C 9C |* ./ ...| 2D60:33 B1 42 30 0B F0 09 48 |31B0.p.H| 2D68:C8 B1 42 A8 68 20 89 2D |H1B(h .-| 2D70:AC 9C 33 C8 C8 D0 E7 AD |,.3HHPg-| 2D78:D3 35 AC D4 35 20 89 2D |S5,T5 .-| 2D80:38 B0 D1 20 FB 2F 4C 7F |80Q {/L.| 2D88:33 38 20 DD 32 A9 00 A2 |38 ]2)."| 2D90:05 9D F0 35 CA 10 FA 60 |..p5J.z`| 2D98:20 DC 2B A9 FF 8D F9 35 | \+)..y5| 2DA0:20 F7 2F A9 16 8D 9D 33 | w/)...3| 2DA8:20 2F 2E 20 2F 2E A2 0B | /. /.".| 2DB0:BD AF 33 20 ED FD CA 10 |=/3 m}J.| 2DB8:F7 86 45 AD F6 37 85 44 |w.E-v7.D| 2DC0:20 42 2E 20 2F 2E 20 2F | B. /. /| 2DC8:2E 18 20 11 30 B0 5D A2 |.. .00]"| 2DD0:00 8E 9C 33 BD C6 34 F0 |...3=F4p| 2DD8:53 30 4A A0 A0 BD C8 34 |S0J =H4| 2DE0:10 02 A0 AA 98 20 ED FD |.. *. m}| 2DE8:BD C8 34 29 7F A0 07 0A |=H4). ..| 2DF0:0A B0 03 88 D0 FA B9 A7 |.0..Pz9'| 2DF8:33 20 ED FD A9 A0 20 ED |3 m}) m| 2E00:FD BD E7 34 85 44 BD E8 |}=g4.D=h| T1SD 2E08:34 85 45 20 42 2E A9 A0 |4.E B.) | 2E10:20 ED FD E8 E8 E8 A0 1D | m}hhh .| 2E18:BD C6 34 20 ED FD E8 88 |=F4 m}h.| 2E20:10 F6 20 2F 2E 20 30 32 |.v /. 02| 2E28:90 A7 B0 9E 4C 7F 33 A9 |.'0.L.3)| 2E30:8D 20 ED FD CE 9D 33 D0 |. m}N.3P| 2E38:08 20 0C FD A9 15 8D 9D |. .})...| 2E40:33 60 A0 02 A9 00 48 A5 |3` .).H%| 2E48:44 D9 A4 33 90 12 F9 A4 |DY$3..y$| 2E50:33 85 44 A5 45 E9 00 85 |3.D%Ei..| 2E58:45 68 69 00 48 4C 47 2E |Ehi.HLG.| 2E60:68 09 B0 20 ED FD 88 10 |h.0 m}..| 2E68:DB 60 20 08 2F A0 00 8C |[` ./ ..| 2E70:C5 35 B1 42 99 D1 35 C8 |E51B.Q5H| 2E78:C0 2D D0 F6 18 60 20 08 |@-Pv.` .| 2E80:2F A0 00 B9 D1 35 91 42 |/ .9Q5.B| 2E88:C8 C0 2D D0 F6 60 20 DC |H@-Pv` \| FMTRWIO, $2E8E .. $2FF6, T1SD - T1SE 2E90:2B A9 04 20 58 30 AD F9 |+). X0-y| 2E98:35 49 FF 8D C1 33 A9 11 |5I..A3).| 2EA0:8D EB 33 A9 01 8D EC 33 |.k3)..l3| 2EA8:A2 38 A9 00 9D BB 33 E8 |"8)..;3h| 2EB0:D0 FA A2 0C E0 8C F0 14 |Pz".`.p.| 2EB8:A0 03 B9 A0 33 9D F3 33 | .9 3.s3| 2EC0:E8 88 10 F6 E0 44 D0 EC |h..v`DPl| 2EC8:A2 48 D0 E8 20 FB 2F A2 |"HPh {/"| 2ED0:00 8A 9D BB 34 E8 D0 FA |...;4hPz| 2ED8:20 45 30 A9 11 AC F0 33 | E0).,p3| 2EE0:88 88 8D EC 37 8D BC 34 |...l7.<4| 2EE8:8C BD 34 C8 8C ED 37 A9 |.=4H.m7)| 2EF0:02 20 58 30 AC BD 34 88 |. X0,=4.| 2EF8:30 05 D0 EC 98 F0 E6 20 |0.Pl.pf | 2F00:C2 37 20 4A 37 4C 7F 33 |B7 J7L.3| T1SE 2F08:A2 00 F0 06 A2 02 D0 02 |".p.".P.| 2F10:A2 04 BD C7 35 85 42 BD |".=G5.B=| 2F18:C8 35 85 43 60 2C D5 35 |H5.C`,U5| 2F20:70 01 60 20 E4 2F A9 02 |p.` d/).| 2F28:20 52 30 A9 BF 2D D5 35 | R0)?-U5| 2F30:8D D5 35 60 AD D5 35 30 |.U5`-U50| 2F38:01 60 20 4B 2F A9 02 20 |.` K/). | 2F40:52 30 A9 7F 2D D5 35 8D |R0).-U5.| 2F48:D5 35 60 AD C9 35 8D F0 |U5`-I5.p| 2F50:37 AD CA 35 8D F1 37 AE |7-J5.q7.| 2F58:D3 35 AC D4 35 60 08 20 |S5,T5`. | 2F60:34 2F 20 4B 2F 20 0C 2F |4/ K/ ./| 2F68:28 B0 09 AE D1 35 AC D2 |(0..Q5,R| 2F70:35 4C B5 2F A0 01 B1 42 |5L5/ .1B| 2F78:F0 08 AA C8 B1 42 A8 4C |p.*H1B(L| 2F80:B5 2F AD BB 35 C9 04 F0 |5/-;5I.p| 2F88:02 38 60 20 44 32 A0 02 |.8` D2 .| 2F90:91 42 48 88 AD F1 35 91 |.BH.-q5.| 2F98:42 48 20 3A 2F 20 D6 37 |BH :/ V7| 2FA0:A0 05 AD DE 35 91 42 C8 | .-^5.BH| 2FA8:AD DF 35 91 42 68 AA 68 |-_5.Bh*h| 2FB0:A8 A9 02 D0 02 A9 01 8E |().P.)..| 2FB8:D3 35 8C D4 35 20 52 30 |S5.T5 R0| 2FC0:A0 05 B1 42 8D DC 35 18 | .1B.\5.| 2FC8:6D DA 35 8D DE 35 C8 B1 |mZ5.^5H1| 2FD0:42 8D DD 35 6D DB 35 8D |B.]5m[5.| 2FD8:DF 35 18 60 20 E4 2F A9 |_5.` d/)| 2FE0:01 4C 52 30 AC CB 35 AD |.LR0,K5-| 2FE8:CC 35 8C F0 37 8D F1 37 |L5.p7.q7| 2FF0:AE D6 35 AC D7 35 60 A9 |.V5,W5`)| FLOCNXB, T1SE - T2S0, $2FF7 .. $31C8 2FF8:01 D0 02 A9 02 AC C3 2A |.P.).,C*| 3000:8C F0 37 AC C4 2A 8C F1 |.p7,D*.q| T1SF 3008:37 AE FA 35 A0 00 4C 52 |7.z5 .LR| 3010:30 08 20 45 30 28 B0 08 |0. E0(0.| 3018:AC BD 33 AE BC 33 D0 0A |,=3.<3P.| 3020:AE BC 34 D0 02 38 60 AC |.<4P.8`,| 3028:BD 34 8E 97 33 8C 98 33 |=4..3..3| 3030:A9 01 20 52 30 18 60 20 |). R0.` | 3038:45 30 AE 97 33 AC 98 33 |E0..3,.3| 3040:A9 02 4C 52 30 AD C5 2A |).LR0-E*| 3048:8D F0 37 AD C6 2A 8D F1 |.p7-F*.q| 3050:37 60 8E EC 37 8C ED 37 |7`.l7.m7| 3058:8D F4 37 C9 02 D0 06 0D |.t7I.P..| 3060:D5 35 8D D5 35 AD F9 35 |U5.U5-y5| 3068:49 FF 8D EB 37 AD F7 35 |I..k7-w5| 3070:8D E9 37 AD F8 35 8D EA |.i7-x5.j| 3078:37 AD E2 35 8D F2 37 AD |7-b5.r7-| 3080:E3 35 8D F3 37 A9 01 8D |c5.s7)..| 3088:E8 37 AC C1 2A AD C2 2A |h7,A*-B*| 3090:20 B5 37 AD F6 37 8D BF | 57-v7.?| 3098:35 A9 FF 8D EB 37 B0 01 |5)..k70.| 30A0:60 AD F5 37 A0 07 C9 20 |`-u7 .I | 30A8:F0 08 A0 04 C9 10 F0 02 |p. .I.p.| 30B0:A0 08 98 4C 85 33 AD E4 | ..L.3-d| 30B8:35 CD E0 35 D0 08 AD E5 |5M`5P.-e| 30C0:35 CD E1 35 F0 66 20 1D |5Ma5pf .| 30C8:2F AD E5 35 CD DD 35 90 |/-e5M]5.| 30D0:1C D0 08 AD E4 35 CD DC |.P.-d5M\| 30D8:35 90 12 AD E5 35 CD DF |5..-e5M_| 30E0:35 90 10 D0 08 AD E4 35 |5..P.-d5| 30E8:CD DE 35 90 06 20 5E 2F |M^5.. ^/| 30F0:90 D7 60 38 AD E4 35 ED |.W`8-d5m| 30F8:DC 35 0A 69 0C A8 20 0C |\5.i.( .| 3100:2F B1 42 D0 0F AD BB 35 |/1BP.-;5| T2S0 3108:C9 04 F0 02 38 60 20 34 |I.p.8` 4| 3110:31 4C 20 31 8D D6 35 C8 |1L 1.V5H| 3118:B1 42 8D D7 35 20 DC 2F |1B.W5 \/| 3120:AD E4 35 8D E0 35 AD E5 |-d5.`5-e| 3128:35 8D E1 35 20 10 2F AC |5.a5 ./,| 3130:E6 35 18 60 8C 9D 33 20 |f5.`..3 | 3138:44 32 AC 9D 33 C8 91 42 |D2,.3H.B| 3140:8D D7 35 88 AD F1 35 91 |.W5.-q5.| 3148:42 8D D6 35 20 10 2F 20 |B.V5 ./ | 3150:D6 37 A9 C0 0D D5 35 8D |V7)@.U5.| 3158:D5 35 60 AE EA 35 8E BD |U5`.j5.=| 3160:35 AE EB 35 8E BE 35 AE |5.k5.>5.| 3168:EC 35 AC ED 35 8E BF 35 |l5,m5.?5| 3170:8C C0 35 E8 D0 01 C8 CC |.@5hP.HL| 3178:E9 35 D0 11 EC E8 35 D0 |i5P.lh5P| 3180:0C A2 00 A0 00 EE EA 35 |.". .nj5| 3188:D0 03 EE EB 35 8E EC 35 |P.nk5.l5| 3190:8C ED 35 60 EE E6 35 D0 |.m5`nf5P| 3198:08 EE E4 35 D0 03 EE E5 |.nd5P.ne| 31A0:35 60 AC C3 35 AE C4 35 |5`,C5.D5| 31A8:84 42 86 43 EE C3 35 D0 |.B.CnC5P| 31B0:03 EE C4 35 60 AC C1 35 |.nD5`,A5| 31B8:D0 08 AE C2 35 F0 07 CE |P..B5p.N| 31C0:C2 35 CE C1 35 60 4C 7F |B5NA5`L.| 31C8:33 20 F7 2F AD C3 35 85 |3 w/-C5.| FLOCSEC, T2S0 - T2S2, $31C9 .. $3396 ($B1C9 .. $B396) 31D0:42 AD C4 35 85 43 A9 01 |B-D5.C).| 31D8:8D 9D 33 A9 00 8D D8 35 |..3)..X5| 31E0:18 EE D8 35 20 11 30 B0 |.nX5 .00| 31E8:51 A2 00 8E 9C 33 BD C6 |Q"...3=F| 31F0:34 F0 1F 30 22 A0 00 E8 |4p.0" .h| 31F8:E8 E8 B1 42 DD C6 34 D0 |hh1B]F4P| 3200:0A C8 C0 1E D0 F3 AE 9C |.H@.Ps..| T2S1 3208:33 18 60 20 30 32 90 DB |3.` 02.[| 3210:B0 CF AC 9D 33 D0 C1 AC |0O,.3PA,| 3218:9D 33 D0 EF A0 00 E8 E8 |.3Po .hh| 3220:E8 B1 42 9D C6 34 C8 C0 |h1B.F4H@| 3228:1E D0 F5 AE 9C 33 38 60 |.Pu..38`| 3230:18 AD 9C 33 69 23 AA E0 |.-.3i#*`| 3238:F5 60 A9 00 AC 9D 33 D0 |u`).,.3P| 3240:97 4C 77 33 AD F1 35 F0 |.Lw3-q5p| 3248:21 CE F0 35 30 17 18 A2 |!Np50.."| 3250:04 3E F1 35 CA D0 FA 90 |.>q5JPz.| 3258:F0 EE EE 35 D0 03 EE EF |pnn5P.no| 3260:35 AD F0 35 60 A9 00 8D |5-p5`)..| 3268:F1 35 A9 00 8D 9E 33 20 |q5)...3 | 3270:F7 2F 18 AD EB 33 6D EC |w/.-k3ml| 3278:33 F0 09 CD EF 33 90 14 |3p.Mo3..| 3280:A9 FF D0 0A AD 9E 33 D0 |).P.-.3P| 3288:37 A9 01 8D 9E 33 8D EC |7)...3.l| 3290:33 18 69 11 8D EB 33 8D |3.i..k3.| 3298:F1 35 A8 0A 0A A8 A2 04 |q5(..(".| 32A0:18 B9 F6 33 9D F1 35 F0 |.9v3.q5p| 32A8:06 38 A9 00 99 F6 33 88 |.8)..v3.| 32B0:CA D0 EE 90 BD 20 FB 2F |JPn.= {/| 32B8:AD F0 33 8D F0 35 D0 89 |-p3.p5P.| 32C0:4C 77 33 AD F1 35 D0 01 |Lw3-q5P.| 32C8:60 48 20 F7 2F AC F0 35 |`H w/,p5| 32D0:68 18 20 DD 32 A9 00 8D |h. ]2)..| 32D8:F1 35 4C FB 2F A2 FC 7E |q5L{/"|~| 32E0:F6 34 E8 D0 FA C8 CC F0 |v4hPzHLp| 32E8:33 D0 F2 0A 0A A8 F0 0F |3Pr..(p.| 32F0:A2 04 BD F1 35 19 F6 33 |".=q5.v3| 32F8:99 F6 33 88 CA D0 F3 60 |.v3.JPs`| 3300:AD BD 35 8D E6 35 8D EA |-=5.f5.j| T2S2 3308:35 AD BE 35 8D E4 35 8D |5->5.d5.| 3310:EB 35 A9 00 8D E5 35 A0 |k5)..e5 | 3318:10 AA AD E6 35 4A B0 03 |.*-f5J0.| 3320:8A 90 0E 18 AD E5 35 6D |....-e5m| 3328:E8 35 8D E5 35 8A 6D E9 |h5.e5.mi| 3330:35 6A 6E E5 35 6E E4 35 |5jne5nd5| 3338:6E E6 35 88 D0 DB 18 AD |nf5.P[.-| 3340:BF 35 8D EC 35 6D E6 35 |?5.l5mf5| 3348:8D E6 35 AD C0 35 8D ED |.f5-@5.m| 3350:35 6D E4 35 8D E4 35 90 |5md5.d5.| 3358:03 EE E5 35 60 00 00 A9 |.ne5`..)| 3360:01 D0 22 A9 02 D0 1E A9 |.P").P.)| 3368:03 D0 1A A9 04 D0 16 A9 |.P.).P.)| 3370:05 D0 12 A9 06 D0 0E 4C |.P.).P.L| 3378:ED 3F EA A9 0A D0 06 AD |m?j).P.-| 3380:C5 35 18 90 01 38 08 8D |E5...8..| 3388:C5 35 A9 00 85 48 20 7E |E5)..H ~| 3390:2E 28 AE 9B 33 9A 60 00 |.(..3.`.| FVCBUFS, T2S2 - T2S4, $3397 .. $35FD ($B397 .. $B5FD) 3398:00 00 00 00 00 00 00 00 |........| 33A0:00 00 FF FF 01 0A 64 D4 |......dT| 33A8:C9 C1 C2 D3 D2 C1 C2 A0 |IABSRAB | 33B0:C5 CD D5 CC CF D6 A0 CB |EMULOV K| 33B8:D3 C9 C4 04 11 0F 04 00 |SID.....| 33C0:00 FE FC FD FF FC FF FC |.~|}.|.|| 33C8:FC FE FF FC FD FF FE FF ||~.|}.~.| 33D0:FD FE FF FD FD FD FF FE |}~.}}}.~| 33D8:FD FF FC FF FF FD FD FC |}.|..}}|| 33E0:FE FE 7A FE FD FF FD FE |~~z~}.}~| 33E8:FE FF FC 11 01 00 00 23 |~.|....#| 33F0:10 00 01 FF FC FC FD FC |....||}|| 33F8:FE FC FC FD FD FE FC FC |~||}}~||| 3400:FF FC FC FD FC FD FD FC |.||}|}}|| T2S3 3408:FF FE FC FC FC FC FE FE |.~||||~~| 3410:FC FD FC FC FC FE FC FD ||}|||~|}| 3418:FC FC FE FC FC FC FE FC |||~|||~|| 3420:FC FF FC FC FC FC FD FD ||.||||}}| 3428:FC FF FF FC FE FD FE FD ||..|~}~}| 3430:FE FC FF FC FE FF FD FC |~|.|~.}|| 3438:FF FC FC FC FD FE FD FE |.|||}~}~| 3440:FC FC FC FF FE FC FC FD ||||.~||}| 3448:FC FD FF FC FC FC FC FE ||}.||||~| 3450:FD FC FD FC FC FC FD FC |}|}|||}|| 3458:FD FF FC FE FD FC FC FD |}.|~}||}| 3460:FC FC FC FC FC FC FF FF |||||||..| 3468:FE FC FF FC FD FF FE FF |~|.|}.~.| 3470:FE FE FC FC FD FC FC FC |~~||}|||| 3478:FE FE FE FD FE FD FC FE |~~~}~}|~| 3480:FD FD FC FC FE FE FC FC |}}||~~||| 3488:FD FC FC FE FC FC FD FC |}||~||}|| 3490:FE FE FC FD FC FC FC FC |~~|}||||| 3498:FC FD FD FC FE FD FC FC ||}}|~}||| 34A0:FE FC FC FC FC FC FE FC |~|||||~|| 34A8:FD FD FC FF FD FC FE FE |}}|.}|~~| 34B0:FC FD FD FE FF FD FE FF ||}}~.}~.| 34B8:FE FF FC 02 FC FD FC FC |~.|.|}||| ← entire sector wasted for unreferenced 1 byte @ $(34)BB !! 34C0:FC FE FE FE FD FE FF FE ||~~~}~.~| 34C8:FC FC FC FC FC FE FC FD ||||||~|}| 34D0:FC FC FF FD FC FE FC FC |||.}|~||| 34D8:FD FE FE FF FC FE FF FD |}~~.|~.}| 34E0:FF FE FC FC FE FE FD FF |.~||~~}.| 34E8:FE FF FF FD FC FE FF FC |~..}|~.|| 34F0:FE FD FE FC FE FC FF FE |~}~|~|.~| 34F8:FE FE FC FD FD FE FF FC |~~|}}~.|| 3500:FC FC FC FC FC FE FC FD ||||||~|}| T2S4 3508:FD FC FF FD FC FE FE FC |}|.}|~~|| 3510:FE FD FC FF FF FC FC FE |~}|..||~| 3518:FE FD FE FD FE FE FC FC |~}~}~~||| 3520:FE FD FD FC FE FD FC FC |~}}|~}||| 3528:FE FC FC FE FC FC FD FC |~||~||}|| 3530:FD FD FC FF FD FC FE FD |}}|.}|~}| 3538:FC FD FF FC FE FC FC FC ||}.|~|||| 3540:FC FC FC FD FC FC FE FC ||||}||~|| 3548:FD FC FC FF FC FC FE FD |}||.||~}| 3550:FC FD FF FC FF FD FE FF ||}.|.}~.| 3558:FD FF FE FC FD FF FF FF |}.~|}...| 3560:FC FC FE FC FC FF FF FC |||~||..|| 3568:FC FD FC FE FC FC FC FC ||}|~||||| 3570:FC FE FC FC FD FD FC FC ||~||}}||| 3578:FE FC FD FC FC FE FE FC |~|}||~~|| 3580:FC FC FC FC FF FC FC FC |||||.|||| 3588:FC FD FD FC FF FC FC FE ||}}|.||~| 3590:FF FC FD FF FC FF FD FE |.|}.|.}~| 3598:FF FD FD FD FF FE FD FF |.}}}.~}.| 35A0:FC FF FD FD FD FC FE FC ||.}}}|~|| 35A8:FC FF FE FC FC FE FC FC ||.~||~||| 35B0:FE FC FD FD FC FF FD FC |~|}}|.}|| 35B8:FE FC FC FF FF FC FC FD |~||..||}| 35C0:FC FE FE FE FC FF FC FF ||~~~|.|.| 35C8:FC FF FF FE FC FE FC FD ||..~|~|}| 35D0:FF FF FD FD FE FC FC FC |..}}~|||| 35D8:FC FC FE FD FD FF FE FC |||~}}.~|| 35E0:FE FC FC FC FF FC FC FE |~|||.||~| 35E8:FE FC FE FC FC FC FF FC |~|~|||.|| 35F0:FC FC FE FC FC FF FD FE |||~||.}~| 35F8:FC FC FD FC FC FF FD FC |||}||.}|| BOOTLDR, $35FE .. $37FF, T0S0 - T0S1 3600:01 A5 27 C9 09 D0 18 A5 |.%'I.P.%| T0S0 3608:2B 4A 4A 4A 4A 09 C0 85 |+JJJJ.@.| 3610:3F A9 5C 85 3E 18 AD FE |?)\.>.-~| 3618:08 6D FF 08 8D FE 08 AE |.m...~..| 3620:FF 08 30 15 BD 4D 08 85 |..0.=M..| 3628:3D CE FF 08 AD FE 08 85 |=N..-~..| 3630:27 CE FE 08 A6 2B 6C 3E |'N~.&+l>| 3638:00 EE FE 08 EE FE 08 20 |.n~.n~. | 3640:89 FE 20 93 FE 20 2F FB |.~ .~ /{| 3648:A6 2B 6C FD 08 00 0D 0B |&+l}....| 3650:09 07 05 03 01 0E 0C 0A |........| 3658:08 06 04 02 0F 00 20 64 |...... d| 3660:27 B0 08 A9 00 A8 8D 5D |'0.).(.]| 3668:36 91 40 AD C5 35 4C D2 |6.@-E5LR| 3670:26 AD 5D 36 F0 08 EE BD |&-]6p.n=| 3678:35 D0 03 EE BE 35 A9 00 |5P.n>5).| 3680:8D 5D 36 4C B3 36 8D BC |.]6L36.<| 3688:35 20 A8 26 20 EA 22 4C |5 (& j"L| 3690:7D 22 A0 13 B1 42 D0 14 |}" .1BP.| 3698:C8 C0 17 D0 F7 A0 19 B1 |H@.Pw .1| 36A0:42 99 A4 35 C8 C0 1D D0 |B.$5H@.P| 36A8:F6 4C BB 26 A2 FF 8E 5D |vL;&"..]| 36B0:36 D0 F6 AD BD 35 8D E6 |6Pv-=5.f| 36B8:35 8D EA 35 AD BE 35 8D |5.j5->5.| 36C0:E7 35 8D EB 35 8D E4 35 |g5.k5.d5| 36C8:BA 8E 9B 33 4C 7F 33 00 |:..3L.3.| 36D0:00 00 00 00 00 00 00 00 |........| 36D8:00 00 00 00 00 00 00 00 |........| 36E0:00 00 00 00 00 00 00 00 |........| 36E8:00 00 00 00 00 00 00 00 |........| 36F0:00 00 00 00 00 00 00 00 |........| 36F8:00 00 00 00 00 00 36 09 |......6.| 3700:8E E9 37 8E F7 37 A9 01 |.i7.w7).| T0S1 3708:8D F8 37 8D EA 37 AD E0 |.x7.j7-`| 3710:37 8D E1 37 A9 02 8D EC |7.a7)..l| 3718:37 A9 04 8D ED 37 AC E7 |7)..m7,g| 3720:37 88 8C F1 37 A9 01 8D |7..q7)..| 3728:F4 37 8A 4A 4A 4A 4A AA |t7.JJJJ*| 3730:A9 00 9D F8 04 9D 78 04 |)..x..x.| 3738:20 93 37 A2 FF 9A 8E EB | .7"...k| 3740:37 4C C8 3F 20 89 FE 4C |7LH? .~L| 3748:03 1B AD E7 37 38 ED F1 |..-g78mq| 3750:37 8D E1 37 AD E7 37 8D |7.a7-g7.| 3758:F1 37 CE F1 37 A9 02 8D |q7Nq7)..| 3760:EC 37 A9 04 8D ED 37 A9 |l7)..m7)| 3768:02 8D F4 37 20 93 37 AD |..t7 .7-| 3770:E7 37 8D FE 36 18 69 09 |g7.~6.i.| 3778:8D F1 37 A9 0A 8D E1 37 |.q7)..a7| 3780:38 E9 01 8D FF 36 8D ED |8i...6.m| 3788:37 20 93 37 60 00 00 00 |7 .7`...| 3790:00 00 00 AD E5 37 AC E4 |...-e7,d| 3798:37 20 B5 37 AC ED 37 88 |7 57,m7.| 37A0:10 07 A0 0F EA EA CE EC |.. .jjNl| 37A8:37 8C ED 37 CE F1 37 CE |7.m7Nq7N| 37B0:E1 37 D0 DF 60 08 78 20 |a7P_`.x | 37B8:00 3D B0 03 28 18 60 28 |.=0.(.`(| 37C0:38 60 AD BC 35 8D F1 37 |8`-<5.q7| 37C8:A9 00 8D F0 37 AD F9 35 |)..p7-y5| 37D0:49 FF 8D EB 37 60 A9 00 |I..k7`).| 37D8:A8 91 42 C8 D0 FB 60 00 |(.BHP{`.| 37E0:1B 00 0A 1B E8 37 00 36 |....h7.6| 37E8:01 60 01 00 00 00 FB 37 |.`....{7| 37F0:00 00 00 01 00 00 00 60 |.......`| 37F8:01 00 00 00 01 EF D8 00 |.....oX.| 3800:A2 00 A0 02 88 B1 3E 4A |". ..1>J| T0S2, PRENIBL, $3800 .. $3829, T0S2 3808:3E 00 3C 4A 3E 00 3C 99 |>.<J>.<.| 3810:00 3B E8 E0 56 90 ED A2 |.;h`V.m"| 3818:00 98 D0 E8 A2 55 BD 00 |..Ph"U=.| 3820:3C 29 3F 9D 00 3C CA 10 |<)?..<J.| 3828:F5 60 38 86 27 8E 78 06 |u`8.'.x.| WRITRTN, $382A .. $38C1, T0S2 3830:BD 8D C0 BD 8E C0 30 7C |=.@=.@0|| 3838:AD 00 3C 85 26 A9 FF 9D |-.<.&)..| 3840:8F C0 1D 8C C0 48 68 EA |.@..@Hhj| 3848:A0 04 48 68 20 B9 38 88 | .Hh 98.| 3850:D0 F8 A9 D5 20 B8 38 A9 |Px)U 88)| 3858:AA 20 B8 38 A9 AD 20 B8 |* 88)- 8| 3860:38 98 A0 56 D0 03 B9 00 |8. VP.9.| 3868:3C 59 FF 3B AA BD 29 3A |<Y.;*=):| 3870:A6 27 9D 8D C0 BD 8C C0 |&'..@=.@| 3878:88 D0 EB A5 26 EA 59 00 |.Pk%&jY.| 3880:3B AA BD 29 3A AE 78 06 |;*=):.x.| 3888:9D 8D C0 BD 8C C0 B9 00 |..@=.@9.| 3890:3B C8 D0 EA AA BD 29 3A |;HPj*=):| 3898:A6 27 20 BB 38 A9 DE 20 |&' ;8)^ | 38A0:B8 38 A9 AA 20 B8 38 A9 |88)* 88)| 38A8:EB 20 B8 38 A9 FF 20 B8 |k 88). 8| 38B0:38 BD 8E C0 BD 8C C0 60 |8=.@=.@`| 38B8:18 48 68 9D 8D C0 1D 8C |.Hh..@..| 38C0:C0 60 A0 00 A2 56 CA 30 |@` ."VJ0| POSTNRD, $38C2 .. $3943, T0S2 - T0S3 38C8:FB B9 00 3B 5E 00 3C 2A |{9.;^.<*| 38D0:5E 00 3C 2A 91 3E C8 C4 |^.<*.>HD| 38D8:26 D0 EB 60 A0 20 88 F0 |&Pk` .p| 38E0:61 BD 8C C0 10 FB 49 D5 |a=.@.{IU| 38E8:D0 F4 EA BD 8C C0 10 FB |Ptj=.@.{| 38F0:C9 AA D0 F2 A0 56 BD 8C |I*Pr V=.| 38F8:C0 10 FB C9 AD D0 E7 A9 |@.{I-Pg)| 3900:00 88 84 26 BC 8C C0 10 |...&<.@.| T0S3 3908:FB 59 00 3A A4 26 99 00 |{Y.:$&..| 3910:3C D0 EE 84 26 BC 8C C0 |<Pn.&<.@| 3918:10 FB 59 00 3A A4 26 99 |.{Y.:$&.| 3920:00 3B C8 D0 EE BC 8C C0 |.;HPn<.@| 3928:10 FB D9 00 3A D0 13 BD |.{Y.:P.=| 3930:8C C0 10 FB C9 DE D0 0A |.@.{I^P.| 3938:EA BD 8C C0 10 FB C9 AA |j=.@.{I*| 3940:F0 5C 38 60 A0 FC 84 26 |p\8` |.&| RDADSEK, $3944 .. $39FC, T0S3 3948:C8 D0 04 E6 26 F0 F3 BD |HP.f&ps=| 3950:8C C0 10 FB C9 D5 D0 F0 |.@.{IUPp| 3958:EA BD 8C C0 10 FB C9 AA |j=.@.{I*| 3960:D0 F2 A0 03 BD 8C C0 10 |Pr .=.@.| 3968:FB C9 96 D0 E7 A9 00 85 |{I.Pg)..| 3970:27 BD 8C C0 10 FB 2A 85 |'=.@.{*.| 3978:26 BD 8C C0 10 FB 25 26 |&=.@.{%&| 3980:99 2C 00 45 27 88 10 E7 |.,.E'..g| 3988:A8 D0 B7 BD 8C C0 10 FB |(P7=.@.{| 3990:C9 DE D0 AE EA BD 8C C0 |I^P.j=.@| 3998:10 FB C9 AA D0 A4 18 60 |.{I*P$.`| 39A0:86 2B 85 2A CD 78 04 F0 |.+.*Mx.p| 39A8:53 A9 00 85 26 AD 78 04 |S)..&-x.| 39B0:85 27 38 E5 2A F0 33 B0 |.'8e*p30| 39B8:07 49 FF EE 78 04 90 05 |.I.nx...| 39C0:69 FE CE 78 04 C5 26 90 |i~Nx.E&.| 39C8:02 A5 26 C9 0C B0 01 A8 |.%&I.0.(| 39D0:38 20 EE 39 B9 11 3A 20 |8 n99.: | 39D8:00 3A A5 27 18 20 F1 39 |.:%'. q9| 39E0:B9 1D 3A 20 00 3A E6 26 |9.: .:f&| 39E8:D0 C3 20 00 3A 18 AD 78 |PC .:.-x| 39F0:04 29 03 2A 05 2B AA BD |.).*.+*=| 39F8:80 C0 A6 2B 60 00 00 00 |.@&+`...| MSWAITR, $39FD .. $3C55, T0S3 - T0S6 3A00:A2 11 CA D0 FD E6 46 D0 |".JP}fFP| T0S4 3A08:02 E6 47 38 E9 01 D0 F0 |.fG8i.Pp| 3A10:60 01 30 28 24 20 1E 1D |`.0($ ..| 3A18:1C 1C 1C 1C 1C 70 2C 26 |.....p,&| 3A20:22 1F 1E 1D 1C 1C 1C 1C |".......| 3A28:1C 96 97 9A 9B 9D 9E 9F |........| 3A30:A6 A7 AB AC AD AE AF B2 |&'+,-./2| 3A38:B3 B4 B5 B6 B7 B9 BA BB |345679:;| 3A40:BC BD BE BF CB CD CE CF |<=>?KMNO| 3A48:D3 D6 D7 D9 DA DB DC DD |SVWYZ[\]| 3A50:DE DF E5 E6 E7 E9 EA EB |^_efgijk| 3A58:EC ED EE EF F2 F3 F4 F5 |lmnorstu| 3A60:F6 F7 F9 FA FB FC FD FE |vwyz{|}~| 3A68:FF AE 5F 2A E0 1C F0 05 |.._*`.p.| 3A70:A2 00 8E 5D 36 60 A9 FF |"..]6`).| 3A78:8D FB 04 8D 0C C0 8D 0E |.{...@..| 3A80:C0 4C 2F FB 00 00 00 00 |@L/{....| 3A88:00 00 00 00 00 00 00 00 |........| 3A90:00 00 00 00 00 00 00 01 |........| 3A98:98 99 02 03 9C 04 05 06 |........| 3AA0:A0 A1 A2 A3 A4 A5 07 08 | !"#$%..| 3AA8:A8 A9 AA 09 0A 0B 0C 0D |()*.....| 3AB0:B0 B1 0E 0F 10 11 12 13 |01......| 3AB8:B8 14 15 16 17 18 19 1A |8.......| 3AC0:C0 C1 C2 C3 C4 C5 C6 C7 |@ABCDEFG| 3AC8:C8 C9 CA 1B CC 1C 1D 1E |HIJ.L...| 3AD0:D0 D1 D2 1F D4 D5 20 21 |PQR.TU !| 3AD8:D8 22 23 24 25 26 27 28 |X"#$%&'(| 3AE0:E0 E1 E2 E3 E4 29 2A 2B |`abcd)*+| 3AE8:E8 2C 2D 2E 2F 30 31 32 |h,-./012| 3AF0:F0 F1 33 34 35 36 37 38 |pq345678| 3AF8:F8 39 3A 3B 3C 3D 3E 3F |x9:;<=>?| 3B00:00 00 00 00 00 00 00 00 |........| T0S5 3B08:00 00 00 00 00 00 00 00 |........| 3B10:00 00 00 00 00 00 00 00 |........| 3B18:00 00 00 00 00 00 00 00 |........| 3B20:00 00 00 00 00 00 00 00 |........| 3B28:00 00 00 00 00 00 00 00 |........| 3B30:00 00 00 00 00 00 00 00 |........| 3B38:00 00 00 00 00 00 00 00 |........| 3B40:00 00 00 00 00 00 00 00 |........| 3B48:00 00 00 00 00 00 00 00 |........| 3B50:00 00 00 00 00 00 00 00 |........| 3B58:00 00 00 00 00 00 00 00 |........| 3B60:00 00 00 00 00 00 00 00 |........| 3B68:00 00 00 00 00 00 00 00 |........| 3B70:00 00 00 00 00 00 00 00 |........| 3B78:00 00 00 00 00 00 00 00 |........| 3B80:00 00 00 00 00 00 00 00 |........| 3B88:00 00 00 00 00 00 00 00 |........| 3B90:00 00 00 00 00 00 00 00 |........| 3B98:00 00 00 00 00 00 00 00 |........| 3BA0:00 00 00 00 00 00 00 00 |........| 3BA8:00 00 00 00 00 00 00 00 |........| 3BB0:00 00 00 00 00 00 00 00 |........| 3BB8:00 00 00 00 00 00 00 00 |........| 3BC0:00 00 00 00 00 00 00 00 |........| 3BC8:00 00 00 00 00 00 00 00 |........| 3BD0:00 00 00 00 00 00 00 00 |........| 3BD8:00 00 00 00 00 00 00 00 |........| 3BE0:00 00 00 00 00 00 00 00 |........| 3BE8:00 00 00 00 00 00 00 00 |........| 3BF0:00 00 00 00 00 00 00 00 |........| 3BF8:00 00 00 00 00 00 00 00 |........| 3C00:00 00 00 00 00 00 00 00 |........| T0S6 3C08:00 00 00 00 00 00 00 00 |........| 3C10:00 00 00 00 00 00 00 00 |........| 3C18:00 00 00 00 00 00 00 00 |........| 3C20:00 00 00 00 00 00 00 00 |........| 3C28:00 00 00 00 00 00 00 00 |........| 3C30:00 00 00 00 00 00 00 00 |........| 3C38:00 00 00 00 00 00 00 00 |........| 3C40:00 00 00 00 00 00 00 00 |........| 3C48:00 00 00 00 00 00 00 00 |........| 3C50:00 00 00 00 00 00 38 BD |......8=| WRITADR, $3C56 .. $3CFF, T0S6 3C58:8D C0 BD 8E C0 30 5E A9 |.@=.@0^)| 3C60:FF 9D 8F C0 DD 8C C0 48 |...@].@H| 3C68:68 20 C3 3C 20 C3 3C 9D |h C< C<.| 3C70:8D C0 DD 8C C0 EA 88 D0 |.@].@j.P| 3C78:F0 A9 D5 20 D5 3C A9 AA |p)U U<)*| 3C80:20 D5 3C A9 96 20 D5 3C | U<). U<| 3C88:A5 41 20 C4 3C A5 44 20 |%A D<%D | 3C90:C4 3C A5 3F 20 C4 3C A5 |D<%? D<%| 3C98:41 45 44 45 3F 48 4A 05 |AEDE?HJ.| 3CA0:3E 9D 8D C0 BD 8C C0 68 |>..@=.@h| 3CA8:09 AA 20 D4 3C A9 DE 20 |.* T<)^ | 3CB0:D5 3C A9 AA 20 D5 3C A9 |U<)* U<)| 3CB8:EB 20 D5 3C 18 BD 8E C0 |k U<.=.@| 3CC0:BD 8C C0 60 48 4A 05 3E |=.@`HJ.>| 3CC8:9D 8D C0 DD 8C C0 68 EA |..@].@hj| 3CD0:EA EA 09 AA EA EA 48 68 |jj.*jjHh| 3CD8:9D 8D C0 DD 8C C0 60 00 |..@].@`.| 3CE0:00 00 00 00 00 00 00 00 |........| 3CE8:00 00 00 00 00 00 00 00 |........| 3CF0:00 00 00 00 00 00 00 00 |........| 3CF8:00 00 00 00 00 00 00 00 |........| 3D00:84 48 85 49 A0 02 8C F8 |.H.I ..x| T0S7, RWTSONE, $3D00 .. $3DAA, T0S7 3D08:06 A0 04 8C F8 04 A0 01 |. ..x. .| 3D10:B1 48 AA A0 0F D1 48 F0 |1H* .QHp| 3D18:1B 8A 48 B1 48 AA 68 48 |..H1H*hH| 3D20:91 48 BD 8E C0 A0 08 BD |.H=.@ .=| 3D28:8C C0 DD 8C C0 D0 F6 88 |.@].@Pv.| 3D30:D0 F8 68 AA BD 8E C0 BD |Pxh*=.@=| 3D38:8C C0 A0 08 BD 8C C0 48 |.@ .=.@H| 3D40:68 48 68 8E F8 05 DD 8C |hHh.x.].| 3D48:C0 D0 03 88 D0 EE 08 BD |@P..Pn.=| 3D50:89 C0 A0 06 B1 48 99 36 |.@ .1H.6| 3D58:00 C8 C0 0A D0 F6 A0 03 |.H@.Pv .| 3D60:B1 3C 85 47 A0 02 B1 48 |1<.G .1H| 3D68:A0 10 D1 48 F0 06 91 48 | .QHp..H| 3D70:28 A0 00 08 6A 90 05 BD |( ..j..=| 3D78:8A C0 B0 03 BD 8B C0 66 |.@0.=.@f| 3D80:35 28 08 D0 0B A0 07 20 |5(.P. . | 3D88:00 3A 88 D0 FA AE F8 05 |.:.Pz.x.| 3D90:A0 04 B1 48 20 5A 3E 28 | .1H Z>(| 3D98:D0 11 A4 47 10 0D A0 12 |P.$G.. .| 3DA0:88 D0 FD E6 46 D0 F7 E6 |.P}fFPwf| 3DA8:47 D0 F3 A0 0C B1 48 F0 |GPs .1Hp| RWTSTWO, T0S7 - T0S8, $3DAB .. $3EAE ($BDAB .. $BEAE) 3DB0:5A C9 04 F0 58 6A 08 B0 |ZI.pXj.0| 3DB8:03 20 00 38 A0 30 8C 78 |. .8 0.x| 3DC0:05 AE F8 05 20 44 39 90 |..x. D9.| 3DC8:24 CE 78 05 10 F3 AD 78 |$Nx..s-x| 3DD0:04 48 A9 60 20 95 3E CE |.H)` .>N| 3DD8:F8 06 F0 28 A9 04 8D F8 |x.p()..x| 3DE0:04 A9 00 20 5A 3E 68 20 |.). Z>h | 3DE8:5A 3E 4C BC 3D A4 2E CC |Z>L<=$.L| 3DF0:78 04 F0 1C AD 78 04 48 |x.p.-x.H| 3DF8:98 20 95 3E 68 CE F8 04 |. .>hNx.| 3E00:D0 E5 F0 CA 68 A9 40 28 |PepJh)@(| T0S8 3E08:4C 48 3E F0 39 4C AF 3E |LH>p9L/>| 3E10:A0 03 B1 48 48 A5 2F A0 | .1HH%/ | 3E18:0E 91 48 68 F0 08 C5 2F |..Hhp.E/| 3E20:F0 04 A9 20 D0 E1 A0 05 |p.) Pa .| 3E28:B1 48 A8 B9 B8 3F C5 2D |1H(98?E-| 3E30:D0 97 28 90 1C 20 DC 38 |P.(.. \8| 3E38:08 B0 8E 28 A2 00 86 26 |.0.("..&| 3E40:20 C2 38 AE F8 05 18 24 | B8.x..$| 3E48:38 A0 0D 91 48 BD 88 C0 |8 ..H=.@| 3E50:60 20 2A 38 90 F0 A9 10 |` *8.p).| 3E58:B0 EE 48 A0 01 B1 3C 6A |0nH .1<j| 3E60:68 90 08 0A 20 6B 3E 4E |h... k>N| 3E68:78 04 60 85 2A 20 8E 3E |x.`.* .>| 3E70:B9 78 04 24 35 30 03 B9 |9x.$50.9| 3E78:F8 04 8D 78 04 A5 2A 24 |x..x.%*$| 3E80:35 30 05 99 F8 04 10 03 |50..x...| 3E88:99 78 04 4C A0 39 8A 4A |.x.L 9.J| 3E90:4A 4A 4A A8 60 48 A0 02 |JJJ(`H .| 3E98:B1 48 6A 66 35 20 8E 3E |1Hjf5 .>| 3EA0:68 0A 24 35 30 05 99 F8 |h.$50..x| 3EA8:04 10 03 99 78 04 60 A0 |....x.` | FORMATR, T0S8 - T0S9, $3EAF .. $3FC7 ($BEAF .. $BFC7) 3EB0:03 B1 48 85 41 A9 AA 85 |.1H.A)*.| 3EB8:3E A0 56 A9 00 85 44 99 |> V)..D.| 3EC0:FF 3B 88 D0 FA 99 00 3B |.;.Pz..;| 3EC8:88 D0 FA A9 50 20 95 3E |.Pz)P .>| 3ED0:A9 28 85 45 A5 44 20 5A |)(.E%D Z| 3ED8:3E 20 0D 3F A9 08 B0 24 |> .?).0$| 3EE0:A9 30 8D 78 05 38 CE 78 |)0.x.8Nx| 3EE8:05 F0 19 20 44 39 B0 F5 |.p. D90u| 3EF0:A5 2D D0 F1 20 DC 38 B0 |%-Pq \80| 3EF8:EC E6 44 A5 44 C9 23 90 |lfD%DI#.| 3F00:D3 18 90 05 A0 0D 91 48 |S... ..H| T0S9 3F08:38 BD 88 C0 60 A9 00 85 |8=.@`)..| 3F10:3F A0 80 D0 02 A4 45 20 |? .P.$E | 3F18:56 3C B0 6B 20 2A 38 B0 |V<0k *80| 3F20:66 E6 3F A5 3F C9 10 90 |ff?%?I..| 3F28:EC A0 0F 84 3F A9 30 8D |l ..?)0.| 3F30:78 05 99 A8 3F 88 10 FA |x..(?..z| 3F38:A4 45 20 87 3F 20 87 3F |$E .? .?| 3F40:20 87 3F 48 68 EA 88 D0 | .?Hhj.P| 3F48:F1 20 44 39 B0 23 A5 2D |q D90#%-| 3F50:F0 15 A9 10 C5 45 A5 45 |p.).EE%E| 3F58:E9 01 85 45 C9 05 B0 11 |i..EI.0.| 3F60:38 60 20 44 39 B0 05 20 |8` D90. | 3F68:DC 38 90 1C CE 78 05 D0 |\8..Nx.P| 3F70:F1 20 44 39 B0 0B A5 2D |q D90.%-| 3F78:C9 0F D0 05 20 DC 38 90 |I.P. \8.| 3F80:8C CE 78 05 D0 EB 38 60 |.Nx.Pk8`| 3F88:A4 2D B9 A8 3F 30 DD A9 |$-9(?0])| 3F90:FF 99 A8 3F C6 3F 10 CA |..(?F?.J| 3F98:A5 44 D0 0A A5 45 C9 10 |%DP.%EI.| 3FA0:90 E5 C6 45 C6 45 18 60 |.eFEFE.`| 3FA8:00 00 00 00 00 00 00 00 |........| 3FB0:00 00 00 00 00 00 00 00 |........| 3FB8:00 0D 0B 09 07 05 03 01 |........| 3FC0:0E 0C 0A 08 06 04 02 0F |........| 3FC8:20 93 FE AD 81 C0 AD 81 | .~-.@-.| DOSPTCH, T0S9, $3FC8 .. $3FFF ($BFC8 .. $BFFF) 3FD0:C0 A9 00 8D 00 E0 20 76 |@)...` v| 3FD8:3A 4C 44 37 8D 63 2A 8D |:LD7.c*.| 3FE0:70 2A 8D 71 2A 60 20 5B |p*.q*` [| 3FE8:27 8C B7 2A 60 20 7E 2E |'.7*` ~.| 3FF0:AE 9B 33 9A 20 16 23 BA |..3. .#:| 3FF8:8E 9B 33 A9 09 4C 85 33 |..3).L.3|
There are several locations where memory and disk space are wasted.
I've annotated *wastes* locations in the listing where memory is wasted.
T/S | Range | File | Func/Var | Line | Bytes | Description |
---|---|---|---|---|---|---|
T0S0 | $36B3..$36FD | BOOTLDR | n/a | 75 | Padding for boot sector | |
T0S1 | $37FF | BOOTLDR | n/a | 1 | Unused slack at end | |
T0S3 | $FD..$FF | MSWAITR | n/a | 3 | Line #30 page align MSWAIT | |
T0S6 | $00..$55 | MSWAITR | NBUF2 | 86 | While we need run-time memory for NBUF2 there is NO need to waste disk space. Data should always either BEFORE or AFTER code -- never interleaved. | |
T0S9 | $3FDA .. $3FDB | DOSPTCH | RCPATCH | 028 | 2 | JMP RCBACK instead of RTS |
T0SA | $1B49 .. $1B49 | RELOCTR | DR2A | 153 | 1 | ZPGFCB can never point to page 0. We can switch the order:
From: LDY ZPGFCB+1 PLA JMP DR2C To: PLA LDY ZPGFCB+1 BNE DR2C |
T0SB | $1B7D .. $1B7D | RELOCTR | DR3 | 181 | 1 | Useless TAY when LDY would suffice
From: LDA ADRTAB+1,X TAY To: LDY ADRTAB+1,X |
T0SB | $1B83 .. $1B83 | RELOCTR | DR3 | 184 | 1 | Start Address (+2) in ADRTAB is never on page 0;
Change (absolute) JMP to (relative) BNE: From: LDA ADRTAB+2,X STA ZPGWRK+1 JMP DR5 To: LDA ADRTAB+2,X STA ZPGWRK+1 BNE DR5 |
T0SB | $1C12 .. $1C12 | RELOCTR | DR9 | 273 | 1 | Useless TAY when LDY and STY would suffice
From: LDA #0 STA ZPGWRK STA ZPGFCB TAY To: LDY #0 STY ZPGWRK STY ZPGFCB |
T0SB | $1C4D .. $1C58 | RELOCTR | ADRTAB | 306 | 11 | Unreferenced data after ADRTAB |
T0SB | $1C81 .. $1CFF | DOSINIT | START | 003 | 127 | Padding so START is aligned on a new memory page
Technically, only 82 bytes. See note at address. |
T0SC | $1D78 .. $1D83 | DOSINIT | AS2VT | 103 | 10 | Dead data: Applesoft in RAM vector table |
T2S2 | $33BB .. $33BB | FVCBUFS | 023 | 1 | Unused sector type 4 = VTOC | |
T2S2 | $33A0 .. $33A3 | FVCBUFS | ALC10S | 4 | 32 sectors/track allocation bitmap mask | |
T2S2 | $33BF .. $33BF | FVCBUFS | n/a | 1 | VTOC spare shenanigans | |
T2S2 | $33C0 .. $33C0 | FVCBUFS | n/a | 1 | VTOC spare shenanigans | |
T2S2 | $33C2 .. $33E1 | FVCBUFS | n/a | 32 | VTOC spare shenanigans | |
T2S2 | $33E3 .. $33EA | FVCBUFS | n/a | 8 | VTOC spare shenanigans | |
T2S2 | $33ED .. $33ED | FVCBUFS | VALCA3 | 1 | VTOC Track Allocation byte 3 | |
T2S2 | $33EE .. $33EE | FVCBUFS | VALCA4 | 1 | VTOC Track Allocation byte 4 | |
T2S2 | $33F3 .. $ | ? | ||||
T2S2 | $3497 .. $34BA | FVCBUFS | n/a | 40 | VTOC tracks 41 - 50 sector bitmaps | |
T2S2 | $34BB .. $34BB | FVCBUFS | VDTCDE | 1 | CAT Unused sector type 2 = CATALOG | |
T0SC | DOSINIT | Wastes 12 bytes for Applesoft/Integer Func Pointers -- IBASVT | ||||
Total | --- | --- | --- | 160 |
There are two types of data that reside in both memory and on disk:
There is no need store the uninitialized ones on disk IF they are placed after code. (Note: This may cause slightly more code, say copying a block of data that has both initialized and uninitialized parts, since the initialized and uninitialized data will no longer be contiguous. Usually uninitialized data are "large", say > 16 bytes, such as an array or buffer.) Even the EDASM manual states on Page 45 (my emphasis added):
This means that if you accidently enter a DS with an expression that comes up with a value of, say 48K bytes, you will suddenly get a very large output file. The expression is most often used as a relatively small constant, for small data areas, since large buffers and work areas should not be part of an object program, (unless of course you have disk space burning a hole in your diskette).
For example, DOS does dumb shit like this: Interleaving code and data bloating the program stored on disk.
Example 1:
ORG $2000 WRK EQU $40 COUT EQU $FDED PRNTYX EQU $F940 ; --- begin code --- MAIN EQU * ;=12 $2000 JSR FUNC1 ; +3 JSR FUNC2 ; +3 LDY #>END ; +2 hi byte of addr LDX #<END ; +2 lo byte of addr JMP PRNTYX ; +2 ; Pade to end of page to page align BUF1 ; $200D .. $20FF = wasted bytes when clearly have room for FUNC1 and FUNC2 HEREL EQU <* ; lo byte ca65, merlin; EDASM >* REMDR EQU 256-HEREL ; pad to end of page ORG *+REMDR ; $2100 BUF1 DS 256,0 ;+256 initialized FNAME EQU * ; $2200 FNAME1 ASC "HELLO_________________________" ; +30 filename FNAME1LEN EQU *-FNAME FUNC1 EQU * ;=14 $221E LDX #0 ; +2 PUTCHAR LDA FNAME,X ; +3 JSR COUT ; +3 INX ; +1 CPX #FNAME1LEN ; +2 BNE PUTCHAR ; +2 RTS ; +1 FCB EQU * ;=4 $222C FCB_SLOT DS 1 ; +1 FCB_DRIVE DS 1 ; +1 FCB_TRACK DS 1 ; +1 FCB_SECTOR DS 1 ; +1 FCB_LEN EQU *-FCB ; FUNC2 EQU * ;=7 $2230 LDA #6 ; +2 STA FCB_SLOT ; +3 RTS ; +1 VTOC EQU * ; $2236 uninitialized ORG VTOC+256 ;+256 END EQU * ;=822 $2336 bytes on disk
Which takes up a whopping total of 822 bytes ($336) in memory or (822 + 255)/256) = 4 sectors on disk!
Instead if we grouped all the code first, followed by all initialized data, and then all uninitialized data at the end "pre-allocating" them we will use significantly less disk space.
The only thing left to do is to add short "zero uninitialized data" stub at the beginning of our programs.
Example 2:
ORG $2000 WRK EQU $40 COUT EQU $FDED PRNTYX EQU $F940 ; --- begin zero uninitialized data (similiar to init bss) --- ; Zero memory from DATA_START .. DATA_END ; in 2 stages: ; ; DATA_START .. page of DATA_END ; page of DATA_END .. DATA_END ; ; +---------------+-------------+ ; | 00 .. 00 | 00 .. 00 | ; +---------------+-------------| ; ^ ^ ^ ; DATA_START DataEndPage DATA_END ; $2100 $2400 $2403 ; INIT ;=33 $2000 LDY #<DATA_START ; +2 lo byte of addr: ca65, merlin; EDASM #> LDX #>DATA_START ; +2 hi byte of addr: ca65, merlin; EDASM #< STY WRK+0 ; +2 STX WRK+1 ; +2 LDA #0 ; +2 CHECK_PAGE LDX WRK+1 ; +2 CPX #>DATA_END ; +2 hi byte of addr BCS CHECK_PART ; +2 src >= end ? CLEAR_PAGE STA (WRK),Y ; +2 INY ; +1 BNE CLEAR_PAGE ; +2 INC WRK+1 ; +2 BNE CHECK_PAGE ; +2 ; Zero from start of memory page of DATA_END .. DATA_END CHECK_PART LDX #<DATA_END ; +2 lo byte of addr; ca65, merlin; EDASM #> CLEAR_PART STA (WRK),Y ; +2 INY ; +1 DEX ; +1 BNE CLEAR_PART ; +2 ; --- end clear stub --- ;Sub-Total 33 bytes header code ; --- begin code --- MAIN EQU * ;=12 $2021 JSR FUNC1 ; +3 JSR FUNC2 ; +3 LDY #>END ; +2 hi byte of addr LDX #<END ; +2 lo byte of addr JMP PRNTYX ; +2 FUNC1 EQU * ;=14 $202E LDX #0 ; +2 PUTCHAR LDA FNAME,X ; +3 JSR COUT ; +3 INX ; +1 CPX #FNAME1LEN ; +2 BNE PUTCHAR ; +2 RTS ; +1 FUNC2 EQU * ;=6 LDA #6 ; +2 STA FCB_SLOT ; +3 RTS ; +1 ;--- end code --- ;Sub-Total 27 bytes program code ; All data grouped together ; There are 2 types of data: ; initialized ; uninitialized ; Only the initialized data needs to be stored on disk ; --- begin data --- Initialized data FNAME EQU * ;=30 $2042 FNAME1 ASC "HELLO_________________________" ; +30 filename FNAME1LEN EQU *-FNAME FCB EQU * ; $2060 FCB_SLOT DS 1 FCB_DRIVE DS 1 FCB_TRACK DS 1 FCB_SECTOR DS 1 FCB_LEN EQU *-FCB ; --- end data --- END EQU * ; $2064 ; Pad to end of page to page align BUF1 HEREL EQU <* ; lo byte ca65, merlin; EDASM >* REMDR EQU 256-HEREL ; pad to end of page ORG *+REMDR ; === begin data === Uninitialized data DATA_START EQU * BUF1 EQU * ; $2100 ORG *+256 VTOC EQU * ; $2200 ORG *+256 DATA_END EQU * ; $2300 ; === end data ===
Track/Sector | File | Description |
---|---|---|
T0S5 | MSWAITR | Wastes 256 bytes for NBUF1 - entire sector is zero! |
T0SB | DOSINIT | Wastes 127 bytes for padding to page align START DOS Vectors |
T2S3 | FCVBUFS | Wastes 255 bytes for VTOC and an unused single byte of the start of the CATALOG ($02) @ $BB ! |
T2S4 | FCVBUFS | Wastes 256 bytes for CATALOG remaining bytes since it spans two sectors |
T2S5 - T2SF | n/a | Rest of Track 2 is reserved. See: HNTDAFS #4 and TODO |
Total sectors wasted: 14 !
Why is DOS 3.3 so slow loading files when faster DOS's such as DiversiDOS, Pronto DOS, FastDOS, are able to load significantly faster?
When DOS has finished reading the raw disk nibbles into a buffer, it must "decode" the 342 nibbles into 256 bytes. Then it must copy the sector back to the caller's address space. This doesn't leave a whole lot of time. While there is sector interleaving DOS to help alleviate the lack of time this it isn't enough due to excessing buffering. DOS has significant overhead where it copies data from/to 3 buffers. TODO: citation In modern terminology this is known as buffer bloat.
Let's trace the BLOAD command to see what happens.
First, prepare a new blank disk that we'll use for testing.
NEW
1 ? CHR$(4);"CATALOG"
2 END
3 HGR
4 FOR C=0 TO 7
5 HCOLOR=C:X=C*14:Z=(C+1)*14-1
6 FOR Y=0 TO 16:HPLOT X,Y TO Z,Y:NEXT
7 NEXT
INIT HELLO
RUN 3
BSAVE TEST,A$2000,L$1FF8
We've created a binary graphics file on track $13, sector $F .. track $14, sector $0. (Remember, DOS start at sector $F and works "down" sector $0.)
Here is the corresponding Track / Sector usage:
T13S0 $2EFC .. $2FFB T13S1 $2DFC .. $2EFB T13S2 $2CFC .. $2DFB T13S3 $2BFC .. $2CFB T13S4 $2AFC .. $2BFB T13S5 $29FC .. $2AFB T13S6 $28FC .. $29FB T13S7 $27FC .. $28FB T13S8 $26FC .. $27FB T13S9 $25FC .. $26FB T13SA $24FC .. $25FB T13SB $23FC .. $24FB T13SC $22FC .. $23FB T13SD $21FC .. $22FB T13SE $20FC .. $21FB T13SE $2000 .. $20FB T13SF Array of sectors for file TEST T14S0 $3EFB .. $3FF7 T14S1 $3DFB .. $3EFB T14S2 $3CFB .. $3DFB T14S3 $3BFB .. $3CFB T14S4 $3AFB .. $3BFB T14S5 $39FB .. $3AFB T14S6 $38FB .. $39FB T14S7 $37FB .. $38FB T14S8 $36FC .. $37FB T14S9 $35FC .. $36FB T14SA $34FC .. $35FB T14SB $33FC .. $34FB T14SC $32FC .. $33FB T14SD $31FC .. $32FB T14SE $30FC .. $31FB T14SF $2FFC .. $30FB
And the corresponding Track / Sector disk map
T00000000000000001111111111111111222 T0123456789ABCDEF0123456789ABCDEF012 0.DDD..............V.BB.............. 1.DDD..............C.BB.............. 2.DDD..............C.BB.............. 3.DDD..............C.BB.............. 4.DDD..............C.BB.............. 5.DD...............C.BB.............. 6.DD...............C.BB.............. 7.DD...............C.BB.............. 8.DD...............C.BB.............. 9.DD...............C.BB.............. A.DD...............C.BB.............. B.DD...............C.BB.............. C.DD...............C.BB.............. D.DD...............C.BB.............. E.DD...............CABB.............. F.DD...............CabB.............. T00000000000000001111111111111111222 T0123456789ABCDEF0123456789ABCDEF012 Legend: a = Track/Sector List: HELLO A = Applesoft program: HELLO b = Track/Sector list of: TEST B = Binary graphics file: TEST C = Catalog D = DOS 3.3 Boot V = VTOC (Volume Table of Contents -- Free/Used sectors bitmap)
A special Thank-You to:
Apple ][ Forever!