diff options
Diffstat (limited to 'v1.25/source/MSDOS.ASM')
| -rw-r--r-- | v1.25/source/MSDOS.ASM | 4031 |
1 files changed, 4031 insertions, 0 deletions
diff --git a/v1.25/source/MSDOS.ASM b/v1.25/source/MSDOS.ASM new file mode 100644 index 0000000..8538b76 --- /dev/null +++ b/v1.25/source/MSDOS.ASM | |||
| @@ -0,0 +1,4031 @@ | |||
| 1 | ; 86-DOS High-performance operating system for the 8086 version 1.25 | ||
| 2 | ; by Tim Paterson | ||
| 3 | |||
| 4 | |||
| 5 | ; ****************** Revision History ************************* | ||
| 6 | ; >> EVERY change must noted below!! << | ||
| 7 | ; | ||
| 8 | ; 0.34 12/29/80 General release, updating all past customers | ||
| 9 | ; 0.42 02/25/81 32-byte directory entries added | ||
| 10 | ; 0.56 03/23/81 Variable record and sector sizes | ||
| 11 | ; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack | ||
| 12 | ; 0.74 04/15/81 Recognize I/O devices with file names | ||
| 13 | ; 0.75 04/17/81 Improve and correct buffer handling | ||
| 14 | ; 0.76 04/23/81 Correct directory size when not 2^N entries | ||
| 15 | ; 0.80 04/27/81 Add console input without echo, Functions 7 & 8 | ||
| 16 | ; 1.00 04/28/81 Renumber for general release | ||
| 17 | ; 1.01 05/12/81 Fix bug in `STORE' | ||
| 18 | ; 1.10 07/21/81 Fatal error trapping, NUL device, hidden files, date & time, | ||
| 19 | ; RENAME fix, general cleanup | ||
| 20 | ; 1.11 09/03/81 Don't set CURRENT BLOCK to 0 on open; fix SET FILE SIZE | ||
| 21 | ; 1.12 10/09/81 Zero high half of CURRENT BLOCK after all (CP/M programs don't) | ||
| 22 | ; 1.13 10/29/81 Fix classic "no write-through" error in buffer handling | ||
| 23 | ; 1.20 12/31/81 Add time to FCB; separate FAT from DPT; Kill SMALLDIR; | ||
| 24 | ; Add FLUSH and MAPDEV calls; allow disk mapping in DSKCHG; | ||
| 25 | ; Lots of smaller improvements | ||
| 26 | ; 1.21 01/06/82 HIGHMEM switch to run DOS in high memory | ||
| 27 | ; 1.22 01/12/82 Add VERIFY system call to enable/disable verify after write | ||
| 28 | ; 1.23 02/11/82 Add defaulting to parser; use variable escape character | ||
| 29 | ; Don't zero extent field in IBM version (back to 1.01!) | ||
| 30 | ; 1.24 03/01/82 Restore fcn. 27 to 1.0 level; add fcn. 28 | ||
| 31 | ; 1.25 03/03/82 Put marker (00) at end of directory to speed searches | ||
| 32 | ; | ||
| 33 | ; ************************************************************* | ||
| 34 | |||
| 35 | |||
| 36 | ; Interrupt Entry Points: | ||
| 37 | |||
| 38 | ; INTBASE: ABORT | ||
| 39 | ; INTBASE+4: COMMAND | ||
| 40 | ; INTBASE+8: BASE EXIT ADDRESS | ||
| 41 | ; INTBASE+C: CONTROL-C ABORT | ||
| 42 | ; INTBASE+10H: FATAL ERROR ABORT | ||
| 43 | ; INTBASE+14H: BIOS DISK READ | ||
| 44 | ; INTBASE+18H: BIOS DISK WRITE | ||
| 45 | ; INTBASE+40H: Long jump to CALL entry point | ||
| 46 | |||
| 47 | IF IBM | ||
| 48 | ESCCH EQU 0 | ||
| 49 | CANCEL EQU 1BH ;Cancel with ESC | ||
| 50 | TOGLINS EQU TRUE ;One key toggles insert mode | ||
| 51 | TOGLPRN EQU TRUE ;One key toggles printer echo | ||
| 52 | NUMDEV EQU 6 ;Include "COM1" as I/O device name | ||
| 53 | ZEROEXT EQU TRUE | ||
| 54 | ELSE | ||
| 55 | ESCCH EQU 1BH | ||
| 56 | CANCEL EQU "X"-"@" ;Cancel with Ctrl-X | ||
| 57 | TOGLINS EQU FALSE ;Separate keys for insert mode on and off | ||
| 58 | TOGLPRN EQU FALSE ;Separate keys for printer echo on and off | ||
| 59 | NUMDEV EQU 5 ;Number of I/O device names | ||
| 60 | ZEROEXT EQU FALSE | ||
| 61 | ENDIF | ||
| 62 | |||
| 63 | MAXCALL EQU 36 | ||
| 64 | MAXCOM EQU 46 | ||
| 65 | INTBASE EQU 80H | ||
| 66 | INTTAB EQU 20H | ||
| 67 | ENTRYPOINTSEG EQU 0CH | ||
| 68 | ENTRYPOINT EQU INTBASE+40H | ||
| 69 | CONTC EQU INTTAB+3 | ||
| 70 | EXIT EQU INTBASE+8 | ||
| 71 | LONGJUMP EQU 0EAH | ||
| 72 | LONGCALL EQU 9AH | ||
| 73 | MAXDIF EQU 0FFFH | ||
| 74 | SAVEXIT EQU 10 | ||
| 75 | |||
| 76 | ; Field definition for FCBs | ||
| 77 | |||
| 78 | FCBLOCK STRUC | ||
| 79 | DB 12 DUP (?) ;Drive code and name | ||
| 80 | EXTENT DW ? | ||
| 81 | RECSIZ DW ? ;Size of record (user settable) | ||
| 82 | FILSIZ DW ? ;Size of file in bytes | ||
| 83 | DRVBP DW ? ;BP for SEARCH FIRST and SEARCH NEXT | ||
| 84 | FDATE DW ? ;Date of last writing | ||
| 85 | FTIME DW ? ;Time of last writing | ||
| 86 | DEVID DB ? ;Device ID number, bits 0-5 | ||
| 87 | ;bit 7=0 for file, bit 7=1 for I/O device | ||
| 88 | ;If file, bit 6=0 if dirty | ||
| 89 | ;If I/O device, bit 6=0 if EOF (input) | ||
| 90 | FIRCLUS DW ? ;First cluster of file | ||
| 91 | LSTCLUS DW ? ;Last cluster accessed | ||
| 92 | CLUSPOS DW ? ;Position of last cluster accessed | ||
| 93 | DB ? ;Forces NR to offset 32 | ||
| 94 | NR DB ? ;Next record | ||
| 95 | RR DB 3 DUP (?) ;Random record | ||
| 96 | FCBLOCK ENDS | ||
| 97 | FILDIRENT = FILSIZ ;Used only by SEARCH FIRST and SEARCH NEXT | ||
| 98 | |||
| 99 | ; Description of 32-byte directory entry (same as returned by SEARCH FIRST | ||
| 100 | ; and SEARCH NEXT, functions 17 and 18). | ||
| 101 | ; | ||
| 102 | ; Location bytes Description | ||
| 103 | ; | ||
| 104 | ; 0 11 File name and extension ( 0E5H if empty) | ||
| 105 | ; 11 1 Attributes. Bits 1 or 2 make file hidden | ||
| 106 | ; 12 10 Zero field (for expansion) | ||
| 107 | ; 22 2 Time. Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour | ||
| 108 | ; 24 2 Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 | ||
| 109 | ; 26 2 First allocation unit ( < 4080 ) | ||
| 110 | ; 28 4 File size, in bytes (LSB first, 30 bits max.) | ||
| 111 | ; | ||
| 112 | ; The File Allocation Table uses a 12-bit entry for each allocation unit on | ||
| 113 | ; the disk. These entries are packed, two for every three bytes. The contents | ||
| 114 | ; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result | ||
| 115 | ; to the base address of the Allocation Table; 3) fetching the 16-bit word at | ||
| 116 | ; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the | ||
| 117 | ; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number | ||
| 118 | ; zero is used as an end-of-file trap in the OS and as a flag for directory | ||
| 119 | ; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The | ||
| 120 | ; first available allocation unit is assigned entry number two, and even | ||
| 121 | ; though it is the first, is called cluster 2. Entries greater than 0FF8H are | ||
| 122 | ; end of file marks; entries of zero are unallocated. Otherwise, the contents | ||
| 123 | ; of a FAT entry is the number of the next cluster in the file. | ||
| 124 | |||
| 125 | |||
| 126 | ; Field definition for Drive Parameter Block | ||
| 127 | |||
| 128 | DPBLOCK STRUC | ||
| 129 | DEVNUM DB ? ;I/O driver number | ||
| 130 | DRVNUM DB ? ;Physical Unit number | ||
| 131 | SECSIZ DW ? ;Size of physical sector in bytes | ||
| 132 | CLUSMSK DB ? ;Sectors/cluster - 1 | ||
| 133 | CLUSSHFT DB ? ;Log2 of sectors/cluster | ||
| 134 | FIRFAT DW ? ;Starting record of FATs | ||
| 135 | FATCNT DB ? ;Number of FATs for this drive | ||
| 136 | MAXENT DW ? ;Number of directory entries | ||
| 137 | FIRREC DW ? ;First sector of first cluster | ||
| 138 | MAXCLUS DW ? ;Number of clusters on drive + 1 | ||
| 139 | FATSIZ DB ? ;Number of records occupied by FAT | ||
| 140 | FIRDIR DW ? ;Starting record of directory | ||
| 141 | FAT DW ? ;Pointer to start of FAT | ||
| 142 | DPBLOCK ENDS | ||
| 143 | |||
| 144 | DPBSIZ EQU 20 ;Size of the structure in bytes | ||
| 145 | DIRSEC = FIRREC ;Number of dir. sectors (init temporary) | ||
| 146 | DSKSIZ = MAXCLUS ;Size of disk (temp used during init only) | ||
| 147 | |||
| 148 | ;The following are all of the segments used | ||
| 149 | ;They are declared in the order that they should be placed in the executable | ||
| 150 | |||
| 151 | CODE SEGMENT | ||
| 152 | CODE ENDS | ||
| 153 | |||
| 154 | CONSTANTS SEGMENT BYTE | ||
| 155 | CONSTANTS ENDS | ||
| 156 | |||
| 157 | DATA SEGMENT WORD | ||
| 158 | DATA ENDS | ||
| 159 | |||
| 160 | DOSGROUP GROUP CODE,CONSTANTS,DATA | ||
| 161 | |||
| 162 | SEGBIOS SEGMENT | ||
| 163 | SEGBIOS ENDS | ||
| 164 | |||
| 165 | |||
| 166 | ; BOIS entry point definitions | ||
| 167 | |||
| 168 | IF IBM | ||
| 169 | BIOSSEG EQU 60H | ||
| 170 | ENDIF | ||
| 171 | IF NOT IBM | ||
| 172 | BIOSSEG EQU 40H | ||
| 173 | ENDIF | ||
| 174 | |||
| 175 | SEGBIOS SEGMENT AT BIOSSEG | ||
| 176 | ORG 0 | ||
| 177 | DB 3 DUP (?) ;Reserve room for jump to init code | ||
| 178 | BIOSSTAT DB 3 DUP (?) ;Console input status check | ||
| 179 | BIOSIN DB 3 DUP (?) ;Get console character | ||
| 180 | BIOSOUT DB 3 DUP (?) ;Output console character | ||
| 181 | BIOSPRINT DB 3 DUP (?) ;Output to printer | ||
| 182 | BIOSAUXIN DB 3 DUP (?) ;Get byte from auxilliary | ||
| 183 | BIOSAUXOUT DB 3 DUP (?) ;Output byte to auxilliary | ||
| 184 | BIOSREAD DB 3 DUP (?) ;Disk read | ||
| 185 | BIOSWRITE DB 3 DUP (?) ;Disk write | ||
| 186 | BIOSDSKCHG DB 3 DUP (?) ;Dsik-change status | ||
| 187 | BIOSSETDATE DB 3 DUP (?) ;Set date | ||
| 188 | BIOSSETTIME DB 3 DUP (?) ;Set time | ||
| 189 | BIOSGETTIME DB 3 DUP (?) ;Get time and date | ||
| 190 | BIOSFLUSH DB 3 DUP (?) ;Clear console input buffer | ||
| 191 | BIOSMAPDEV DB 3 DUP (?) ;Dynamic disk table mapper | ||
| 192 | |||
| 193 | SEGBIOS ENDS | ||
| 194 | ; Location of user registers relative user stack pointer | ||
| 195 | |||
| 196 | STKPTRS STRUC | ||
| 197 | AXSAVE DW ? | ||
| 198 | BXSAVE DW ? | ||
| 199 | CXSAVE DW ? | ||
| 200 | DXSAVE DW ? | ||
| 201 | SISAVE DW ? | ||
| 202 | DISAVE DW ? | ||
| 203 | BPSAVE DW ? | ||
| 204 | DSSAVE DW ? | ||
| 205 | ESSAVE DW ? | ||
| 206 | IPSAVE DW ? | ||
| 207 | CSSAVE DW ? | ||
| 208 | FSAVE DW ? | ||
| 209 | STKPTRS ENDS | ||
| 210 | |||
| 211 | ; Start of code | ||
| 212 | |||
| 213 | CODE SEGMENT | ||
| 214 | ASSUME CS:DOSGROUP,DS:DOSGROUP,ES:DOSGROUP,SS:DOSGROUP | ||
| 215 | |||
| 216 | ORG 0 | ||
| 217 | CODSTRT EQU $ | ||
| 218 | JMP DOSINIT | ||
| 219 | |||
| 220 | ESCCHAR DB ESCCH ;Lead-in character for escape sequences | ||
| 221 | ESCTAB: | ||
| 222 | IF NOT IBM | ||
| 223 | DB "S" ;Copy one char | ||
| 224 | DB "V" ;Skip one char | ||
| 225 | DB "T" ;Copy to char | ||
| 226 | DB "W" ;Skip to char | ||
| 227 | DB "U" ;Copy line | ||
| 228 | DB "E" ;Kill line (no change in template) | ||
| 229 | DB "J" ;Reedit line (new template) | ||
| 230 | DB "D" ;Backspace | ||
| 231 | DB "P" ;Enter insert mode | ||
| 232 | DB "Q" ;Exit insert mode | ||
| 233 | DB "R" ;Escape character | ||
| 234 | DB "R" ;End of table | ||
| 235 | ENDIF | ||
| 236 | IF IBM | ||
| 237 | DB 64 ;Crtl-Z - F6 | ||
| 238 | DB 77 ;Copy one char - --> | ||
| 239 | DB 59 ;Copy one char - F1 | ||
| 240 | DB 83 ;Skip one char - DEL | ||
| 241 | DB 60 ;Copy to char - F2 | ||
| 242 | DB 62 ;Skip to char - F4 | ||
| 243 | DB 61 ;Copy line - F3 | ||
| 244 | DB 61 ;Kill line (no change to template ) - Not used | ||
| 245 | DB 63 ;Reedit line (new template) - F5 | ||
| 246 | DB 75 ;Backspace - <-- | ||
| 247 | DB 82 ;Enter insert mode - INS (toggle) | ||
| 248 | DB 65 ;Escape character - F7 | ||
| 249 | DB 65 ;End of table | ||
| 250 | ENDIF | ||
| 251 | |||
| 252 | ESCTABLEN EQU $-ESCTAB | ||
| 253 | IF NOT IBM | ||
| 254 | HEADER DB 13,10,"MS-DOS version 1.25" | ||
| 255 | IF HIGHMEM | ||
| 256 | DB "H" | ||
| 257 | ENDIF | ||
| 258 | IF DSKTEST | ||
| 259 | DB "D" | ||
| 260 | ENDIF | ||
| 261 | |||
| 262 | DB 13,10 | ||
| 263 | DB "Copyright 1981,82 Microsoft, Inc.",13,10,"$" | ||
| 264 | ENDIF | ||
| 265 | |||
| 266 | QUIT: | ||
| 267 | MOV AH,0 | ||
| 268 | JMP SHORT SAVREGS | ||
| 269 | |||
| 270 | COMMAND: ;Interrupt call entry point | ||
| 271 | CMP AH,MAXCOM | ||
| 272 | JBE SAVREGS | ||
| 273 | BADCALL: | ||
| 274 | MOV AL,0 | ||
| 275 | IRET: IRET | ||
| 276 | |||
| 277 | ENTRY: ;System call entry point and dispatcher | ||
| 278 | POP AX ;IP from the long call at 5 | ||
| 279 | POP AX ;Segment from the long call at 5 | ||
| 280 | POP CS:[TEMP] ;IP from the CALL 5 | ||
| 281 | PUSHF ;Start re-ordering the stack | ||
| 282 | CLI | ||
| 283 | PUSH AX ;Save segment | ||
| 284 | PUSH CS:[TEMP] ;Stack now ordered as if INT had been used | ||
| 285 | CMP CL,MAXCALL ;This entry point doesn't get as many calls | ||
| 286 | JA BADCALL | ||
| 287 | MOV AH,CL | ||
| 288 | SAVREGS: | ||
| 289 | PUSH ES | ||
| 290 | PUSH DS | ||
| 291 | PUSH BP | ||
| 292 | PUSH DI | ||
| 293 | PUSH SI | ||
| 294 | PUSH DX | ||
| 295 | PUSH CX | ||
| 296 | PUSH BX | ||
| 297 | PUSH AX | ||
| 298 | |||
| 299 | IF DSKTEST | ||
| 300 | MOV AX,CS:[SPSAVE] | ||
| 301 | MOV CS:[NSP],AX | ||
| 302 | MOV AX,CS:[SSSAVE] | ||
| 303 | MOV CS:[NSS],AX | ||
| 304 | POP AX | ||
| 305 | PUSH AX | ||
| 306 | ENDIF | ||
| 307 | |||
| 308 | MOV CS:[SPSAVE],SP | ||
| 309 | MOV CS:[SSSAVE],SS | ||
| 310 | MOV SP,CS | ||
| 311 | MOV SS,SP | ||
| 312 | REDISP: | ||
| 313 | MOV SP,OFFSET DOSGROUP:IOSTACK | ||
| 314 | STI ;Stack OK now | ||
| 315 | MOV BL,AH | ||
| 316 | MOV BH,0 | ||
| 317 | SHL BX,1 | ||
| 318 | CLD | ||
| 319 | CMP AH,12 | ||
| 320 | JLE SAMSTK | ||
| 321 | MOV SP,OFFSET DOSGROUP:DSKSTACK | ||
| 322 | SAMSTK: | ||
| 323 | CALL CS:[BX+DISPATCH] | ||
| 324 | LEAVE: | ||
| 325 | CLI | ||
| 326 | MOV SP,CS:[SPSAVE] | ||
| 327 | MOV SS,CS:[SSSAVE] | ||
| 328 | MOV BP,SP | ||
| 329 | MOV BYTE PTR [BP.AXSAVE],AL | ||
| 330 | |||
| 331 | IF DSKTEST | ||
| 332 | MOV AX,CS:[NSP] | ||
| 333 | MOV CS:[SPSAVE],AX | ||
| 334 | MOV AX,CS:[NSS] | ||
| 335 | MOV CS:[SSSAVE],AX | ||
| 336 | ENDIF | ||
| 337 | |||
| 338 | POP AX | ||
| 339 | POP BX | ||
| 340 | POP CX | ||
| 341 | POP DX | ||
| 342 | POP SI | ||
| 343 | POP DI | ||
| 344 | POP BP | ||
| 345 | POP DS | ||
| 346 | POP ES | ||
| 347 | IRET | ||
| 348 | ; Standard Functions | ||
| 349 | DISPATCH DW ABORT ;0 | ||
| 350 | DW CONIN | ||
| 351 | DW CONOUT | ||
| 352 | DW READER | ||
| 353 | DW PUNCH | ||
| 354 | DW LIST ;5 | ||
| 355 | DW RAWIO | ||
| 356 | DW RAWINP | ||
| 357 | DW IN | ||
| 358 | DW PRTBUF | ||
| 359 | DW BUFIN ;10 | ||
| 360 | DW CONSTAT | ||
| 361 | DW FLUSHKB | ||
| 362 | DW DSKRESET | ||
| 363 | DW SELDSK | ||
| 364 | DW OPEN ;15 | ||
| 365 | DW CLOSE | ||
| 366 | DW SRCHFRST | ||
| 367 | DW SRCHNXT | ||
| 368 | DW DELETE | ||
| 369 | DW SEQRD ;20 | ||
| 370 | DW SEQWRT | ||
| 371 | DW CREATE | ||
| 372 | DW RENAME | ||
| 373 | DW INUSE | ||
| 374 | DW GETDRV ;25 | ||
| 375 | DW SETDMA | ||
| 376 | DW GETFATPT | ||
| 377 | DW GETFATPTDL | ||
| 378 | DW GETRDONLY | ||
| 379 | DW SETATTRIB ;30 | ||
| 380 | DW GETDSKPT | ||
| 381 | DW USERCODE | ||
| 382 | DW RNDRD | ||
| 383 | DW RNDWRT | ||
| 384 | DW FILESIZE ;35 | ||
| 385 | DW SETRNDREC | ||
| 386 | ; Extended Functions | ||
| 387 | DW SETVECT | ||
| 388 | DW NEWBASE | ||
| 389 | DW BLKRD | ||
| 390 | DW BLKWRT ;40 | ||
| 391 | DW MAKEFCB | ||
| 392 | DW GETDATE | ||
| 393 | DW SETDATE | ||
| 394 | DW GETTIME | ||
| 395 | DW SETTIME ;45 | ||
| 396 | DW VERIFY | ||
| 397 | |||
| 398 | INUSE: | ||
| 399 | GETIO: | ||
| 400 | SETIO: | ||
| 401 | GETRDONLY: | ||
| 402 | SETATTRIB: | ||
| 403 | USERCODE: | ||
| 404 | MOV AL,0 | ||
| 405 | RET | ||
| 406 | |||
| 407 | VERIFY: | ||
| 408 | AND AL,1 | ||
| 409 | MOV CS:VERFLG,AL | ||
| 410 | RET | ||
| 411 | |||
| 412 | FLUSHKB: | ||
| 413 | PUSH AX | ||
| 414 | CALL FAR PTR BIOSFLUSH | ||
| 415 | POP AX | ||
| 416 | MOV AH,AL | ||
| 417 | CMP AL,1 | ||
| 418 | JZ REDISPJ | ||
| 419 | CMP AL,6 | ||
| 420 | JZ REDISPJ | ||
| 421 | CMP AL,7 | ||
| 422 | JZ REDISPJ | ||
| 423 | CMP AL,8 | ||
| 424 | JZ REDISPJ | ||
| 425 | CMP AL,10 | ||
| 426 | JZ REDISPJ | ||
| 427 | MOV AL,0 | ||
| 428 | RET | ||
| 429 | |||
| 430 | REDISPJ:JMP REDISP | ||
| 431 | |||
| 432 | READER: | ||
| 433 | AUXIN: | ||
| 434 | CALL STATCHK | ||
| 435 | CALL FAR PTR BIOSAUXIN | ||
| 436 | RET | ||
| 437 | |||
| 438 | PUNCH: | ||
| 439 | MOV AL,DL | ||
| 440 | AUXOUT: | ||
| 441 | PUSH AX | ||
| 442 | CALL STATCHK | ||
| 443 | POP AX | ||
| 444 | CALL FAR PTR BIOSAUXOUT | ||
| 445 | RET | ||
| 446 | |||
| 447 | |||
| 448 | UNPACK: | ||
| 449 | |||
| 450 | ; Inputs: | ||
| 451 | ; DS = CS | ||
| 452 | ; BX = Cluster number | ||
| 453 | ; BP = Base of drive parameters | ||
| 454 | ; SI = Pointer to drive FAT | ||
| 455 | ; Outputs: | ||
| 456 | ; DI = Contents of FAT for given cluster | ||
| 457 | ; Zero set means DI=0 (free cluster) | ||
| 458 | ; No other registers affected. Fatal error if cluster too big. | ||
| 459 | |||
| 460 | CMP BX,[BP.MAXCLUS] | ||
| 461 | JA HURTFAT | ||
| 462 | LEA DI,[SI+BX] | ||
| 463 | SHR BX,1 | ||
| 464 | MOV DI,[DI+BX] | ||
| 465 | JNC HAVCLUS | ||
| 466 | SHR DI,1 | ||
| 467 | SHR DI,1 | ||
| 468 | SHR DI,1 | ||
| 469 | SHR DI,1 | ||
| 470 | STC | ||
| 471 | HAVCLUS: | ||
| 472 | RCL BX,1 | ||
| 473 | AND DI,0FFFH | ||
| 474 | RET | ||
| 475 | HURTFAT: | ||
| 476 | PUSH AX | ||
| 477 | MOV AH,80H ;Signal Bad FAT to INT 24H handler | ||
| 478 | MOV DI,0FFFH ;In case INT 24H returns (it shouldn't) | ||
| 479 | CALL FATAL | ||
| 480 | POP AX ;Try to ignore bad FAT | ||
| 481 | RET | ||
| 482 | |||
| 483 | |||
| 484 | PACK: | ||
| 485 | |||
| 486 | ; Inputs: | ||
| 487 | ; DS = CS | ||
| 488 | ; BX = Cluster number | ||
| 489 | ; DX = Data | ||
| 490 | ; SI = Pointer to drive FAT | ||
| 491 | ; Outputs: | ||
| 492 | ; The data is stored in the FAT at the given cluster. | ||
| 493 | ; BX,DX,DI all destroyed | ||
| 494 | ; No other registers affected | ||
| 495 | |||
| 496 | MOV DI,BX | ||
| 497 | SHR BX,1 | ||
| 498 | ADD BX,SI | ||
| 499 | ADD BX,DI | ||
| 500 | SHR DI,1 | ||
| 501 | MOV DI,[BX] | ||
| 502 | JNC ALIGNED | ||
| 503 | SHL DX,1 | ||
| 504 | SHL DX,1 | ||
| 505 | SHL DX,1 | ||
| 506 | SHL DX,1 | ||
| 507 | AND DI,0FH | ||
| 508 | JMP SHORT PACKIN | ||
| 509 | ALIGNED: | ||
| 510 | AND DI,0F000H | ||
| 511 | PACKIN: | ||
| 512 | OR DI,DX | ||
| 513 | MOV [BX],DI | ||
| 514 | RET | ||
| 515 | |||
| 516 | DEVNAME: | ||
| 517 | MOV SI,OFFSET DOSGROUP:IONAME ;List of I/O devices with file names | ||
| 518 | MOV BH,NUMDEV ;BH = number of device names | ||
| 519 | LOOKIO: | ||
| 520 | MOV DI,OFFSET DOSGROUP:NAME1 | ||
| 521 | MOV CX,4 ;All devices are 4 letters | ||
| 522 | REPE CMPSB ;Check for name in list | ||
| 523 | JZ IOCHK ;If first 3 letters OK, check for the rest | ||
| 524 | ADD SI,CX ;Point to next device name | ||
| 525 | DEC BH | ||
| 526 | JNZ LOOKIO | ||
| 527 | CRET: | ||
| 528 | STC ;Not found | ||
| 529 | RET | ||
| 530 | |||
| 531 | IOCHK: | ||
| 532 | IF IBM | ||
| 533 | CMP BH,NUMDEV ;Is it the first device? | ||
| 534 | JNZ NOTCOM1 | ||
| 535 | MOV BH,2 ;Make it the same as AUX | ||
| 536 | NOTCOM1: | ||
| 537 | ENDIF | ||
| 538 | NEG BH | ||
| 539 | MOV CX,2 ;Check rest of name but not extension | ||
| 540 | MOV AX,2020H | ||
| 541 | REPE SCASW ;Make sure rest of name is blanks | ||
| 542 | JNZ CRET | ||
| 543 | RET1: RET ;Zero set so CREATE works | ||
| 544 | |||
| 545 | GETFILE: | ||
| 546 | ; Same as GETNAME except ES:DI points to FCB on successful return | ||
| 547 | CALL MOVNAME | ||
| 548 | JC RET1 | ||
| 549 | PUSH DX | ||
| 550 | PUSH DS | ||
| 551 | CALL FINDNAME | ||
| 552 | POP ES | ||
| 553 | POP DI | ||
| 554 | RET2: RET | ||
| 555 | |||
| 556 | |||
| 557 | GETNAME: | ||
| 558 | |||
| 559 | ; Inputs: | ||
| 560 | ; DS,DX point to FCB | ||
| 561 | ; Function: | ||
| 562 | ; Find file name in disk directory. First byte is | ||
| 563 | ; drive number (0=current disk). "?" matches any | ||
| 564 | ; character. | ||
| 565 | ; Outputs: | ||
| 566 | ; Carry set if file not found | ||
| 567 | ; ELSE | ||
| 568 | ; Zero set if attributes match (always except when creating) | ||
| 569 | ; BP = Base of drive parameters | ||
| 570 | ; DS = CS | ||
| 571 | ; ES = CS | ||
| 572 | ; BX = Pointer into directory buffer | ||
| 573 | ; SI = Pointer to First Cluster field in directory entry | ||
| 574 | ; [DIRBUF] has directory record with match | ||
| 575 | ; [NAME1] has file name | ||
| 576 | ; All other registers destroyed. | ||
| 577 | |||
| 578 | CALL MOVNAME | ||
| 579 | JC RET2 ;Bad file name? | ||
| 580 | FINDNAME: | ||
| 581 | MOV AX,CS | ||
| 582 | MOV DS,AX | ||
| 583 | CALL DEVNAME | ||
| 584 | JNC RET2 | ||
| 585 | CALL STARTSRCH | ||
| 586 | CONTSRCH: | ||
| 587 | CALL GETENTRY | ||
| 588 | JC RET2 | ||
| 589 | SRCH: | ||
| 590 | MOV AH,BYTE PTR [BX] | ||
| 591 | OR AH,AH ;End of directory? | ||
| 592 | JZ FREE | ||
| 593 | CMP AH,[DELALL] ;Free entry? | ||
| 594 | JZ FREE | ||
| 595 | MOV SI,BX | ||
| 596 | MOV DI,OFFSET DOSGROUP:NAME1 | ||
| 597 | MOV CX,11 | ||
| 598 | WILDCRD: | ||
| 599 | REPE CMPSB | ||
| 600 | JZ FOUND | ||
| 601 | CMP BYTE PTR [DI-1],"?" | ||
| 602 | JZ WILDCRD | ||
| 603 | NEXTENT: | ||
| 604 | CALL NEXTENTRY | ||
| 605 | JNC SRCH | ||
| 606 | RET3: RET | ||
| 607 | |||
| 608 | FREE: | ||
| 609 | CMP [ENTFREE],-1 ;Found a free entry before? | ||
| 610 | JNZ TSTALL ;If so, ignore this one | ||
| 611 | MOV CX,[LASTENT] | ||
| 612 | MOV [ENTFREE],CX | ||
| 613 | TSTALL: | ||
| 614 | CMP AH,[DELALL] ;At end of directory? | ||
| 615 | JZ NEXTENT ;No - continue search | ||
| 616 | STC ;Report not found | ||
| 617 | RET | ||
| 618 | |||
| 619 | FOUND: | ||
| 620 | ;Check if attributes allow finding it | ||
| 621 | MOV AH,[ATTRIB] ;Attributes of search | ||
| 622 | NOT AH | ||
| 623 | AND AH,[SI] ;Compare with attributes of file | ||
| 624 | ADD SI,15 | ||
| 625 | AND AH,6 ;Only look at bits 1 and 2 | ||
| 626 | JZ RET3 | ||
| 627 | TEST BYTE PTR [CREATING],-1 ;Pass back mismatch if creating | ||
| 628 | JZ NEXTENT ;Otherwise continue searching | ||
| 629 | RET | ||
| 630 | |||
| 631 | |||
| 632 | GETENTRY: | ||
| 633 | |||
| 634 | ; Inputs: | ||
| 635 | ; [LASTENT] has previously searched directory entry | ||
| 636 | ; Function: | ||
| 637 | ; Locates next sequential directory entry in preparation for search | ||
| 638 | ; Outputs: | ||
| 639 | ; Carry set if none | ||
| 640 | ; ELSE | ||
| 641 | ; AL = Current directory block | ||
| 642 | ; BX = Pointer to next directory entry in [DIRBUF] | ||
| 643 | ; DX = Pointer to first byte after end of DIRBUF | ||
| 644 | ; [LASTENT] = New directory entry number | ||
| 645 | |||
| 646 | MOV AX,[LASTENT] | ||
| 647 | INC AX ;Start with next entry | ||
| 648 | CMP AX,[BP.MAXENT] | ||
| 649 | JAE NONE | ||
| 650 | GETENT: | ||
| 651 | MOV [LASTENT],AX | ||
| 652 | MOV CL,4 | ||
| 653 | SHL AX,CL | ||
| 654 | XOR DX,DX | ||
| 655 | SHL AX,1 | ||
| 656 | RCL DX,1 ;Account for overflow in last shift | ||
| 657 | MOV BX,[BP.SECSIZ] | ||
| 658 | AND BL,255-31 ;Must be multiple of 32 | ||
| 659 | DIV BX | ||
| 660 | MOV BX,DX ;Position within sector | ||
| 661 | MOV AH,[BP.DEVNUM] ;AL=Directory sector no. | ||
| 662 | CMP AX,[DIRBUFID] | ||
| 663 | JZ HAVDIRBUF | ||
| 664 | PUSH BX | ||
| 665 | CALL DIRREAD | ||
| 666 | POP BX | ||
| 667 | HAVDIRBUF: | ||
| 668 | MOV DX,OFFSET DOSGROUP:DIRBUF | ||
| 669 | ADD BX,DX | ||
| 670 | ADD DX,[BP.SECSIZ] | ||
| 671 | RET | ||
| 672 | |||
| 673 | NEXTENTRY: | ||
| 674 | |||
| 675 | ; Inputs: | ||
| 676 | ; Same as outputs of GETENTRY, above | ||
| 677 | ; Function: | ||
| 678 | ; Update AL, BX, and [LASTENT] for next directory entry. | ||
| 679 | ; Carry set if no more. | ||
| 680 | |||
| 681 | MOV DI,[LASTENT] | ||
| 682 | INC DI | ||
| 683 | CMP DI,[BP.MAXENT] | ||
| 684 | JAE NONE | ||
| 685 | MOV [LASTENT],DI | ||
| 686 | ADD BX,32 | ||
| 687 | CMP BX,DX | ||
| 688 | JB HAVIT | ||
| 689 | INC AL ;Next directory sector | ||
| 690 | PUSH DX ;Save limit | ||
| 691 | CALL DIRREAD | ||
| 692 | POP DX | ||
| 693 | MOV BX,OFFSET DOSGROUP:DIRBUF | ||
| 694 | HAVIT: | ||
| 695 | CLC | ||
| 696 | RET | ||
| 697 | |||
| 698 | NONE: | ||
| 699 | CALL CHKDIRWRITE | ||
| 700 | STC | ||
| 701 | RET4: RET | ||
| 702 | |||
| 703 | |||
| 704 | DELETE: ; System call 19 | ||
| 705 | CALL MOVNAME | ||
| 706 | MOV AL,-1 | ||
| 707 | JC RET4 | ||
| 708 | MOV AL,CS:[ATTRIB] | ||
| 709 | AND AL,6 ;Look only at hidden bits | ||
| 710 | CMP AL,6 ;Both must be set | ||
| 711 | JNZ NOTALL | ||
| 712 | MOV CX,11 | ||
| 713 | MOV AL,"?" | ||
| 714 | MOV DI,OFFSET DOSGROUP:NAME1 | ||
| 715 | REPE SCASB ;See if name is *.* | ||
| 716 | JNZ NOTALL | ||
| 717 | MOV BYTE PTR CS:[DELALL],0 ;DEL *.* - flag deleting all | ||
| 718 | NOTALL: | ||
| 719 | CALL FINDNAME | ||
| 720 | MOV AL,-1 | ||
| 721 | JC RET4 | ||
| 722 | OR BH,BH ;Check if device name | ||
| 723 | JS RET4 ;Can't delete I/O devices | ||
| 724 | DELFILE: | ||
| 725 | MOV BYTE PTR [DIRTYDIR],-1 | ||
| 726 | MOV AH,[DELALL] | ||
| 727 | MOV BYTE PTR [BX],AH | ||
| 728 | MOV BX,[SI] | ||
| 729 | MOV SI,[BP.FAT] | ||
| 730 | OR BX,BX | ||
| 731 | JZ DELNXT | ||
| 732 | CMP BX,[BP.MAXCLUS] | ||
| 733 | JA DELNXT | ||
| 734 | CALL RELEASE | ||
| 735 | DELNXT: | ||
| 736 | CALL CONTSRCH | ||
| 737 | JNC DELFILE | ||
| 738 | CALL FATWRT | ||
| 739 | CALL CHKDIRWRITE | ||
| 740 | XOR AL,AL | ||
| 741 | RET | ||
| 742 | |||
| 743 | |||
| 744 | RENAME: ;System call 23 | ||
| 745 | CALL MOVNAME | ||
| 746 | JC ERRET | ||
| 747 | ADD SI,5 | ||
| 748 | MOV DI,OFFSET DOSGROUP:NAME2 | ||
| 749 | CALL LODNAME | ||
| 750 | JC ERRET ;Report error if second name invalid | ||
| 751 | CALL FINDNAME | ||
| 752 | JC ERRET | ||
| 753 | OR BH,BH ;Check if I/O device name | ||
| 754 | JS ERRET ;If so, can't rename it | ||
| 755 | MOV SI,OFFSET DOSGROUP:NAME1 | ||
| 756 | MOV DI,OFFSET DOSGROUP:NAME3 | ||
| 757 | MOV CX,6 ;6 words (12 bytes)--include attribute byte | ||
| 758 | REP MOVSW ;Copy name to search for | ||
| 759 | RENFIL: | ||
| 760 | MOV DI,OFFSET DOSGROUP:NAME1 | ||
| 761 | MOV SI,OFFSET DOSGROUP:NAME2 | ||
| 762 | MOV CX,11 | ||
| 763 | NEWNAM: | ||
| 764 | LODSB | ||
| 765 | CMP AL,"?" | ||
| 766 | JNZ NOCHG | ||
| 767 | MOV AL,[BX] | ||
| 768 | NOCHG: | ||
| 769 | STOSB | ||
| 770 | INC BX | ||
| 771 | LOOP NEWNAM | ||
| 772 | MOV BYTE PTR [DI],6 ;Stop duplicates with any attributes | ||
| 773 | CALL DEVNAME ;Check if giving it a device name | ||
| 774 | JNC RENERR | ||
| 775 | PUSH [LASTENT] ;Save position of match | ||
| 776 | MOV [LASTENT],-1 ;Search entire directory for duplicate | ||
| 777 | CALL CONTSRCH ;See if new name already exists | ||
| 778 | POP AX | ||
| 779 | JNC RENERR ;Error if found | ||
| 780 | CALL GETENT ;Re-read matching entry | ||
| 781 | MOV DI,BX | ||
| 782 | MOV SI,OFFSET DOSGROUP:NAME1 | ||
| 783 | MOV CX,5 | ||
| 784 | MOVSB | ||
| 785 | REP MOVSW ;Replace old name with new one | ||
| 786 | MOV BYTE PTR [DIRTYDIR],-1 ;Flag change in directory | ||
| 787 | MOV SI,OFFSET DOSGROUP:NAME3 | ||
| 788 | MOV DI,OFFSET DOSGROUP:NAME1 | ||
| 789 | MOV CX,6 ;Include attribute byte | ||
| 790 | REP MOVSW ;Copy name back into search buffer | ||
| 791 | CALL CONTSRCH | ||
| 792 | JNC RENFIL | ||
| 793 | CALL CHKDIRWRITE | ||
| 794 | XOR AL,AL | ||
| 795 | RET | ||
| 796 | |||
| 797 | RENERR: | ||
| 798 | CALL CHKDIRWRITE | ||
| 799 | ERRET: | ||
| 800 | MOV AL,-1 | ||
| 801 | RET5: RET | ||
| 802 | |||
| 803 | |||
| 804 | MOVNAME: | ||
| 805 | |||
| 806 | ; Inputs: | ||
| 807 | ; DS, DX point to FCB or extended FCB | ||
| 808 | ; Outputs: | ||
| 809 | ; DS:DX point to normal FCB | ||
| 810 | ; ES = CS | ||
| 811 | ; If file name OK: | ||
| 812 | ; BP has base of driver parameters | ||
| 813 | ; [NAME1] has name in upper case | ||
| 814 | ; All registers except DX destroyed | ||
| 815 | ; Carry set if bad file name or drive | ||
| 816 | |||
| 817 | MOV CS:WORD PTR [CREATING],0E500H ;Not creating, not DEL *.* | ||
| 818 | MOV AX,CS | ||
| 819 | MOV ES,AX | ||
| 820 | MOV DI,OFFSET DOSGROUP:NAME1 | ||
| 821 | MOV SI,DX | ||
| 822 | LODSB | ||
| 823 | MOV CS:[EXTFCB],AL ;Set flag if extended FCB in use | ||
| 824 | MOV AH,0 ;Set default attributes | ||
| 825 | CMP AL,-1 ;Is it an extended FCB? | ||
| 826 | JNZ HAVATTRB | ||
| 827 | ADD DX,7 ;Adjust to point to normal FCB | ||
| 828 | ADD SI,6 ;Point to drive select byte | ||
| 829 | MOV AH,[SI-1] ;Get attribute byte | ||
| 830 | LODSB ;Get drive select byte | ||
| 831 | HAVATTRB: | ||
| 832 | MOV CS:[ATTRIB],AH ;Save attributes | ||
| 833 | CALL GETTHISDRV | ||
| 834 | LODNAME: | ||
| 835 | ; This entry point copies a file name from DS,SI | ||
| 836 | ; to ES,DI converting to upper case. | ||
| 837 | CMP BYTE PTR [SI]," " ;Don't allow blank as first letter | ||
| 838 | STC ;In case of error | ||
| 839 | JZ RET5 | ||
| 840 | MOV CX,11 | ||
| 841 | MOVCHK: | ||
| 842 | CALL GETLET | ||
| 843 | JB RET5 | ||
| 844 | JNZ STOLET ;Is it a delimiter? | ||
| 845 | CMP AL," " ;This is the only delimiter allowed | ||
| 846 | STC ;In case of error | ||
| 847 | JNZ RET5 | ||
| 848 | STOLET: | ||
| 849 | STOSB | ||
| 850 | LOOP MOVCHK | ||
| 851 | CLC ;Got through whole name - no error | ||
| 852 | RET6: RET | ||
| 853 | |||
| 854 | GETTHISDRV: | ||
| 855 | CMP CS:[NUMDRV],AL | ||
| 856 | JC RET6 | ||
| 857 | DEC AL | ||
| 858 | JNS PHYDRV | ||
| 859 | MOV AL,CS:[CURDRV] | ||
| 860 | PHYDRV: | ||
| 861 | MOV CS:[THISDRV],AL | ||
| 862 | RET | ||
| 863 | |||
| 864 | |||
| 865 | OPEN: ;System call 15 | ||
| 866 | CALL GETFILE | ||
| 867 | DOOPEN: | ||
| 868 | ; Enter here to perform OPEN on file already found | ||
| 869 | ; in directory. DS=CS, BX points to directory | ||
| 870 | ; entry in DIRBUF, SI points to First Cluster field, and | ||
| 871 | ; ES:DI point to the FCB to be opened. This entry point | ||
| 872 | ; is used by CREATE. | ||
| 873 | JC ERRET | ||
| 874 | OR BH,BH ;Check if file is I/O device | ||
| 875 | JS OPENDEV ;Special handler if so | ||
| 876 | MOV AL,[THISDRV] | ||
| 877 | INC AX | ||
| 878 | STOSB | ||
| 879 | XOR AX,AX | ||
| 880 | IF ZEROEXT | ||
| 881 | ADD DI,11 | ||
| 882 | STOSW ;Zero low byte of extent field if IBM only | ||
| 883 | ENDIF | ||
| 884 | IF NOT ZEROEXT | ||
| 885 | ADD DI,12 ;Point to high half of CURRENT BLOCK field | ||
| 886 | STOSB ;Set it to zero (CP/M programs set low byte) | ||
| 887 | ENDIF | ||
| 888 | MOV AL,128 ;Default record size | ||
| 889 | STOSW ;Set record size | ||
| 890 | LODSW ;Get starting cluster | ||
| 891 | MOV DX,AX ;Save it for the moment | ||
| 892 | MOVSW ;Transfer size to FCB | ||
| 893 | MOVSW | ||
| 894 | MOV AX,[SI-8] ;Get date | ||
| 895 | STOSW ;Save date in FCB | ||
| 896 | MOV AX,[SI-10] ;Get time | ||
| 897 | STOSW ;Save it in FCB | ||
| 898 | MOV AL,[BP.DEVNUM] | ||
| 899 | OR AL,40H | ||
| 900 | STOSB | ||
| 901 | MOV AX,DX ;Restore starting cluster | ||
| 902 | STOSW ; first cluster | ||
| 903 | STOSW ; last cluster accessed | ||
| 904 | XOR AX,AX | ||
| 905 | STOSW ; position of last cluster | ||
| 906 | RET | ||
| 907 | |||
| 908 | |||
| 909 | OPENDEV: | ||
| 910 | ADD DI,13 ;point to 2nd half of extent field | ||
| 911 | XOR AX,AX | ||
| 912 | STOSB ;Set it to zero | ||
| 913 | MOV AL,128 | ||
| 914 | STOSW ;Set record size to 128 | ||
| 915 | XOR AX,AX | ||
| 916 | STOSW | ||
| 917 | STOSW ;Set current size to zero | ||
| 918 | CALL DATE16 | ||
| 919 | STOSW ;Date is todays | ||
| 920 | XCHG AX,DX | ||
| 921 | STOSW ;Use current time | ||
| 922 | MOV AL,BH ;Get device number | ||
| 923 | STOSB | ||
| 924 | XOR AL,AL ;No error | ||
| 925 | RET | ||
| 926 | FATERR: | ||
| 927 | XCHG AX,DI ;Put error code in DI | ||
| 928 | MOV AH,2 ;While trying to read FAT | ||
| 929 | MOV AL,[THISDRV] ;Tell which drive | ||
| 930 | CALL FATAL1 | ||
| 931 | JMP SHORT FATREAD | ||
| 932 | STARTSRCH: | ||
| 933 | MOV AX,-1 | ||
| 934 | MOV [LASTENT],AX | ||
| 935 | MOV [ENTFREE],AX | ||
| 936 | FATREAD: | ||
| 937 | |||
| 938 | ; Inputs: | ||
| 939 | ; DS = CS | ||
| 940 | ; Function: | ||
| 941 | ; If disk may have been changed, FAT is read in and buffers are | ||
| 942 | ; flagged invalid. If not, no action is taken. | ||
| 943 | ; Outputs: | ||
| 944 | ; BP = Base of drive parameters | ||
| 945 | ; Carry set if invalid drive returned by MAPDEV | ||
| 946 | ; All other registers destroyed | ||
| 947 | |||
| 948 | MOV AL,[THISDRV] | ||
| 949 | XOR AH,AH ;Set default response to zero & clear carry | ||
| 950 | CALL FAR PTR BIOSDSKCHG ;See what BIOS has to say | ||
| 951 | JC FATERR | ||
| 952 | CALL GETBP | ||
| 953 | MOV AL,[THISDRV] ;Use physical unit number | ||
| 954 | MOV SI,[BP.FAT] | ||
| 955 | OR AH,[SI-1] ;Dirty byte for FAT | ||
| 956 | JS NEWDSK ;If either say new disk, then it's so | ||
| 957 | JNZ MAPDRV | ||
| 958 | MOV AH,1 | ||
| 959 | CMP AX,WORD PTR [BUFDRVNO] ;Does buffer have dirty sector of this drive? | ||
| 960 | JZ MAPDRV | ||
| 961 | NEWDSK: | ||
| 962 | CMP AL,[BUFDRVNO] ;See if buffer is for this drive | ||
| 963 | JNZ BUFOK ;If not, don't touch it | ||
| 964 | MOV [BUFSECNO],0 ;Flag buffers invalid | ||
| 965 | MOV WORD PTR [BUFDRVNO],00FFH | ||
| 966 | BUFOK: | ||
| 967 | MOV [DIRBUFID],-1 | ||
| 968 | CALL FIGFAT | ||
| 969 | NEXTFAT: | ||
| 970 | PUSH AX | ||
| 971 | CALL DSKREAD | ||
| 972 | POP AX | ||
| 973 | JC BADFAT | ||
| 974 | SUB AL,[BP.FATCNT] | ||
| 975 | JZ NEWFAT | ||
| 976 | CALL FATWRT | ||
| 977 | NEWFAT: | ||
| 978 | MOV SI,[BP.FAT] | ||
| 979 | MOV AL,[BP.DEVNUM] | ||
| 980 | MOV AH,[SI] ;Get first byte of FAT | ||
| 981 | OR AH,0F8H ;Put in range | ||
| 982 | CALL FAR PTR BIOSMAPDEV | ||
| 983 | MOV AH,0 | ||
| 984 | MOV [SI-2],AX ;Set device no. and reset dirty bit | ||
| 985 | MAPDRV: | ||
| 986 | MOV AL,[SI-2] ;Get device number | ||
| 987 | GETBP: | ||
| 988 | MOV BP,[DRVTAB] ;Just in case drive isn't valid | ||
| 989 | AND AL,3FH ;Mask out dirty bit | ||
| 990 | CMP AL,[NUMIO] | ||
| 991 | CMC | ||
| 992 | JC RET7 | ||
| 993 | PUSH AX | ||
| 994 | MOV AH,DPBSIZ | ||
| 995 | MUL AH | ||
| 996 | ADD BP,AX | ||
| 997 | POP AX | ||
| 998 | RET7: RET | ||
| 999 | |||
| 1000 | BADFAT: | ||
| 1001 | MOV CX,DI | ||
| 1002 | ADD DX,CX | ||
| 1003 | DEC AL | ||
| 1004 | JNZ NEXTFAT | ||
| 1005 | CALL FIGFAT ;Reset registers | ||
| 1006 | CALL DREAD ;Try first FAT once more | ||
| 1007 | JMP SHORT NEWFAT | ||
| 1008 | |||
| 1009 | OKRET1: | ||
| 1010 | MOV AL,0 | ||
| 1011 | RET | ||
| 1012 | |||
| 1013 | CLOSE: ;System call 16 | ||
| 1014 | MOV DI,DX | ||
| 1015 | CMP BYTE PTR [DI],-1 ;Check for extended FCB | ||
| 1016 | JNZ NORMFCB3 | ||
| 1017 | ADD DI,7 | ||
| 1018 | NORMFCB3: | ||
| 1019 | TEST BYTE PTR [DI.DEVID],0C0H ;Allow only dirty files | ||
| 1020 | JNZ OKRET1 ;can't close if I/O device, or not writen | ||
| 1021 | MOV AL,[DI] ;Get physical unit number | ||
| 1022 | DEC AL ;Make zero = drive A | ||
| 1023 | MOV AH,1 ;Look for dirty buffer | ||
| 1024 | CMP AX,CS:WORD PTR [BUFDRVNO] | ||
| 1025 | JNZ FNDDIR | ||
| 1026 | ;Write back dirty buffer if on same drive | ||
| 1027 | PUSH DX | ||
| 1028 | PUSH DS | ||
| 1029 | PUSH CS | ||
| 1030 | POP DS | ||
| 1031 | MOV BYTE PTR [DIRTYBUF],0 | ||
| 1032 | MOV BX,[BUFFER] | ||
| 1033 | MOV CX,1 | ||
| 1034 | MOV DX,[BUFSECNO] | ||
| 1035 | MOV BP,[BUFDRVBP] | ||
| 1036 | CALL DWRITE | ||
| 1037 | POP DS | ||
| 1038 | POP DX | ||
| 1039 | FNDDIR: | ||
| 1040 | CALL GETFILE | ||
| 1041 | BADCLOSEJ: | ||
| 1042 | JC BADCLOSE | ||
| 1043 | MOV CX,ES:[DI.FIRCLUS] | ||
| 1044 | MOV [SI],CX | ||
| 1045 | MOV DX,ES:WORD PTR [DI.FILSIZ] | ||
| 1046 | MOV [SI+2],DX | ||
| 1047 | MOV DX,ES:WORD PTR [DI.FILSIZ+2] | ||
| 1048 | MOV [SI+4],DX | ||
| 1049 | MOV DX,ES:[DI.FDATE] | ||
| 1050 | MOV [SI-2],DX | ||
| 1051 | MOV DX,ES:[DI.FTIME] | ||
| 1052 | MOV [SI-4],DX | ||
| 1053 | CALL DIRWRITE | ||
| 1054 | |||
| 1055 | CHKFATWRT: | ||
| 1056 | ; Do FATWRT only if FAT is dirty and uses same I/O driver | ||
| 1057 | MOV SI,[BP.FAT] | ||
| 1058 | MOV AL,[BP.DEVNUM] | ||
| 1059 | MOV AH,1 | ||
| 1060 | CMP [SI-2],AX ;See if FAT dirty and uses same driver | ||
| 1061 | JNZ OKRET | ||
| 1062 | |||
| 1063 | FATWRT: | ||
| 1064 | |||
| 1065 | ; Inputs: | ||
| 1066 | ; DS = CS | ||
| 1067 | ; BP = Base of drive parameter table | ||
| 1068 | ; Function: | ||
| 1069 | ; Write the FAT back to disk and reset FAT | ||
| 1070 | ; dirty bit. | ||
| 1071 | ; Outputs: | ||
| 1072 | ; AL = 0 | ||
| 1073 | ; BP unchanged | ||
| 1074 | ; All other registers destroyed | ||
| 1075 | |||
| 1076 | CALL FIGFAT | ||
| 1077 | MOV BYTE PTR [BX-1],0 | ||
| 1078 | EACHFAT: | ||
| 1079 | PUSH DX | ||
| 1080 | PUSH CX | ||
| 1081 | PUSH BX | ||
| 1082 | PUSH AX | ||
| 1083 | CALL DWRITE | ||
| 1084 | POP AX | ||
| 1085 | POP BX | ||
| 1086 | POP CX | ||
| 1087 | POP DX | ||
| 1088 | ADD DX,CX | ||
| 1089 | DEC AL | ||
| 1090 | JNZ EACHFAT | ||
| 1091 | OKRET: | ||
| 1092 | MOV AL,0 | ||
| 1093 | RET | ||
| 1094 | |||
| 1095 | BADCLOSE: | ||
| 1096 | MOV SI,[BP.FAT] | ||
| 1097 | MOV BYTE PTR [SI-1],0 | ||
| 1098 | MOV AL,-1 | ||
| 1099 | RET | ||
| 1100 | |||
| 1101 | |||
| 1102 | FIGFAT: | ||
| 1103 | ; Loads registers with values needed to read or | ||
| 1104 | ; write a FAT. | ||
| 1105 | MOV AL,[BP.FATCNT] | ||
| 1106 | MOV BX,[BP.FAT] | ||
| 1107 | MOV CL,[BP.FATSIZ] ;No. of records occupied by FAT | ||
| 1108 | MOV CH,0 | ||
| 1109 | MOV DX,[BP.FIRFAT] ;Record number of start of FATs | ||
| 1110 | RET | ||
| 1111 | |||
| 1112 | |||
| 1113 | DIRCOMP: | ||
| 1114 | ; Prepare registers for directory read or write | ||
| 1115 | CBW | ||
| 1116 | ADD AX,[BP.FIRDIR] | ||
| 1117 | MOV DX,AX | ||
| 1118 | MOV BX,OFFSET DOSGROUP:DIRBUF | ||
| 1119 | MOV CX,1 | ||
| 1120 | RET | ||
| 1121 | |||
| 1122 | |||
| 1123 | CREATE: ;System call 22 | ||
| 1124 | CALL MOVNAME | ||
| 1125 | JC ERRET3 | ||
| 1126 | MOV DI,OFFSET DOSGROUP:NAME1 | ||
| 1127 | MOV CX,11 | ||
| 1128 | MOV AL,"?" | ||
| 1129 | REPNE SCASB | ||
| 1130 | JZ ERRET3 | ||
| 1131 | MOV CS:BYTE PTR [CREATING],-1 | ||
| 1132 | PUSH DX | ||
| 1133 | PUSH DS | ||
| 1134 | CALL FINDNAME | ||
| 1135 | JNC EXISTENT | ||
| 1136 | MOV AX,[ENTFREE] ;First free entry found in FINDNAME | ||
| 1137 | CMP AX,-1 | ||
| 1138 | JZ ERRPOP | ||
| 1139 | CALL GETENT ;Point at that free entry | ||
| 1140 | JMP SHORT FREESPOT | ||
| 1141 | ERRPOP: | ||
| 1142 | POP DS | ||
| 1143 | POP DX | ||
| 1144 | ERRET3: | ||
| 1145 | MOV AL,-1 | ||
| 1146 | RET | ||
| 1147 | |||
| 1148 | EXISTENT: | ||
| 1149 | JNZ ERRPOP ;Error if attributes don't match | ||
| 1150 | OR BH,BH ;Check if file is I/O device | ||
| 1151 | JS OPENJMP ;If so, no action | ||
| 1152 | MOV CX,[SI] ;Get pointer to clusters | ||
| 1153 | JCXZ FREESPOT | ||
| 1154 | CMP CX,[BP.MAXCLUS] | ||
| 1155 | JA FREESPOT | ||
| 1156 | PUSH BX | ||
| 1157 | MOV BX,CX | ||
| 1158 | MOV SI,[BP.FAT] | ||
| 1159 | CALL RELEASE ;Free any data already allocated | ||
| 1160 | CALL FATWRT | ||
| 1161 | POP BX | ||
| 1162 | FREESPOT: | ||
| 1163 | MOV DI,BX | ||
| 1164 | MOV SI,OFFSET DOSGROUP:NAME1 | ||
| 1165 | MOV CX,5 | ||
| 1166 | MOVSB | ||
| 1167 | REP MOVSW | ||
| 1168 | MOV AL,[ATTRIB] | ||
| 1169 | STOSB | ||
| 1170 | XOR AX,AX | ||
| 1171 | MOV CL,5 | ||
| 1172 | REP STOSW | ||
| 1173 | CALL DATE16 | ||
| 1174 | XCHG AX,DX | ||
| 1175 | STOSW | ||
| 1176 | XCHG AX,DX | ||
| 1177 | STOSW | ||
| 1178 | XOR AX,AX | ||
| 1179 | PUSH DI | ||
| 1180 | MOV CL,6 | ||
| 1181 | SMALLENT: | ||
| 1182 | REP STOSB | ||
| 1183 | PUSH BX | ||
| 1184 | CALL DIRWRITE | ||
| 1185 | POP BX | ||
| 1186 | POP SI | ||
| 1187 | OPENJMP: | ||
| 1188 | CLC ;Clear carry so OPEN won't fail | ||
| 1189 | POP ES | ||
| 1190 | POP DI | ||
| 1191 | JMP DOOPEN | ||
| 1192 | |||
| 1193 | |||
| 1194 | DIRREAD: | ||
| 1195 | |||
| 1196 | ; Inputs: | ||
| 1197 | ; DS = CS | ||
| 1198 | ; AL = Directory block number | ||
| 1199 | ; BP = Base of drive parameters | ||
| 1200 | ; Function: | ||
| 1201 | ; Read the directory block into DIRBUF. | ||
| 1202 | ; Outputs: | ||
| 1203 | ; AX,BP unchanged | ||
| 1204 | ; All other registers destroyed. | ||
| 1205 | |||
| 1206 | PUSH AX | ||
| 1207 | CALL CHKDIRWRITE | ||
| 1208 | POP AX | ||
| 1209 | PUSH AX | ||
| 1210 | MOV AH,[BP.DEVNUM] | ||
| 1211 | MOV [DIRBUFID],AX | ||
| 1212 | CALL DIRCOMP | ||
| 1213 | CALL DREAD | ||
| 1214 | POP AX | ||
| 1215 | RET8: RET | ||
| 1216 | |||
| 1217 | |||
| 1218 | DREAD: | ||
| 1219 | |||
| 1220 | ; Inputs: | ||
| 1221 | ; BX,DS = Transfer address | ||
| 1222 | ; CX = Number of sectors | ||
| 1223 | ; DX = Absolute record number | ||
| 1224 | ; BP = Base of drive parameters | ||
| 1225 | ; Function: | ||
| 1226 | ; Calls BIOS to perform disk read. If BIOS reports | ||
| 1227 | ; errors, will call HARDERR for further action. | ||
| 1228 | ; BP preserved. All other registers destroyed. | ||
| 1229 | |||
| 1230 | CALL DSKREAD | ||
| 1231 | JNC RET8 | ||
| 1232 | MOV CS:BYTE PTR [READOP],0 | ||
| 1233 | CALL HARDERR | ||
| 1234 | CMP AL,1 ;Check for retry | ||
| 1235 | JZ DREAD | ||
| 1236 | RET ;Ignore otherwise | ||
| 1237 | |||
| 1238 | |||
| 1239 | HARDERR: | ||
| 1240 | |||
| 1241 | ;Hard disk error handler. Entry conditions: | ||
| 1242 | ; DS:BX = Original disk transfer address | ||
| 1243 | ; DX = Original logical sector number | ||
| 1244 | ; CX = Number of sectors to go (first one gave the error) | ||
| 1245 | ; AX = Hardware error code | ||
| 1246 | ; DI = Original sector transfer count | ||
| 1247 | ; BP = Base of drive parameters | ||
| 1248 | ; [READOP] = 0 for read, 1 for write | ||
| 1249 | |||
| 1250 | XCHG AX,DI ;Error code in DI, count in AX | ||
| 1251 | SUB AX,CX ;Number of sectors successfully transferred | ||
| 1252 | ADD DX,AX ;First sector number to retry | ||
| 1253 | PUSH DX | ||
| 1254 | MUL [BP.SECSIZ] ;Number of bytes transferred | ||
| 1255 | POP DX | ||
| 1256 | ADD BX,AX ;First address for retry | ||
| 1257 | MOV AH,0 ;Flag disk section in error | ||
| 1258 | CMP DX,[BP.FIRFAT] ;In reserved area? | ||
| 1259 | JB ERRINT | ||
| 1260 | INC AH ;Flag for FAT | ||
| 1261 | CMP DX,[BP.FIRDIR] ;In FAT? | ||
| 1262 | JB ERRINT | ||
| 1263 | INC AH | ||
| 1264 | CMP DX,[BP.FIRREC] ;In directory? | ||
| 1265 | JB ERRINT | ||
| 1266 | INC AH ;Must be in data area | ||
| 1267 | ERRINT: | ||
| 1268 | SHL AH,1 ;Make room for read/write bit | ||
| 1269 | OR AH,CS:[READOP] | ||
| 1270 | FATAL: | ||
| 1271 | MOV AL,[BP.DRVNUM] ;Get drive number | ||
| 1272 | FATAL1: | ||
| 1273 | PUSH BP ;The only thing we preserve | ||
| 1274 | MOV CS:[CONTSTK],SP | ||
| 1275 | CLI ;Prepare to play with stack | ||
| 1276 | MOV SS,CS:[SSSAVE] | ||
| 1277 | MOV SP,CS:[SPSAVE] ;User stack pointer restored | ||
| 1278 | INT 24H ;Fatal error interrupt vector | ||
| 1279 | MOV CS:[SPSAVE],SP | ||
| 1280 | MOV CS:[SSSAVE],SS | ||
| 1281 | MOV SP,CS | ||
| 1282 | MOV SS,SP | ||
| 1283 | MOV SP,CS:[CONTSTK] | ||
| 1284 | STI | ||
| 1285 | POP BP | ||
| 1286 | CMP AL,2 | ||
| 1287 | JZ ERROR | ||
| 1288 | RET | ||
| 1289 | |||
| 1290 | DSKREAD: | ||
| 1291 | MOV AL,[BP.DEVNUM] | ||
| 1292 | PUSH BP | ||
| 1293 | PUSH BX | ||
| 1294 | PUSH CX | ||
| 1295 | PUSH DX | ||
| 1296 | CALL FAR PTR BIOSREAD | ||
| 1297 | POP DX | ||
| 1298 | POP DI | ||
| 1299 | POP BX | ||
| 1300 | POP BP | ||
| 1301 | RET9: RET | ||
| 1302 | |||
| 1303 | |||
| 1304 | CHKDIRWRITE: | ||
| 1305 | TEST BYTE PTR [DIRTYDIR],-1 | ||
| 1306 | JZ RET9 | ||
| 1307 | |||
| 1308 | DIRWRITE: | ||
| 1309 | |||
| 1310 | ; Inputs: | ||
| 1311 | ; DS = CS | ||
| 1312 | ; AL = Directory block number | ||
| 1313 | ; BP = Base of drive parameters | ||
| 1314 | ; Function: | ||
| 1315 | ; Write the directory block into DIRBUF. | ||
| 1316 | ; Outputs: | ||
| 1317 | ; BP unchanged | ||
| 1318 | ; All other registers destroyed. | ||
| 1319 | |||
| 1320 | MOV BYTE PTR [DIRTYDIR],0 | ||
| 1321 | MOV AL,BYTE PTR [DIRBUFID] | ||
| 1322 | CALL DIRCOMP | ||
| 1323 | |||
| 1324 | |||
| 1325 | DWRITE: | ||
| 1326 | |||
| 1327 | ; Inputs: | ||
| 1328 | ; BX,DS = Transfer address | ||
| 1329 | ; CX = Number of sectors | ||
| 1330 | ; DX = Absolute record number | ||
| 1331 | ; BP = Base of drive parameters | ||
| 1332 | ; Function: | ||
| 1333 | ; Calls BIOS to perform disk write. If BIOS reports | ||
| 1334 | ; errors, will call HARDERR for further action. | ||
| 1335 | ; BP preserved. All other registers destroyed. | ||
| 1336 | |||
| 1337 | MOV AL,[BP.DEVNUM] | ||
| 1338 | MOV AH,CS:VERFLG | ||
| 1339 | PUSH BP | ||
| 1340 | PUSH BX | ||
| 1341 | PUSH CX | ||
| 1342 | PUSH DX | ||
| 1343 | CALL FAR PTR BIOSWRITE | ||
| 1344 | POP DX | ||
| 1345 | POP DI | ||
| 1346 | POP BX | ||
| 1347 | POP BP | ||
| 1348 | JNC RET9 | ||
| 1349 | MOV CS:BYTE PTR [READOP],1 | ||
| 1350 | CALL HARDERR | ||
| 1351 | CMP AL,1 ;Check for retry | ||
| 1352 | JZ DWRITE | ||
| 1353 | RET | ||
| 1354 | |||
| 1355 | |||
| 1356 | ABORT: | ||
| 1357 | LDS SI,CS:DWORD PTR [SPSAVE] | ||
| 1358 | MOV DS,[SI.CSSAVE] | ||
| 1359 | XOR AX,AX | ||
| 1360 | MOV ES,AX | ||
| 1361 | MOV SI,SAVEXIT | ||
| 1362 | MOV DI,EXIT | ||
| 1363 | MOVSW | ||
| 1364 | MOVSW | ||
| 1365 | MOVSW | ||
| 1366 | MOVSW | ||
| 1367 | MOVSW | ||
| 1368 | MOVSW | ||
| 1369 | ERROR: | ||
| 1370 | MOV AX,CS | ||
| 1371 | MOV DS,AX | ||
| 1372 | MOV ES,AX | ||
| 1373 | CALL WRTFATS | ||
| 1374 | XOR AX,AX | ||
| 1375 | CLI | ||
| 1376 | MOV SS,[SSSAVE] | ||
| 1377 | MOV SP,[SPSAVE] | ||
| 1378 | MOV DS,AX | ||
| 1379 | MOV SI,EXIT | ||
| 1380 | MOV DI,OFFSET DOSGROUP:EXITHOLD | ||
| 1381 | MOVSW | ||
| 1382 | MOVSW | ||
| 1383 | POP AX | ||
| 1384 | POP BX | ||
| 1385 | POP CX | ||
| 1386 | POP DX | ||
| 1387 | POP SI | ||
| 1388 | POP DI | ||
| 1389 | POP BP | ||
| 1390 | POP DS | ||
| 1391 | POP ES | ||
| 1392 | STI ;Stack OK now | ||
| 1393 | JMP CS:DWORD PTR [EXITHOLD] | ||
| 1394 | |||
| 1395 | |||
| 1396 | SEQRD: ;System call 20 | ||
| 1397 | CALL GETREC | ||
| 1398 | CALL LOAD | ||
| 1399 | JMP SHORT FINSEQ | ||
| 1400 | |||
| 1401 | SEQWRT: ;System call 21 | ||
| 1402 | CALL GETREC | ||
| 1403 | CALL STORE | ||
| 1404 | FINSEQ: | ||
| 1405 | JCXZ SETNREX | ||
| 1406 | ADD AX,1 | ||
| 1407 | ADC DX,0 | ||
| 1408 | JMP SHORT SETNREX | ||
| 1409 | |||
| 1410 | RNDRD: ;System call 33 | ||
| 1411 | CALL GETRRPOS1 | ||
| 1412 | CALL LOAD | ||
| 1413 | JMP SHORT FINRND | ||
| 1414 | |||
| 1415 | RNDWRT: ;System call 34 | ||
| 1416 | CALL GETRRPOS1 | ||
| 1417 | CALL STORE | ||
| 1418 | JMP SHORT FINRND | ||
| 1419 | |||
| 1420 | BLKRD: ;System call 39 | ||
| 1421 | CALL GETRRPOS | ||
| 1422 | CALL LOAD | ||
| 1423 | JMP SHORT FINBLK | ||
| 1424 | |||
| 1425 | BLKWRT: ;System call 40 | ||
| 1426 | CALL GETRRPOS | ||
| 1427 | CALL STORE | ||
| 1428 | FINBLK: | ||
| 1429 | LDS SI,DWORD PTR [SPSAVE] | ||
| 1430 | MOV [SI.CXSAVE],CX | ||
| 1431 | JCXZ FINRND | ||
| 1432 | ADD AX,1 | ||
| 1433 | ADC DX,0 | ||
| 1434 | FINRND: | ||
| 1435 | MOV ES:WORD PTR [DI.RR],AX | ||
| 1436 | MOV ES:[DI.RR+2],DL | ||
| 1437 | OR DH,DH | ||
| 1438 | JZ SETNREX | ||
| 1439 | MOV ES:[DI.RR+3],DH ;Save 4 byte of RECPOS only if significant | ||
| 1440 | SETNREX: | ||
| 1441 | MOV CX,AX | ||
| 1442 | AND AL,7FH | ||
| 1443 | MOV ES:[DI.NR],AL | ||
| 1444 | AND CL,80H | ||
| 1445 | SHL CX,1 | ||
| 1446 | RCL DX,1 | ||
| 1447 | MOV AL,CH | ||
| 1448 | MOV AH,DL | ||
| 1449 | MOV ES:[DI.EXTENT],AX | ||
| 1450 | MOV AL,CS:[DSKERR] | ||
| 1451 | RET | ||
| 1452 | |||
| 1453 | GETRRPOS1: | ||
| 1454 | MOV CX,1 | ||
| 1455 | GETRRPOS: | ||
| 1456 | MOV DI,DX | ||
| 1457 | CMP BYTE PTR [DI],-1 | ||
| 1458 | JNZ NORMFCB1 | ||
| 1459 | ADD DI,7 | ||
| 1460 | NORMFCB1: | ||
| 1461 | MOV AX,WORD PTR [DI.RR] | ||
| 1462 | MOV DX,WORD PTR [DI.RR+2] | ||
| 1463 | RET | ||
| 1464 | |||
| 1465 | NOFILERR: | ||
| 1466 | XOR CX,CX | ||
| 1467 | MOV BYTE PTR [DSKERR],4 | ||
| 1468 | POP BX | ||
| 1469 | RET | ||
| 1470 | |||
| 1471 | SETUP: | ||
| 1472 | |||
| 1473 | ; Inputs: | ||
| 1474 | ; DS:DI point to FCB | ||
| 1475 | ; DX:AX = Record position in file of disk transfer | ||
| 1476 | ; CX = Record count | ||
| 1477 | ; Outputs: | ||
| 1478 | ; DS = CS | ||
| 1479 | ; ES:DI point to FCB | ||
| 1480 | ; BL = DEVID from FCB | ||
| 1481 | ; CX = No. of bytes to transfer | ||
| 1482 | ; BP = Base of drive parameters | ||
| 1483 | ; SI = FAT pointer | ||
| 1484 | ; [RECCNT] = Record count | ||
| 1485 | ; [RECPOS] = Record position in file | ||
| 1486 | ; [FCB] = DI | ||
| 1487 | ; [NEXTADD] = Displacement of disk transfer within segment | ||
| 1488 | ; [SECPOS] = Position of first sector | ||
| 1489 | ; [BYTPOS] = Byte position in file | ||
| 1490 | ; [BYTSECPOS] = Byte position in first sector | ||
| 1491 | ; [CLUSNUM] = First cluster | ||
| 1492 | ; [SECCLUSPOS] = Sector within first cluster | ||
| 1493 | ; [DSKERR] = 0 (no errors yet) | ||
| 1494 | ; [TRANS] = 0 (No transfers yet) | ||
| 1495 | ; [THISDRV] = Physical drive unit number | ||
| 1496 | ; If SETUP detects no records will be transfered, it returns 1 level up | ||
| 1497 | ; with CX = 0. | ||
| 1498 | |||
| 1499 | PUSH AX | ||
| 1500 | MOV AL,[DI] | ||
| 1501 | DEC AL | ||
| 1502 | MOV CS:[THISDRV],AL | ||
| 1503 | MOV AL,[DI.DEVID] | ||
| 1504 | MOV SI,[DI.RECSIZ] | ||
| 1505 | OR SI,SI | ||
| 1506 | JNZ HAVRECSIZ | ||
| 1507 | MOV SI,128 | ||
| 1508 | MOV [DI.RECSIZ],SI | ||
| 1509 | HAVRECSIZ: | ||
| 1510 | PUSH DS | ||
| 1511 | POP ES ;Set ES to DS | ||
| 1512 | PUSH CS | ||
| 1513 | POP DS ;Set DS to CS | ||
| 1514 | OR AL,AL ;Is it a device? | ||
| 1515 | JNS NOTDEVICE | ||
| 1516 | MOV AL,0 ;Fake in drive 0 so we can get SP | ||
| 1517 | NOTDEVICE: | ||
| 1518 | CALL GETBP | ||
| 1519 | POP AX | ||
| 1520 | JC NOFILERR | ||
| 1521 | CMP SI,64 ;Check if highest byte of RECPOS is significant | ||
| 1522 | JB SMALREC | ||
| 1523 | MOV DH,0 ;Ignore MSB if record >= 64 bytes | ||
| 1524 | SMALREC: | ||
| 1525 | MOV [RECCNT],CX | ||
| 1526 | MOV WORD PTR [RECPOS],AX | ||
| 1527 | MOV WORD PTR [RECPOS+2],DX | ||
| 1528 | MOV [FCB],DI | ||
| 1529 | MOV BX,[DMAADD] | ||
| 1530 | MOV [NEXTADD],BX | ||
| 1531 | MOV BYTE PTR [DSKERR],0 | ||
| 1532 | MOV BYTE PTR [TRANS],0 | ||
| 1533 | MOV BX,DX | ||
| 1534 | MUL SI | ||
| 1535 | MOV WORD PTR [BYTPOS],AX | ||
| 1536 | PUSH DX | ||
| 1537 | MOV AX,BX | ||
| 1538 | MUL SI | ||
| 1539 | POP BX | ||
| 1540 | ADD AX,BX | ||
| 1541 | ADC DX,0 ;Ripple carry | ||
| 1542 | JNZ EOFERR | ||
| 1543 | MOV WORD PTR [BYTPOS+2],AX | ||
| 1544 | MOV DX,AX | ||
| 1545 | MOV AX,WORD PTR [BYTPOS] | ||
| 1546 | MOV BX,[BP.SECSIZ] | ||
| 1547 | CMP DX,BX ;See if divide will overflow | ||
| 1548 | JNC EOFERR | ||
| 1549 | DIV BX | ||
| 1550 | MOV [SECPOS],AX | ||
| 1551 | MOV [BYTSECPOS],DX | ||
| 1552 | MOV DX,AX | ||
| 1553 | AND AL,[BP.CLUSMSK] | ||
| 1554 | MOV [SECCLUSPOS],AL | ||
| 1555 | MOV AX,CX ;Record count | ||
| 1556 | MOV CL,[BP.CLUSSHFT] | ||
| 1557 | SHR DX,CL | ||
| 1558 | MOV [CLUSNUM],DX | ||
| 1559 | MUL SI ;Multiply by bytes per record | ||
| 1560 | MOV CX,AX | ||
| 1561 | ADD AX,[DMAADD] ;See if it will fit in one segment | ||
| 1562 | ADC DX,0 | ||
| 1563 | JZ OK ;Must be less than 64K | ||
| 1564 | MOV AX,[DMAADD] | ||
| 1565 | NEG AX ;Amount of room left in segment | ||
| 1566 | JNZ PARTSEG ;All 64K available? | ||
| 1567 | DEC AX ;If so, reduce by one | ||
| 1568 | PARTSEG: | ||
| 1569 | XOR DX,DX | ||
| 1570 | DIV SI ;How many records will fit? | ||
| 1571 | MOV [RECCNT],AX | ||
| 1572 | MUL SI ;Translate that back into bytes | ||
| 1573 | MOV BYTE PTR [DSKERR],2 ;Flag that trimming took place | ||
| 1574 | MOV CX,AX | ||
| 1575 | JCXZ NOROOM | ||
| 1576 | OK: | ||
| 1577 | MOV BL,ES:[DI.DEVID] | ||
| 1578 | MOV SI,[BP.FAT] | ||
| 1579 | RET | ||
| 1580 | |||
| 1581 | EOFERR: | ||
| 1582 | MOV BYTE PTR [DSKERR],1 | ||
| 1583 | XOR CX,CX | ||
| 1584 | NOROOM: | ||
| 1585 | POP BX ;Kill return address | ||
| 1586 | RET | ||
| 1587 | |||
| 1588 | BREAKDOWN: | ||
| 1589 | |||
| 1590 | ;Inputs: | ||
| 1591 | ; DS = CS | ||
| 1592 | ; CX = Length of disk transfer in bytes | ||
| 1593 | ; BP = Base of drive parameters | ||
| 1594 | ; [BYTSECPOS] = Byte position witin first sector | ||
| 1595 | ;Outputs: | ||
| 1596 | ; [BYTCNT1] = Bytes to transfer in first sector | ||
| 1597 | ; [SECCNT] = No. of whole sectors to transfer | ||
| 1598 | ; [BYTCNT2] = Bytes to transfer in last sector | ||
| 1599 | ;AX, BX, DX destroyed. No other registers affected. | ||
| 1600 | |||
| 1601 | MOV AX,[BYTSECPOS] | ||
| 1602 | MOV BX,CX | ||
| 1603 | OR AX,AX | ||
| 1604 | JZ SAVFIR ;Partial first sector? | ||
| 1605 | SUB AX,[BP.SECSIZ] | ||
| 1606 | NEG AX ;Max number of bytes left in first sector | ||
| 1607 | SUB BX,AX ;Subtract from total length | ||
| 1608 | JAE SAVFIR | ||
| 1609 | ADD AX,BX ;Don't use all of the rest of the sector | ||
| 1610 | XOR BX,BX ;And no bytes are left | ||
| 1611 | SAVFIR: | ||
| 1612 | MOV [BYTCNT1],AX | ||
| 1613 | MOV AX,BX | ||
| 1614 | XOR DX,DX | ||
| 1615 | DIV [BP.SECSIZ] ;How many whole sectors? | ||
| 1616 | MOV [SECCNT],AX | ||
| 1617 | MOV [BYTCNT2],DX ;Bytes remaining for last sector | ||
| 1618 | RET10: RET | ||
| 1619 | |||
| 1620 | |||
| 1621 | FNDCLUS: | ||
| 1622 | |||
| 1623 | ; Inputs: | ||
| 1624 | ; DS = CS | ||
| 1625 | ; CX = No. of clusters to skip | ||
| 1626 | ; BP = Base of drive parameters | ||
| 1627 | ; SI = FAT pointer | ||
| 1628 | ; ES:DI point to FCB | ||
| 1629 | ; Outputs: | ||
| 1630 | ; BX = Last cluster skipped to | ||
| 1631 | ; CX = No. of clusters remaining (0 unless EOF) | ||
| 1632 | ; DX = Position of last cluster | ||
| 1633 | ; DI destroyed. No other registers affected. | ||
| 1634 | |||
| 1635 | MOV BX,ES:[DI.LSTCLUS] | ||
| 1636 | MOV DX,ES:[DI.CLUSPOS] | ||
| 1637 | OR BX,BX | ||
| 1638 | JZ NOCLUS | ||
| 1639 | SUB CX,DX | ||
| 1640 | JNB FINDIT | ||
| 1641 | ADD CX,DX | ||
| 1642 | XOR DX,DX | ||
| 1643 | MOV BX,ES:[DI.FIRCLUS] | ||
| 1644 | FINDIT: | ||
| 1645 | JCXZ RET10 | ||
| 1646 | SKPCLP: | ||
| 1647 | CALL UNPACK | ||
| 1648 | CMP DI,0FF8H | ||
| 1649 | JAE RET10 | ||
| 1650 | XCHG BX,DI | ||
| 1651 | INC DX | ||
| 1652 | LOOP SKPCLP | ||
| 1653 | RET | ||
| 1654 | NOCLUS: | ||
| 1655 | INC CX | ||
| 1656 | DEC DX | ||
| 1657 | RET | ||
| 1658 | |||
| 1659 | |||
| 1660 | BUFSEC: | ||
| 1661 | ; Inputs: | ||
| 1662 | ; AL = 0 if buffer must be read, 1 if no pre-read needed | ||
| 1663 | ; BP = Base of drive parameters | ||
| 1664 | ; [CLUSNUM] = Physical cluster number | ||
| 1665 | ; [SECCLUSPOS] = Sector position of transfer within cluster | ||
| 1666 | ; [BYTCNT1] = Size of transfer | ||
| 1667 | ; Function: | ||
| 1668 | ; Insure specified sector is in buffer, flushing buffer before | ||
| 1669 | ; read if necessary. | ||
| 1670 | ; Outputs: | ||
| 1671 | ; SI = Pointer to buffer | ||
| 1672 | ; DI = Pointer to transfer address | ||
| 1673 | ; CX = Number of bytes | ||
| 1674 | ; [NEXTADD] updated | ||
| 1675 | ; [TRANS] set to indicate a transfer will occur | ||
| 1676 | |||
| 1677 | MOV DX,[CLUSNUM] | ||
| 1678 | MOV BL,[SECCLUSPOS] | ||
| 1679 | CALL FIGREC | ||
| 1680 | MOV [PREREAD],AL | ||
| 1681 | CMP DX,[BUFSECNO] | ||
| 1682 | JNZ GETSEC | ||
| 1683 | MOV AL,[BUFDRVNO] | ||
| 1684 | CMP AL,[THISDRV] | ||
| 1685 | JZ FINBUF ;Already have it? | ||
| 1686 | GETSEC: | ||
| 1687 | XOR AL,AL | ||
| 1688 | XCHG [DIRTYBUF],AL ;Read dirty flag and reset it | ||
| 1689 | OR AL,AL | ||
| 1690 | JZ RDSEC | ||
| 1691 | PUSH DX | ||
| 1692 | PUSH BP | ||
| 1693 | MOV BP,[BUFDRVBP] | ||
| 1694 | MOV BX,[BUFFER] | ||
| 1695 | MOV CX,1 | ||
| 1696 | MOV DX,[BUFSECNO] | ||
| 1697 | CALL DWRITE | ||
| 1698 | POP BP | ||
| 1699 | POP DX | ||
| 1700 | RDSEC: | ||
| 1701 | TEST BYTE PTR [PREREAD],-1 | ||
| 1702 | JNZ SETBUF | ||
| 1703 | XOR AX,AX | ||
| 1704 | MOV [BUFSECNO],AX ;Set buffer valid in case of disk error | ||
| 1705 | DEC AX | ||
| 1706 | MOV [BUFDRVNO],AL | ||
| 1707 | MOV BX,[BUFFER] | ||
| 1708 | MOV CX,1 | ||
| 1709 | PUSH DX | ||
| 1710 | CALL DREAD | ||
| 1711 | POP DX | ||
| 1712 | SETBUF: | ||
| 1713 | MOV [BUFSECNO],DX | ||
| 1714 | MOV AL,[THISDRV] | ||
| 1715 | MOV [BUFDRVNO],AL | ||
| 1716 | MOV [BUFDRVBP],BP | ||
| 1717 | FINBUF: | ||
| 1718 | MOV BYTE PTR [TRANS],1 ;A transfer is taking place | ||
| 1719 | MOV DI,[NEXTADD] | ||
| 1720 | MOV SI,DI | ||
| 1721 | MOV CX,[BYTCNT1] | ||
| 1722 | ADD SI,CX | ||
| 1723 | MOV [NEXTADD],SI | ||
| 1724 | MOV SI,[BUFFER] | ||
| 1725 | ADD SI,[BYTSECPOS] | ||
| 1726 | RET | ||
| 1727 | |||
| 1728 | BUFRD: | ||
| 1729 | XOR AL,AL ;Pre-read necessary | ||
| 1730 | CALL BUFSEC | ||
| 1731 | PUSH ES | ||
| 1732 | MOV ES,[DMAADD+2] | ||
| 1733 | SHR CX,1 | ||
| 1734 | JNC EVENRD | ||
| 1735 | MOVSB | ||
| 1736 | EVENRD: | ||
| 1737 | REP MOVSW | ||
| 1738 | POP ES | ||
| 1739 | RET | ||
| 1740 | |||
| 1741 | BUFWRT: | ||
| 1742 | MOV AX,[SECPOS] | ||
| 1743 | INC AX ;Set for next sector | ||
| 1744 | MOV [SECPOS],AX | ||
| 1745 | CMP AX,[VALSEC] ;Has sector been written before? | ||
| 1746 | MOV AL,1 | ||
| 1747 | JA NOREAD ;Skip preread if SECPOS>VALSEC | ||
| 1748 | MOV AL,0 | ||
| 1749 | NOREAD: | ||
| 1750 | CALL BUFSEC | ||
| 1751 | XCHG DI,SI | ||
| 1752 | PUSH DS | ||
| 1753 | PUSH ES | ||
| 1754 | PUSH CS | ||
| 1755 | POP ES | ||
| 1756 | MOV DS,[DMAADD+2] | ||
| 1757 | SHR CX,1 | ||
| 1758 | JNC EVENWRT | ||
| 1759 | MOVSB | ||
| 1760 | EVENWRT: | ||
| 1761 | REP MOVSW | ||
| 1762 | POP ES | ||
| 1763 | POP DS | ||
| 1764 | MOV BYTE PTR [DIRTYBUF],1 | ||
| 1765 | RET | ||
| 1766 | |||
| 1767 | NEXTSEC: | ||
| 1768 | TEST BYTE PTR [TRANS],-1 | ||
| 1769 | JZ CLRET | ||
| 1770 | MOV AL,[SECCLUSPOS] | ||
| 1771 | INC AL | ||
| 1772 | CMP AL,[BP.CLUSMSK] | ||
| 1773 | JBE SAVPOS | ||
| 1774 | MOV BX,[CLUSNUM] | ||
| 1775 | CMP BX,0FF8H | ||
| 1776 | JAE NONEXT | ||
| 1777 | MOV SI,[BP.FAT] | ||
| 1778 | CALL UNPACK | ||
| 1779 | MOV [CLUSNUM],DI | ||
| 1780 | INC [LASTPOS] | ||
| 1781 | MOV AL,0 | ||
| 1782 | SAVPOS: | ||
| 1783 | MOV [SECCLUSPOS],AL | ||
| 1784 | CLRET: | ||
| 1785 | CLC | ||
| 1786 | RET | ||
| 1787 | NONEXT: | ||
| 1788 | STC | ||
| 1789 | RET | ||
| 1790 | |||
| 1791 | TRANBUF: | ||
| 1792 | LODSB | ||
| 1793 | STOSB | ||
| 1794 | CMP AL,13 ;Check for carriage return | ||
| 1795 | JNZ NORMCH | ||
| 1796 | MOV BYTE PTR [SI],10 | ||
| 1797 | NORMCH: | ||
| 1798 | CMP AL,10 | ||
| 1799 | LOOPNZ TRANBUF | ||
| 1800 | JNZ ENDRDCON | ||
| 1801 | CALL OUT ;Transmit linefeed | ||
| 1802 | XOR SI,SI | ||
| 1803 | OR CX,CX | ||
| 1804 | JNZ GETBUF | ||
| 1805 | OR AL,1 ;Clear zero flag--not end of file | ||
| 1806 | ENDRDCON: | ||
| 1807 | MOV [CONTPOS],SI | ||
| 1808 | ENDRDDEV: | ||
| 1809 | MOV [NEXTADD],DI | ||
| 1810 | POP ES | ||
| 1811 | JNZ SETFCBJ ;Zero set if Ctrl-Z found in input | ||
| 1812 | MOV DI,[FCB] | ||
| 1813 | AND ES:BYTE PTR [DI.DEVID],0FFH-40H ;Mark as no more data available | ||
| 1814 | SETFCBJ: | ||
| 1815 | JMP SETFCB | ||
| 1816 | |||
| 1817 | READDEV: | ||
| 1818 | PUSH ES | ||
| 1819 | LES DI,DWORD PTR [DMAADD] | ||
| 1820 | INC BL | ||
| 1821 | JZ READCON | ||
| 1822 | INC BL | ||
| 1823 | JNZ ENDRDDEV | ||
| 1824 | READAUX: | ||
| 1825 | CALL AUXIN | ||
| 1826 | STOSB | ||
| 1827 | CMP AL,1AH | ||
| 1828 | LOOPNZ READAUX | ||
| 1829 | JMP SHORT ENDRDDEV | ||
| 1830 | |||
| 1831 | READCON: | ||
| 1832 | PUSH CS | ||
| 1833 | POP DS | ||
| 1834 | MOV SI,[CONTPOS] | ||
| 1835 | OR SI,SI | ||
| 1836 | JNZ TRANBUF | ||
| 1837 | CMP BYTE PTR [CONBUF],128 | ||
| 1838 | JZ GETBUF | ||
| 1839 | MOV WORD PTR [CONBUF],0FF80H ;Set up 128-byte buffer with no template | ||
| 1840 | GETBUF: | ||
| 1841 | PUSH CX | ||
| 1842 | PUSH ES | ||
| 1843 | PUSH DI | ||
| 1844 | MOV DX,OFFSET DOSGROUP:CONBUF | ||
| 1845 | CALL BUFIN ;Get input buffer | ||
| 1846 | POP DI | ||
| 1847 | POP ES | ||
| 1848 | POP CX | ||
| 1849 | MOV SI,2 + OFFSET DOSGROUP:CONBUF | ||
| 1850 | CMP BYTE PTR [SI],1AH ;Check for Ctrl-Z in first character | ||
| 1851 | JNZ TRANBUF | ||
| 1852 | MOV AL,1AH | ||
| 1853 | STOSB | ||
| 1854 | MOV AL,10 | ||
| 1855 | CALL OUT ;Send linefeed | ||
| 1856 | XOR SI,SI | ||
| 1857 | JMP SHORT ENDRDCON | ||
| 1858 | |||
| 1859 | RDERR: | ||
| 1860 | XOR CX,CX | ||
| 1861 | JMP WRTERR | ||
| 1862 | |||
| 1863 | RDLASTJ:JMP RDLAST | ||
| 1864 | |||
| 1865 | LOAD: | ||
| 1866 | |||
| 1867 | ; Inputs: | ||
| 1868 | ; DS:DI point to FCB | ||
| 1869 | ; DX:AX = Position in file to read | ||
| 1870 | ; CX = No. of records to read | ||
| 1871 | ; Outputs: | ||
| 1872 | ; DX:AX = Position of last record read | ||
| 1873 | ; CX = No. of bytes read | ||
| 1874 | ; ES:DI point to FCB | ||
| 1875 | ; LSTCLUS, CLUSPOS fields in FCB set | ||
| 1876 | |||
| 1877 | CALL SETUP | ||
| 1878 | OR BL,BL ;Check for named device I/O | ||
| 1879 | JS READDEV | ||
| 1880 | MOV AX,ES:WORD PTR [DI.FILSIZ] | ||
| 1881 | MOV BX,ES:WORD PTR [DI.FILSIZ+2] | ||
| 1882 | SUB AX,WORD PTR [BYTPOS] | ||
| 1883 | SBB BX,WORD PTR [BYTPOS+2] | ||
| 1884 | JB RDERR | ||
| 1885 | JNZ ENUF | ||
| 1886 | OR AX,AX | ||
| 1887 | JZ RDERR | ||
| 1888 | CMP AX,CX | ||
| 1889 | JAE ENUF | ||
| 1890 | MOV CX,AX | ||
| 1891 | ENUF: | ||
| 1892 | CALL BREAKDOWN | ||
| 1893 | MOV CX,[CLUSNUM] | ||
| 1894 | CALL FNDCLUS | ||
| 1895 | OR CX,CX | ||
| 1896 | JNZ RDERR | ||
| 1897 | MOV [LASTPOS],DX | ||
| 1898 | MOV [CLUSNUM],BX | ||
| 1899 | CMP [BYTCNT1],0 | ||
| 1900 | JZ RDMID | ||
| 1901 | CALL BUFRD | ||
| 1902 | RDMID: | ||
| 1903 | CMP [SECCNT],0 | ||
| 1904 | JZ RDLASTJ | ||
| 1905 | CALL NEXTSEC | ||
| 1906 | JC SETFCB | ||
| 1907 | MOV BYTE PTR [TRANS],1 ;A transfer is taking place | ||
| 1908 | ONSEC: | ||
| 1909 | MOV DL,[SECCLUSPOS] | ||
| 1910 | MOV CX,[SECCNT] | ||
| 1911 | MOV BX,[CLUSNUM] | ||
| 1912 | RDLP: | ||
| 1913 | CALL OPTIMIZE | ||
| 1914 | PUSH DI | ||
| 1915 | PUSH AX | ||
| 1916 | PUSH DS | ||
| 1917 | MOV DS,[DMAADD+2] | ||
| 1918 | PUSH DX | ||
| 1919 | PUSH BX | ||
| 1920 | PUSHF ;Save carry flag | ||
| 1921 | CALL DREAD | ||
| 1922 | POPF ;Restore carry flag | ||
| 1923 | POP DI ;Initial transfer address | ||
| 1924 | POP AX ;First sector transfered | ||
| 1925 | POP DS | ||
| 1926 | JC NOTBUFFED ;Was one of those sectors in the buffer? | ||
| 1927 | CMP BYTE PTR [DIRTYBUF],0 ;Is buffer dirty? | ||
| 1928 | JZ NOTBUFFED ;If not no problem | ||
| 1929 | ;We have transfered in a sector from disk when a dirty copy of it is in the buffer. | ||
| 1930 | ;We must transfer the sector from the buffer to correct memory address | ||
| 1931 | SUB AX,[BUFSECNO] ;How many sectors into the transfer? | ||
| 1932 | NEG AX | ||
| 1933 | MOV CX,[BP.SECSIZ] | ||
| 1934 | MUL CX ;How many bytes into the transfer? | ||
| 1935 | ADD DI,AX | ||
| 1936 | MOV SI,[BUFFER] | ||
| 1937 | PUSH ES | ||
| 1938 | MOV ES,[DMAADD+2] ;Get disk transfer segment | ||
| 1939 | SHR CX,1 | ||
| 1940 | REP MOVSW | ||
| 1941 | JNC EVENMOV | ||
| 1942 | MOVSB | ||
| 1943 | EVENMOV: | ||
| 1944 | POP ES | ||
| 1945 | NOTBUFFED: | ||
| 1946 | POP CX | ||
| 1947 | POP BX | ||
| 1948 | JCXZ RDLAST | ||
| 1949 | CMP BX,0FF8H | ||
| 1950 | JAE SETFCB | ||
| 1951 | MOV DL,0 | ||
| 1952 | INC [LASTPOS] ;We'll be using next cluster | ||
| 1953 | JMP SHORT RDLP | ||
| 1954 | |||
| 1955 | SETFCB: | ||
| 1956 | MOV SI,[FCB] | ||
| 1957 | MOV AX,[NEXTADD] | ||
| 1958 | MOV DI,AX | ||
| 1959 | SUB AX,[DMAADD] ;Number of bytes transfered | ||
| 1960 | XOR DX,DX | ||
| 1961 | MOV CX,ES:[SI.RECSIZ] | ||
| 1962 | DIV CX ;Number of records | ||
| 1963 | CMP AX,[RECCNT] ;Check if all records transferred | ||
| 1964 | JZ FULLREC | ||
| 1965 | MOV BYTE PTR [DSKERR],1 | ||
| 1966 | OR DX,DX | ||
| 1967 | JZ FULLREC ;If remainder 0, then full record transfered | ||
| 1968 | MOV BYTE PTR [DSKERR],3 ;Flag partial last record | ||
| 1969 | SUB CX,DX ;Bytes left in last record | ||
| 1970 | PUSH ES | ||
| 1971 | MOV ES,[DMAADD+2] | ||
| 1972 | XCHG AX,BX ;Save the record count temporarily | ||
| 1973 | XOR AX,AX ;Fill with zeros | ||
| 1974 | SHR CX,1 | ||
| 1975 | JNC EVENFIL | ||
| 1976 | STOSB | ||
| 1977 | EVENFIL: | ||
| 1978 | REP STOSW | ||
| 1979 | XCHG AX,BX ;Restore record count to AX | ||
| 1980 | POP ES | ||
| 1981 | INC AX ;Add last (partial) record to total | ||
| 1982 | FULLREC: | ||
| 1983 | MOV CX,AX | ||
| 1984 | MOV DI,SI ;ES:DI point to FCB | ||
| 1985 | SETCLUS: | ||
| 1986 | MOV AX,[CLUSNUM] | ||
| 1987 | MOV ES:[DI.LSTCLUS],AX | ||
| 1988 | MOV AX,[LASTPOS] | ||
| 1989 | MOV ES:[DI.CLUSPOS],AX | ||
| 1990 | ADDREC: | ||
| 1991 | MOV AX,WORD PTR [RECPOS] | ||
| 1992 | MOV DX,WORD PTR [RECPOS+2] | ||
| 1993 | JCXZ RET28 ;If no records read, don't change position | ||
| 1994 | DEC CX | ||
| 1995 | ADD AX,CX ;Update current record position | ||
| 1996 | ADC DX,0 | ||
| 1997 | INC CX | ||
| 1998 | RET28: RET | ||
| 1999 | |||
| 2000 | RDLAST: | ||
| 2001 | MOV AX,[BYTCNT2] | ||
| 2002 | OR AX,AX | ||
| 2003 | JZ SETFCB | ||
| 2004 | MOV [BYTCNT1],AX | ||
| 2005 | CALL NEXTSEC | ||
| 2006 | JC SETFCB | ||
| 2007 | MOV [BYTSECPOS],0 | ||
| 2008 | CALL BUFRD | ||
| 2009 | JMP SHORT SETFCB | ||
| 2010 | |||
| 2011 | WRTDEV: | ||
| 2012 | PUSH DS | ||
| 2013 | LDS SI,DWORD PTR [DMAADD] | ||
| 2014 | OR BL,40H | ||
| 2015 | INC BL | ||
| 2016 | JZ WRTCON | ||
| 2017 | INC BL | ||
| 2018 | JZ WRTAUX | ||
| 2019 | INC BL | ||
| 2020 | JZ ENDWRDEV ;Done if device is NUL | ||
| 2021 | WRTLST: | ||
| 2022 | LODSB | ||
| 2023 | CMP AL,1AH | ||
| 2024 | JZ ENDWRDEV | ||
| 2025 | CALL LISTOUT | ||
| 2026 | LOOP WRTLST | ||
| 2027 | JMP SHORT ENDWRDEV | ||
| 2028 | |||
| 2029 | WRTAUX: | ||
| 2030 | LODSB | ||
| 2031 | CALL AUXOUT | ||
| 2032 | CMP AL,1AH | ||
| 2033 | LOOPNZ WRTAUX | ||
| 2034 | JMP SHORT ENDWRDEV | ||
| 2035 | |||
| 2036 | WRTCON: | ||
| 2037 | LODSB | ||
| 2038 | CMP AL,1AH | ||
| 2039 | JZ ENDWRDEV | ||
| 2040 | CALL OUT | ||
| 2041 | LOOP WRTCON | ||
| 2042 | ENDWRDEV: | ||
| 2043 | POP DS | ||
| 2044 | MOV CX,[RECCNT] | ||
| 2045 | MOV DI,[FCB] | ||
| 2046 | JMP SHORT ADDREC | ||
| 2047 | |||
| 2048 | HAVSTART: | ||
| 2049 | MOV CX,AX | ||
| 2050 | CALL SKPCLP | ||
| 2051 | JCXZ DOWRTJ | ||
| 2052 | CALL ALLOCATE | ||
| 2053 | JNC DOWRTJ | ||
| 2054 | WRTERR: | ||
| 2055 | MOV BYTE PTR [DSKERR],1 | ||
| 2056 | LVDSK: | ||
| 2057 | MOV AX,WORD PTR [RECPOS] | ||
| 2058 | MOV DX,WORD PTR [RECPOS+2] | ||
| 2059 | MOV DI,[FCB] | ||
| 2060 | RET | ||
| 2061 | |||
| 2062 | DOWRTJ: JMP DOWRT | ||
| 2063 | |||
| 2064 | WRTEOFJ: | ||
| 2065 | JMP WRTEOF | ||
| 2066 | |||
| 2067 | STORE: | ||
| 2068 | |||
| 2069 | ; Inputs: | ||
| 2070 | ; DS:DI point to FCB | ||
| 2071 | ; DX:AX = Position in file of disk transfer | ||
| 2072 | ; CX = Record count | ||
| 2073 | ; Outputs: | ||
| 2074 | ; DX:AX = Position of last record written | ||
| 2075 | ; CX = No. of records written | ||
| 2076 | ; ES:DI point to FCB | ||
| 2077 | ; LSTCLUS, CLUSPOS fields in FCB set | ||
| 2078 | |||
| 2079 | CALL SETUP | ||
| 2080 | CALL DATE16 | ||
| 2081 | MOV ES:[DI.FDATE],AX | ||
| 2082 | MOV ES:[DI.FTIME],DX | ||
| 2083 | OR BL,BL | ||
| 2084 | JS WRTDEV | ||
| 2085 | AND BL,3FH ;Mark file as dirty | ||
| 2086 | MOV ES:[DI.DEVID],BL | ||
| 2087 | CALL BREAKDOWN | ||
| 2088 | MOV AX,WORD PTR [BYTPOS] | ||
| 2089 | MOV DX,WORD PTR [BYTPOS+2] | ||
| 2090 | JCXZ WRTEOFJ | ||
| 2091 | DEC CX | ||
| 2092 | ADD AX,CX | ||
| 2093 | ADC DX,0 ;AX:DX=last byte accessed | ||
| 2094 | DIV [BP.SECSIZ] ;AX=last sector accessed | ||
| 2095 | MOV CL,[BP.CLUSSHFT] | ||
| 2096 | SHR AX,CL ;Last cluster to be accessed | ||
| 2097 | PUSH AX | ||
| 2098 | MOV AX,ES:WORD PTR [DI.FILSIZ] | ||
| 2099 | MOV DX,ES:WORD PTR [DI.FILSIZ+2] | ||
| 2100 | DIV [BP.SECSIZ] | ||
| 2101 | OR DX,DX | ||
| 2102 | JZ NORNDUP | ||
| 2103 | INC AX ;Round up if any remainder | ||
| 2104 | NORNDUP: | ||
| 2105 | MOV [VALSEC],AX ;Number of sectors that have been written | ||
| 2106 | POP AX | ||
| 2107 | MOV CX,[CLUSNUM] ;First cluster accessed | ||
| 2108 | CALL FNDCLUS | ||
| 2109 | MOV [CLUSNUM],BX | ||
| 2110 | MOV [LASTPOS],DX | ||
| 2111 | SUB AX,DX ;Last cluster minus current cluster | ||
| 2112 | JZ DOWRT ;If we have last clus, we must have first | ||
| 2113 | JCXZ HAVSTART ;See if no more data | ||
| 2114 | PUSH CX ;No. of clusters short of first | ||
| 2115 | MOV CX,AX | ||
| 2116 | CALL ALLOCATE | ||
| 2117 | POP AX | ||
| 2118 | JC WRTERR | ||
| 2119 | MOV CX,AX | ||
| 2120 | MOV DX,[LASTPOS] | ||
| 2121 | INC DX | ||
| 2122 | DEC CX | ||
| 2123 | JZ NOSKIP | ||
| 2124 | CALL SKPCLP | ||
| 2125 | NOSKIP: | ||
| 2126 | MOV [CLUSNUM],BX | ||
| 2127 | MOV [LASTPOS],DX | ||
| 2128 | DOWRT: | ||
| 2129 | CMP [BYTCNT1],0 | ||
| 2130 | JZ WRTMID | ||
| 2131 | MOV BX,[CLUSNUM] | ||
| 2132 | CALL BUFWRT | ||
| 2133 | WRTMID: | ||
| 2134 | MOV AX,[SECCNT] | ||
| 2135 | OR AX,AX | ||
| 2136 | JZ WRTLAST | ||
| 2137 | ADD [SECPOS],AX | ||
| 2138 | CALL NEXTSEC | ||
| 2139 | MOV BYTE PTR [TRANS],1 ;A transfer is taking place | ||
| 2140 | MOV DL,[SECCLUSPOS] | ||
| 2141 | MOV BX,[CLUSNUM] | ||
| 2142 | MOV CX,[SECCNT] | ||
| 2143 | WRTLP: | ||
| 2144 | CALL OPTIMIZE | ||
| 2145 | JC NOTINBUF ;Is one of the sectors buffered? | ||
| 2146 | MOV [BUFSECNO],0 ;If so, invalidate the buffer since we're | ||
| 2147 | MOV WORD PTR [BUFDRVNO],0FFH ; completely rewritting it | ||
| 2148 | NOTINBUF: | ||
| 2149 | PUSH DI | ||
| 2150 | PUSH AX | ||
| 2151 | PUSH DS | ||
| 2152 | MOV DS,[DMAADD+2] | ||
| 2153 | CALL DWRITE | ||
| 2154 | POP DS | ||
| 2155 | POP CX | ||
| 2156 | POP BX | ||
| 2157 | JCXZ WRTLAST | ||
| 2158 | MOV DL,0 | ||
| 2159 | INC [LASTPOS] ;We'll be using next cluster | ||
| 2160 | JMP SHORT WRTLP | ||
| 2161 | WRTLAST: | ||
| 2162 | MOV AX,[BYTCNT2] | ||
| 2163 | OR AX,AX | ||
| 2164 | JZ FINWRT | ||
| 2165 | MOV [BYTCNT1],AX | ||
| 2166 | CALL NEXTSEC | ||
| 2167 | MOV [BYTSECPOS],0 | ||
| 2168 | CALL BUFWRT | ||
| 2169 | FINWRT: | ||
| 2170 | MOV AX,[NEXTADD] | ||
| 2171 | SUB AX,[DMAADD] | ||
| 2172 | ADD AX,WORD PTR [BYTPOS] | ||
| 2173 | MOV DX,WORD PTR [BYTPOS+2] | ||
| 2174 | ADC DX,0 | ||
| 2175 | MOV CX,DX | ||
| 2176 | MOV DI,[FCB] | ||
| 2177 | CMP AX,ES:WORD PTR [DI.FILSIZ] | ||
| 2178 | SBB CX,ES:WORD PTR [DI.FILSIZ+2] | ||
| 2179 | JB SAMSIZ | ||
| 2180 | MOV ES:WORD PTR [DI.FILSIZ],AX | ||
| 2181 | MOV ES:WORD PTR [DI.FILSIZ+2],DX | ||
| 2182 | SAMSIZ: | ||
| 2183 | MOV CX,[RECCNT] | ||
| 2184 | JMP SETCLUS | ||
| 2185 | |||
| 2186 | |||
| 2187 | WRTERRJ:JMP WRTERR | ||
| 2188 | |||
| 2189 | WRTEOF: | ||
| 2190 | MOV CX,AX | ||
| 2191 | OR CX,DX | ||
| 2192 | JZ KILLFIL | ||
| 2193 | SUB AX,1 | ||
| 2194 | SBB DX,0 | ||
| 2195 | DIV [BP.SECSIZ] | ||
| 2196 | MOV CL,[BP.CLUSSHFT] | ||
| 2197 | SHR AX,CL | ||
| 2198 | MOV CX,AX | ||
| 2199 | CALL FNDCLUS | ||
| 2200 | JCXZ RELFILE | ||
| 2201 | CALL ALLOCATE | ||
| 2202 | JC WRTERRJ | ||
| 2203 | UPDATE: | ||
| 2204 | MOV DI,[FCB] | ||
| 2205 | MOV AX,WORD PTR [BYTPOS] | ||
| 2206 | MOV ES:WORD PTR [DI.FILSIZ],AX | ||
| 2207 | MOV AX,WORD PTR [BYTPOS+2] | ||
| 2208 | MOV ES:WORD PTR [DI.FILSIZ+2],AX | ||
| 2209 | XOR CX,CX | ||
| 2210 | JMP ADDREC | ||
| 2211 | |||
| 2212 | RELFILE: | ||
| 2213 | MOV DX,0FFFH | ||
| 2214 | CALL RELBLKS | ||
| 2215 | SETDIRT: | ||
| 2216 | MOV BYTE PTR [SI-1],1 | ||
| 2217 | JMP SHORT UPDATE | ||
| 2218 | |||
| 2219 | KILLFIL: | ||
| 2220 | XOR BX,BX | ||
| 2221 | XCHG BX,ES:[DI.FIRCLUS] | ||
| 2222 | OR BX,BX | ||
| 2223 | JZ UPDATE | ||
| 2224 | CALL RELEASE | ||
| 2225 | JMP SHORT SETDIRT | ||
| 2226 | |||
| 2227 | |||
| 2228 | OPTIMIZE: | ||
| 2229 | |||
| 2230 | ; Inputs: | ||
| 2231 | ; DS = CS | ||
| 2232 | ; BX = Physical cluster | ||
| 2233 | ; CX = No. of records | ||
| 2234 | ; DL = sector within cluster | ||
| 2235 | ; BP = Base of drives parameters | ||
| 2236 | ; [NEXTADD] = transfer address | ||
| 2237 | ; Outputs: | ||
| 2238 | ; AX = No. of records remaining | ||
| 2239 | ; BX = Transfer address | ||
| 2240 | ; CX = No. or records to be transferred | ||
| 2241 | ; DX = Physical sector address | ||
| 2242 | ; DI = Next cluster | ||
| 2243 | ; Carry clear if a sector to transfer is in the buffer | ||
| 2244 | ; Carry set otherwise | ||
| 2245 | ; [CLUSNUM] = Last cluster accessed | ||
| 2246 | ; [NEXTADD] updated | ||
| 2247 | ; BP unchanged. Note that segment of transfer not set. | ||
| 2248 | |||
| 2249 | PUSH DX | ||
| 2250 | PUSH BX | ||
| 2251 | MOV AL,[BP.CLUSMSK] | ||
| 2252 | INC AL ;Number of sectors per cluster | ||
| 2253 | MOV AH,AL | ||
| 2254 | SUB AL,DL ;AL = Number of sectors left in first cluster | ||
| 2255 | MOV DX,CX | ||
| 2256 | MOV SI,[BP.FAT] | ||
| 2257 | MOV CX,0 | ||
| 2258 | OPTCLUS: | ||
| 2259 | ;AL has number of sectors available in current cluster | ||
| 2260 | ;AH has number of sectors available in next cluster | ||
| 2261 | ;BX has current physical cluster | ||
| 2262 | ;CX has number of sequential sectors found so far | ||
| 2263 | ;DX has number of sectors left to transfer | ||
| 2264 | ;SI has FAT pointer | ||
| 2265 | CALL UNPACK | ||
| 2266 | ADD CL,AL | ||
| 2267 | ADC CH,0 | ||
| 2268 | CMP CX,DX | ||
| 2269 | JAE BLKDON | ||
| 2270 | MOV AL,AH | ||
| 2271 | INC BX | ||
| 2272 | CMP DI,BX | ||
| 2273 | JZ OPTCLUS | ||
| 2274 | DEC BX | ||
| 2275 | FINCLUS: | ||
| 2276 | MOV [CLUSNUM],BX ;Last cluster accessed | ||
| 2277 | SUB DX,CX ;Number of sectors still needed | ||
| 2278 | PUSH DX | ||
| 2279 | MOV AX,CX | ||
| 2280 | MUL [BP.SECSIZ] ;Number of sectors times sector size | ||
| 2281 | MOV SI,[NEXTADD] | ||
| 2282 | ADD AX,SI ;Adjust by size of transfer | ||
| 2283 | MOV [NEXTADD],AX | ||
| 2284 | POP AX ;Number of sectors still needed | ||
| 2285 | POP DX ;Starting cluster | ||
| 2286 | SUB BX,DX ;Number of new clusters accessed | ||
| 2287 | ADD [LASTPOS],BX | ||
| 2288 | POP BX ;BL = sector postion within cluster | ||
| 2289 | CALL FIGREC | ||
| 2290 | MOV BX,SI | ||
| 2291 | ;Now let's see if any of these sectors are already in the buffer | ||
| 2292 | CMP [BUFSECNO],DX | ||
| 2293 | JC RET100 ;If DX > [BUFSECNO] then not in buffer | ||
| 2294 | MOV SI,DX | ||
| 2295 | ADD SI,CX ;Last sector + 1 | ||
| 2296 | CMP [BUFSECNO],SI | ||
| 2297 | CMC | ||
| 2298 | JC RET100 ;If SI <= [BUFSECNO] then not in buffer | ||
| 2299 | PUSH AX | ||
| 2300 | MOV AL,[BP.DEVNUM] | ||
| 2301 | CMP AL,[BUFDRVNO] ;Is buffer for this drive? | ||
| 2302 | POP AX | ||
| 2303 | JZ RET100 ;If so, then we match | ||
| 2304 | STC ;No match | ||
| 2305 | RET100: RET | ||
| 2306 | BLKDON: | ||
| 2307 | SUB CX,DX ;Number of sectors in cluster we don't want | ||
| 2308 | SUB AH,CL ;Number of sectors in cluster we accepted | ||
| 2309 | DEC AH ;Adjust to mean position within cluster | ||
| 2310 | MOV [SECCLUSPOS],AH | ||
| 2311 | MOV CX,DX ;Anyway, make the total equal to the request | ||
| 2312 | JMP SHORT FINCLUS | ||
| 2313 | |||
| 2314 | |||
| 2315 | FIGREC: | ||
| 2316 | |||
| 2317 | ;Inputs: | ||
| 2318 | ; DX = Physical cluster number | ||
| 2319 | ; BL = Sector postion within cluster | ||
| 2320 | ; BP = Base of drive parameters | ||
| 2321 | ;Outputs: | ||
| 2322 | ; DX = physical sector number | ||
| 2323 | ;No other registers affected. | ||
| 2324 | |||
| 2325 | PUSH CX | ||
| 2326 | MOV CL,[BP.CLUSSHFT] | ||
| 2327 | DEC DX | ||
| 2328 | DEC DX | ||
| 2329 | SHL DX,CL | ||
| 2330 | OR DL,BL | ||
| 2331 | ADD DX,[BP.FIRREC] | ||
| 2332 | POP CX | ||
| 2333 | RET | ||
| 2334 | |||
| 2335 | GETREC: | ||
| 2336 | |||
| 2337 | ; Inputs: | ||
| 2338 | ; DS:DX point to FCB | ||
| 2339 | ; Outputs: | ||
| 2340 | ; CX = 1 | ||
| 2341 | ; DX:AX = Record number determined by EXTENT and NR fields | ||
| 2342 | ; DS:DI point to FCB | ||
| 2343 | ; No other registers affected. | ||
| 2344 | |||
| 2345 | MOV DI,DX | ||
| 2346 | CMP BYTE PTR [DI],-1 ;Check for extended FCB | ||
| 2347 | JNZ NORMFCB2 | ||
| 2348 | ADD DI,7 | ||
| 2349 | NORMFCB2: | ||
| 2350 | MOV CX,1 | ||
| 2351 | MOV AL,[DI.NR] | ||
| 2352 | MOV DX,[DI.EXTENT] | ||
| 2353 | SHL AL,1 | ||
| 2354 | SHR DX,1 | ||
| 2355 | RCR AL,1 | ||
| 2356 | MOV AH,DL | ||
| 2357 | MOV DL,DH | ||
| 2358 | MOV DH,0 | ||
| 2359 | RET | ||
| 2360 | |||
| 2361 | |||
| 2362 | ALLOCATE: | ||
| 2363 | |||
| 2364 | ; Inputs: | ||
| 2365 | ; DS = CS | ||
| 2366 | ; ES = Segment of FCB | ||
| 2367 | ; BX = Last cluster of file (0 if null file) | ||
| 2368 | ; CX = No. of clusters to allocate | ||
| 2369 | ; DX = Position of cluster BX | ||
| 2370 | ; BP = Base of drive parameters | ||
| 2371 | ; SI = FAT pointer | ||
| 2372 | ; [FCB] = Displacement of FCB within segment | ||
| 2373 | ; Outputs: | ||
| 2374 | ; IF insufficient space | ||
| 2375 | ; THEN | ||
| 2376 | ; Carry set | ||
| 2377 | ; CX = max. no. of records that could be added to file | ||
| 2378 | ; ELSE | ||
| 2379 | ; Carry clear | ||
| 2380 | ; BX = First cluster allocated | ||
| 2381 | ; FAT is fully updated including dirty bit | ||
| 2382 | ; FIRCLUS field of FCB set if file was null | ||
| 2383 | ; SI,BP unchanged. All other registers destroyed. | ||
| 2384 | |||
| 2385 | PUSH [SI] | ||
| 2386 | PUSH DX | ||
| 2387 | PUSH CX | ||
| 2388 | PUSH BX | ||
| 2389 | MOV AX,BX | ||
| 2390 | ALLOC: | ||
| 2391 | MOV DX,BX | ||
| 2392 | FINDFRE: | ||
| 2393 | INC BX | ||
| 2394 | CMP BX,[BP.MAXCLUS] | ||
| 2395 | JLE TRYOUT | ||
| 2396 | CMP AX,1 | ||
| 2397 | JG TRYIN | ||
| 2398 | POP BX | ||
| 2399 | MOV DX,0FFFH | ||
| 2400 | CALL RELBLKS | ||
| 2401 | POP AX ;No. of clusters requested | ||
| 2402 | SUB AX,CX ;AX=No. of clusters allocated | ||
| 2403 | POP DX | ||
| 2404 | POP [SI] | ||
| 2405 | INC DX ;Position of first cluster allocated | ||
| 2406 | ADD AX,DX ;AX=max no. of cluster in file | ||
| 2407 | MOV DL,[BP.CLUSMSK] | ||
| 2408 | MOV DH,0 | ||
| 2409 | INC DX ;DX=records/cluster | ||
| 2410 | MUL DX ;AX=max no. of records in file | ||
| 2411 | MOV CX,AX | ||
| 2412 | SUB CX,WORD PTR [RECPOS] ;CX=max no. of records that could be written | ||
| 2413 | JA MAXREC | ||
| 2414 | XOR CX,CX ;If CX was negative, zero it | ||
| 2415 | MAXREC: | ||
| 2416 | STC | ||
| 2417 | RET11: RET | ||
| 2418 | |||
| 2419 | TRYOUT: | ||
| 2420 | CALL UNPACK | ||
| 2421 | JZ HAVFRE | ||
| 2422 | TRYIN: | ||
| 2423 | DEC AX | ||
| 2424 | JLE FINDFRE | ||
| 2425 | XCHG AX,BX | ||
| 2426 | CALL UNPACK | ||
| 2427 | JZ HAVFRE | ||
| 2428 | XCHG AX,BX | ||
| 2429 | JMP SHORT FINDFRE | ||
| 2430 | HAVFRE: | ||
| 2431 | XCHG BX,DX | ||
| 2432 | MOV AX,DX | ||
| 2433 | CALL PACK | ||
| 2434 | MOV BX,AX | ||
| 2435 | LOOP ALLOC | ||
| 2436 | MOV DX,0FFFH | ||
| 2437 | CALL PACK | ||
| 2438 | MOV BYTE PTR [SI-1],1 | ||
| 2439 | POP BX | ||
| 2440 | POP CX ;Don't need this stuff since we're successful | ||
| 2441 | POP DX | ||
| 2442 | CALL UNPACK | ||
| 2443 | POP [SI] | ||
| 2444 | XCHG BX,DI | ||
| 2445 | OR DI,DI | ||
| 2446 | JNZ RET11 | ||
| 2447 | MOV DI,[FCB] | ||
| 2448 | MOV ES:[DI.FIRCLUS],BX | ||
| 2449 | RET12: RET | ||
| 2450 | |||
| 2451 | |||
| 2452 | RELEASE: | ||
| 2453 | |||
| 2454 | ; Inputs: | ||
| 2455 | ; DS = CS | ||
| 2456 | ; BX = Cluster in file | ||
| 2457 | ; SI = FAT pointer | ||
| 2458 | ; BP = Base of drive parameters | ||
| 2459 | ; Function: | ||
| 2460 | ; Frees cluster chain starting with [BX] | ||
| 2461 | ; AX,BX,DX,DI all destroyed. Other registers unchanged. | ||
| 2462 | |||
| 2463 | XOR DX,DX | ||
| 2464 | RELBLKS: | ||
| 2465 | ; Enter here with DX=0FFFH to put an end-of-file mark | ||
| 2466 | ; in the first cluster and free the rest in the chain. | ||
| 2467 | CALL UNPACK | ||
| 2468 | JZ RET12 | ||
| 2469 | MOV AX,DI | ||
| 2470 | CALL PACK | ||
| 2471 | CMP AX,0FF8H | ||
| 2472 | MOV BX,AX | ||
| 2473 | JB RELEASE | ||
| 2474 | RET13: RET | ||
| 2475 | |||
| 2476 | |||
| 2477 | GETEOF: | ||
| 2478 | |||
| 2479 | ; Inputs: | ||
| 2480 | ; BX = Cluster in a file | ||
| 2481 | ; SI = Base of drive FAT | ||
| 2482 | ; DS = CS | ||
| 2483 | ; Outputs: | ||
| 2484 | ; BX = Last cluster in the file | ||
| 2485 | ; DI destroyed. No other registers affected. | ||
| 2486 | |||
| 2487 | CALL UNPACK | ||
| 2488 | CMP DI,0FF8H | ||
| 2489 | JAE RET13 | ||
| 2490 | MOV BX,DI | ||
| 2491 | JMP SHORT GETEOF | ||
| 2492 | |||
| 2493 | |||
| 2494 | SRCHFRST: ;System call 17 | ||
| 2495 | CALL GETFILE | ||
| 2496 | SAVPLCE: | ||
| 2497 | ; Search-for-next enters here to save place and report | ||
| 2498 | ; findings. | ||
| 2499 | JC KILLSRCH | ||
| 2500 | OR BH,BH | ||
| 2501 | JS SRCHDEV | ||
| 2502 | MOV AX,[LASTENT] | ||
| 2503 | MOV ES:[DI.FILDIRENT],AX | ||
| 2504 | MOV ES:[DI.DRVBP],BP | ||
| 2505 | ;Information in directory entry must be copied into the first | ||
| 2506 | ; 33 bytes starting at the disk transfer address. | ||
| 2507 | MOV SI,BX | ||
| 2508 | LES DI,DWORD PTR [DMAADD] | ||
| 2509 | MOV AX,00FFH | ||
| 2510 | CMP AL,[EXTFCB] | ||
| 2511 | JNZ NORMFCB | ||
| 2512 | STOSW | ||
| 2513 | INC AL | ||
| 2514 | STOSW | ||
| 2515 | STOSW | ||
| 2516 | MOV AL,[ATTRIB] | ||
| 2517 | STOSB | ||
| 2518 | NORMFCB: | ||
| 2519 | MOV AL,[THISDRV] | ||
| 2520 | INC AL | ||
| 2521 | STOSB ;Set drive number | ||
| 2522 | MOV CX,16 | ||
| 2523 | REP MOVSW ;Copy remaining 10 characters of name | ||
| 2524 | XOR AL,AL | ||
| 2525 | RET | ||
| 2526 | |||
| 2527 | KILLSRCH: | ||
| 2528 | KILLSRCH1 EQU KILLSRCH+1 | ||
| 2529 | ;The purpose of the KILLSRCH1 label is to provide a jump label to the following | ||
| 2530 | ; instruction which leaves out the segment override. | ||
| 2531 | MOV WORD PTR ES:[DI.FILDIRENT],-1 | ||
| 2532 | MOV AL,-1 | ||
| 2533 | RET | ||
| 2534 | |||
| 2535 | SRCHDEV: | ||
| 2536 | MOV ES:[DI.FILDIRENT],BX | ||
| 2537 | LES DI,DWORD PTR [DMAADD] | ||
| 2538 | XOR AX,AX | ||
| 2539 | STOSB ;Zero drive byte | ||
| 2540 | SUB SI,4 ;Point to device name | ||
| 2541 | MOVSW | ||
| 2542 | MOVSW | ||
| 2543 | MOV AX,2020H | ||
| 2544 | STOSB | ||
| 2545 | STOSW | ||
| 2546 | STOSW | ||
| 2547 | STOSW ;Fill with 8 blanks | ||
| 2548 | XOR AX,AX | ||
| 2549 | MOV CX,10 | ||
| 2550 | REP STOSW | ||
| 2551 | STOSB | ||
| 2552 | RET14: RET | ||
| 2553 | |||
| 2554 | SRCHNXT: ;System call 18 | ||
| 2555 | CALL MOVNAME | ||
| 2556 | MOV DI,DX | ||
| 2557 | JC NEAR PTR KILLSRCH1 | ||
| 2558 | MOV BP,[DI.DRVBP] | ||
| 2559 | MOV AX,[DI.FILDIRENT] | ||
| 2560 | OR AX,AX | ||
| 2561 | JS NEAR PTR KILLSRCH1 | ||
| 2562 | PUSH DX | ||
| 2563 | PUSH DS | ||
| 2564 | PUSH CS | ||
| 2565 | POP DS | ||
| 2566 | MOV [LASTENT],AX | ||
| 2567 | CALL CONTSRCH | ||
| 2568 | POP ES | ||
| 2569 | POP DI | ||
| 2570 | JMP SAVPLCE | ||
| 2571 | |||
| 2572 | |||
| 2573 | FILESIZE: ;System call 35 | ||
| 2574 | CALL GETFILE | ||
| 2575 | MOV AL,-1 | ||
| 2576 | JC RET14 | ||
| 2577 | ADD DI,33 ;Write size in RR field | ||
| 2578 | MOV CX,ES:[DI.RECSIZ-33] | ||
| 2579 | OR CX,CX | ||
| 2580 | JNZ RECOK | ||
| 2581 | MOV CX,128 | ||
| 2582 | RECOK: | ||
| 2583 | XOR AX,AX | ||
| 2584 | XOR DX,DX ;Intialize size to zero | ||
| 2585 | OR BH,BH ;Check for named I/O device | ||
| 2586 | JS DEVSIZ | ||
| 2587 | INC SI | ||
| 2588 | INC SI ;Point to length field | ||
| 2589 | MOV AX,[SI+2] ;Get high word of size | ||
| 2590 | DIV CX | ||
| 2591 | PUSH AX ;Save high part of result | ||
| 2592 | LODSW ;Get low word of size | ||
| 2593 | DIV CX | ||
| 2594 | OR DX,DX ;Check for zero remainder | ||
| 2595 | POP DX | ||
| 2596 | JZ DEVSIZ | ||
| 2597 | INC AX ;Round up for partial record | ||
| 2598 | JNZ DEVSIZ ;Propagate carry? | ||
| 2599 | INC DX | ||
| 2600 | DEVSIZ: | ||
| 2601 | STOSW | ||
| 2602 | MOV AX,DX | ||
| 2603 | STOSB | ||
| 2604 | MOV AL,0 | ||
| 2605 | CMP CX,64 | ||
| 2606 | JAE RET14 ;Only 3-byte field if RECSIZ >= 64 | ||
| 2607 | MOV ES:[DI],AH | ||
| 2608 | RET | ||
| 2609 | |||
| 2610 | |||
| 2611 | SETDMA: ;System call 26 | ||
| 2612 | MOV CS:[DMAADD],DX | ||
| 2613 | MOV CS:[DMAADD+2],DS | ||
| 2614 | RET | ||
| 2615 | |||
| 2616 | NOSUCHDRV: | ||
| 2617 | MOV AL,-1 | ||
| 2618 | RET | ||
| 2619 | |||
| 2620 | GETFATPT: ;System call 27 | ||
| 2621 | MOV DL,0 ;Use default drive | ||
| 2622 | |||
| 2623 | GETFATPTDL: ;System call 28 | ||
| 2624 | PUSH CS | ||
| 2625 | POP DS | ||
| 2626 | MOV AL,DL | ||
| 2627 | CALL GETTHISDRV | ||
| 2628 | JC NOSUCHDRV | ||
| 2629 | CALL FATREAD | ||
| 2630 | MOV BX,[BP.FAT] | ||
| 2631 | MOV AL,[BP.CLUSMSK] | ||
| 2632 | INC AL | ||
| 2633 | MOV DX,[BP.MAXCLUS] | ||
| 2634 | DEC DX | ||
| 2635 | MOV CX,[BP.SECSIZ] | ||
| 2636 | LDS SI,DWORD PTR [SPSAVE] | ||
| 2637 | MOV [SI.BXSAVE],BX | ||
| 2638 | MOV [SI.DXSAVE],DX | ||
| 2639 | MOV [SI.CXSAVE],CX | ||
| 2640 | MOV [SI.DSSAVE],CS | ||
| 2641 | RET | ||
| 2642 | |||
| 2643 | |||
| 2644 | GETDSKPT: ;System call 31 | ||
| 2645 | PUSH CS | ||
| 2646 | POP DS | ||
| 2647 | MOV AL,[CURDRV] | ||
| 2648 | MOV [THISDRV],AL | ||
| 2649 | CALL FATREAD | ||
| 2650 | LDS SI,DWORD PTR [SPSAVE] | ||
| 2651 | MOV [SI.BXSAVE],BP | ||
| 2652 | MOV [SI.DSSAVE],CS | ||
| 2653 | RET | ||
| 2654 | |||
| 2655 | |||
| 2656 | DSKRESET: ;System call 13 | ||
| 2657 | PUSH CS | ||
| 2658 | POP DS | ||
| 2659 | WRTFATS: | ||
| 2660 | ; DS=CS. Writes back all dirty FATs. All registers destroyed. | ||
| 2661 | XOR AL,AL | ||
| 2662 | XCHG AL,[DIRTYBUF] | ||
| 2663 | OR AL,AL | ||
| 2664 | JZ NOBUF | ||
| 2665 | MOV BP,[BUFDRVBP] | ||
| 2666 | MOV DX,[BUFSECNO] | ||
| 2667 | MOV BX,[BUFFER] | ||
| 2668 | MOV CX,1 | ||
| 2669 | CALL DWRITE | ||
| 2670 | NOBUF: | ||
| 2671 | MOV CL,[NUMIO] | ||
| 2672 | MOV CH,0 | ||
| 2673 | MOV BP,[DRVTAB] | ||
| 2674 | WRTFAT: | ||
| 2675 | PUSH CX | ||
| 2676 | CALL CHKFATWRT | ||
| 2677 | POP CX | ||
| 2678 | ADD BP,DPBSIZ | ||
| 2679 | LOOP WRTFAT | ||
| 2680 | RET | ||
| 2681 | |||
| 2682 | |||
| 2683 | GETDRV: ;System call 25 | ||
| 2684 | MOV AL,CS:[CURDRV] | ||
| 2685 | RET15: RET | ||
| 2686 | |||
| 2687 | |||
| 2688 | SETRNDREC: ;System call 36 | ||
| 2689 | CALL GETREC | ||
| 2690 | MOV [DI+33],AX | ||
| 2691 | MOV [DI+35],DL | ||
| 2692 | CMP [DI.RECSIZ],64 | ||
| 2693 | JAE RET15 | ||
| 2694 | MOV [DI+36],DH ;Set 4th byte only if record size < 64 | ||
| 2695 | RET16: RET | ||
| 2696 | |||
| 2697 | |||
| 2698 | SELDSK: ;System call 14 | ||
| 2699 | MOV AL,CS:[NUMDRV] | ||
| 2700 | CMP DL,AL | ||
| 2701 | JNB RET17 | ||
| 2702 | MOV CS:[CURDRV],DL | ||
| 2703 | RET17: RET | ||
| 2704 | |||
| 2705 | BUFIN: ;System call 10 | ||
| 2706 | MOV AX,CS | ||
| 2707 | MOV ES,AX | ||
| 2708 | MOV SI,DX | ||
| 2709 | MOV CH,0 | ||
| 2710 | LODSW | ||
| 2711 | OR AL,AL | ||
| 2712 | JZ RET17 | ||
| 2713 | MOV BL,AH | ||
| 2714 | MOV BH,CH | ||
| 2715 | CMP AL,BL | ||
| 2716 | JBE NOEDIT | ||
| 2717 | CMP BYTE PTR [BX+SI],0DH | ||
| 2718 | JZ EDITON | ||
| 2719 | NOEDIT: | ||
| 2720 | MOV BL,CH | ||
| 2721 | EDITON: | ||
| 2722 | MOV DL,AL | ||
| 2723 | DEC DX | ||
| 2724 | NEWLIN: | ||
| 2725 | MOV AL,CS:[CARPOS] | ||
| 2726 | MOV CS:[STARTPOS],AL | ||
| 2727 | PUSH SI | ||
| 2728 | MOV DI,OFFSET DOSGROUP:INBUF | ||
| 2729 | MOV AH,CH | ||
| 2730 | MOV BH,CH | ||
| 2731 | MOV DH,CH | ||
| 2732 | GETCH: | ||
| 2733 | CALL IN | ||
| 2734 | CMP AL,"F"-"@" ;Ignore ^F | ||
| 2735 | JZ GETCH | ||
| 2736 | CMP AL,CS:ESCCHAR | ||
| 2737 | JZ ESC | ||
| 2738 | CMP AL,7FH | ||
| 2739 | JZ BACKSP | ||
| 2740 | CMP AL,8 | ||
| 2741 | JZ BACKSP | ||
| 2742 | CMP AL,13 | ||
| 2743 | JZ ENDLIN | ||
| 2744 | CMP AL,10 | ||
| 2745 | JZ PHYCRLF | ||
| 2746 | CMP AL,CANCEL | ||
| 2747 | JZ KILNEW | ||
| 2748 | SAVCH: | ||
| 2749 | CMP DH,DL | ||
| 2750 | JAE BUFFUL | ||
| 2751 | STOSB | ||
| 2752 | INC DH | ||
| 2753 | CALL BUFOUT | ||
| 2754 | OR AH,AH | ||
| 2755 | JNZ GETCH | ||
| 2756 | CMP BH,BL | ||
| 2757 | JAE GETCH | ||
| 2758 | INC SI | ||
| 2759 | INC BH | ||
| 2760 | JMP SHORT GETCH | ||
| 2761 | |||
| 2762 | BUFFUL: | ||
| 2763 | MOV AL,7 | ||
| 2764 | CALL OUT | ||
| 2765 | JMP SHORT GETCH | ||
| 2766 | |||
| 2767 | ESC: | ||
| 2768 | CALL IN | ||
| 2769 | MOV CL,ESCTABLEN | ||
| 2770 | PUSH DI | ||
| 2771 | MOV DI,OFFSET DOSGROUP:ESCTAB | ||
| 2772 | REPNE SCASB | ||
| 2773 | POP DI | ||
| 2774 | SHL CX,1 | ||
| 2775 | MOV BP,CX | ||
| 2776 | JMP [BP+OFFSET DOSGROUP:ESCFUNC] | ||
| 2777 | |||
| 2778 | ENDLIN: | ||
| 2779 | STOSB | ||
| 2780 | CALL OUT | ||
| 2781 | POP DI | ||
| 2782 | MOV [DI-1],DH | ||
| 2783 | INC DH | ||
| 2784 | COPYNEW: | ||
| 2785 | MOV BP,ES | ||
| 2786 | MOV BX,DS | ||
| 2787 | MOV ES,BX | ||
| 2788 | MOV DS,BP | ||
| 2789 | MOV SI,OFFSET DOSGROUP:INBUF | ||
| 2790 | MOV CL,DH | ||
| 2791 | REP MOVSB | ||
| 2792 | RET | ||
| 2793 | CRLF: | ||
| 2794 | MOV AL,13 | ||
| 2795 | CALL OUT | ||
| 2796 | MOV AL,10 | ||
| 2797 | JMP OUT | ||
| 2798 | |||
| 2799 | PHYCRLF: | ||
| 2800 | CALL CRLF | ||
| 2801 | JMP SHORT GETCH | ||
| 2802 | |||
| 2803 | KILNEW: | ||
| 2804 | MOV AL,"\" | ||
| 2805 | CALL OUT | ||
| 2806 | POP SI | ||
| 2807 | PUTNEW: | ||
| 2808 | CALL CRLF | ||
| 2809 | MOV AL,CS:[STARTPOS] | ||
| 2810 | CALL TAB | ||
| 2811 | JMP NEWLIN | ||
| 2812 | |||
| 2813 | BACKSP: | ||
| 2814 | OR DH,DH | ||
| 2815 | JZ OLDBAK | ||
| 2816 | CALL BACKUP | ||
| 2817 | MOV AL,ES:[DI] | ||
| 2818 | CMP AL," " | ||
| 2819 | JAE OLDBAK | ||
| 2820 | CMP AL,9 | ||
| 2821 | JZ BAKTAB | ||
| 2822 | CALL BACKMES | ||
| 2823 | OLDBAK: | ||
| 2824 | OR AH,AH | ||
| 2825 | JNZ GETCH1 | ||
| 2826 | OR BH,BH | ||
| 2827 | JZ GETCH1 | ||
| 2828 | DEC BH | ||
| 2829 | DEC SI | ||
| 2830 | GETCH1: | ||
| 2831 | JMP GETCH | ||
| 2832 | BAKTAB: | ||
| 2833 | PUSH DI | ||
| 2834 | DEC DI | ||
| 2835 | STD | ||
| 2836 | MOV CL,DH | ||
| 2837 | MOV AL," " | ||
| 2838 | PUSH BX | ||
| 2839 | MOV BL,7 | ||
| 2840 | JCXZ FIGTAB | ||
| 2841 | FNDPOS: | ||
| 2842 | SCASB | ||
| 2843 | JNA CHKCNT | ||
| 2844 | CMP ES:BYTE PTR [DI+1],9 | ||
| 2845 | JZ HAVTAB | ||
| 2846 | DEC BL | ||
| 2847 | CHKCNT: | ||
| 2848 | LOOP FNDPOS | ||
| 2849 | FIGTAB: | ||
| 2850 | SUB BL,CS:[STARTPOS] | ||
| 2851 | HAVTAB: | ||
| 2852 | SUB BL,DH | ||
| 2853 | ADD CL,BL | ||
| 2854 | AND CL,7 | ||
| 2855 | CLD | ||
| 2856 | POP BX | ||
| 2857 | POP DI | ||
| 2858 | JZ OLDBAK | ||
| 2859 | TABBAK: | ||
| 2860 | CALL BACKMES | ||
| 2861 | LOOP TABBAK | ||
| 2862 | JMP SHORT OLDBAK | ||
| 2863 | BACKUP: | ||
| 2864 | DEC DH | ||
| 2865 | DEC DI | ||
| 2866 | BACKMES: | ||
| 2867 | MOV AL,8 | ||
| 2868 | CALL OUT | ||
| 2869 | MOV AL," " | ||
| 2870 | CALL OUT | ||
| 2871 | MOV AL,8 | ||
| 2872 | JMP OUT | ||
| 2873 | |||
| 2874 | TWOESC: | ||
| 2875 | MOV AL,ESCCH | ||
| 2876 | JMP SAVCH | ||
| 2877 | |||
| 2878 | COPYLIN: | ||
| 2879 | MOV CL,BL | ||
| 2880 | SUB CL,BH | ||
| 2881 | JMP SHORT COPYEACH | ||
| 2882 | |||
| 2883 | COPYSTR: | ||
| 2884 | CALL FINDOLD | ||
| 2885 | JMP SHORT COPYEACH | ||
| 2886 | |||
| 2887 | COPYONE: | ||
| 2888 | MOV CL,1 | ||
| 2889 | COPYEACH: | ||
| 2890 | MOV AH,0 | ||
| 2891 | CMP DH,DL | ||
| 2892 | JZ GETCH2 | ||
| 2893 | CMP BH,BL | ||
| 2894 | JZ GETCH2 | ||
| 2895 | LODSB | ||
| 2896 | STOSB | ||
| 2897 | CALL BUFOUT | ||
| 2898 | INC BH | ||
| 2899 | INC DH | ||
| 2900 | LOOP COPYEACH | ||
| 2901 | GETCH2: | ||
| 2902 | JMP GETCH | ||
| 2903 | |||
| 2904 | SKIPONE: | ||
| 2905 | CMP BH,BL | ||
| 2906 | JZ GETCH2 | ||
| 2907 | INC BH | ||
| 2908 | INC SI | ||
| 2909 | JMP GETCH | ||
| 2910 | |||
| 2911 | SKIPSTR: | ||
| 2912 | CALL FINDOLD | ||
| 2913 | ADD SI,CX | ||
| 2914 | ADD BH,CL | ||
| 2915 | JMP GETCH | ||
| 2916 | |||
| 2917 | FINDOLD: | ||
| 2918 | CALL IN | ||
| 2919 | MOV CL,BL | ||
| 2920 | SUB CL,BH | ||
| 2921 | JZ NOTFND | ||
| 2922 | DEC CX | ||
| 2923 | JZ NOTFND | ||
| 2924 | PUSH ES | ||
| 2925 | PUSH DS | ||
| 2926 | POP ES | ||
| 2927 | PUSH DI | ||
| 2928 | MOV DI,SI | ||
| 2929 | INC DI | ||
| 2930 | REPNE SCASB | ||
| 2931 | POP DI | ||
| 2932 | POP ES | ||
| 2933 | JNZ NOTFND | ||
| 2934 | NOT CL | ||
| 2935 | ADD CL,BL | ||
| 2936 | SUB CL,BH | ||
| 2937 | RET30: RET | ||
| 2938 | NOTFND: | ||
| 2939 | POP BP | ||
| 2940 | JMP GETCH | ||
| 2941 | |||
| 2942 | REEDIT: | ||
| 2943 | MOV AL,"@" | ||
| 2944 | CALL OUT | ||
| 2945 | POP DI | ||
| 2946 | PUSH DI | ||
| 2947 | PUSH ES | ||
| 2948 | PUSH DS | ||
| 2949 | CALL COPYNEW | ||
| 2950 | POP DS | ||
| 2951 | POP ES | ||
| 2952 | POP SI | ||
| 2953 | MOV BL,DH | ||
| 2954 | JMP PUTNEW | ||
| 2955 | |||
| 2956 | ENTERINS: | ||
| 2957 | IF TOGLINS | ||
| 2958 | NOT AH | ||
| 2959 | JMP GETCH | ||
| 2960 | ENDIF | ||
| 2961 | IF NOT TOGLINS | ||
| 2962 | MOV AH,-1 | ||
| 2963 | JMP GETCH | ||
| 2964 | |||
| 2965 | EXITINS: | ||
| 2966 | MOV AH,0 | ||
| 2967 | JMP GETCH | ||
| 2968 | ENDIF | ||
| 2969 | |||
| 2970 | ESCFUNC DW GETCH | ||
| 2971 | DW TWOESC | ||
| 2972 | IF NOT TOGLINS | ||
| 2973 | DW EXITINS | ||
| 2974 | ENDIF | ||
| 2975 | DW ENTERINS | ||
| 2976 | DW BACKSP | ||
| 2977 | DW REEDIT | ||
| 2978 | DW KILNEW | ||
| 2979 | DW COPYLIN | ||
| 2980 | DW SKIPSTR | ||
| 2981 | DW COPYSTR | ||
| 2982 | DW SKIPONE | ||
| 2983 | DW COPYONE | ||
| 2984 | |||
| 2985 | IF IBM | ||
| 2986 | DW COPYONE | ||
| 2987 | DW CTRLZ | ||
| 2988 | CTRLZ: | ||
| 2989 | MOV AL,"Z"-"@" | ||
| 2990 | JMP SAVCH | ||
| 2991 | ENDIF | ||
| 2992 | BUFOUT: | ||
| 2993 | CMP AL," " | ||
| 2994 | JAE OUT | ||
| 2995 | CMP AL,9 | ||
| 2996 | JZ OUT | ||
| 2997 | PUSH AX | ||
| 2998 | MOV AL,"^" | ||
| 2999 | CALL OUT | ||
| 3000 | POP AX | ||
| 3001 | OR AL,40H | ||
| 3002 | JMP SHORT OUT | ||
| 3003 | |||
| 3004 | NOSTOP: | ||
| 3005 | CMP AL,"P"-"@" | ||
| 3006 | JZ INCHK | ||
| 3007 | IF NOT TOGLPRN | ||
| 3008 | CMP AL,"N"-"@" | ||
| 3009 | JZ INCHK | ||
| 3010 | ENDIF | ||
| 3011 | CMP AL,"C"-"@" | ||
| 3012 | JZ INCHK | ||
| 3013 | RET | ||
| 3014 | |||
| 3015 | CONOUT: ;System call 2 | ||
| 3016 | MOV AL,DL | ||
| 3017 | OUT: | ||
| 3018 | CMP AL,20H | ||
| 3019 | JB CTRLOUT | ||
| 3020 | CMP AL,7FH | ||
| 3021 | JZ OUTCH | ||
| 3022 | INC CS:BYTE PTR [CARPOS] | ||
| 3023 | OUTCH: | ||
| 3024 | PUSH AX | ||
| 3025 | CALL STATCHK | ||
| 3026 | POP AX | ||
| 3027 | CALL FAR PTR BIOSOUT | ||
| 3028 | TEST CS:BYTE PTR [PFLAG],-1 | ||
| 3029 | JZ RET18 | ||
| 3030 | CALL FAR PTR BIOSPRINT | ||
| 3031 | RET18: RET | ||
| 3032 | |||
| 3033 | STATCHK: | ||
| 3034 | CALL FAR PTR BIOSSTAT | ||
| 3035 | JZ RET18 | ||
| 3036 | CMP AL,'S'-'@' | ||
| 3037 | JNZ NOSTOP | ||
| 3038 | CALL FAR PTR BIOSIN ;Eat Cntrl-S | ||
| 3039 | INCHK: | ||
| 3040 | CALL FAR PTR BIOSIN | ||
| 3041 | CMP AL,'P'-'@' | ||
| 3042 | JZ PRINTON | ||
| 3043 | IF NOT TOGLPRN | ||
| 3044 | CMP AL,'N'-'@' | ||
| 3045 | JZ PRINTOFF | ||
| 3046 | ENDIF | ||
| 3047 | CMP AL,'C'-'@' | ||
| 3048 | JNZ RET18 | ||
| 3049 | ; Ctrl-C handler. | ||
| 3050 | ; "^C" and CR/LF is printed. Then the user registers are restored and the | ||
| 3051 | ; user CTRL-C handler is executed. At this point the top of the stack has | ||
| 3052 | ; 1) the interrupt return address should the user CTRL-C handler wish to | ||
| 3053 | ; allow processing to continue; 2) the original interrupt return address | ||
| 3054 | ; to the code that performed the function call in the first place. If the | ||
| 3055 | ; user CTRL-C handler wishes to continue, it must leave all registers | ||
| 3056 | ; unchanged and IRET. The function that was interrupted will simply be | ||
| 3057 | ; repeated. | ||
| 3058 | MOV AL,3 ;Display "^C" | ||
| 3059 | CALL BUFOUT | ||
| 3060 | CALL CRLF | ||
| 3061 | CLI ;Prepare to play with stack | ||
| 3062 | MOV SS,CS:[SSSAVE] | ||
| 3063 | MOV SP,CS:[SPSAVE] ;User stack now restored | ||
| 3064 | POP AX | ||
| 3065 | POP BX | ||
| 3066 | POP CX | ||
| 3067 | POP DX | ||
| 3068 | POP SI | ||
| 3069 | POP DI | ||
| 3070 | POP BP | ||
| 3071 | POP DS | ||
| 3072 | POP ES ;User registers now restored | ||
| 3073 | INT CONTC ;Execute user Ctrl-C handler | ||
| 3074 | JMP COMMAND ;Repeat command otherwise | ||
| 3075 | |||
| 3076 | PRINTON: | ||
| 3077 | IF TOGLPRN | ||
| 3078 | NOT CS:BYTE PTR [PFLAG] | ||
| 3079 | RET | ||
| 3080 | ENDIF | ||
| 3081 | IF NOT TOGLPRN | ||
| 3082 | MOV CS:BYTE PTR [PFLAG],1 | ||
| 3083 | RET | ||
| 3084 | |||
| 3085 | PRINTOFF: | ||
| 3086 | MOV CS:BYTE PTR [PFLAG],0 | ||
| 3087 | RET | ||
| 3088 | ENDIF | ||
| 3089 | |||
| 3090 | CTRLOUT: | ||
| 3091 | CMP AL,13 | ||
| 3092 | JZ ZERPOS | ||
| 3093 | CMP AL,8 | ||
| 3094 | JZ BACKPOS | ||
| 3095 | CMP AL,9 | ||
| 3096 | JNZ OUTCHJ | ||
| 3097 | MOV AL,CS:[CARPOS] | ||
| 3098 | OR AL,0F8H | ||
| 3099 | NEG AL | ||
| 3100 | TAB: | ||
| 3101 | PUSH CX | ||
| 3102 | MOV CL,AL | ||
| 3103 | MOV CH,0 | ||
| 3104 | JCXZ POPTAB | ||
| 3105 | TABLP: | ||
| 3106 | MOV AL," " | ||
| 3107 | CALL OUT | ||
| 3108 | LOOP TABLP | ||
| 3109 | POPTAB: | ||
| 3110 | POP CX | ||
| 3111 | RET19: RET | ||
| 3112 | |||
| 3113 | ZERPOS: | ||
| 3114 | MOV CS:BYTE PTR [CARPOS],0 | ||
| 3115 | OUTCHJ: JMP OUTCH | ||
| 3116 | |||
| 3117 | BACKPOS: | ||
| 3118 | DEC CS:BYTE PTR [CARPOS] | ||
| 3119 | JMP OUTCH | ||
| 3120 | |||
| 3121 | |||
| 3122 | CONSTAT: ;System call 11 | ||
| 3123 | CALL STATCHK | ||
| 3124 | MOV AL,0 | ||
| 3125 | JZ RET19 | ||
| 3126 | OR AL,-1 | ||
| 3127 | RET | ||
| 3128 | |||
| 3129 | |||
| 3130 | CONIN: ;System call 1 | ||
| 3131 | CALL IN | ||
| 3132 | PUSH AX | ||
| 3133 | CALL OUT | ||
| 3134 | POP AX | ||
| 3135 | RET | ||
| 3136 | |||
| 3137 | |||
| 3138 | IN: ;System call 8 | ||
| 3139 | CALL INCHK | ||
| 3140 | JZ IN | ||
| 3141 | RET29: RET | ||
| 3142 | |||
| 3143 | RAWIO: ;System call 6 | ||
| 3144 | MOV AL,DL | ||
| 3145 | CMP AL,-1 | ||
| 3146 | JNZ RAWOUT | ||
| 3147 | LDS SI,DWORD PTR CS:[SPSAVE] ;Get pointer to register save area | ||
| 3148 | CALL FAR PTR BIOSSTAT | ||
| 3149 | JNZ RESFLG | ||
| 3150 | OR BYTE PTR [SI.FSAVE],40H ;Set user's zero flag | ||
| 3151 | XOR AL,AL | ||
| 3152 | RET | ||
| 3153 | |||
| 3154 | RESFLG: | ||
| 3155 | AND BYTE PTR [SI.FSAVE],0FFH-40H ;Reset user's zero flag | ||
| 3156 | RAWINP: ;System call 7 | ||
| 3157 | CALL FAR PTR BIOSIN | ||
| 3158 | RET | ||
| 3159 | RAWOUT: | ||
| 3160 | CALL FAR PTR BIOSOUT | ||
| 3161 | RET | ||
| 3162 | |||
| 3163 | LIST: ;System call 5 | ||
| 3164 | MOV AL,DL | ||
| 3165 | LISTOUT: | ||
| 3166 | PUSH AX | ||
| 3167 | CALL STATCHK | ||
| 3168 | POP AX | ||
| 3169 | CALL FAR PTR BIOSPRINT | ||
| 3170 | RET20: RET | ||
| 3171 | |||
| 3172 | PRTBUF: ;System call 9 | ||
| 3173 | MOV SI,DX | ||
| 3174 | OUTSTR: | ||
| 3175 | LODSB | ||
| 3176 | CMP AL,"$" | ||
| 3177 | JZ RET20 | ||
| 3178 | CALL OUT | ||
| 3179 | JMP SHORT OUTSTR | ||
| 3180 | |||
| 3181 | OUTMES: ;String output for internal messages | ||
| 3182 | LODS CS:BYTE PTR [SI] | ||
| 3183 | CMP AL,"$" | ||
| 3184 | JZ RET20 | ||
| 3185 | CALL OUT | ||
| 3186 | JMP SHORT OUTMES | ||
| 3187 | |||
| 3188 | |||
| 3189 | MAKEFCB: ;Interrupt call 41 | ||
| 3190 | DRVBIT EQU 2 | ||
| 3191 | NAMBIT EQU 4 | ||
| 3192 | EXTBIT EQU 8 | ||
| 3193 | MOV DL,0 ;Flag--not ambiguous file name | ||
| 3194 | TEST AL,DRVBIT ;Use current drive field if default? | ||
| 3195 | JNZ DEFDRV | ||
| 3196 | MOV BYTE PTR ES:[DI],0 ;No - use default drive | ||
| 3197 | DEFDRV: | ||
| 3198 | INC DI | ||
| 3199 | MOV CX,8 | ||
| 3200 | TEST AL,NAMBIT ;Use current name fiels as defualt? | ||
| 3201 | XCHG AX,BX ;Save bits in BX | ||
| 3202 | MOV AL," " | ||
| 3203 | JZ FILLB ;If not, go fill with blanks | ||
| 3204 | ADD DI,CX | ||
| 3205 | XOR CX,CX ;Don't fill any | ||
| 3206 | FILLB: | ||
| 3207 | REP STOSB | ||
| 3208 | MOV CL,3 | ||
| 3209 | TEST BL,EXTBIT ;Use current extension as default | ||
| 3210 | JZ FILLB2 | ||
| 3211 | ADD DI,CX | ||
| 3212 | XOR CX,CX | ||
| 3213 | FILLB2: | ||
| 3214 | REP STOSB | ||
| 3215 | XCHG AX,CX ;Put zero in AX | ||
| 3216 | STOSW | ||
| 3217 | STOSW ;Initialize two words after to zero | ||
| 3218 | SUB DI,16 ;Point back at start | ||
| 3219 | TEST BL,1 ;Scan off separators if not zero | ||
| 3220 | JZ SKPSPC | ||
| 3221 | CALL SCANB ;Peel off blanks and tabs | ||
| 3222 | CALL DELIM ;Is it a one-time-only delimiter? | ||
| 3223 | JNZ NOSCAN | ||
| 3224 | INC SI ;Skip over the delimiter | ||
| 3225 | SKPSPC: | ||
| 3226 | CALL SCANB ;Always kill preceding blanks and tabs | ||
| 3227 | NOSCAN: | ||
| 3228 | CALL GETLET | ||
| 3229 | JBE NODRV ;Quit if termination character | ||
| 3230 | CMP BYTE PTR[SI],":" ;Check for potential drive specifier | ||
| 3231 | JNZ NODRV | ||
| 3232 | INC SI ;Skip over colon | ||
| 3233 | SUB AL,"@" ;Convert drive letter to binary drive number | ||
| 3234 | JBE BADDRV ;Valid drive numbers are 1-15 | ||
| 3235 | CMP AL,CS:[NUMDRV] | ||
| 3236 | JBE HAVDRV | ||
| 3237 | BADDRV: | ||
| 3238 | MOV DL,-1 | ||
| 3239 | HAVDRV: | ||
| 3240 | STOSB ;Put drive specifier in first byte | ||
| 3241 | INC SI | ||
| 3242 | DEC DI ;Counteract next two instructions | ||
| 3243 | NODRV: | ||
| 3244 | DEC SI ;Back up | ||
| 3245 | INC DI ;Skip drive byte | ||
| 3246 | MOV CX,8 | ||
| 3247 | CALL GETWORD ;Get 8-letter file name | ||
| 3248 | CMP BYTE PTR [SI],"." | ||
| 3249 | JNZ NODOT | ||
| 3250 | INC SI ;Skip over dot if present | ||
| 3251 | MOV CX,3 ;Get 3-letter extension | ||
| 3252 | CALL MUSTGETWORD | ||
| 3253 | NODOT: | ||
| 3254 | LDS BX,CS:DWORD PTR [SPSAVE] | ||
| 3255 | MOV [BX.SISAVE],SI | ||
| 3256 | MOV AL,DL | ||
| 3257 | RET | ||
| 3258 | |||
| 3259 | NONAM: | ||
| 3260 | ADD DI,CX | ||
| 3261 | DEC SI | ||
| 3262 | RET | ||
| 3263 | |||
| 3264 | GETWORD: | ||
| 3265 | CALL GETLET | ||
| 3266 | JBE NONAM ;Exit if invalid character | ||
| 3267 | DEC SI | ||
| 3268 | MUSTGETWORD: | ||
| 3269 | CALL GETLET | ||
| 3270 | JBE FILLNAM | ||
| 3271 | JCXZ MUSTGETWORD | ||
| 3272 | DEC CX | ||
| 3273 | CMP AL,"*" ;Check for ambiguous file specifier | ||
| 3274 | JNZ NOSTAR | ||
| 3275 | MOV AL,"?" | ||
| 3276 | REP STOSB | ||
| 3277 | NOSTAR: | ||
| 3278 | STOSB | ||
| 3279 | CMP AL,"?" | ||
| 3280 | JNZ MUSTGETWORD | ||
| 3281 | OR DL,1 ;Flag ambiguous file name | ||
| 3282 | JMP MUSTGETWORD | ||
| 3283 | FILLNAM: | ||
| 3284 | MOV AL," " | ||
| 3285 | REP STOSB | ||
| 3286 | DEC SI | ||
| 3287 | RET21: RET | ||
| 3288 | |||
| 3289 | SCANB: | ||
| 3290 | LODSB | ||
| 3291 | CALL SPCHK | ||
| 3292 | JZ SCANB | ||
| 3293 | DEC SI | ||
| 3294 | RET | ||
| 3295 | |||
| 3296 | GETLET: | ||
| 3297 | ;Get a byte from [SI], convert it to upper case, and compare for delimiter. | ||
| 3298 | ;ZF set if a delimiter, CY set if a control character (other than TAB). | ||
| 3299 | LODSB | ||
| 3300 | AND AL,7FH | ||
| 3301 | CMP AL,"a" | ||
| 3302 | JB CHK | ||
| 3303 | CMP AL,"z" | ||
| 3304 | JA CHK | ||
| 3305 | SUB AL,20H ;Convert to upper case | ||
| 3306 | CHK: | ||
| 3307 | CMP AL,"." | ||
| 3308 | JZ RET21 | ||
| 3309 | CMP AL,'"' | ||
| 3310 | JZ RET21 | ||
| 3311 | CMP AL,"/" | ||
| 3312 | JZ RET21 | ||
| 3313 | CMP AL,"[" | ||
| 3314 | JZ RET21 | ||
| 3315 | CMP AL,"]" | ||
| 3316 | JZ RET21 | ||
| 3317 | |||
| 3318 | IF IBM | ||
| 3319 | DELIM: | ||
| 3320 | ENDIF | ||
| 3321 | CMP AL,":" ;Allow ":" as separator in IBM version | ||
| 3322 | JZ RET21 | ||
| 3323 | IF NOT IBM | ||
| 3324 | DELIM: | ||
| 3325 | ENDIF | ||
| 3326 | |||
| 3327 | CMP AL,"+" | ||
| 3328 | JZ RET101 | ||
| 3329 | CMP AL,"=" | ||
| 3330 | JZ RET101 | ||
| 3331 | CMP AL,";" | ||
| 3332 | JZ RET101 | ||
| 3333 | CMP AL,"," | ||
| 3334 | JZ RET101 | ||
| 3335 | SPCHK: | ||
| 3336 | CMP AL,9 ;Filter out tabs too | ||
| 3337 | JZ RET101 | ||
| 3338 | ;WARNING! " " MUST be the last compare | ||
| 3339 | CMP AL," " | ||
| 3340 | RET101: RET | ||
| 3341 | |||
| 3342 | SETVECT: ; Interrupt call 37 | ||
| 3343 | XOR BX,BX | ||
| 3344 | MOV ES,BX | ||
| 3345 | MOV BL,AL | ||
| 3346 | SHL BX,1 | ||
| 3347 | SHL BX,1 | ||
| 3348 | MOV ES:[BX],DX | ||
| 3349 | MOV ES:[BX+2],DS | ||
| 3350 | RET | ||
| 3351 | |||
| 3352 | |||
| 3353 | NEWBASE: ; Interrupt call 38 | ||
| 3354 | MOV ES,DX | ||
| 3355 | LDS SI,CS:DWORD PTR [SPSAVE] | ||
| 3356 | MOV DS,[SI.CSSAVE] | ||
| 3357 | XOR SI,SI | ||
| 3358 | MOV DI,SI | ||
| 3359 | MOV AX,DS:[2] | ||
| 3360 | MOV CX,80H | ||
| 3361 | REP MOVSW | ||
| 3362 | |||
| 3363 | SETMEM: | ||
| 3364 | |||
| 3365 | ; Inputs: | ||
| 3366 | ; AX = Size of memory in paragraphs | ||
| 3367 | ; DX = Segment | ||
| 3368 | ; Function: | ||
| 3369 | ; Completely prepares a program base at the | ||
| 3370 | ; specified segment. | ||
| 3371 | ; Outputs: | ||
| 3372 | ; DS = DX | ||
| 3373 | ; ES = DX | ||
| 3374 | ; [0] has INT 20H | ||
| 3375 | ; [2] = First unavailable segment ([ENDMEM]) | ||
| 3376 | ; [5] to [9] form a long call to the entry point | ||
| 3377 | ; [10] to [13] have exit address (from INT 22H) | ||
| 3378 | ; [14] to [17] have ctrl-C exit address (from INT 23H) | ||
| 3379 | ; [18] to [21] have fatal error address (from INT 24H) | ||
| 3380 | ; DX,BP unchanged. All other registers destroyed. | ||
| 3381 | |||
| 3382 | XOR CX,CX | ||
| 3383 | MOV DS,CX | ||
| 3384 | MOV ES,DX | ||
| 3385 | MOV SI,EXIT | ||
| 3386 | MOV DI,SAVEXIT | ||
| 3387 | MOVSW | ||
| 3388 | MOVSW | ||
| 3389 | MOVSW | ||
| 3390 | MOVSW | ||
| 3391 | MOVSW | ||
| 3392 | MOVSW | ||
| 3393 | MOV ES:[2],AX | ||
| 3394 | SUB AX,DX | ||
| 3395 | CMP AX,MAXDIF | ||
| 3396 | JBE HAVDIF | ||
| 3397 | MOV AX,MAXDIF | ||
| 3398 | HAVDIF: | ||
| 3399 | MOV BX,ENTRYPOINTSEG | ||
| 3400 | SUB BX,AX | ||
| 3401 | SHL AX,1 | ||
| 3402 | SHL AX,1 | ||
| 3403 | SHL AX,1 | ||
| 3404 | SHL AX,1 | ||
| 3405 | MOV DS,DX | ||
| 3406 | MOV DS:[6],AX | ||
| 3407 | MOV DS:[8],BX | ||
| 3408 | MOV DS:[0],20CDH ;"INT INTTAB" | ||
| 3409 | MOV DS:(BYTE PTR [5]),LONGCALL | ||
| 3410 | RET | ||
| 3411 | |||
| 3412 | DATE16: | ||
| 3413 | PUSH CX | ||
| 3414 | CALL READTIME | ||
| 3415 | SHL CL,1 ;Minutes to left part of byte | ||
| 3416 | SHL CL,1 | ||
| 3417 | SHL CX,1 ;Push hours and minutes to left end | ||
| 3418 | SHL CX,1 | ||
| 3419 | SHL CX,1 | ||
| 3420 | SHR DH,1 ;Count every two seconds | ||
| 3421 | OR CL,DH ;Combine seconds with hours and minutes | ||
| 3422 | MOV DX,CX | ||
| 3423 | POP CX | ||
| 3424 | MOV AX,WORD PTR [MONTH] ;Fetch month and year | ||
| 3425 | SHL AL,1 ;Push month to left to make room for day | ||
| 3426 | SHL AL,1 | ||
| 3427 | SHL AL,1 | ||
| 3428 | SHL AL,1 | ||
| 3429 | SHL AX,1 | ||
| 3430 | OR AL,[DAY] | ||
| 3431 | RET22: RET | ||
| 3432 | |||
| 3433 | FOURYEARS EQU 3*365+366 | ||
| 3434 | |||
| 3435 | READTIME: | ||
| 3436 | ;Gets time in CX:DX. Figures new date if it has changed. | ||
| 3437 | ;Uses AX, CX, DX. | ||
| 3438 | CALL FAR PTR BIOSGETTIME | ||
| 3439 | CMP AX,[DAYCNT] ;See if day count is the same | ||
| 3440 | JZ RET22 | ||
| 3441 | CMP AX,FOURYEARS*30 ;Number of days in 120 years | ||
| 3442 | JAE RET22 ;Ignore if too large | ||
| 3443 | MOV [DAYCNT],AX | ||
| 3444 | PUSH SI | ||
| 3445 | PUSH CX | ||
| 3446 | PUSH DX ;Save time | ||
| 3447 | XOR DX,DX | ||
| 3448 | MOV CX,FOURYEARS ;Number of days in 4 years | ||
| 3449 | DIV CX ;Compute number of 4-year units | ||
| 3450 | SHL AX,1 | ||
| 3451 | SHL AX,1 | ||
| 3452 | SHL AX,1 ;Multiply by 8 (no. of half-years) | ||
| 3453 | MOV CX,AX ;<240 implies AH=0 | ||
| 3454 | MOV SI,OFFSET DOSGROUP:YRTAB ;Table of days in each year | ||
| 3455 | CALL DSLIDE ;Find out which of four years we're in | ||
| 3456 | SHR CX,1 ;Convert half-years to whole years | ||
| 3457 | JNC SK ;Extra half-year? | ||
| 3458 | ADD DX,200 | ||
| 3459 | SK: | ||
| 3460 | CALL SETYEAR | ||
| 3461 | MOV CL,1 ;At least at first month in year | ||
| 3462 | MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month | ||
| 3463 | CALL DSLIDE ;Find out which month we're in | ||
| 3464 | MOV [MONTH],CL | ||
| 3465 | INC DX ;Remainder is day of month (start with one) | ||
| 3466 | MOV [DAY],DL | ||
| 3467 | CALL WKDAY ;Set day of week | ||
| 3468 | POP DX | ||
| 3469 | POP CX | ||
| 3470 | POP SI | ||
| 3471 | RET23: RET | ||
| 3472 | |||
| 3473 | DSLIDE: | ||
| 3474 | MOV AH,0 | ||
| 3475 | DSLIDE1: | ||
| 3476 | LODSB ;Get count of days | ||
| 3477 | CMP DX,AX ;See if it will fit | ||
| 3478 | JB RET23 ;If not, done | ||
| 3479 | SUB DX,AX | ||
| 3480 | INC CX ;Count one more month/year | ||
| 3481 | JMP SHORT DSLIDE1 | ||
| 3482 | |||
| 3483 | SETYEAR: | ||
| 3484 | ;Set year with value in CX. Adjust length of February for this year. | ||
| 3485 | MOV BYTE PTR [YEAR],CL | ||
| 3486 | CHKYR: | ||
| 3487 | TEST CL,3 ;Check for leap year | ||
| 3488 | MOV AL,28 | ||
| 3489 | JNZ SAVFEB ;28 days if no leap year | ||
| 3490 | INC AL ;Add leap day | ||
| 3491 | SAVFEB: | ||
| 3492 | MOV [MONTAB+1],AL ;Store for February | ||
| 3493 | RET | ||
| 3494 | |||
| 3495 | ;Days in year | ||
| 3496 | YRTAB DB 200,166 ;Leap year | ||
| 3497 | DB 200,165 | ||
| 3498 | DB 200,165 | ||
| 3499 | DB 200,165 | ||
| 3500 | |||
| 3501 | ;Days of each month | ||
| 3502 | MONTAB DB 31 ;January | ||
| 3503 | DB 28 ;February--reset each time year changes | ||
| 3504 | DB 31 ;March | ||
| 3505 | DB 30 ;April | ||
| 3506 | DB 31 ;May | ||
| 3507 | DB 30 ;June | ||
| 3508 | DB 31 ;July | ||
| 3509 | DB 31 ;August | ||
| 3510 | DB 30 ;September | ||
| 3511 | DB 31 ;October | ||
| 3512 | DB 30 ;November | ||
| 3513 | DB 31 ;December | ||
| 3514 | |||
| 3515 | GETDATE: ;Function call 42 | ||
| 3516 | PUSH CS | ||
| 3517 | POP DS | ||
| 3518 | CALL READTIME ;Check for rollover to next day | ||
| 3519 | MOV AX,[YEAR] | ||
| 3520 | MOV BX,WORD PTR [DAY] | ||
| 3521 | LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers | ||
| 3522 | MOV [SI.DXSAVE],BX ;DH=month, DL=day | ||
| 3523 | ADD AX,1980 ;Put bias back | ||
| 3524 | MOV [SI.CXSAVE],AX ;CX=year | ||
| 3525 | MOV AL,CS:[WEEKDAY] | ||
| 3526 | RET24: RET | ||
| 3527 | |||
| 3528 | SETDATE: ;Function call 43 | ||
| 3529 | MOV AL,-1 ;Be ready to flag error | ||
| 3530 | SUB CX,1980 ;Fix bias in year | ||
| 3531 | JC RET24 ;Error if not big enough | ||
| 3532 | CMP CX,119 ;Year must be less than 2100 | ||
| 3533 | JA RET24 | ||
| 3534 | OR DH,DH | ||
| 3535 | JZ RET24 | ||
| 3536 | OR DL,DL | ||
| 3537 | JZ RET24 ;Error if either month or day is 0 | ||
| 3538 | CMP DH,12 ;Check against max. month | ||
| 3539 | JA RET24 | ||
| 3540 | PUSH CS | ||
| 3541 | POP DS | ||
| 3542 | CALL CHKYR ;Set Feb. up for new year | ||
| 3543 | MOV AL,DH | ||
| 3544 | MOV BX,OFFSET DOSGROUP:MONTAB-1 | ||
| 3545 | XLAT ;Look up days in month | ||
| 3546 | CMP AL,DL | ||
| 3547 | MOV AL,-1 ;Restore error flag, just in case | ||
| 3548 | JB RET24 ;Error if too many days | ||
| 3549 | CALL SETYEAR | ||
| 3550 | MOV WORD PTR [DAY],DX ;Set both day and month | ||
| 3551 | SHR CX,1 | ||
| 3552 | SHR CX,1 | ||
| 3553 | MOV AX,FOURYEARS | ||
| 3554 | MOV BX,DX | ||
| 3555 | MUL CX | ||
| 3556 | MOV CL,BYTE PTR [YEAR] | ||
| 3557 | AND CL,3 | ||
| 3558 | MOV SI,OFFSET DOSGROUP:YRTAB | ||
| 3559 | MOV DX,AX | ||
| 3560 | SHL CX,1 ;Two entries per year, so double count | ||
| 3561 | CALL DSUM ;Add up the days in each year | ||
| 3562 | MOV CL,BH ;Month of year | ||
| 3563 | MOV SI,OFFSET DOSGROUP:MONTAB | ||
| 3564 | DEC CX ;Account for months starting with one | ||
| 3565 | CALL DSUM ;Add up days in each month | ||
| 3566 | MOV CL,BL ;Day of month | ||
| 3567 | DEC CX ;Account for days starting with one | ||
| 3568 | ADD DX,CX ;Add in to day total | ||
| 3569 | XCHG AX,DX ;Get day count in AX | ||
| 3570 | MOV [DAYCNT],AX | ||
| 3571 | CALL FAR PTR BIOSSETDATE | ||
| 3572 | WKDAY: | ||
| 3573 | MOV AX,[DAYCNT] | ||
| 3574 | XOR DX,DX | ||
| 3575 | MOV CX,7 | ||
| 3576 | INC AX | ||
| 3577 | INC AX ;First day was Tuesday | ||
| 3578 | DIV CX ;Compute day of week | ||
| 3579 | MOV [WEEKDAY],DL | ||
| 3580 | XOR AL,AL ;Flag OK | ||
| 3581 | RET25: RET | ||
| 3582 | |||
| 3583 | DSUM: | ||
| 3584 | MOV AH,0 | ||
| 3585 | JCXZ RET25 | ||
| 3586 | DSUM1: | ||
| 3587 | LODSB | ||
| 3588 | ADD DX,AX | ||
| 3589 | LOOP DSUM1 | ||
| 3590 | RET | ||
| 3591 | |||
| 3592 | GETTIME: ;Function call 44 | ||
| 3593 | PUSH CS | ||
| 3594 | POP DS | ||
| 3595 | CALL READTIME | ||
| 3596 | LDS SI,DWORD PTR [SPSAVE] ;Get pointer to user registers | ||
| 3597 | MOV [SI.DXSAVE],DX | ||
| 3598 | MOV [SI.CXSAVE],CX | ||
| 3599 | XOR AL,AL | ||
| 3600 | RET26: RET | ||
| 3601 | |||
| 3602 | SETTIME: ;Function call 45 | ||
| 3603 | ;Time is in CX:DX in hours, minutes, seconds, 1/100 sec. | ||
| 3604 | MOV AL,-1 ;Flag in case of error | ||
| 3605 | CMP CH,24 ;Check hours | ||
| 3606 | JAE RET26 | ||
| 3607 | CMP CL,60 ;Check minutes | ||
| 3608 | JAE RET26 | ||
| 3609 | CMP DH,60 ;Check seconds | ||
| 3610 | JAE RET26 | ||
| 3611 | CMP DL,100 ;Check 1/100's | ||
| 3612 | JAE RET26 | ||
| 3613 | CALL FAR PTR BIOSSETTIME | ||
| 3614 | XOR AL,AL | ||
| 3615 | RET | ||
| 3616 | |||
| 3617 | |||
| 3618 | ; Default handler for division overflow trap | ||
| 3619 | DIVOV: | ||
| 3620 | PUSH SI | ||
| 3621 | PUSH AX | ||
| 3622 | MOV SI,OFFSET DOSGROUP:DIVMES | ||
| 3623 | CALL OUTMES | ||
| 3624 | POP AX | ||
| 3625 | POP SI | ||
| 3626 | INT 23H ;Use Ctrl-C abort on divide overflow | ||
| 3627 | IRET | ||
| 3628 | |||
| 3629 | CODSIZ EQU $-CODSTRT ;Size of code segment | ||
| 3630 | CODE ENDS | ||
| 3631 | |||
| 3632 | |||
| 3633 | ;***** DATA AREA ***** | ||
| 3634 | CONSTANTS SEGMENT BYTE | ||
| 3635 | ORG 0 | ||
| 3636 | CONSTRT EQU $ ;Start of constants segment | ||
| 3637 | |||
| 3638 | IONAME: | ||
| 3639 | IF NOT IBM | ||
| 3640 | DB "PRN ","LST ","NUL ","AUX ","CON " | ||
| 3641 | ENDIF | ||
| 3642 | IF IBM | ||
| 3643 | DB "COM1","PRN ","LPT1","NUL ","AUX ","CON " | ||
| 3644 | ENDIF | ||
| 3645 | DIVMES DB 13,10,"Divide overflow",13,10,"$" | ||
| 3646 | CARPOS DB 0 | ||
| 3647 | STARTPOS DB 0 | ||
| 3648 | PFLAG DB 0 | ||
| 3649 | DIRTYDIR DB 0 ;Dirty buffer flag | ||
| 3650 | NUMDRV DB 0 ;Number of drives | ||
| 3651 | NUMIO DB ? ;Number of disk tables | ||
| 3652 | VERFLG DB 0 ;Initialize with verify off | ||
| 3653 | CONTPOS DW 0 | ||
| 3654 | DMAADD DW 80H ;User's disk transfer address (disp/seg) | ||
| 3655 | DW ? | ||
| 3656 | ENDMEM DW ? | ||
| 3657 | MAXSEC DW 0 | ||
| 3658 | BUFFER DW ? | ||
| 3659 | BUFSECNO DW 0 | ||
| 3660 | BUFDRVNO DB -1 | ||
| 3661 | DIRTYBUF DB 0 | ||
| 3662 | BUFDRVBP DW ? | ||
| 3663 | DIRBUFID DW -1 | ||
| 3664 | DAY DB 0 | ||
| 3665 | MONTH DB 0 | ||
| 3666 | YEAR DW 0 | ||
| 3667 | DAYCNT DW -1 | ||
| 3668 | WEEKDAY DB 0 | ||
| 3669 | CURDRV DB 0 ;Default to drive A | ||
| 3670 | DRVTAB DW 0 ;Address of start of DPBs | ||
| 3671 | DOSLEN EQU CODSIZ+($-CONSTRT) ;Size of CODE + CONSTANTS segments | ||
| 3672 | CONSTANTS ENDS | ||
| 3673 | |||
| 3674 | DATA SEGMENT WORD | ||
| 3675 | ; Init code overlaps with data area below | ||
| 3676 | |||
| 3677 | ORG 0 | ||
| 3678 | INBUF DB 128 DUP (?) | ||
| 3679 | CONBUF DB 131 DUP (?) ;The rest of INBUF and console buffer | ||
| 3680 | LASTENT DW ? | ||
| 3681 | EXITHOLD DB 4 DUP (?) | ||
| 3682 | FATBASE DW ? | ||
| 3683 | NAME1 DB 11 DUP (?) ;File name buffer | ||
| 3684 | ATTRIB DB ? | ||
| 3685 | NAME2 DB 11 DUP (?) | ||
| 3686 | NAME3 DB 12 DUP (?) | ||
| 3687 | EXTFCB DB ? | ||
| 3688 | ;WARNING - the following two items are accessed as a word | ||
| 3689 | CREATING DB ? | ||
| 3690 | DELALL DB ? | ||
| 3691 | TEMP LABEL WORD | ||
| 3692 | SPSAVE DW ? | ||
| 3693 | SSSAVE DW ? | ||
| 3694 | CONTSTK DW ? | ||
| 3695 | SECCLUSPOS DB ? ;Position of first sector within cluster | ||
| 3696 | DSKERR DB ? | ||
| 3697 | TRANS DB ? | ||
| 3698 | PREREAD DB ? ;0 means preread; 1 means optional | ||
| 3699 | READOP DB ? | ||
| 3700 | THISDRV DB ? | ||
| 3701 | |||
| 3702 | EVEN | ||
| 3703 | FCB DW ? ;Address of user FCB | ||
| 3704 | NEXTADD DW ? | ||
| 3705 | RECPOS DB 4 DUP (?) | ||
| 3706 | RECCNT DW ? | ||
| 3707 | LASTPOS DW ? | ||
| 3708 | CLUSNUM DW ? | ||
| 3709 | SECPOS DW ? ;Position of first sector accessed | ||
| 3710 | VALSEC DW ? ;Number of valid (previously written) sectors | ||
| 3711 | BYTSECPOS DW ? ;Position of first byte within sector | ||
| 3712 | BYTPOS DB 4 DUP (?) ;Byte position in file of access | ||
| 3713 | BYTCNT1 DW ? ;No. of bytes in first sector | ||
| 3714 | BYTCNT2 DW ? ;No. of bytes in last sector | ||
| 3715 | SECCNT DW ? ;No. of whole sectors | ||
| 3716 | ENTFREE DW ? | ||
| 3717 | |||
| 3718 | DB 80H DUP (?) ;Stack space | ||
| 3719 | IOSTACK LABEL BYTE | ||
| 3720 | DB 80H DUP (?) | ||
| 3721 | DSKSTACK LABEL BYTE | ||
| 3722 | |||
| 3723 | IF DSKTEST | ||
| 3724 | NSS DW ? | ||
| 3725 | NSP DW ? | ||
| 3726 | ENDIF | ||
| 3727 | |||
| 3728 | DIRBUF LABEL WORD | ||
| 3729 | |||
| 3730 | ;Init code below overlaps with data area above | ||
| 3731 | |||
| 3732 | ORG 0 | ||
| 3733 | |||
| 3734 | MOVFAT: | ||
| 3735 | ;This section of code is safe from being overwritten by block move | ||
| 3736 | REP MOVS BYTE PTR [DI],[SI] | ||
| 3737 | CLD | ||
| 3738 | MOV ES:[DMAADD+2],DX | ||
| 3739 | MOV SI,[DRVTAB] ;Address of first DPB | ||
| 3740 | MOV AL,-1 | ||
| 3741 | MOV CL,[NUMIO] ;Number of DPBs | ||
| 3742 | FLGFAT: | ||
| 3743 | MOV DI,ES:[SI.FAT] ;get pointer to FAT | ||
| 3744 | DEC DI ;Point to dirty byte | ||
| 3745 | STOSB ;Flag as unused | ||
| 3746 | ADD SI,DPBSIZ ;Point to next DPB | ||
| 3747 | LOOP FLGFAT | ||
| 3748 | MOV AX,[ENDMEM] | ||
| 3749 | CALL SETMEM ;Set up segment | ||
| 3750 | |||
| 3751 | XXX PROC FAR | ||
| 3752 | RET | ||
| 3753 | XXX ENDP | ||
| 3754 | |||
| 3755 | DOSINIT: | ||
| 3756 | CLI | ||
| 3757 | CLD | ||
| 3758 | PUSH CS | ||
| 3759 | POP ES | ||
| 3760 | MOV ES:[ENDMEM],DX | ||
| 3761 | LODSB ;Get no. of drives & no. of I/O drivers | ||
| 3762 | MOV ES:[NUMIO],AL | ||
| 3763 | MOV DI,OFFSET DOSGROUP:MEMSTRT | ||
| 3764 | PERDRV: | ||
| 3765 | MOV BP,DI | ||
| 3766 | MOV AL,ES:[DRVCNT] | ||
| 3767 | STOSB ;DEVNUM | ||
| 3768 | LODSB ;Physical unit no. | ||
| 3769 | STOSB ;DRVNUM | ||
| 3770 | CMP AL,15 | ||
| 3771 | JA BADINIT | ||
| 3772 | CBW ;Index into FAT size table | ||
| 3773 | SHL AX,1 | ||
| 3774 | ADD AX,OFFSET DOSGROUP:FATSIZTAB | ||
| 3775 | XCHG BX,AX | ||
| 3776 | LODSW ;Pointer to DPT | ||
| 3777 | PUSH SI | ||
| 3778 | MOV SI,AX | ||
| 3779 | LODSW | ||
| 3780 | STOSW ;SECSIZ | ||
| 3781 | MOV DX,AX | ||
| 3782 | CMP AX,ES:[MAXSEC] | ||
| 3783 | JBE NOTMAX | ||
| 3784 | MOV ES:[MAXSEC],AX | ||
| 3785 | NOTMAX: | ||
| 3786 | LODSB | ||
| 3787 | DEC AL | ||
| 3788 | STOSB ;CLUSMSK | ||
| 3789 | JZ HAVSHFT | ||
| 3790 | CBW | ||
| 3791 | FIGSHFT: | ||
| 3792 | INC AH | ||
| 3793 | SAR AL,1 | ||
| 3794 | JNZ FIGSHFT | ||
| 3795 | MOV AL,AH | ||
| 3796 | HAVSHFT: | ||
| 3797 | STOSB ;CLUSSHFT | ||
| 3798 | MOVSW ;FIRFAT (= number of reserved sectors) | ||
| 3799 | MOVSB ;FATCNT | ||
| 3800 | MOVSW ;MAXENT | ||
| 3801 | MOV AX,DX ;SECSIZ again | ||
| 3802 | MOV CL,5 | ||
| 3803 | SHR AX,CL | ||
| 3804 | MOV CX,AX ;Directory entries per sector | ||
| 3805 | DEC AX | ||
| 3806 | ADD AX,ES:[BP.MAXENT] | ||
| 3807 | XOR DX,DX | ||
| 3808 | DIV CX | ||
| 3809 | STOSW ;DIRSEC (temporarily) | ||
| 3810 | MOVSW ;DSKSIZ (temporarily) | ||
| 3811 | FNDFATSIZ: | ||
| 3812 | MOV AL,1 | ||
| 3813 | MOV DX,1 | ||
| 3814 | GETFATSIZ: | ||
| 3815 | PUSH DX | ||
| 3816 | CALL FIGFATSIZ | ||
| 3817 | POP DX | ||
| 3818 | CMP AL,DL ;Compare newly computed FAT size with trial | ||
| 3819 | JZ HAVFATSIZ ;Has sequence converged? | ||
| 3820 | CMP AL,DH ;Compare with previous trial | ||
| 3821 | MOV DH,DL | ||
| 3822 | MOV DL,AL ;Shuffle trials | ||
| 3823 | JNZ GETFATSIZ ;Continue iterations if not oscillating | ||
| 3824 | DEC WORD PTR ES:[BP.DSKSIZ] ;Damp those oscillations | ||
| 3825 | JMP SHORT FNDFATSIZ ;Try again | ||
| 3826 | |||
| 3827 | BADINIT: | ||
| 3828 | MOV SI,OFFSET DOSGROUP:BADMES | ||
| 3829 | CALL OUTMES | ||
| 3830 | STI | ||
| 3831 | HLT | ||
| 3832 | |||
| 3833 | HAVFATSIZ: | ||
| 3834 | STOSB ;FATSIZ | ||
| 3835 | MUL ES:BYTE PTR[BP.FATCNT] ;Space occupied by all FATs | ||
| 3836 | ADD AX,ES:[BP.FIRFAT] | ||
| 3837 | STOSW ;FIRDIR | ||
| 3838 | ADD AX,ES:[BP.DIRSEC] | ||
| 3839 | MOV ES:[BP.FIRREC],AX ;Destroys DIRSEC | ||
| 3840 | CALL FIGMAX | ||
| 3841 | MOV ES:[BP.MAXCLUS],CX | ||
| 3842 | MOV AX,BX ;Pointer into FAT size table | ||
| 3843 | STOSW ;Allocate space for FAT pointer | ||
| 3844 | MOV AL,ES:[BP.FATSIZ] | ||
| 3845 | XOR AH,AH | ||
| 3846 | MUL ES:[BP.SECSIZ] | ||
| 3847 | CMP AX,ES:[BX] ;Bigger than already allocated | ||
| 3848 | JBE SMFAT | ||
| 3849 | MOV ES:[BX],AX | ||
| 3850 | SMFAT: | ||
| 3851 | POP SI ;Restore pointer to init. table | ||
| 3852 | MOV AL,ES:[DRVCNT] | ||
| 3853 | INC AL | ||
| 3854 | MOV ES:[DRVCNT],AL | ||
| 3855 | CMP AL,ES:[NUMIO] | ||
| 3856 | JAE CONTINIT | ||
| 3857 | JMP PERDRV | ||
| 3858 | |||
| 3859 | BADINITJ: | ||
| 3860 | JMP BADINIT | ||
| 3861 | |||
| 3862 | CONTINIT: | ||
| 3863 | PUSH CS | ||
| 3864 | POP DS | ||
| 3865 | ;Calculate true address of buffers, FATs, free space | ||
| 3866 | MOV BP,[MAXSEC] | ||
| 3867 | MOV AX,OFFSET DOSGROUP:DIRBUF | ||
| 3868 | ADD AX,BP | ||
| 3869 | MOV [BUFFER],AX ;Start of buffer | ||
| 3870 | ADD AX,BP | ||
| 3871 | MOV [DRVTAB],AX ;Start of DPBs | ||
| 3872 | SHL BP,1 ;Two sectors - directory and buffer | ||
| 3873 | ADD BP,DI ;Allocate buffer space | ||
| 3874 | ADD BP,ADJFAC ;True address of FATs | ||
| 3875 | PUSH BP | ||
| 3876 | MOV SI,OFFSET DOSGROUP:FATSIZTAB | ||
| 3877 | MOV DI,SI | ||
| 3878 | MOV CX,16 | ||
| 3879 | TOTFATSIZ: | ||
| 3880 | INC BP ;Add one for Dirty byte | ||
| 3881 | INC BP ;Add one for I/O device number | ||
| 3882 | LODSW ;Get size of this FAT | ||
| 3883 | XCHG AX,BP | ||
| 3884 | STOSW ;Save address of this FAT | ||
| 3885 | ADD BP,AX ;Compute size of next FAT | ||
| 3886 | CMP AX,BP ;If size was zero done | ||
| 3887 | LOOPNZ TOTFATSIZ | ||
| 3888 | MOV AL,15 | ||
| 3889 | SUB AL,CL ;Compute number of FATs used | ||
| 3890 | MOV [NUMDRV],AL | ||
| 3891 | XOR AX,AX ;Set zero flag | ||
| 3892 | REPZ SCASW ;Make sure all other entries are zero | ||
| 3893 | JNZ BADINITJ | ||
| 3894 | ADD BP,15 ;True start of free space | ||
| 3895 | MOV CL,4 | ||
| 3896 | SHR BP,CL ;First free segment | ||
| 3897 | MOV DX,CS | ||
| 3898 | ADD DX,BP | ||
| 3899 | MOV BX,0FH | ||
| 3900 | MOV CX,[ENDMEM] | ||
| 3901 | CMP CX,1 ;Use memory scan? | ||
| 3902 | JNZ SETEND | ||
| 3903 | MOV CX,DX ;Start scanning just after DOS | ||
| 3904 | MEMSCAN: | ||
| 3905 | INC CX | ||
| 3906 | JZ SETEND | ||
| 3907 | MOV DS,CX | ||
| 3908 | MOV AL,[BX] | ||
| 3909 | NOT AL | ||
| 3910 | MOV [BX],AL | ||
| 3911 | CMP AL,[BX] | ||
| 3912 | NOT AL | ||
| 3913 | MOV [BX],AL | ||
| 3914 | JZ MEMSCAN | ||
| 3915 | SETEND: | ||
| 3916 | IF HIGHMEM | ||
| 3917 | SUB CX,BP | ||
| 3918 | MOV BP,CX ;Segment of DOS | ||
| 3919 | MOV DX,CS ;Program segment | ||
| 3920 | ENDIF | ||
| 3921 | IF NOT HIGHMEM | ||
| 3922 | MOV BP,CS | ||
| 3923 | ENDIF | ||
| 3924 | ; BP has segment of DOS (whether to load high or run in place) | ||
| 3925 | ; DX has program segment (whether after DOS or overlaying DOS) | ||
| 3926 | ; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM) | ||
| 3927 | MOV CS:[ENDMEM],CX | ||
| 3928 | IF HIGHMEM | ||
| 3929 | MOV ES,BP | ||
| 3930 | XOR SI,SI | ||
| 3931 | MOV DI,SI | ||
| 3932 | MOV CX,(DOSLEN+1)/2 | ||
| 3933 | PUSH CS | ||
| 3934 | POP DS | ||
| 3935 | REP MOVSW ;Move DOS to high memory | ||
| 3936 | ENDIF | ||
| 3937 | XOR AX,AX | ||
| 3938 | MOV DS,AX | ||
| 3939 | MOV ES,AX | ||
| 3940 | MOV DI,INTBASE | ||
| 3941 | MOV AX,OFFSET DOSGROUP:QUIT | ||
| 3942 | STOSW ;Set abort address--displacement | ||
| 3943 | MOV AX,BP | ||
| 3944 | MOV BYTE PTR DS:[ENTRYPOINT],LONGJUMP | ||
| 3945 | MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:ENTRY | ||
| 3946 | MOV WORD PTR DS:[ENTRYPOINT+3],AX | ||
| 3947 | MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ;Set default divide trap address | ||
| 3948 | MOV DS:[2],AX | ||
| 3949 | MOV CX,9 | ||
| 3950 | REP STOSW ;Set 5 segments (skip 2 between each) | ||
| 3951 | MOV WORD PTR DS:[INTBASE+4],OFFSET DOSGROUP:COMMAND | ||
| 3952 | MOV WORD PTR DS:[INTBASE+12],OFFSET DOSGROUP:IRET ;Ctrl-C exit | ||
| 3953 | MOV WORD PTR DS:[INTBASE+16],OFFSET DOSGROUP:IRET ;Fatal error exit | ||
| 3954 | MOV AX,OFFSET BIOSREAD | ||
| 3955 | STOSW | ||
| 3956 | MOV AX,BIOSSEG | ||
| 3957 | STOSW | ||
| 3958 | STOSW ;Add 2 to DI | ||
| 3959 | STOSW | ||
| 3960 | MOV WORD PTR DS:[INTBASE+18H],OFFSET BIOSWRITE | ||
| 3961 | MOV WORD PTR DS:[EXIT],100H | ||
| 3962 | MOV WORD PTR DS:[EXIT+2],DX | ||
| 3963 | IF NOT IBM | ||
| 3964 | MOV SI,OFFSET DOSGROUP:HEADER | ||
| 3965 | CALL OUTMES | ||
| 3966 | ENDIF | ||
| 3967 | PUSH CS | ||
| 3968 | POP DS | ||
| 3969 | PUSH CS | ||
| 3970 | POP ES | ||
| 3971 | ;Move the FATs into position | ||
| 3972 | MOV AL,[NUMIO] | ||
| 3973 | CBW | ||
| 3974 | XCHG AX,CX | ||
| 3975 | MOV DI,OFFSET DOSGROUP:MEMSTRT.FAT | ||
| 3976 | FATPOINT: | ||
| 3977 | MOV SI,WORD PTR [DI] ;Get address within FAT address table | ||
| 3978 | MOVSW ;Set address of this FAT | ||
| 3979 | ADD DI,DPBSIZ-2 ;Point to next DPB | ||
| 3980 | LOOP FATPOINT | ||
| 3981 | POP CX ;True address of first FAT | ||
| 3982 | MOV SI,OFFSET DOSGROUP:MEMSTRT ;Place to move DPBs from | ||
| 3983 | MOV DI,[DRVTAB] ;Place to move DPBs to | ||
| 3984 | SUB CX,DI ;Total length of DPBs | ||
| 3985 | CMP DI,SI | ||
| 3986 | JBE MOVJMP ;Are we moving to higher or lower memory? | ||
| 3987 | DEC CX ;Move backwards to higher memory | ||
| 3988 | ADD DI,CX | ||
| 3989 | ADD SI,CX | ||
| 3990 | INC CX | ||
| 3991 | STD | ||
| 3992 | MOVJMP: | ||
| 3993 | MOV ES,BP | ||
| 3994 | JMP MOVFAT | ||
| 3995 | |||
| 3996 | FIGFATSIZ: | ||
| 3997 | MUL ES:BYTE PTR[BP.FATCNT] | ||
| 3998 | ADD AX,ES:[BP.FIRFAT] | ||
| 3999 | ADD AX,ES:[BP.DIRSEC] | ||
| 4000 | FIGMAX: | ||
| 4001 | ;AX has equivalent of FIRREC | ||
| 4002 | SUB AX,ES:[BP.DSKSIZ] | ||
| 4003 | NEG AX | ||
| 4004 | MOV CL,ES:[BP.CLUSSHFT] | ||
| 4005 | SHR AX,CL | ||
| 4006 | INC AX | ||
| 4007 | MOV CX,AX ;MAXCLUS | ||
| 4008 | INC AX | ||
| 4009 | MOV DX,AX | ||
| 4010 | SHR DX,1 | ||
| 4011 | ADC AX,DX ;Size of FAT in bytes | ||
| 4012 | MOV SI,ES:[BP.SECSIZ] | ||
| 4013 | ADD AX,SI | ||
| 4014 | DEC AX | ||
| 4015 | XOR DX,DX | ||
| 4016 | DIV SI | ||
| 4017 | RET | ||
| 4018 | |||
| 4019 | BADMES: | ||
| 4020 | DB 13,10,"INIT TABLE BAD",13,10,"$" | ||
| 4021 | |||
| 4022 | FATSIZTAB: | ||
| 4023 | DW 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 | ||
| 4024 | |||
| 4025 | DRVCNT DB 0 | ||
| 4026 | |||
| 4027 | MEMSTRT LABEL WORD | ||
| 4028 | ADJFAC EQU DIRBUF-MEMSTRT | ||
| 4029 | DATA ENDS | ||
| 4030 | END | ||
| 4031 | \ No newline at end of file | ||