2259 lines
32 KiB
Plaintext
2259 lines
32 KiB
Plaintext
; QDOS High-performance operating system for the 8086 version 0.11
|
|
; by Tim Paterson
|
|
|
|
|
|
; Interrupt Entry Points:
|
|
|
|
; INTBASE: ABORT
|
|
; INTBASE+4: COMMAND
|
|
; INTBASE+8: BASE EXIT ADDRESS
|
|
; INTBASE+C: CONTROL-C ABORT
|
|
; INTBASE+10H: FATAL ERROR ABORT
|
|
; INTBASE+14H: BIOS DISK READ
|
|
; INTBASE+18H: BIOS DISK WRITE
|
|
; INTBASE+40H: Long jump to CALL entry point
|
|
|
|
|
|
MAXCALL:EQU 36
|
|
MAXCOM: EQU 40
|
|
ESCCH: EQU 1BH
|
|
INTBASE:EQU 80H
|
|
INTTAB: EQU 20H
|
|
ENTRYPOINTSEG: EQU 0CH
|
|
ENTRYPOINT: EQU INTBASE+40H
|
|
CONTC: EQU INTTAB+3
|
|
EXIT: EQU INTBASE+8
|
|
LONGJUMP:EQU 0EAH
|
|
LONGCALL:EQU 9AH
|
|
MAXDIF: EQU 0FFFH
|
|
SAVEXIT:EQU 10
|
|
|
|
; Field definition for FCBs
|
|
|
|
ORG 0
|
|
DS 12 ;Drive code and name
|
|
EXTENT: DS 4
|
|
ENTPOS: DS 2 ;Position of entry in directory
|
|
DRVBP: DS 2 ;BP for SEARCH FIRST and SEARCH NEXT
|
|
FIRCLUS:DS 2 ;First cluster of file
|
|
LSTCLUS:DS 2 ;Last cluster accessed
|
|
FILSIZ: DS 2 ;Size of file in records
|
|
CLUSPOS:DS 2 ;Position of last cluster accessed
|
|
DIRTYFIL:DS 1 ;File has been written to if <>0
|
|
SIZCHG: DS 1 ;Directory needs update if <>0
|
|
ORG 32
|
|
NR: DS 1 ;Next record
|
|
RR: DS 3 ;Random record
|
|
|
|
|
|
; Description of 16-byte directory entry (same as returned by SEARCH FIRST
|
|
; and SEARCH NEXT, functions 17 and 18).
|
|
;
|
|
; Location bytes Description
|
|
;
|
|
; 0 11 File name and extension ( 0E5H if empty)
|
|
; 11 2 First allocation unit ( < 4080 )
|
|
; 13 3 File size, in bytes (LSB first, 24 bits max.)
|
|
|
|
|
|
; Field definition for Drive Parameter Block
|
|
|
|
ORG 0
|
|
DRVNUM: DS 1 ;Drive number
|
|
SECSIZ: DS 1 ;Size of physical sector in records
|
|
CLUSMSK:DS 1 ;Records/cluster - 1
|
|
CLUSSHFT:DS 1 ;Log2 of records/cluster
|
|
FIRFAT: DS 2 ;Starting record of FATs
|
|
FATSIZ: DS 1 ;Number of records occupied by FAT
|
|
FATCNT: DS 1 ;Number of FATs for this drive
|
|
FIRDIR: DS 2 ;Starting record of directory
|
|
DIRSIZ: DS 1 ;Number of records occupied by directory
|
|
FIRREC: DS 2 ;First record of first cluster
|
|
MAXCLUS:DS 2 ;Number of clusters on drive + 1
|
|
DIRTYFAT:DS 1 ;-1=FAT has been changed
|
|
FAT: DS 2 ;Start of FAT
|
|
|
|
DPBSIZ: EQU $
|
|
|
|
|
|
; BIOS entry point defintions
|
|
|
|
BIOSSEG: EQU 40H
|
|
ORG 0
|
|
DS 3
|
|
BIOSSTAT: DS 3
|
|
BIOSIN: DS 3
|
|
BIOSOUT: DS 3
|
|
BIOSPRINT: DS 3
|
|
BIOSAUXIN: DS 3
|
|
BIOSAUXOUT: DS 3
|
|
BIOSREAD: DS 3
|
|
BIOSWRITE: DS 3
|
|
BIOSFLUSH: DS 3
|
|
|
|
|
|
; Start of code
|
|
|
|
ORG 0
|
|
PUT 100H
|
|
|
|
JMP DOSINIT
|
|
|
|
ESCTAB:
|
|
DB "SC" ;Copy one char
|
|
DB "VN" ;Skip one char
|
|
DB "TA" ;Copy to char
|
|
DB "WB" ;Skip to char
|
|
DB "UH" ;Copy line
|
|
DB "HH" ;Kill line (no change in template)
|
|
DB "RM" ;Reedit line (new template)
|
|
DB "DD" ;Backspace
|
|
DB "P@" ;Enter insert mode
|
|
DB "QL" ;Exit insert mode
|
|
DB ESCCH,ESCCH ;Escape character
|
|
DB ESCCH,ESCCH ;End of table
|
|
|
|
ESCTABLEN:EQU $-ESCTAB
|
|
|
|
HEADER: DB 13,10,"86-DOS version 0.11"
|
|
DB 13,10
|
|
DB "Copyright 1980 Seattle Computer Products, Inc.",13,10,"$"
|
|
|
|
DOSINIT:
|
|
DI
|
|
UP
|
|
MOV AX,CS
|
|
MOV ES,AX
|
|
LODB
|
|
CBW
|
|
MOV CX,AX
|
|
SEG CS
|
|
MOV [NUMDRV],AL
|
|
MOV DI,AX
|
|
SHL DI
|
|
MOV AH,DPBSIZ
|
|
MUL AX,AH
|
|
MOV BX,DRVTAB
|
|
ADD DI,BX
|
|
ADD AX,DI
|
|
MOV BP,AX
|
|
SEG CS
|
|
MOV [FATBASE],AX
|
|
PERDEV:
|
|
SEG CS
|
|
MOV [BX],DI
|
|
INC BX
|
|
INC BX
|
|
MOV AL,CH
|
|
STOB ;DRVNUM
|
|
LODW ;Pointer to DPT
|
|
PUSH SI
|
|
MOV SI,AX
|
|
MOVB ;SECSIZ
|
|
LODB
|
|
DEC AL
|
|
STOB ;CLUSMSK
|
|
CBW
|
|
FIGSHFT:
|
|
INC AH
|
|
SAR AL
|
|
JNZ FIGSHFT
|
|
MOV AL,AH
|
|
STOB ;CLUSSHFT
|
|
LODW
|
|
STOW ;FIRFAT (= number of reserved records)
|
|
MOV DX,AX
|
|
LODB
|
|
STOB ;FATSIZ
|
|
MOV AH,AL
|
|
PUSH AX
|
|
LODB
|
|
STOB ;FATCNT
|
|
MUL AX,AH
|
|
ADD AX,DX
|
|
STOW ;FIRDIR
|
|
MOV DX,AX
|
|
LODB
|
|
STOB ;DIRSIZ
|
|
CBW
|
|
ADD AX,DX
|
|
STOW ;FIRREC
|
|
POP DX
|
|
LODW
|
|
INC AX
|
|
STOW ;MAXCLUS
|
|
XOR AL,AL
|
|
STOB
|
|
POP SI ;Restore pointer to init. table
|
|
LODW ;Allocation table displacement
|
|
SEG CS
|
|
ADD AX,[FATBASE]
|
|
STOW ;FAT
|
|
MOV DL,0
|
|
SHR DX ;FAT size in bytes
|
|
ADD AX,DX
|
|
CMP AX,BP ;Bigger than already allocated
|
|
JBE SMFAT
|
|
MOV BP,AX
|
|
SMFAT:
|
|
INC CH ;Next I/O device number
|
|
DEC CL
|
|
JNZ PERDEV
|
|
ADD BP,15 ;True start of free space
|
|
MOV CL,4
|
|
SHR BP,CL ;First free segment
|
|
XOR AX,AX
|
|
MOV DS,AX
|
|
MOV ES,AX
|
|
MOV DI,INTBASE
|
|
MOV AX,QUIT
|
|
STOW ;Set abort address--displacement
|
|
MOV AX,CS
|
|
MOV B,[ENTRYPOINT],LONGJUMP
|
|
MOV [ENTRYPOINT+1],ENTRY
|
|
MOV [ENTRYPOINT+3],CS
|
|
STOW
|
|
STOW
|
|
STOW
|
|
MOV [INTBASE+4],COMMAND
|
|
MOV DI,INTBASE+14H
|
|
MOV AX,BIOSREAD
|
|
STOW
|
|
MOV AX,BIOSSEG
|
|
STOW
|
|
STOW ;Add 2 to DI
|
|
STOW
|
|
MOV [INTBASE+18H],BIOSWRITE
|
|
MOV DX,CS
|
|
MOV DS,DX
|
|
ADD DX,BP
|
|
MOV [DMAADD],80H
|
|
MOV [DMAADD+2],DX
|
|
MOV AX,[DRVTAB]
|
|
MOV [CURDRVPT],AX
|
|
MOV CX,DX
|
|
MOV BX,0FH
|
|
MEMSCAN:
|
|
INC CX
|
|
JZ HAVMEM
|
|
MOV DS,CX
|
|
MOV AL,[BX]
|
|
NOT AL
|
|
MOV [BX],AL
|
|
CMP AL,[BX]
|
|
NOT AL
|
|
MOV [BX],AL
|
|
JZ MEMSCAN
|
|
HAVMEM:
|
|
SEG CS
|
|
MOV [ENDMEM],CX
|
|
XOR CX,CX
|
|
MOV DS,CX
|
|
MOV [EXIT],100H
|
|
MOV [EXIT+2],DX
|
|
MOV [INTBASE+0CH],100H
|
|
MOV [INTBASE+0EH],DX
|
|
CALL SETMEM
|
|
MOV SI,HEADER
|
|
CALL OUTMES
|
|
RET L
|
|
|
|
QUIT:
|
|
MOV AH,0
|
|
JP SAVREGS
|
|
|
|
COMMAND: ;Interrupt call entry point
|
|
CMP AH,MAXCOM
|
|
JBE SAVREGS
|
|
BADCALL:
|
|
MOV AL,0
|
|
IRET: IRET
|
|
|
|
ENTRY: ;System call entry point and dispatcher
|
|
POP AX ;IP from the long call at 5
|
|
POP AX ;Segment from the long call at 5
|
|
SEG CS
|
|
POP [TEMP] ;IP from the CALL 5
|
|
PUSHF ;Start re-ordering the stack
|
|
DI
|
|
PUSH AX ;Save segment
|
|
SEG CS
|
|
PUSH [TEMP] ;Stack now ordered as if INT had been used
|
|
CMP CL,MAXCALL ;This entry point doesn't get as many calls
|
|
JA BADCALL
|
|
MOV AH,CL
|
|
SAVREGS:
|
|
SEG CS
|
|
MOV [SPSAVE],SP
|
|
SEG CS
|
|
MOV [SSSAVE],SS
|
|
INC SP
|
|
INC SP
|
|
SEG CS
|
|
POP [TEMP]
|
|
MOV SP,CS
|
|
MOV SS,SP
|
|
MOV SP,STACK
|
|
PUSH ES
|
|
PUSH DS
|
|
PUSH BP
|
|
PUSH DI
|
|
PUSH SI
|
|
PUSH DX
|
|
PUSH CX
|
|
PUSH BX
|
|
PUSH AX
|
|
MOV BL,AH
|
|
MOV BH,0
|
|
SHL BX
|
|
UP
|
|
SEG CS
|
|
CALL [BX+DISPATCH]
|
|
SEG CS
|
|
MOV [AXSAVE],AL
|
|
POP AX
|
|
POP BX
|
|
POP CX
|
|
POP DX
|
|
POP SI
|
|
POP DI
|
|
POP BP
|
|
POP DS
|
|
POP ES
|
|
POP SS
|
|
SEG CS
|
|
MOV SP,[SPSAVE]
|
|
IRET
|
|
|
|
DISPATCH:
|
|
; Standard Functions
|
|
DW ABORT ;0
|
|
DW CONIN
|
|
DW CONOUT
|
|
DW READER
|
|
DW PUNCH
|
|
DW LIST ;5
|
|
DW RAWIO
|
|
DW GETIO
|
|
DW SETIO
|
|
DW PRTBUF
|
|
DW BUFIN ;10
|
|
DW CONSTAT
|
|
DW VERSION
|
|
DW DSKRESET
|
|
DW SELDSK
|
|
DW OPEN ;15
|
|
DW CLOSE
|
|
DW SRCHFRST
|
|
DW SRCHNXT
|
|
DW DELETE
|
|
DW SEQRD ;20
|
|
DW SEQWRT
|
|
DW CREATE
|
|
DW RENAME
|
|
DW INUSE
|
|
DW CURDRV ;25
|
|
DW SETDMA
|
|
DW GETFATPT
|
|
DW WRTPROT
|
|
DW GETRDONLY
|
|
DW SETATTRIB ;30
|
|
DW GETDSKPT
|
|
DW USERCODE
|
|
DW RNDRD
|
|
DW RNDWRT
|
|
DW FILESIZE ;35
|
|
DW SETRNDREC
|
|
; Extended Functions
|
|
DW SETVECT
|
|
DW NEWBASE
|
|
DW BLKRD
|
|
DW BLKWRT ;40
|
|
|
|
VERSION:
|
|
GETIO:
|
|
SETIO:
|
|
WRTPROT:
|
|
GETRDONLY:
|
|
SETATTRIB:
|
|
USERCODE:
|
|
MOV AL,0
|
|
RET
|
|
|
|
|
|
READER:
|
|
CALL BIOSAUXIN,BIOSSEG
|
|
RET
|
|
|
|
PUNCH:
|
|
MOV AL,DL
|
|
CALL BIOSAUXOUT,BIOSSEG
|
|
RET
|
|
|
|
|
|
UNPACK:
|
|
|
|
; Inputs:
|
|
; DS = CS
|
|
; BX = Cluster number
|
|
; BP = Base of drive parameters
|
|
; SI = Pointer to drive FAT
|
|
; Outputs:
|
|
; DI = Contents of FAT for given cluster
|
|
; Zero set means DI=0 (free cluster)
|
|
; No other registers affected. Fatal error if cluster too big.
|
|
|
|
CMP BX,[BP+MAXCLUS]
|
|
JA HURTFAT
|
|
LEA DI,[SI+BX]
|
|
SHR BX
|
|
MOV DI,[DI+BX]
|
|
JNC HAVCLUS
|
|
SHR DI
|
|
SHR DI
|
|
SHR DI
|
|
SHR DI
|
|
STC
|
|
HAVCLUS:
|
|
RCL BX
|
|
AND DI,0FFFH
|
|
RET
|
|
HURTFAT:
|
|
MOV SI,BADMES
|
|
CALL OUTMES
|
|
JMP ERROR
|
|
|
|
|
|
PACK:
|
|
|
|
; Inputs:
|
|
; DS = CS
|
|
; BX = Cluster number
|
|
; DX = Data
|
|
; SI = Pointer to drive FAT
|
|
; Outputs:
|
|
; The data is stored in the FAT at the given cluster.
|
|
; BX,DX,DI all destroyed
|
|
; No other registers affected
|
|
|
|
MOV DI,BX
|
|
SHR BX
|
|
ADD BX,SI
|
|
ADD BX,DI
|
|
SHR DI
|
|
MOV DI,[BX]
|
|
JNC ALIGNED
|
|
SHL DX
|
|
SHL DX
|
|
SHL DX
|
|
SHL DX
|
|
AND DI,0FH
|
|
JP PACKIN
|
|
ALIGNED:
|
|
AND DI,0F000H
|
|
PACKIN:
|
|
OR DI,DX
|
|
MOV [BX],DI
|
|
RET
|
|
|
|
GETFILE:
|
|
|
|
; Inputs:
|
|
; DS,DX point to FCB
|
|
; Function:
|
|
; Find file name in disk directory. First byte is
|
|
; drive number (0=current disk). "?" matches any
|
|
; character.
|
|
; Outputs:
|
|
; Carry set if file not found
|
|
; ELSE
|
|
; BP = Base of drive parameters
|
|
; DS = CS
|
|
; ES = CS
|
|
; AL = Directory record number
|
|
; BX = Pointer into directory buffer
|
|
; SI = Pointer to First Cluster field in directory entry
|
|
; [DIRBUF] has directory record with match
|
|
; [NAME1] has file name
|
|
; All other registers destroyed.
|
|
|
|
CALL MOVNAME
|
|
JC RET ;Bad file name?
|
|
FINDNAME:
|
|
MOV AX,CS
|
|
MOV DS,AX
|
|
MOV AL,0
|
|
RDIRREC:
|
|
PUSH AX
|
|
CALL DIRREAD
|
|
POP AX
|
|
MOV BX,DIRBUF-16
|
|
CONTSRCH:
|
|
CALL NEXTENT
|
|
JZ RET
|
|
NDIRREC:
|
|
INC AL ;Next directory record
|
|
CMP AL,[BP+DIRSIZ]
|
|
JB RDIRREC
|
|
STC
|
|
RET
|
|
|
|
NEXTENT:
|
|
ADD BX,16
|
|
CMP BX,DIRBUF+127
|
|
JA RET
|
|
CMP B,[BX],0E5H
|
|
JZ NEXTENT
|
|
MOV SI,BX
|
|
MOV DI,NAME1
|
|
MOV CX,11
|
|
WILDCRD:
|
|
REPE
|
|
CMPB
|
|
JZ RET
|
|
CMP B,[DI-1],"?"
|
|
JZ WILDCRD
|
|
JP NEXTENT
|
|
|
|
|
|
DELETE: ; System call 19
|
|
CALL GETFILE
|
|
JC ERRET
|
|
PUSH AX
|
|
PUSH BX
|
|
CALL FATREAD
|
|
POP BX
|
|
DELFILE:
|
|
MOV B,[BX],0E5H
|
|
PUSH BX
|
|
MOV BX,[BX+11]
|
|
MOV SI,[BP+FAT]
|
|
OR BX,BX
|
|
JZ DELNXT
|
|
CMP BX,[BP+MAXCLUS]
|
|
JA DELNXT
|
|
CALL RELEASE
|
|
DELNXT:
|
|
POP BX
|
|
CALL NEXTENT
|
|
JZ DELFILE
|
|
POP AX
|
|
PUSH AX
|
|
CALL DIRWRITE
|
|
POP AX
|
|
CALL NDIRREC
|
|
PUSH AX
|
|
JNC DELFILE
|
|
POP AX
|
|
CALL FATWRT
|
|
XOR AL,AL
|
|
RET
|
|
|
|
|
|
RENAME: ;System call 23
|
|
CALL MOVNAME
|
|
JC ERRET
|
|
ADD SI,5
|
|
MOV DI,NAME2
|
|
CALL LODNAME
|
|
CALL FINDNAME
|
|
JC ERRET
|
|
SAVDREC:
|
|
MOV AH,AL
|
|
RENFIL:
|
|
MOV DI,BX
|
|
MOV SI,NAME2
|
|
MOV CX,11
|
|
NEWNAM:
|
|
LODB
|
|
CMP AL,"?"
|
|
JZ NOCHG
|
|
MOV [DI],AL
|
|
NOCHG:
|
|
INC DI
|
|
LOOP NEWNAM
|
|
CALL NEXTENT
|
|
JZ RENFIL
|
|
MOV AL,AH
|
|
PUSH AX
|
|
CALL DIRWRITE
|
|
POP AX
|
|
CALL NDIRREC
|
|
JNC SAVDREC ;New record read, save current number
|
|
XOR AL,AL
|
|
RET
|
|
|
|
ERRET:
|
|
MOV AL,-1
|
|
RET
|
|
|
|
|
|
MOVNAME:
|
|
|
|
; Inputs:
|
|
; DS, DX point to FCB
|
|
; Outputs:
|
|
; ES = CS
|
|
; If file name OK:
|
|
; BP has base of driver parameters
|
|
; [NAME1] has name in upper case
|
|
; All registers except DX destroyed
|
|
; Carry set if bad file name or drive
|
|
|
|
MOV AX,CS
|
|
MOV ES,AX
|
|
MOV DI,NAME1
|
|
MOV SI,DX
|
|
LODB
|
|
SEG ES
|
|
CMP [NUMDRV],AL
|
|
JC RET
|
|
CBW
|
|
XCHG AX,BP
|
|
SHL BP
|
|
MOV BP,[BP+CURDRVPT]
|
|
LODNAME:
|
|
; This entry point copies a file name from DS,SI
|
|
; to ES,DI converting to upper case.
|
|
MOV CX,11
|
|
MOVCHK:
|
|
LODB
|
|
AND AL,7FH
|
|
CMP AL,60H
|
|
JLE CASEOK
|
|
AND AL,5FH
|
|
CASEOK:
|
|
CMP AL,20H
|
|
JC RET
|
|
STOB
|
|
LOOP MOVCHK
|
|
RET
|
|
|
|
OPEN: ;System call 15
|
|
PUSH DX
|
|
PUSH DS
|
|
CALL GETFILE
|
|
DOOPEN:
|
|
; Enter here to perform OPEN on file already found
|
|
; in directory. DS=ES=CS, BX points to directory
|
|
; entry in DIRBUF, and the top of the stack has the
|
|
; address and segment of the FCB to be opened. This
|
|
; entry point is used by CREATE.
|
|
POP ES
|
|
POP DI
|
|
JC ERRET
|
|
MOV AH,[BP+DRVNUM]
|
|
INC AH
|
|
SEG ES
|
|
MOV [DI],AH
|
|
SEG ES
|
|
MOV [DI+EXTENT],0 ;Set extent field to 0
|
|
ADD DI,16 ;Point to entry pos. field
|
|
MOV CX,BX
|
|
SUB CX,DIRBUF
|
|
MOV AH,CL
|
|
STOW ;directory location
|
|
MOV AX,BP
|
|
STOW ;pointer to driver parameters
|
|
LEA SI,[BX+11]
|
|
LODW ;Get starting cluster
|
|
STOW ; first cluster
|
|
STOW ; last cluster accessed
|
|
LODB
|
|
SHL AL
|
|
LODW
|
|
RCL AX
|
|
STOW ; size of file in records
|
|
XOR AX,AX
|
|
STOW ; position of last cluster
|
|
STOW ; file not dirty
|
|
|
|
FATREAD:
|
|
TEST B,[BP+DIRTYFAT],-1
|
|
JNZ RET
|
|
CALL FIGFAT
|
|
NEXTFAT:
|
|
PUSH DX
|
|
PUSH CX
|
|
PUSH BX
|
|
PUSH AX
|
|
CALL DREAD
|
|
OR AL,AL
|
|
POP AX
|
|
POP BX
|
|
POP CX
|
|
POP DX
|
|
JNZ BADFAT
|
|
SUB AL,[BP+FATCNT]
|
|
JZ RET
|
|
NEG AL
|
|
;{Insert error code here. AL=number of bad fats.
|
|
;Since one good FAT was read, should include option
|
|
;to rewrite all FATs.}
|
|
JP FATWRT
|
|
|
|
BADFAT:
|
|
ADD DX,CX
|
|
DEC AL
|
|
JNZ NEXTFAT
|
|
POP BP
|
|
;{Insert error code here. All FATs on drive are bad.}
|
|
MOV SI,BADFATMES
|
|
CALL HARDERR
|
|
JP FATREAD
|
|
|
|
CLOSE: ;System call 16
|
|
MOV DI,DX
|
|
TEST B,[DI+DIRTYFIL],-1
|
|
JZ NOFLSH
|
|
PUSH DI
|
|
MOV BP,[DI+DRVBP]
|
|
MOV AL,[BP+DRVNUM]
|
|
CALL BIOSFLUSH,BIOSSEG
|
|
POP DI
|
|
NOFLSH:
|
|
TEST B,[DI+SIZCHG],-1
|
|
JZ OKRET
|
|
MOV DX,DI
|
|
PUSH DX
|
|
PUSH DS
|
|
CALL GETFILE
|
|
POP ES
|
|
POP DI
|
|
JC BADCLOSE
|
|
MOV CX,BX
|
|
SUB CX,DIRBUF
|
|
MOV AH,CL
|
|
SEG ES
|
|
CMP AX,[DI+ENTPOS]
|
|
JNZ BADCLOSE
|
|
SEG ES
|
|
MOV CX,[DI+FIRCLUS]
|
|
MOV [BX+11],CX
|
|
SEG ES
|
|
MOV DX,[DI+FILSIZ]
|
|
SHR DX
|
|
MOV [BX+14],DX
|
|
MOV DL,0
|
|
RCR DL
|
|
MOV [BX+13],DL
|
|
CALL DIRWRITE
|
|
|
|
CHKFATWRT:
|
|
; Do FATWRT only if FAT is dirty
|
|
|
|
TEST B,[BP+DIRTYFAT],-1
|
|
JZ OKRET
|
|
|
|
FATWRT:
|
|
|
|
; Inputs:
|
|
; DS = CS
|
|
; BP = Base of drive parameter table
|
|
; Function:
|
|
; Write the FAT back to disk and reset FAT
|
|
; dirty bit.
|
|
; Outputs:
|
|
; AL = 0
|
|
; BP unchanged
|
|
; All other registers destroyed
|
|
|
|
MOV B,[BP+DIRTYFAT],0
|
|
CALL FIGFAT
|
|
EACHFAT:
|
|
PUSH DX
|
|
PUSH CX
|
|
PUSH BX
|
|
PUSH AX
|
|
CALL DWRITE
|
|
POP AX
|
|
POP BX
|
|
POP CX
|
|
POP DX
|
|
ADD DX,CX
|
|
DEC AL
|
|
JNZ EACHFAT
|
|
OKRET:
|
|
MOV AL,0
|
|
RET
|
|
|
|
BADCLOSE:
|
|
MOV B,[BP+DIRTYFAT],0
|
|
MOV AL,-1
|
|
RET
|
|
|
|
|
|
FIGFAT:
|
|
; Loads registers with values needed to read or
|
|
; write a FAT.
|
|
MOV AL,[BP+FATCNT]
|
|
MOV BX,[BP+FAT]
|
|
MOV CL,[BP+FATSIZ] ;No. of records occupied by FAT
|
|
MOV CH,0
|
|
MOV DX,[BP+FIRFAT] ;Record number of start of FATs
|
|
RET
|
|
|
|
|
|
DIRCOMP:
|
|
; Prepare registers for directory read or write
|
|
CBW
|
|
ADD AX,[BP+FIRDIR]
|
|
MOV DX,AX
|
|
MOV BX,DIRBUF
|
|
MOV CX,1
|
|
RET
|
|
|
|
|
|
CREATE: ;System call 22
|
|
CALL MOVNAME
|
|
JC ERRET3
|
|
MOV DI,NAME1
|
|
MOV CX,11
|
|
MOV AL,"?"
|
|
REPNE
|
|
SCAB
|
|
JZ ERRET3
|
|
PUSH DX
|
|
PUSH DS
|
|
MOV AX,CS
|
|
MOV DS,AX
|
|
XOR AX,AX
|
|
RDIRREC2:
|
|
PUSH AX
|
|
CALL DIRREAD
|
|
POP AX
|
|
MOV DI,DIRBUF-16
|
|
MOV CX,8
|
|
FNDFRE:
|
|
ADD DI,16
|
|
CMP B,[DI],0E5H
|
|
LOOPNE FNDFRE
|
|
JZ FREESPOT
|
|
INC AL
|
|
CMP AL,[BP+DIRSIZ]
|
|
JC RDIRREC2
|
|
POP DS
|
|
POP DX
|
|
ERRET3:
|
|
MOV AL,-1
|
|
RET
|
|
FREESPOT:
|
|
MOV BX,DI
|
|
MOV SI,NAME1
|
|
MOV CX,5
|
|
MOVB
|
|
REP
|
|
MOVW
|
|
XCHG AL,AH
|
|
MOV CL,5
|
|
REP
|
|
STOB
|
|
XCHG AL,AH
|
|
PUSH AX
|
|
PUSH BX
|
|
CALL DIRWRITE
|
|
POP BX
|
|
POP AX
|
|
JMP DOOPEN
|
|
|
|
|
|
DIRREAD:
|
|
|
|
; Inputs:
|
|
; DS = CS
|
|
; AL = Directory block number
|
|
; BP = Base of drive parameters
|
|
; Function:
|
|
; Read the directory block into DIRBUF.
|
|
; Outputs:
|
|
; BP unchanged
|
|
; All other registers destroyed.
|
|
|
|
CALL DIRCOMP
|
|
|
|
DREAD:
|
|
|
|
; Inputs:
|
|
; BX,DS = Transfer address
|
|
; CX = Number of records
|
|
; DX = Absolute record number
|
|
; BP = Base of drive parameters
|
|
; Function:
|
|
; Calls BIOS to perform disk read. If BIOS reports
|
|
; errors, will call HARDERR for further action.
|
|
; Outputs:
|
|
; AL = 0 if no error, otherwise non-zero
|
|
; BP preserved. All other registers destroyed.
|
|
|
|
MOV AL,[BP+DRVNUM]
|
|
PUSH BP
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
CALL BIOSREAD,BIOSSEG
|
|
POP DX
|
|
POP DI
|
|
POP BX
|
|
POP BP
|
|
JC HARDREAD
|
|
XOR AL,AL
|
|
RET
|
|
|
|
HARDREAD:
|
|
MOV SI,RDERRMES
|
|
CALL HARDERR
|
|
JP DREAD
|
|
|
|
DIRWRITE:
|
|
|
|
; Inputs:
|
|
; DS = CS
|
|
; AL = Directory block number
|
|
; BP = Base of drive parameters
|
|
; Function:
|
|
; Write the directory block into DIRBUF.
|
|
; Outputs:
|
|
; BP unchanged
|
|
; All other registers destroyed.
|
|
|
|
CALL DIRCOMP
|
|
|
|
|
|
DWRITE:
|
|
|
|
; Inputs:
|
|
; BX,DS = Transfer address
|
|
; CX = Number of records
|
|
; DX = Absolute record number
|
|
; BP = Base of drive parameters
|
|
; Function:
|
|
; Calls BIOS to perform disk write. If BIOS reports
|
|
; errors, will call HARDERR for further action.
|
|
; Outputs:
|
|
; AL = 0 if no error, otherwise non-zero
|
|
; BP preserved. All other registers destroyed.
|
|
|
|
MOV AL,[BP+DRVNUM]
|
|
MOV AH,0
|
|
CMP DX,[BP+FIRREC]
|
|
RCR AH
|
|
PUSH BP
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
CALL BIOSWRITE,BIOSSEG
|
|
POP DX
|
|
POP DI
|
|
POP BX
|
|
POP BP
|
|
JC HARDWRITE
|
|
XOR AL,AL
|
|
RET
|
|
HARDWRITE:
|
|
MOV SI,WRTERRMES
|
|
CALL HARDERR
|
|
JP DWRITE
|
|
|
|
HARDERR:
|
|
SUB DI,CX
|
|
ADD DX,DI
|
|
CALL SHFTDI7
|
|
ADD BX,DI
|
|
CALL OUTMES
|
|
GETINSTR:
|
|
CALL IN
|
|
OR AL,20H
|
|
CMP AL,"a"
|
|
JZ ERROR
|
|
CMP AL,"r"
|
|
JZ RET
|
|
CMP AL,"i"
|
|
JZ IGNORE
|
|
CMP AL,"c"
|
|
JNZ GETINSTR
|
|
POP AX
|
|
MOV AL,1
|
|
RET
|
|
IGNORE:
|
|
POP AX
|
|
MOV AL,0
|
|
RET
|
|
|
|
ABORT:
|
|
SEG CS
|
|
MOV DS,[CSLOC]
|
|
XOR AX,AX
|
|
MOV ES,AX
|
|
MOV SI,SAVEXIT
|
|
MOV DI,EXIT
|
|
MOVW
|
|
MOVW
|
|
MOVW
|
|
MOVW
|
|
ERROR:
|
|
MOV SP,BPSAVE
|
|
MOV AX,CS
|
|
MOV DS,AX
|
|
MOV ES,AX
|
|
CALL WRTFATS
|
|
XOR AX,AX
|
|
MOV DS,AX
|
|
MOV SI,EXIT
|
|
MOV DI,EXITHOLD
|
|
MOVW
|
|
MOVW
|
|
POP BP
|
|
POP ES
|
|
POP ES
|
|
POP DS
|
|
POP SS
|
|
MOV SP,[SPSAVE]
|
|
MOV DS,[DSSAVE]
|
|
SEG CS
|
|
JMP L,[EXITHOLD]
|
|
|
|
|
|
SEQRD: ;System call 20
|
|
CALL GETREC
|
|
MOV CX,1
|
|
CALL LOAD
|
|
JCXZ SETNREX
|
|
INC AX
|
|
JP SETNREX
|
|
|
|
SEQWRT: ;System call 21
|
|
CALL GETREC
|
|
MOV CX,1
|
|
CALL STORE
|
|
JCXZ SETNREX
|
|
INC AX
|
|
JP SETNREX
|
|
|
|
RNDRD: ;System call 33
|
|
MOV CX,1
|
|
MOV DI,DX
|
|
MOV AX,[DI+RR]
|
|
CALL LOAD
|
|
JP FINRND
|
|
|
|
RNDWRT: ;System call 34
|
|
MOV CX,1
|
|
MOV DI,DX
|
|
MOV AX,[DI+RR]
|
|
CALL STORE
|
|
JP FINRND
|
|
|
|
BLKRD: ;System call 39
|
|
MOV DI,DX
|
|
MOV AX,[DI+RR]
|
|
CALL LOAD
|
|
JP FINBLK
|
|
|
|
BLKWRT: ;System call 40
|
|
MOV DI,DX
|
|
MOV AX,[DI+RR]
|
|
CALL STORE
|
|
FINBLK:
|
|
MOV [CXSAVE],CX
|
|
JCXZ FINRND
|
|
INC AX
|
|
FINRND:
|
|
SEG ES
|
|
MOV [DI+RR],AX
|
|
SETNREX:
|
|
MOV CX,AX
|
|
AND AL,7FH
|
|
SEG ES
|
|
MOV [DI+NR],AL
|
|
AND CL,80H
|
|
ROL CX
|
|
XCHG CL,CH
|
|
SEG ES
|
|
MOV [DI+EXTENT],CX
|
|
MOV AL,[DSKERR]
|
|
RET
|
|
|
|
SETUP:
|
|
|
|
; Inputs:
|
|
; DS:DI point to FCB
|
|
; AX = Record position in file of disk transfer
|
|
; CX = Record count
|
|
; Outputs:
|
|
; DS = CS
|
|
; ES:DI point to FCB
|
|
; CX = No. of records to transfer
|
|
; BP = Base of drive parameters
|
|
; SI = FAT pointer
|
|
; [RECCNT] = Record count
|
|
; [RECPOS] = Record position in file
|
|
; [FCB] = DX
|
|
; [NEXTADD] = Displacement of disk transfer within segment
|
|
; [DSKERR] = 0 (no errors yet)
|
|
; [TRANS] = 0 (No transfers yet)
|
|
; If SETUP detects no records will be transfered, it returns 1 level up
|
|
; with CX = 0.
|
|
|
|
MOV BP,[DI+DRVBP]
|
|
MOV BX,DS
|
|
MOV ES,BX
|
|
MOV BX,CS
|
|
MOV DS,BX
|
|
MOV [RECPOS],AX
|
|
MOV [FCB],DX
|
|
MOV BX,[DMAADD]
|
|
MOV [NEXTADD],BX
|
|
MOV B,[DSKERR],0
|
|
MOV [TRANS],0
|
|
MOV SI,[BP+FAT]
|
|
ADD BX,7FH ;See if there is any space left
|
|
JC SEGEND
|
|
AND BL,80H
|
|
NEG BX ;These instructions divide by 128
|
|
ROL BX
|
|
XCHG BL,BH
|
|
JNZ CHKMAX
|
|
MOV BH,2 ;All 512 records OK
|
|
CHKMAX:
|
|
CMP CX,BX
|
|
JBE SAVCNT
|
|
MOV CX,BX
|
|
MOV B,[DSKERR],2 ;Flag that trimming took place
|
|
SAVCNT:
|
|
MOV [RECCNT],CX
|
|
RET
|
|
SEGEND:
|
|
MOV B,[DSKERR],2
|
|
MOV CX,0
|
|
POP BX
|
|
RET
|
|
|
|
|
|
FNDCLUS:
|
|
|
|
; Inputs:
|
|
; DS = CS
|
|
; CX = No. of clusters to skip
|
|
; BP = Base of drive parameters
|
|
; SI = FAT pointer
|
|
; ES:DI point to FCB
|
|
; Outputs:
|
|
; BX = Last cluster skipped to
|
|
; CX = No. of clusters remaining (0 unless EOF)
|
|
; DX = Position of last cluster
|
|
; DI destroyed. No other registers affected.
|
|
|
|
SEG ES
|
|
MOV BX,[DI+LSTCLUS]
|
|
SEG ES
|
|
MOV DX,[DI+CLUSPOS]
|
|
OR BX,BX
|
|
JZ NOCLUS
|
|
SUB CX,DX
|
|
JNB FINDIT
|
|
ADD CX,DX
|
|
XOR DX,DX
|
|
SEG ES
|
|
MOV BX,[DI+FIRCLUS]
|
|
FINDIT:
|
|
JCXZ RET
|
|
SKPCLP:
|
|
CALL UNPACK
|
|
CMP DI,0FFFH
|
|
JZ RET
|
|
XCHG BX,DI
|
|
INC DX
|
|
LOOP SKPCLP
|
|
RET
|
|
NOCLUS:
|
|
INC CX
|
|
DEC DX
|
|
RET
|
|
|
|
|
|
LOAD:
|
|
|
|
; Inputs:
|
|
; DS:DI point to FCB
|
|
; AX = Position in file to read
|
|
; CX = No. of records to read
|
|
; Outputs:
|
|
; AX = Position of last record read
|
|
; CX = No. of records read
|
|
; ES:DI point to FCB
|
|
; LSTCLUS, CLUSPOS fields in FCB set
|
|
|
|
CALL SETUP
|
|
SEG ES
|
|
MOV BX,[DI+FILSIZ]
|
|
SUB BX,AX
|
|
JBE WRTERRJ
|
|
CMP BX,CX
|
|
JNB ENUF
|
|
MOV B,[DSKERR],1
|
|
MOV [RECCNT],BX
|
|
ENUF:
|
|
MOV CL,[BP+CLUSSHFT]
|
|
SHR AX,CL
|
|
MOV CX,AX
|
|
CALL FNDCLUS
|
|
OR CX,CX
|
|
JNZ WRTERR
|
|
MOV DL,[RECPOS]
|
|
AND DL,[BP+CLUSMSK]
|
|
MOV CX,[RECCNT]
|
|
RDLP:
|
|
CALL OPTIMIZE
|
|
PUSH DI
|
|
PUSH AX
|
|
PUSH DS
|
|
MOV DS,[DMAADD+2]
|
|
CALL DREAD
|
|
POP DS
|
|
POP CX
|
|
POP BX
|
|
JCXZ SETFCB
|
|
MOV DL,0
|
|
CMP BX,0FFFH
|
|
JNZ RDLP
|
|
MOV B,[DSKERR],1
|
|
|
|
SETFCB:
|
|
MOV AX,[CLUSNUM]
|
|
MOV DI,[FCB]
|
|
SEG ES
|
|
MOV [DI+LSTCLUS],AX
|
|
MOV AX,[RECPOS]
|
|
MOV BX,[TRANS]
|
|
ADD AX,BX
|
|
SEG ES
|
|
CMP AX,[DI+FILSIZ]
|
|
JBE SAMSIZ
|
|
SEG ES
|
|
MOV [DI+FILSIZ],AX
|
|
SEG ES
|
|
MOV B,[DI+SIZCHG],-1
|
|
SAMSIZ:
|
|
DEC AX
|
|
MOV DX,AX
|
|
MOV CL,[BP+CLUSSHFT]
|
|
SHR DX,CL
|
|
SEG ES
|
|
MOV [DI+CLUSPOS],DX
|
|
MOV CX,BX
|
|
RET
|
|
|
|
WRTERRJ:JP WRTERR
|
|
|
|
HAVSTART:
|
|
MOV CX,AX
|
|
PUSH BX
|
|
CALL FNDCLUS
|
|
JCXZ WRCLUS
|
|
CALL ALLOCATE
|
|
POP BX
|
|
JNC NOSKIP
|
|
WRTERR:
|
|
MOV B,[DSKERR],1
|
|
LVDSK:
|
|
MOV AX,[RECPOS]
|
|
XOR CX,CX
|
|
MOV DI,[FCB]
|
|
RET
|
|
WRTEOF:
|
|
MOV CL,[BP+CLUSSHFT]
|
|
SHR AX,CL
|
|
MOV CX,AX
|
|
CALL FNDCLUS
|
|
OR CX,CX
|
|
JNZ LVDSK
|
|
MOV DX,0FFFH
|
|
MOV B,[BP+DIRTYFAT],-1
|
|
MOV DI,[FCB]
|
|
MOV AX,[RECPOS]
|
|
SEG ES
|
|
MOV [DI+FILSIZ],AX
|
|
SEG ES
|
|
MOV B,[DI+SIZCHG],-1
|
|
XOR CX,CX
|
|
RET
|
|
|
|
STORE:
|
|
|
|
; Inputs:
|
|
; DS:DI point to FCB
|
|
; AX = Position in file of disk transfer
|
|
; CX = Record count
|
|
; Outputs:
|
|
; AX = Position of last record written
|
|
; CX = No. of records written
|
|
; ES:DI point to FCB
|
|
; LSTCLUS, CLUSPOS fields in FCB set
|
|
|
|
CALL SETUP
|
|
JCXZ WRTEOF
|
|
MOV BX,CX
|
|
ADD BX,AX
|
|
DEC BX
|
|
MOV CL,[BP+CLUSSHFT]
|
|
SHR AX,CL
|
|
SHR BX,CL
|
|
MOV CX,AX
|
|
MOV AX,BX
|
|
CALL FNDCLUS
|
|
SUB AX,DX ;Last cluster minus current cluster
|
|
JCXZ HAVSTART ;See if no more data
|
|
PUSH CX ;No. of clusters of first
|
|
MOV CX,AX
|
|
CALL ALLOCATE
|
|
POP CX
|
|
JC WRTERR
|
|
DEC CX
|
|
JZ NOSKIP
|
|
CALL SKPCLP
|
|
PUSH BX
|
|
WRCLUS:
|
|
POP BX
|
|
NOSKIP:
|
|
MOV DL,[RECPOS]
|
|
AND DL,[BP+CLUSMSK]
|
|
MOV CX,[RECCNT]
|
|
WRTLP:
|
|
CALL OPTIMIZE
|
|
PUSH DI
|
|
PUSH AX
|
|
PUSH DS
|
|
MOV DS,[DMAADD+2]
|
|
CALL DWRITE
|
|
POP DS
|
|
POP CX
|
|
POP BX
|
|
MOV DL,0
|
|
OR CX,CX
|
|
JNZ WRTLP
|
|
CALL SETFCB
|
|
SEG ES
|
|
MOV B,[DI+DIRTYFIL],-1
|
|
RET
|
|
|
|
|
|
OPTIMIZE:
|
|
|
|
; Inputs:
|
|
; DS = CS
|
|
; BX = Physical cluster
|
|
; CX = No. of records
|
|
; DL = record within cluster
|
|
; BP = Base of drives parameters
|
|
; [NEXTADD] = transfer address
|
|
; Outputs:
|
|
; AX = No. of records remaining
|
|
; BX = Transfer address
|
|
; CX = No. or records to be transferred
|
|
; DX = Physical record address
|
|
; DI = Next cluster
|
|
; [CLUSNUM] = Last cluster accessed
|
|
; [NEXTADD] updated
|
|
; BP unchanged. Note that segment of transfer not set.
|
|
|
|
PUSH DX
|
|
PUSH BX
|
|
MOV AL,[BP+CLUSMSK]
|
|
INC AL ;Number of records per cluster
|
|
MOV AH,AL
|
|
SUB AL,DL ;AL = Number of records left in first cluster
|
|
MOV DX,CX
|
|
MOV SI,[BP+FAT]
|
|
MOV CX,0
|
|
OPTCLUS:
|
|
;AL has number of records available in current cluster
|
|
;AH has number of records available in next cluster
|
|
;BX has current physical cluster
|
|
;CX has number of sequential records found so far
|
|
;DX has number of records left to transfer
|
|
;SI has FAT pointer
|
|
CALL UNPACK
|
|
ADD CL,AL
|
|
ADC CH,0
|
|
CMP CX,DX
|
|
JAE BLKDON
|
|
MOV AL,AH
|
|
INC BX
|
|
CMP DI,BX
|
|
JZ OPTCLUS
|
|
DEC BX
|
|
FINCLUS:
|
|
MOV [CLUSNUM],BX ;Last cluster accessed
|
|
SUB DX,CX ;Number of records still needed
|
|
MOV AX,DX
|
|
MOV BX,CX
|
|
XCHG BL,BH
|
|
ROR BX
|
|
MOV SI,[NEXTADD]
|
|
ADD BX,SI ;Adjust by size of transfer
|
|
MOV [NEXTADD],BX
|
|
ADD [TRANS],CX
|
|
POP DX
|
|
POP BX
|
|
PUSH CX
|
|
MOV CL,[BP+CLUSSHFT]
|
|
DEC DX
|
|
DEC DX
|
|
SHL DX,CL
|
|
OR DL,BL
|
|
ADD DX,[BP+FIRREC]
|
|
POP CX
|
|
MOV BX,SI
|
|
RET
|
|
BLKDON:
|
|
MOV CX,DX ;Make the total equal to the request
|
|
JP FINCLUS
|
|
|
|
|
|
GETREC:
|
|
|
|
; Inputs:
|
|
; DS:DX point to FCB
|
|
; Outputs:
|
|
; AX = Record number determined by EXTENT and NR fields
|
|
; DS:DI point to FCB
|
|
; BX destroyed. No other registers affected.
|
|
|
|
MOV DI,DX
|
|
MOV AL,[DI+NR]
|
|
MOV BX,[DI+EXTENT]
|
|
SHL AL
|
|
SHR BX
|
|
RCR AL
|
|
MOV AH,BL
|
|
RET
|
|
|
|
|
|
ALLOCATE:
|
|
|
|
; Inputs:
|
|
; DS = CS
|
|
; ES = Segment of FCB
|
|
; BX = Last cluster of file (0 if null file)
|
|
; CX = No. of clusters to allocate
|
|
; DX = Position of cluster BX
|
|
; BP = Base of drive parameters
|
|
; SI = FAT pointer
|
|
; [FCB] = Displacement of FCB within segment
|
|
; Outputs:
|
|
; IF insufficient space
|
|
; THEN
|
|
; Carry set
|
|
; ELSE
|
|
; Carry clear
|
|
; BX = First cluster allocated
|
|
; FAT is fully updated including dirty bit
|
|
; FIRCLUS field of FCB set if file was null
|
|
; SI,BP unchanged. All other registers destroyed.
|
|
|
|
PUSH BX
|
|
MOV AX,BX
|
|
ALLOC:
|
|
MOV DX,BX
|
|
FINDFRE:
|
|
INC BX
|
|
CMP BX,[BP+MAXCLUS]
|
|
JL TRYOUT
|
|
CMP AX,1
|
|
JG TRYIN
|
|
POP BX
|
|
MOV DX,0FFFH
|
|
CALL RELBLKS
|
|
OR [SI],0FFFH
|
|
STC
|
|
RET
|
|
|
|
TRYOUT:
|
|
CALL UNPACK
|
|
JZ HAVFRE
|
|
TRYIN:
|
|
DEC AX
|
|
JLE FINDFRE
|
|
XCHG AX,BX
|
|
CALL UNPACK
|
|
JZ HAVFRE
|
|
XCHG AX,BX
|
|
JP FINDFRE
|
|
HAVFRE:
|
|
XCHG BX,DX
|
|
MOV AX,DX
|
|
CALL PACK
|
|
MOV BX,AX
|
|
LOOP ALLOC
|
|
MOV DX,0FFFH
|
|
CALL PACK
|
|
MOV B,[BP+DIRTYFAT],-1
|
|
POP BX
|
|
CALL UNPACK
|
|
XCHG BX,DI
|
|
OR DI,DI
|
|
JNZ RET
|
|
MOV DI,[FCB]
|
|
SEG ES
|
|
MOV [DI+FIRCLUS],BX
|
|
OR [SI],0FFFH
|
|
RET
|
|
|
|
|
|
RELEASE:
|
|
|
|
; Inputs:
|
|
; DS = CS
|
|
; BX = Cluster in file
|
|
; SI = FAT pointer
|
|
; BP = Base of drive parameters
|
|
; Function:
|
|
; Frees cluster chain starting with [BX]
|
|
; AX,BX,DX,DI all destroyed. Other registers unchanged.
|
|
|
|
XOR DX,DX
|
|
RELBLKS:
|
|
; Enter here with DX=0FFFH to put an end-of-file mark
|
|
; in the first cluster and free the rest in the chain.
|
|
CALL UNPACK
|
|
JZ RET
|
|
MOV AX,DI
|
|
CALL PACK
|
|
CMP AX,0FFFH
|
|
MOV BX,AX
|
|
JNZ RELEASE
|
|
RET
|
|
|
|
|
|
GETEOF:
|
|
|
|
; Inputs:
|
|
; BX = Cluster in a file
|
|
; SI = Base of drive FAT
|
|
; DS = CS
|
|
; Outputs:
|
|
; BX = Last cluster in the file
|
|
; DI destroyed. No other registers affected.
|
|
|
|
CALL UNPACK
|
|
CMP DI,0FFFH
|
|
JZ RET
|
|
MOV BX,DI
|
|
JP GETEOF
|
|
|
|
|
|
SRCHFRST: ;System call 17
|
|
CALL GETFILE
|
|
SAVPLCE:
|
|
; Search-for-next enters here to save place and report
|
|
; findings.
|
|
JC KILLSRCH
|
|
MOV [SRCHDON],AL
|
|
MOV [PDIR],BX
|
|
MOV [SRCHBP],BP
|
|
;Information in directory entry must be copied into the first
|
|
; 16 bytes starting at the disk transfer address.
|
|
MOV SI,BX
|
|
LES DI,[DMAADD]
|
|
MOV CX,8
|
|
REP
|
|
MOVW
|
|
MOV AL,0
|
|
RET
|
|
|
|
KILLSRCH:
|
|
MOV AL,-1
|
|
MOV [SRCHDON],AL
|
|
RET
|
|
|
|
|
|
SRCHNXT: ;System call 18
|
|
MOV AX,CS
|
|
MOV ES,AX
|
|
MOV DS,AX
|
|
MOV AL,[SRCHDON]
|
|
CMP AL,-1
|
|
JZ RET
|
|
MOV BX,[PDIR]
|
|
MOV BP,[SRCHBP]
|
|
CALL CONTSRCH
|
|
JP SAVPLCE
|
|
|
|
|
|
FILESIZE: ;System call 35
|
|
PUSH DI
|
|
PUSH DX
|
|
CALL GETFILE
|
|
POP DI
|
|
POP ES
|
|
MOV AL,-1
|
|
JC RET
|
|
ADD DI,33 ;Write size in RR field
|
|
LEA SI,[BX+13]
|
|
LODB
|
|
SHL AL
|
|
LODW
|
|
RCL AX ;Round to nearest record
|
|
STOW
|
|
MOV AL,0
|
|
RCL AL
|
|
STOB
|
|
RET
|
|
|
|
|
|
SETDMA: ;System call 26
|
|
SEG CS
|
|
MOV [DMAADD],DX
|
|
SEG CS
|
|
MOV [DMAADD+2],DS
|
|
RET
|
|
|
|
GETFATPT: ;System call 27
|
|
MOV AX,CS
|
|
MOV DS,AX
|
|
MOV [DSSAVE],CS
|
|
MOV BP,[CURDRVPT]
|
|
CALL FATREAD
|
|
MOV BX,[BP+FAT]
|
|
MOV AL,[BP+CLUSMSK]
|
|
INC AL
|
|
MOV DX,[BP+MAXCLUS]
|
|
DEC DX
|
|
MOV B,[BP+DIRTYFAT],-1
|
|
MOV [BXSAVE],BX
|
|
MOV [DXSAVE],DX
|
|
RET
|
|
|
|
|
|
GETDSKPT: ;System call 31
|
|
SEG CS
|
|
MOV [DSSAVE],CS
|
|
SEG CS
|
|
MOV BX,[CURDRVPT]
|
|
SEG CS
|
|
MOV [BXSAVE],BX
|
|
RET
|
|
|
|
|
|
DSKRESET: ;System call 13
|
|
SEG CS
|
|
MOV [DMAADD+2],DS
|
|
MOV AX,CS
|
|
MOV DS,AX
|
|
MOV [DMAADD],80H
|
|
MOV AX,[CURDRVPT+2]
|
|
MOV [CURDRVPT],AX
|
|
WRTFATS:
|
|
; DS=CS. Writes back all dirty FATs. All registers destroyed.
|
|
MOV CL,[NUMDRV]
|
|
MOV CH,0
|
|
MOV SI,CURDRVPT+2
|
|
WRTFAT:
|
|
LODW
|
|
PUSH CX
|
|
PUSH SI
|
|
MOV BP,AX
|
|
CALL CHKFATWRT
|
|
POP SI
|
|
POP CX
|
|
LOOP WRTFAT
|
|
MOV AL,-1
|
|
CALL BIOSFLUSH,BIOSSEG
|
|
RET
|
|
|
|
|
|
CURDRV: ;System call 25
|
|
SEG CS
|
|
MOV BP,[CURDRVPT]
|
|
MOV AL,[BP+DRVNUM]
|
|
RET
|
|
|
|
|
|
INUSE: ;System call 24
|
|
MOV AX,CS
|
|
MOV DS,AX
|
|
MOV CL,[NUMDRV]
|
|
MOV CH,0
|
|
MOV SI,CX
|
|
SHL SI
|
|
ADD SI,CURDRVPT
|
|
MOV BX,0
|
|
DOWN
|
|
CHKUSE:
|
|
LODW
|
|
MOV BP,AX
|
|
TEST B,[BP+DIRTYFAT],-1
|
|
JZ SETBIT
|
|
STC
|
|
SETBIT:
|
|
RCL BX
|
|
LOOP CHKUSE
|
|
MOV AL,BL
|
|
RET
|
|
|
|
|
|
SETRNDREC: ;System call 36
|
|
CALL GETREC
|
|
MOV [DI+33],AX
|
|
MOV AL,0
|
|
JZ BIGRR
|
|
INC AL
|
|
BIGRR:
|
|
MOV [DI+35],AL
|
|
RET
|
|
|
|
|
|
SELDSK: ;System call 14
|
|
MOV DH,0
|
|
MOV BX,DX
|
|
PUSH CS
|
|
POP DS
|
|
CMP BL,[NUMDRV]
|
|
JGE RET
|
|
SHL BX
|
|
MOV AX,[BX+CURDRVPT+2]
|
|
MOV [CURDRVPT],AX
|
|
RET
|
|
|
|
|
|
BUFIN: ;System call 10
|
|
MOV AX,CS
|
|
MOV ES,AX
|
|
MOV SI,DX
|
|
MOV CH,0
|
|
LODW
|
|
OR AL,AL
|
|
JZ RET
|
|
MOV BL,AH
|
|
MOV BH,CH
|
|
CMP AL,BL
|
|
JBE NOEDIT
|
|
CMP B,[BX+SI],0DH
|
|
JZ EDITON
|
|
NOEDIT:
|
|
MOV BL,CH
|
|
EDITON:
|
|
MOV DL,AL
|
|
DEC DX
|
|
NEWLIN:
|
|
SEG CS
|
|
MOV AL,[CARPOS]
|
|
SEG CS
|
|
MOV [STARTPOS],AL
|
|
PUSH SI
|
|
MOV DI,INBUF
|
|
MOV AH,CH
|
|
MOV BH,CH
|
|
MOV DH,CH
|
|
GETCH:
|
|
CALL IN
|
|
CMP AL,7FH
|
|
JZ BACKSP
|
|
CMP AL,8
|
|
JZ BACKSP
|
|
CMP AL,13
|
|
JZ ENDLIN
|
|
CMP AL,10
|
|
JZ PHYCRLF
|
|
CMP AL,"X"-"@"
|
|
JZ KILNEW
|
|
CMP AL,ESCCH
|
|
JZ ESC
|
|
SAVCH:
|
|
CMP DH,DL
|
|
JAE GETCH
|
|
STOB
|
|
INC DH
|
|
CALL OUT
|
|
OR AH,AH
|
|
JNZ GETCH
|
|
CMP BH,BL
|
|
JAE GETCH
|
|
INC SI
|
|
INC BH
|
|
JP GETCH
|
|
|
|
ESC:
|
|
CALL IN
|
|
MOV CL,ESCTABLEN
|
|
PUSH DI
|
|
MOV DI,ESCTAB
|
|
REPNE
|
|
SCAB
|
|
POP DI
|
|
AND CL,0FEH
|
|
MOV BP,CX
|
|
JMP [BP+ESCFUNC]
|
|
|
|
ENDLIN:
|
|
STOB
|
|
CALL OUT
|
|
POP DI
|
|
MOV [DI-1],DH
|
|
INC DH
|
|
COPYNEW:
|
|
MOV BP,ES
|
|
MOV BX,DS
|
|
MOV ES,BX
|
|
MOV DS,BP
|
|
MOV SI,INBUF
|
|
MOV CL,DH
|
|
REP
|
|
MOVB
|
|
RET
|
|
CRLF:
|
|
MOV AL,13
|
|
CALL OUT
|
|
MOV AL,10
|
|
JMP OUT
|
|
|
|
PHYCRLF:
|
|
CALL CRLF
|
|
JP GETCH
|
|
|
|
KILNEW:
|
|
MOV AL,"\"
|
|
CALL OUT
|
|
POP SI
|
|
PUTNEW:
|
|
CALL CRLF
|
|
JMP NEWLIN
|
|
|
|
BACKSP:
|
|
OR DH,DH
|
|
JZ OLDBAK
|
|
CALL BACKUP
|
|
SEG ES
|
|
MOV AL,[DI]
|
|
CMP AL," "
|
|
JAE OLDBAK
|
|
CMP AL,9
|
|
JZ BAKTAB
|
|
CALL BACKMES
|
|
OLDBAK:
|
|
OR AH,AH
|
|
JNZ GETCH1
|
|
OR BH,BH
|
|
JZ GETCH1
|
|
DEC BH
|
|
DEC SI
|
|
GETCH1:
|
|
JMP GETCH
|
|
BAKTAB:
|
|
PUSH DI
|
|
DEC DI
|
|
DOWN
|
|
MOV CL,DH
|
|
MOV AL," "
|
|
PUSH BX
|
|
MOV BL,7
|
|
JCXZ FIGTAB
|
|
FNDPOS:
|
|
SCAB
|
|
JNA CHKCNT
|
|
SEG ES
|
|
CMP B,[DI+1],9
|
|
JZ HAVTAB
|
|
DEC BL
|
|
CHKCNT:
|
|
LOOP FNDPOS
|
|
FIGTAB:
|
|
SEG CS
|
|
SUB BL,[STARTPOS]
|
|
HAVTAB:
|
|
SUB BL,DH
|
|
ADD CL,BL
|
|
AND CL,7
|
|
UP
|
|
POP BX
|
|
POP DI
|
|
JZ OLDBAK
|
|
TABBAK:
|
|
CALL BACKMES
|
|
LOOP TABBAK
|
|
JP OLDBAK
|
|
BACKUP:
|
|
DEC DH
|
|
DEC DI
|
|
BACKMES:
|
|
MOV AL,8
|
|
CALL OUT
|
|
MOV AL," "
|
|
CALL OUTCH
|
|
MOV AL,8
|
|
JMP OUTCH
|
|
|
|
TWOESC:
|
|
MOV AL,ESCCH
|
|
JMP SAVCH
|
|
|
|
COPYLIN:
|
|
MOV CL,BL
|
|
SUB CL,BH
|
|
JP COPYEACH
|
|
|
|
COPYSTR:
|
|
CALL FINDOLD
|
|
JP COPYEACH
|
|
|
|
COPYONE:
|
|
MOV CL,1
|
|
COPYEACH:
|
|
CMP DH,DL
|
|
JZ GETCH2
|
|
CMP BH,BL
|
|
JZ GETCH2
|
|
LODB
|
|
STOB
|
|
CALL OUT
|
|
INC BH
|
|
INC DH
|
|
LOOP COPYEACH
|
|
GETCH2:
|
|
JMP GETCH
|
|
|
|
SKIPONE:
|
|
CMP BH,BL
|
|
JZ GETCH2
|
|
INC BH
|
|
INC SI
|
|
JMP GETCH
|
|
|
|
SKIPSTR:
|
|
CALL FINDOLD
|
|
ADD SI,CX
|
|
ADD BH,CL
|
|
JMP GETCH
|
|
|
|
FINDOLD:
|
|
CALL IN
|
|
MOV CL,BL
|
|
SUB CL,BH
|
|
JZ NOTFND
|
|
DEC CX
|
|
JZ NOTFND
|
|
PUSH ES
|
|
PUSH DS
|
|
POP ES
|
|
PUSH DI
|
|
MOV DI,SI
|
|
INC DI
|
|
REPNE
|
|
SCAB
|
|
POP DI
|
|
POP ES
|
|
JNZ NOTFND
|
|
NOT CL
|
|
ADD CL,BL
|
|
SUB CL,BH
|
|
RET
|
|
NOTFND:
|
|
POP BP
|
|
JMP GETCH
|
|
|
|
REEDIT:
|
|
MOV AL,"@"
|
|
CALL OUT
|
|
POP DI
|
|
PUSH DI
|
|
PUSH ES
|
|
PUSH DS
|
|
CALL COPYNEW
|
|
POP DS
|
|
POP ES
|
|
POP SI
|
|
MOV BL,DH
|
|
JMP PUTNEW
|
|
|
|
ENTERINS:
|
|
MOV AH,-1
|
|
JMP GETCH
|
|
|
|
EXITINS:
|
|
MOV AH,0
|
|
JMP GETCH
|
|
|
|
ESCFUNC:
|
|
DW GETCH
|
|
DW TWOESC
|
|
DW EXITINS
|
|
DW ENTERINS
|
|
DW BACKSP
|
|
DW REEDIT
|
|
DW KILNEW
|
|
DW COPYLIN
|
|
DW SKIPSTR
|
|
DW COPYSTR
|
|
DW SKIPONE
|
|
DW COPYONE
|
|
|
|
CONOUT: ;System call 2
|
|
MOV AL,DL
|
|
OUT:
|
|
CMP AL,20H
|
|
JB CTRLOUT
|
|
CMP AL,7FH
|
|
JZ OUTCH
|
|
SEG CS
|
|
INC B,[CARPOS]
|
|
OUTCH:
|
|
CALL BIOSOUT,BIOSSEG
|
|
SEG CS
|
|
TEST B,[PFLAG],-1
|
|
JZ STATCHK
|
|
CALL BIOSPRINT,BIOSSEG
|
|
STATCHK:
|
|
CALL BIOSSTAT,BIOSSEG
|
|
JZ RET
|
|
INCHK:
|
|
CALL BIOSIN,BIOSSEG
|
|
CMP AL,'S'-'@'
|
|
JNZ NOSTOP
|
|
CALL BIOSIN,BIOSSEG
|
|
NOSTOP:
|
|
CMP AL,'P'-'@'
|
|
JZ PRINTON
|
|
CMP AL,'N'-'@'
|
|
JZ PRINTOFF
|
|
CMP AL,'C'-'@'
|
|
JNZ RET
|
|
INT CONTC ;Execute user Ctrl-C handler
|
|
RET
|
|
|
|
PRINTON:
|
|
SEG CS
|
|
MOV B,[PFLAG],1
|
|
RET
|
|
PRINTOFF:
|
|
SEG CS
|
|
MOV B,[PFLAG],0
|
|
RET
|
|
CTRLOUT:
|
|
CMP AL,10
|
|
JZ OUTCH
|
|
CMP AL,13
|
|
JZ ZERPOS
|
|
CMP AL,8
|
|
JZ BACKPOS
|
|
CMP AL,9
|
|
JZ TAB
|
|
PUSH AX
|
|
MOV AL,"^"
|
|
CALL OUT
|
|
POP AX
|
|
OR AL,40H
|
|
JP OUT
|
|
|
|
ZERPOS:
|
|
SEG CS
|
|
MOV B,[CARPOS],0
|
|
JP OUTCH
|
|
BACKPOS:
|
|
SEG CS
|
|
DEC B,[CARPOS]
|
|
JP OUTCH
|
|
|
|
TAB:
|
|
MOV AL,0
|
|
SEG CS
|
|
XCHG AL,[CARPOS]
|
|
OR AL,0F8H
|
|
NEG AL
|
|
PUSH CX
|
|
MOV CL,AL
|
|
MOV CH,0
|
|
TABLP:
|
|
MOV AL," "
|
|
CALL OUTCH
|
|
LOOP TABLP
|
|
POP CX
|
|
RET
|
|
|
|
|
|
CONSTAT: ;System call 11
|
|
CALL BIOSSTAT,BIOSSEG
|
|
JZ RET
|
|
OR AL,-1
|
|
RET
|
|
|
|
|
|
CONIN: ;System call 1
|
|
CALL INCHK
|
|
PUSH AX
|
|
CALL OUT
|
|
POP AX
|
|
RET
|
|
|
|
|
|
IN: ;Internal input routine
|
|
CALL INCHK
|
|
JZ IN
|
|
RET
|
|
|
|
RAWIO: ;System call 6
|
|
MOV AL,DL
|
|
CMP AL,-1
|
|
JNZ RAWOUT
|
|
CALL BIOSSTAT,BIOSSEG
|
|
JZ RET
|
|
CALL BIOSIN,BIOSSEG
|
|
RET
|
|
RAWOUT:
|
|
CALL BIOSOUT,BIOSSEG
|
|
RET
|
|
|
|
LIST: ;System call 5
|
|
MOV AL,DL
|
|
CALL BIOSPRINT,BIOSSEG
|
|
RET
|
|
|
|
PRTBUF: ;System call 9
|
|
MOV SI,DX
|
|
OUTSTR:
|
|
LODB
|
|
CMP AL,"$"
|
|
JZ RET
|
|
CALL OUT
|
|
JP OUTSTR
|
|
|
|
OUTMES: ;String output for internal messages
|
|
SEG CS
|
|
LODB
|
|
CMP AL,"$"
|
|
JZ RET
|
|
CALL OUT
|
|
JP OUTMES
|
|
|
|
|
|
SETVECT: ; Interrupt call 37
|
|
XOR BX,BX
|
|
MOV ES,BX
|
|
MOV BL,AL
|
|
SHL BX
|
|
SHL BX
|
|
SEG ES
|
|
MOV [BX],DX
|
|
SEG ES
|
|
MOV [BX+2],DS
|
|
RET
|
|
|
|
|
|
NEWBASE: ; Interrupt call 38
|
|
MOV ES,DX
|
|
SEG CS
|
|
MOV DS,[CSLOC]
|
|
XOR SI,SI
|
|
MOV DI,SI
|
|
MOV CX,80H
|
|
REP
|
|
MOVW
|
|
|
|
SETMEM:
|
|
|
|
; Inputs:
|
|
; DX = Segment
|
|
; Function:
|
|
; Completely prepares a program base at the
|
|
; specified segment.
|
|
; Outputs:
|
|
; DS = DX
|
|
; ES = DX
|
|
; [0] has INT 20H
|
|
; [2] = First unavailable segment ([ENDMEM])
|
|
; [5] to [9] form a long call to the entry point
|
|
; [10] to [13] have exit address (from INT 22H)
|
|
; [14] to [17] have ctrl-C exit address (from INT 23H)
|
|
; AX,DX,BP unchanged. All other registers destroyed.
|
|
|
|
XOR CX,CX
|
|
MOV DS,CX
|
|
MOV ES,DX
|
|
MOV SI,EXIT
|
|
MOV DI,SAVEXIT
|
|
MOVW
|
|
MOVW
|
|
MOVW
|
|
MOVW
|
|
SEG CS
|
|
MOV CX,[ENDMEM]
|
|
SEG ES
|
|
MOV [2],CX
|
|
SUB CX,DX
|
|
CMP CX,MAXDIF
|
|
JBE HAVDIF
|
|
MOV CX,MAXDIF
|
|
HAVDIF:
|
|
MOV BX,ENTRYPOINTSEG
|
|
SUB BX,CX
|
|
SHL CX
|
|
SHL CX
|
|
SHL CX
|
|
SHL CX
|
|
MOV DS,DX
|
|
MOV [6],CX
|
|
MOV [8],BX
|
|
MOV [0],20CDH ;"INT INTTAB"
|
|
MOV B,[5],LONGCALL
|
|
RET
|
|
|
|
|
|
SHFTDI7:
|
|
SHL DI
|
|
SHL DI
|
|
SHL DI
|
|
SHL DI
|
|
SHL DI
|
|
SHL DI
|
|
SHL DI
|
|
RET
|
|
|
|
|
|
;***** DATA AREA *****
|
|
|
|
BADMES: DB 13,10,"Bad FAT",13,10,"$"
|
|
BADFATMES:DB 13,10,"All FATs on disk are bad",13,10,"$"
|
|
RDERRMES:DB 13,10,"Disk read error",13,10,"$"
|
|
WRTERRMES:DB 13,10,"Disk write error",13,10,"$"
|
|
|
|
CARPOS: DB 0
|
|
STARTPOS:DB 0
|
|
PFLAG: DB 0
|
|
SRCHDON:DB -1
|
|
PDIR: DS 2
|
|
SRCHBP: DS 2
|
|
EXITHOLD:DS 4
|
|
ENDMEM: DS 2
|
|
FATBASE:DS 2
|
|
INBUF: DS 255
|
|
DIRBUF: DS 128
|
|
NUMDRV: DS 1 ;Number of drives
|
|
NAME1: DS 11 ;File name buffer
|
|
NAME2: DS 11
|
|
DMAADD: DS 4 ;User's disk transfer address (disp/seg)
|
|
TEMP:
|
|
CSLOC: DS 2
|
|
DSKERR: DS 1
|
|
FCB: DS 2 ;Address of user FCB
|
|
RECPOS: DS 2
|
|
NEXTADD:DS 2
|
|
RECCNT: DS 2
|
|
CLUSNUM:DS 2
|
|
TRANS: DS 2
|
|
|
|
DS 50 ;Stack space
|
|
AXSAVE: DS 2
|
|
BXSAVE: DS 2
|
|
CXSAVE: DS 2
|
|
DXSAVE: DS 2
|
|
SISAVE: DS 2
|
|
DISAVE: DS 2
|
|
BPSAVE: DS 2
|
|
DSSAVE: DS 2
|
|
ESSAVE: DS 2
|
|
STACK:
|
|
SSSAVE: DS 2
|
|
SPSAVE: DS 2
|
|
|
|
CURDRVPT:DS 2
|
|
DRVTAB: ;Address of start of DPBs
|
|
|