2020-09-30 17:12:29 +02:00

354 lines
8.5 KiB
NASM

TITLE DSYS - sys routines for slm specific to DOS
ifndef MEDIUM
memL EQU 1
else
memM EQU 1
endif
?PLM = 0
?WIN = 0
.xlist
include cmacros.inc
.list
;
; NOTE: all cProc routines follow the Cmerge convention:
;
; ax and dx hold return values
; bx,cx,es can be trashed at will
; si,di,ss,sp,bp,ds are never trashed
;
; So the at the end of a routine, the only interesting registers are ax and
; possibly dx.
sBegin DATA
assumes ds, DATA
globalW enInt24 <1,0>
globalW eaInt24 <1,0>
globalW enCur <1,0>
globalW eaCur <1,0>
staticW sbInt24, 0 ; sb of saved int 24 vector
staticW ibInt24, 0 ; ib of saved int 24 vector
sEnd DATA
sBegin CODE
assumes ds,DATA
assumes cs,CODE
pointer struc
loword dw ?
hiword dw ?
pointer ends
;============================================================================|
; InitInt24 - save the current int24 vector and initialize the int 24 vector
; to our code
;
cProc InitInt24, <PUBLIC,FAR>, <ds>
cBegin InitInt24
mov ax,3524h ; get current int 24 vector
int 21h
mov ibInt24,bx ; save for later restore
mov sbInt24,es ; " " " "
mov ax,2524h ; set int 24 vector
push cs
pop ds
mov dx,codeOFFSET _SlmInt24 ; ds:dx pointer to SlmInt24
int 21h
cEnd InitInt24
;
; Exit: ibInt24,sbInt24 - saved int vector
;
; Return: nothing
;
;----------------------------------------------------------------------------|
;============================================================================|
; SlmInt24 - our int 24 handler. We simply save the world, call
; GetExtendedErr, save the result in globals, and return failure.
;
labelNP SlmInt24
push bx
push cx
push dx
push si
push di
push ds
push es
mov ax,DGROUP
mov ds,ax ; ds = our data segment!
mov ah,59h ; get extended error
xor bx,bx ; version = 0
int 21h ; get extended err
mov enInt24,ax ; save Error Number globally
xor bh,bh ; clear error class
mov eaInt24,bx ; save Error Action globally
mov al,3 ; return failure
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
iret
;
; Exit: enInt24 - saved Error Number
; eaInt24 - saved Error Action
;
; Return: al = 3 (fail the system call)
;
;----------------------------------------------------------------------------|
;============================================================================|
; FiniInt24 - restore the old int 24 vector
;
; Entry: ds:ibInt24,ds:sbInt24 - saved int vectors
;
cProc FiniInt24, <PUBLIC,FAR>, <ds>
cBegin FiniInt24
mov ax,2524h ; set int 24 vector
mov dx,ibInt24
mov ds,sbInt24 ; ds:dx = old int 24 vector
int 21h
cEnd FiniInt24
;
; Return: nothing
;
;----------------------------------------------------------------------------|
;============================================================================|
; lockfile(fd, fUnLock) - lock/unlock the whole file
;
; NOTE: we lock from 0-7fffffff. According to the Xenix manual, length 0
; implies the whole file, but this does not work for DOS. DOS treats
; the length as unsigned, bug Xenix as signed. So, we use the largest
; positive long value and assume that files will never be this big.
;
cProc lockfile, <PUBLIC,FAR>, <si,di>
parmW fd ; file descriptor
parmB fUnLock ; 0 or 1
cBegin lockfile
mov ax,440ah ; get local/network destinction
mov bx,fd ; bx = pass file handle
int 21h
jb lockfile_ret ; return non-zero if error
test dx,8000h ; test high bit
jz lockfile_ok ; local drive; return 0
mov ah,5ch ; lock file (bx set above)
mov al,fUnLock
xor cx,cx
xor dx,dx ; cx:dx = pos = 0L
mov si,7fffh
mov di,0ffffh ; si:di = cb = 7fffffffh
int 21h
jb lockfile_ret ; return error number if error (non-zero!)
lockfile_ok:
xor ax,ax ; return zero if no error
lockfile_ret:
cEnd lockfile
;
; Return: 0 if success, non-zero if error
;
;----------------------------------------------------------------------------|
;============================================================================|
; LpbAllocCb(cb,fClear) -- allocate cb bytes in far memory.
;
externP _fmemset
cProc LpbAllocCb,<PUBLIC,FAR>
parmW cb ; number of bytes to be allocated
parmW fClear ; should block be cleared before use?
localD lpb ; holder for return value
parmW value
cBegin LpbAllocCb
mov Off_lpb,0 ; offset always zero
mov bx,cb
add bx,0fh ; add 15 for proper paragraph conversion
rcr bx,1
mov cl,3
shr bx,cl ; number of paragraphs to allocate.
mov ah,48h ; allocate memory
int 21h
jc LpbAllocCb_err ; error, jump
mov cx,fClear ; don't clear block if fClear zero
jcxz LpbAllocCb_noclear
mov Seg_lpb,ax ; save segment value
mov value,0
cCall _fmemset,<lpb,value,cb>
mov dx,Seg_lpb ; restore segment value
jmp LpbAllocCb_ret ; return
LpbAllocCb_err:
xor ax,ax ; return NULL if error
LpbAllocCb_noclear:
mov dx,ax ; dx <-- segment value
LpbAllocCb_ret:
xor ax,ax ; offset always zero
cEnd LpbAllocCb
;
; Exit: buffer filled if success
;
; Return: dx:ax = far pointer or NULL if error
;
;----------------------------------------------------------------------------|
;============================================================================|
; FreeLpb(lpb) -- free pointer allocated with LpbAllocCb
;
cProc FreeLpb,<PUBLIC,FAR>
parmD lpb ; char far * which has been allocated
cBegin FreeLpb
mov es,Seg_lpb ; es <-- segment value, offset always 0
mov ah,49h ; free allocated memory
int 21h
cEnd FreeLpb
;
;----------------------------------------------------------------------------|
;============================================================================|
; ClearHpbCb(hpb,cb) - clear huge buffer (long cb)
;
cProc ClearHpbCb, <PUBLIC,FAR>, <di>
parmD hpb ; pointer to far buffer
parmD cb ; unsigned cb
cBegin ClearHpbCb
mov bx,Off_cb
mov dx,Seg_cb
or bx,bx
jnz ClearHpbCb_cbOk
or dx,dx
jz ClearHpbCb_ret ; don't do anything if cb == 0
ClearHpbCb_cbOk:
les di,hpb ; es:di = hpb
xor ax,ax ; ax = 0 (for filling)
ClearHpbCb_loop:
mov cx,-1 ; cx = max number bytes in seg
sub cx,di ; cx -= Off_hpb
or dx,dx
jnz ClearHpbCb_cont ; jump if cb > 64k
cmp bx,cx
ja ClearHpbCb_cont ; jump if cb > bx
mov cx,bx ; use cb
jcxz ClearHpbCb_ret ; nop if no bytes to clear
dec cx ; decrement so inc will set correct
ClearHpbCb_cont:
sub bx,cx ; subtract number being cleared from cb
sbb dx,0
dec bx ; subtract one extra
shr cx,1 ; cx = # words; carry indicates odd cb
rep stosw ; fill with zeros; cx zero after rep
rcl cx,1 ; put zero or one in cx
inc cx ; add one to account for -1 subtract
rep stosb ; store zero or one more byte
mov cx,es
add cx,1000h ; reset segment selector for next iteration
mov es,cx
or di,di ; if offset != 0, no bytes left
jz ClearHpbCb_loop ; loop
ClearHpbCb_ret:
cEnd ClearHpbCb
;
; Return: nothing
;
;----------------------------------------------------------------------------|
;============================================================================|
; HpbAllocCb(cb,fClear) -- allocate cb (long) bytes in far memory.
;
cProc HpbAllocCb,<PUBLIC,FAR>
parmD cb ; number of bytes to be allocated
parmW fClear ; should block be cleared before use?
localD hpb ; holder for return value
cBegin HpbAllocCb
mov Off_hpb,0 ; offset always zero
mov ax,Off_cb
mov dx,Seg_cb
mov cx,16
div cx ; number of paragraphs to allocate.
or dx,dx
jz HpbAllocCb_norem
inc ax ; add one if remainder.
HpbAllocCb_norem:
mov bx,ax
mov ah,48h ; allocate memory
int 21h
jc HpbAllocCb_err ; error, jump
mov cx,fClear ; don't clear block if fClear zero
jcxz HpbAllocCb_noclear
mov Seg_hpb,ax ; save segment value
cCall ClearHpbCb,<hpb,cb>
mov dx,Seg_hpb ; restore segment value
jmp HpbAllocCb_ret ; return
HpbAllocCb_err:
xor ax,ax ; return NULL if error
HpbAllocCb_noclear:
mov dx,ax ; dx <-- segment value
HpbAllocCb_ret:
xor ax,ax ; offset always zero
cEnd HpbAllocCb
;
; Exit: buffer filled if success
;
; Return: dx:ax = far pointer or NULL if error
;
;----------------------------------------------------------------------------|
;============================================================================|
; LpbFromHpb(hpb) -- normalize huge pointer to far.
;
cProc LpbFromHpb,<PUBLIC,FAR>
parmD hpb ; huge pointer
cBegin LpbFromHpb
mov ax,Off_hpb ; ax = offset
mov dx,Seg_hpb ; dx = seg
mov bx,ax ; bx = offset
and ax,0fh ; ax = hpb % 16
mov cl,4 ;
shr bx,cl ; bx = #paras in offset
add dx,bx ; normalize
cEnd LpbFromHpb
; Return: dx:ax = far pointer or NULL if error
;
;----------------------------------------------------------------------------|
sEnd CODE
END