This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/deps/odoors/ODSwap.asm

1454 lines
51 KiB
NASM
Raw Permalink Normal View History

2016-12-03 05:08:50 +00:00
; OpenDoors Online Software Programming Toolkit
; (C) Copyright 1991 - 1999 by Brian Pirie.
;
; This library is free software; you can redistribute it and/or
; modify it under the terms of the GNU Lesser General Public
; License as published by the Free Software Foundation; either
; version 2 of the License, or (at your option) any later version.
;
; This library is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; Lesser General Public License for more details.
;
; You should have received a copy of the GNU Lesser General Public
; License along with this library; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
;
;
; File: ODSwap.asm
;
; Description: Performs EMS/disk swapping and low level spawning
; activities. This file should only be included when building
; the MS-DOS version of OpenDoors.
;
; Revisions: Date Ver Who Change
; ---------------------------------------------------------------
; Oct 13, 1994 6.00 BP New file header format.
; Feb 19, 1996 6.00 BP Changed version number to 6.00.
; Mar 03, 1996 6.10 BP Begin version 6.10.
; If you have increased the file handle table size so that more than 20 files
; may be open in the parent process, set FHTSZ to the new size.
FHTSZ EQU 20
IFDEF LCODE
ARG_1 EQU 6
ELSE
ARG_1 EQU 4
ENDIF
arena struc ; arena header
sig db 0 ; 'M' or 'Z' if last block
own dw 0 ; PSP of owner or 0 if free
siz dw 0 ; size not including header
arena ends
vector struc
number db 0 ; vector number
flag db 0 ; 0-CURRENT,1-IRET,2-free,3-end
vseg dw 0 ; vector segment
voff dw 0 ; vector offset
vector ends
_TEXT SEGMENT word public 'CODE'
ASSUME cs:_TEXT
ASSUME ds:nothing
ASSUME es:nothing
ASSUME ss:nothing
; The code between slidetop and slidebot constitutes the spawn kernel. The
; kernel is copied to the front of the parent process immediately following the
; parent's PSP. The environment passed to the child is copied to immediately
; following the kernel.
slidetop:
path db 79 dup (0) ; program to execute
command db 128 dup (0) ; command-line
file db 79 dup (0) ; swap file
parmblk label byte ; parameter block
environ dw 0 ; environment block
cmd dw 0,0 ; command-line tail
fcb1 dw 0,0 ; first file control block
fcb2 dw 0,0 ; second file control block
fcb5c db 10h dup (0) ; first file control block
fcb6c db 10h dup (0) ; second file control block
cntsvl dw 0 ; count save low
cntsvh dw 0 ; count save high
tmpcode dw 0 ; temporary return code
env dw 0 ; environment segment
envlen dw 0 ; environment length
parsz dw 0 ; parent size
ttlsz dw 0 ; total size
oldsz dw 0 ; old size
newsz dw 0 ; new size
emsseg dw 0 ; EMS page frame segment
handle dw 0 ; EMS handle
useems db 0 ; if 0, use EMS
save db 4 dup (0) ; save 4 bytes at DS:[2Eh]
f1add dd 0 ; fnish1 address
last db 0 ; if 0, last block swap
IF FHTSZ - 20
fhtsv db FHTSZ dup (0) ; file handle table save
ENDIF
errmsg db 'spawn error',0Dh,0Ah
msglen EQU $-errmsg
EVEN
lclstk dw 64 dup (0) ; local stack
stktop label word ; stack top
slide1: mov ax,cs ; install local stack
cli
mov ss,ax
mov sp,offset stktop - offset slidetop + 100h
sti
; copy environment
mov bx,offset slidebot - offset slidetop + 15 + 100h
mov cl,4
shr bx,cl ; convert to paragraphs
add bx,ax ; add CS (actually PSP)
index = offset environ - offset slidetop + 100h
mov cs:[index],bx ; parameter block
mov es,bx
xor di,di
index = offset env - offset slidetop + 100h
mov ds,cs:[index]
xor si,si
index = offset envlen - offset slidetop + 100h
mov cx,cs:[index]
shr cx,1 ; translate to word count
rep movsw ; CF set if one byte left over
adc cx,cx ; CX = 1 or 0, depending CF
rep movsb ; possible final byte
dec ax ; PSP segment
mov es,ax ; program arena header
mov bx,es:[siz]
index = offset oldsz - offset slidetop + 100h
mov cs:[index],bx ; old size
mov byte ptr es:[sig],'M' ; not last
index = offset newsz - offset slidetop + 100h
mov bx,cs:[index] ; new size
mov es:[siz],bx
inc ax ; PSP segment
add ax,bx ; add new size
mov es,ax ; new last arena header
mov byte ptr es:[sig],'Z' ; last
index = offset last - offset slidetop + 100h
cmp byte ptr cs:[index],0
je slide2 ; jump if last block swap
mov byte ptr es:[sig],'M' ; not last
slide2: mov word ptr es:[own],0 ; free
index = offset ttlsz - offset slidetop + 100h
mov ax,cs:[index] ; total size
sub ax,bx ; subtract new size
dec ax ; account for arena header
mov es:[siz],ax
; save 4 bytes destroyed by DOS 2.0 at DS:2Eh
mov ax,cs ; PSP segment
mov es,ax
mov bx,es:[2Eh]
index = offset save - offset slidetop + 100h
mov cs:[index],bx
mov bx,es:[30h]
index = offset save - offset slidetop + 102h
mov cs:[index],bx
mov bx,offset parmblk - offset slidetop + 100h
mov ds,ax ; PSP segment
mov dx,100h ; offset path
mov ax,4B00h ; load and execute program
int 21h
jnc slide3 ; jump if no error
index = offset tmpcode - offset slidetop + 100h
mov cs:[index],ax ; temporary return code
slide3: mov ax,cs ; install local stack
cli
mov ss,ax
mov sp,offset stktop - offset slidetop + 100h
sti
; restore 4 bytes destroyed by DOS 2.0 at DS:2Eh
mov es,ax ; PSP segment
index = offset save - offset slidetop + 100h
mov bx,cs:[index]
mov es:[2Eh],bx
index = offset save - offset slidetop + 102h
mov bx,cs:[index]
mov es:[30h],bx
index = offset oldsz - offset slidetop + 100h
mov bx,cs:[index] ; old size
mov ah,4Ah ; resize memory block
int 21h
jnc slide7
index = offset useems - offset slidetop + 100h
slide4: cmp byte ptr cs:[index],0
jne slide6 ; jump if don't use EMS
index = offset handle - offset slidetop + 100h
mov dx,cs:[index] ; EMS handle
slide5: mov ah,45h ; release handle and memory
int 67h
cmp ah,82h ; memory manager busy?
je slide5 ; jump if busy
slide6: jmp slide18 ; exit
index = offset parsz - offset slidetop + 100h
slide7: mov bx,cs:[index] ; parent size
index = offset ttlsz - offset slidetop + 100h
mov ax,cs:[index] ; total size
sub ax,bx ; subtract parent size
or ax,ax
jz slide9
mov dx,cs ; PSP segment
add dx,bx ; add parent size
mov es,dx ; new last arena header
mov byte ptr es:[sig],'Z' ; last
index = offset last - offset slidetop + 100h
cmp byte ptr cs:[index],0
je slide8 ; jump if last block swap
mov byte ptr es:[sig],'M' ; not last
slide8: mov word ptr es:[own],0 ; free
dec ax ; account for arena header
mov es:[siz],ax
slide9: push cs ; PSP segment
index = offset useems - offset slidetop + 100h
cmp byte ptr cs:[index],0
jne slide14 ; jump if don't use EMS
pop es ; PSP segment
mov di,offset slidebot - offset slidetop + 100h
index = offset emsseg - offset slidetop + 100h
mov ds,cs:[index] ; EMS page frame segment
mov si,offset slidebot - offset slidetop
index = offset handle - offset slidetop + 100h
mov dx,cs:[index] ; EMS handle
xor bx,bx ; logical page number
mov cx,16384 - ( offset slidebot - offset slidetop )
jmp short slide13
index = offset cntsvl - offset slidetop + 100h
slide10: sub cs:[index],cx
index = offset cntsvh - offset slidetop + 100h
sbb word ptr cs:[index],0
xor al,al ; physical page number
slide11: mov ah,44h ; map memory
int 67h
or ah,ah
jz slide12
cmp ah,82h ; memory manager busy?
je slide11 ; jump if busy
jmp slide4 ; exit
slide12: shr cx,1 ; translate to word count
rep movsw ; CF set if one byte left over
adc cx,cx ; CX = 1 or 0, depending CF
rep movsb ; possible final byte
xor si,si
mov cx,16384 ; assume copy full block
inc bx ; logical page number
cmp bx,1
je slide13
mov ax,es
add ax,1024 ; 16384 bytes
mov es,ax
mov di,16640 ; 16384 + 100h
index = offset cntsvh - offset slidetop + 100h
slide13: cmp word ptr cs:[index],0
jne slide10 ; jump if more than full block
index = offset cntsvl - offset slidetop + 100h
cmp cs:[index],cx
jae slide10 ; jump if at least full block
mov cx,cs:[index] ; CX = cntsvl
cmp cx,0
jne slide10 ; jump if more left to copy
jmp short slide17
slide14: pop ds ; PSP segment
IF FHTSZ - 20
; restore the file handle table from the kernel
mov si,offset fhtsv - offset slidetop + 100h
mov es,ds:[36h] ; file handle table segment
mov di,ds:[34h] ; file handle table offset
mov cx,FHTSZ ; file handle table size
rep movsb
ENDIF
mov dx,offset file - offset slidetop + 100h
mov ax,3D00h ; open file read only
int 21h
jc slide18 ; exit if error
mov bx,ax ; handle
xor cx,cx
mov dx,offset slidebot - offset slidetop
mov ax,4200h ; move file pointer
int 21h ; from beginning of file
mov dx,offset slidebot - offset slidetop + 100h
mov cx,65520 ; assume read full block
jmp short slide16
index = offset cntsvl - offset slidetop + 100h
slide15: sub cs:[index],cx
index = offset cntsvh - offset slidetop + 100h
sbb word ptr cs:[index],0
mov ah,3Fh ; read file
int 21h
jc slide18 ; exit if error
cmp ax,cx
jne slide18 ; exit if not all read
mov ax,ds
add ax,4095 ; 65520 bytes
mov ds,ax
index = offset cntsvh - offset slidetop + 100h
slide16: cmp word ptr cs:[index],0
jne slide15 ; jump if more than full block
index = offset cntsvl - offset slidetop + 100h
cmp word ptr cs:[index],65520
jae slide15 ; jump if at least full block
mov cx,cs:[index] ; CX = cntsvl
cmp cx,0
jne slide15 ; jump if more left to read
index = offset tmpcode - offset slidetop + 100h
slide17: mov ax,cs:[index] ; temporary return code
index = offset f1add - offset slidetop + 100h
jmp dword ptr cs:[index]
slide18: push cs ; PSP segment
pop ds
mov dx,offset errmsg - offset slidetop + 100h
mov cx,msglen ; errmsg length
mov bx,2 ; standard error device handle
mov ah,40h ; write error message
int 21h
mov ax,4C01h ; terminate with return code
int 21h
handler: iret ; interrupt handler
slidebot:
cntl dw 0 ; count low
cnth dw 0 ; count high
stks dw 0 ; original SS contents
stkp dw 0 ; original SP contents
psp dw 0 ; PSP segment
s1add dd 0 ; slide1 address
rcode dw 0 ; return code
useems2 db 0 ; if 0, use EMS
vtabseg dw 0 ; vectab1 segment
vtaboff dw 0 ; vectab1 offset
errmsg2 db 'spawn error',0Dh,0Ah
msglen2 EQU $-errmsg2
;
; int _xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
;
PUBLIC __xspawn
IFDEF LCODE
__xspawn PROC far
ELSE
__xspawn PROC near
ENDIF
push bp
mov bp,sp
push di ; preserve register variables
push si
push ds
IFDEF LDATA
lds si,dword ptr [bp+ARG_1]
ELSE
mov si,word ptr [bp+ARG_1]
ENDIF
mov di,offset path
start1: mov al,ds:[si] ; copy path string
mov cs:[di],al ; to code segment
inc si
inc di
or al,al ; null char?
jnz start1 ; no, get next char
IFDEF LDATA
lds si,dword ptr [bp+ARG_1+4]
ELSE
mov si,word ptr [bp+ARG_1+2]
ENDIF
mov bx,si ; preserve si
mov di,offset command
mov cx,2 ; account for count and '\r'
add cl,byte ptr ds:[bx] ; add count byte
start2: mov al,ds:[bx] ; copy command
mov cs:[di],al ; to code segment
inc bx
inc di
loop start2 ; get next char
inc si ; skip count byte
push cs
pop es
mov di,offset fcb5c
mov ax,2901h ; parse filename
int 21h ; skip leading separators
mov di,offset fcb6c
mov al,1 ; parse filename
int 21h ; skip leading separators
IFDEF LDATA
mov ax,word ptr [bp+ARG_1+8]
ELSE
mov ax,word ptr [bp+ARG_1+4]
ENDIF
mov cl,4
shr ax,cl ; convert to paragraphs
IFDEF LDATA
mov bx,word ptr [bp+ARG_1+10]
ELSE
mov bx,ds
ENDIF
add ax,bx
mov cs:[env],ax ; environment segment
IFDEF LDATA
lds bx,dword ptr [bp+ARG_1+12] ; vectab1
ELSE
mov bx,word ptr [bp+ARG_1+6] ; vectab1
ENDIF
mov cs:[vtabseg],ds ; vectab1 segment
mov cs:[vtaboff],bx ; vectab1 offset
mov cs:[stks],ss ; original SS contents
mov cs:[stkp],sp ; original SP contents
mov cs:[rcode],0 ; assume success
IFDEF LDATA
mov ax,word ptr [bp+ARG_1+16]
ELSE
mov ax,word ptr [bp+ARG_1+8]
ENDIF
or ax,ax ; do swap?
jz start3 ; yes, jump
jmp noswap1
IFDEF LDATA
start3: mov ax,word ptr [bp+ARG_1+18]
ELSE
start3: mov ax,word ptr [bp+ARG_1+10]
ENDIF
mov cs:[envlen],ax ; environment length
add ax,offset slidebot - offset slidetop + 30 + 100h
mov cl,4
shr ax,cl ; convert to paragraphs
mov cs:[newsz],ax ; new size
IFDEF LDATA
lds si,dword ptr [bp+ARG_1+20]
ELSE
mov si,word ptr [bp+ARG_1+12]
ENDIF
mov di,offset file
mov cs:[useems2],1 ; assume don't use EMS
cmp byte ptr ds:[si],0
jne start4
mov cs:[useems2],0 ; use EMS
start4: mov al,ds:[si] ; copy file string
mov cs:[di],al ; to code segment
inc si
inc di
or al,al ; null char?
jnz start4 ; no, get next char
; save fnish1 address
mov word ptr cs:[f1add+2],cs
mov word ptr cs:[f1add],offset fnish1
; initialize parameter block
mov ax,cs:[psp] ; PSP segment
mov cs:[cmd],offset command - offset slidetop + 100h
mov cs:[cmd+2],ax
mov cs:[fcb1],offset fcb5c - offset slidetop + 100h
mov cs:[fcb1+2],ax
mov cs:[fcb2],offset fcb6c - offset slidetop + 100h
mov cs:[fcb2+2],ax
cld ; left to right direction
mov ds,ax ; PSP segment
IFDEF LDATA
mov dx,word ptr [bp+ARG_1+24]
ELSE
mov dx,word ptr [bp+ARG_1+14]
ENDIF
IF FHTSZ - 20
cmp word ptr ds:[32h],FHTSZ ; file handle table size
je start5 ; jump if OK
mov cs:[rcode],5
jmp short start6
ENDIF
start5: mov ax,cs:[newsz] ; new size
cmp ax,cs:[ttlsz] ; new size < total size?
jb start8 ; yes, jump
mov cs:[rcode],7 ; extremely unlikely
start6: cmp cs:[useems2],0
jne start7 ; jump if don't use EMS
jmp fnish2
start7: mov bx,dx ; file handle
jmp fnish6
start8: cmp cs:[useems2],0
jne start12 ; jump if don't use EMS
mov cs:[useems],0 ; use EMS
mov cs:[handle],dx ; EMS handle
mov es,cs:[emsseg] ; EMS page frame segment
xor bx,bx ; logical page number
jmp short start11
start9: sub cs:[cntl],cx
sbb cs:[cnth],0
call mapems
or ah,ah
jz start10 ; jump if map succeeded
jmp fnish2
start10: mov si,100h
xor di,di
shr cx,1 ; translate to word count
rep movsw ; CF set if one byte left over
adc cx,cx ; CX = 1 or 0, depending CF
rep movsb ; possible final byte
inc bx ; logical page number
mov ax,ds
add ax,1024 ; 16384 bytes
mov ds,ax
start11: mov cx,16384 ; assume copy full block
cmp cs:[cnth],0
jne start9 ; jump if more than full block
cmp cs:[cntl],16384
jae start9 ; jump if at least full block
mov cx,cs:[cntl]
cmp cx,0
jne start9 ; jump if more left to copy
jmp short start17
start12: mov cs:[useems],1 ; don't use EMS
mov bx,dx ; handle
mov dx,100h ; DS:DX segment:offset buffer
mov cx,65520 ; assume write full block
jmp short start16
start13: sub cs:[cntl],cx
sbb cs:[cnth],0
mov ah,40h ; write file
int 21h
jc start14 ; jump if error
cmp ax,cx
je start15 ; jump if all written
start14: mov ah,3Eh ; close file
int 21h
mov cs:[rcode],5
jmp fnish7
start15: mov ax,ds
add ax,4095 ; 65520 bytes
mov ds,ax
start16: cmp cs:[cnth],0
jne start13 ; jump if more than full block
cmp cs:[cntl],65520
jae start13 ; jump if at least full block
mov cx,cs:[cntl]
cmp cx,0
jne start13 ; jump if more left to write
mov ah,3Eh ; close file
int 21h
IF FHTSZ - 20
; save the file handle table in the kernel
mov es,cs:[psp] ; PSP segment
mov ds,es:[36h] ; file handle table segment
mov si,es:[34h] ; file handle table offset
push cs
pop es
mov di,offset fhtsv ; file handle table save
mov cx,FHTSZ ; file handle table size
rep movsb
ENDIF
start17: mov cx,cs
mov dx,offset handler ; interrupt handler offset
call safevect ; set vectors in vectab1
; time to copy the kernel
mov es,cs:[psp] ; PSP segment
mov di,100h
mov ds,cx ; DS = CS
mov si,offset slidetop
mov cx,offset slidebot - offset slidetop
shr cx,1 ; translate to word count
rep movsw ; CF set if one byte left over
adc cx,cx ; CX = 1 or 0, depending CF
rep movsb ; possible final byte
mov word ptr cs:[s1add+2],es ; PSP segment
index = offset slide1 - offset slidetop + 100h
mov word ptr cs:[s1add],index ; slide1 offset
mov cx,es ; PSP segment
index = offset handler - offset slidetop + 100h
mov dx,index ; interrupt handler offset
call safevect ; set vectors in vectab1
jmp dword ptr cs:[s1add] ; jump to the kernel
; If all goes well, this is where we come back to from the kernel.
fnish1: mov cs:[rcode],ax ; return code
cli ; restore original stack
mov ss,cs:[stks]
mov sp,cs:[stkp]
sti
push ds ; maybe EMS page frame segment
push dx ; maybe EMS handle
push bx ; maybe swap file handle
mov cx,cs
mov dx,offset handler ; interrupt handler offset
call safevect ; set vectors in vectab1
pop bx
pop dx
pop ds
cmp cs:[useems2],0
jne fnish4 ; jump if don't use EMS
; DS = EMS page frame segment
; DX = EMS handle
mov cx,offset slidebot - offset slidetop
mov es,cs:[psp] ; PSP segment
mov di,100h
xor si,si
xor bx,bx ; logical page number
call mapems
or ah,ah
jnz fnish3 ; jump if map failed
shr cx,1 ; translate to word count
rep movsw ; CF set if one byte left over
adc cx,cx ; CX = 1 or 0, depending CF
rep movsb ; possible final byte
fnish2: mov ah,45h ; release handle and memory
int 67h
cmp ah,82h ; memory manager busy?
je fnish2 ; jump if busy
jmp short fnish7
fnish3: mov ah,45h ; release handle and memory
int 67h
cmp ah,82h ; memory manager busy?
je fnish3 ; jump if busy
jmp short fnish5 ; exit
; BX = swap file handle
fnish4: xor cx,cx ; offset 0
xor dx,dx ; offset 0
mov ax,4200h ; move file pointer
int 21h ; from beginning of file
mov cx,offset slidebot - offset slidetop
mov ds,cs:[psp] ; PSP segment
mov dx,100h
mov ah,3Fh ; read file
int 21h
jc fnish5 ; exit if error
cmp ax,cx
je fnish6
fnish5: push cs
pop ds
mov dx,offset errmsg2
mov cx,msglen2 ; errmsg2 length
mov bx,2 ; standard error device handle
mov ah,40h ; write error message
int 21h
mov ax,4C01h ; terminate with return code
int 21h
fnish6: mov ah,3Eh ; close file
int 21h
push cs
pop ds
mov dx,offset file
mov ah,41h ; delete file
int 21h
fnish7: pop ds
pop si ; restore register variables
pop di
pop bp
mov ax,cs:[rcode] ; return code
or ax,ax
jz fnish11
push ax
mov ax,3000h ; get DOS version number
int 21h
cmp al,3 ; major version number
pop ax
jb fnish8
cmp al,34 ; unknown error - 3.0
jae fnish9
cmp al,32 ; sharing violation
jb fnish8
mov al,5 ; access denied
jmp short fnish10
fnish8: cmp al,19 ; unknown error - 2.0
jbe fnish10
fnish9: mov al,19 ; unknown error - 2.0
fnish10: xor ah,ah
fnish11: ret
; If we are not swapping, we jump here.
noswap1: mov ax,cs
; initialize parameter block
mov bx,cs:[env]
mov cs:[environ],bx
mov cs:[cmd],offset command
mov cs:[cmd+2],ax
mov cs:[fcb1],offset fcb5c
mov cs:[fcb1+2],ax
mov cs:[fcb2],offset fcb6c
mov cs:[fcb2+2],ax
; save 4 bytes destroyed by DOS 2.0 at DS:2Eh
mov si,cs:[2Eh]
mov word ptr cs:[save],si
mov si,cs:[30h]
mov word ptr cs:[save+2],si
mov cx,cs
mov dx,offset handler ; interrupt handler offset
call safevect ; set vectors in vectab1
mov es,cx ; ES = CS
mov bx,offset parmblk
mov ds,cx ; DS = CS
mov dx,offset path
mov ax,4B00h ; load and execute program
int 21h
jnc noswap2 ; jump if no error
mov cs:[rcode],ax ; return code
noswap2: cli ; restore original stack
mov ss,cs:[stks]
mov sp,cs:[stkp]
sti
; restore 4 bytes destroyed by DOS 2.0 at DS:2Eh
mov si,word ptr cs:[save]
mov cs:[2Eh],si
mov si,word ptr cs:[save+2]
mov cs:[30h],si
jmp fnish7
__xspawn ENDP
mapems PROC near
; DX = handle
; BX = logical page number
xor al,al ; physical page number
map1: mov ah,44h ; map memory
int 67h
cmp ah,82h ; memory manager busy?
je map1 ; jump if busy
ret
mapems ENDP
setvectsub PROC near
; ES = vector table segment
; BX = vector table offset
mov ah,25h ; set interrupt vector
setvectsub1: mov al,es:[bx+flag] ; 0-CURRENT,1-IRET,2-free,3-end
cmp al,3 ; is it the end?
je setvectsub3 ; yes, jump
cmp al,2 ; is it free?
je setvectsub2 ; yes, jump
mov al,es:[bx+number] ; vector number
mov ds,es:[bx+vseg] ; vector segment
mov dx,es:[bx+voff] ; vector offset
int 21h ; set interrupt vector
setvectsub2: add bx,6 ; size of vector structure
jmp setvectsub1 ; next
setvectsub3: ret
setvectsub ENDP
safevect PROC near
; CX = handler segment
; DX = handler offset
mov es,cs:[vtabseg] ; vectab1 segment
mov bx,cs:[vtaboff] ; vectab1 offset
safevect1: mov al,es:[bx+flag] ; 0-CURRENT,1-IRET,2-free,3-end
cmp al,3 ; is it the end?
je safevect3 ; yes, jump
cmp al,1 ; is it IRET?
jne safevect2 ; no, jump
mov es:[bx+vseg],cx ; handler segment
mov es:[bx+voff],dx ; handler offset
safevect2: add bx,6 ; size of vector structure
jmp safevect1 ; next
safevect3: mov bx,cs:[vtaboff] ; vectab1 offset
call setvectsub
ret
safevect ENDP
;
; int _xsize( unsigned int, long *, long * );
;
PUBLIC __xsize
IFDEF LCODE
__xsize PROC far
ELSE
__xsize PROC near
ENDIF
push bp
mov bp,sp
push di ; preserve register variables
push si
push ds
mov cs:[last],0 ; assume last block swap
mov bx,word ptr [bp+ARG_1] ; PSP segment
mov cs:[psp],bx
mov dx,bx
dec bx ; program arena header
size1: mov es,bx ; current arena header
mov ax,es:[own]
or ax,ax ; is it free?
jz size2 ; yes, count it
cmp ax,dx ; do we own it?
jne size4 ; no, jump
mov cx,bx ; last owned block
size2: inc bx
add bx,es:[siz] ; block size
jc size3 ; carry, arena is trashed
mov al,es:[sig] ; get arena signature
cmp al,'M' ; are we at end of memory?
je size1 ; no, jump
cmp al,'Z'
je size5
size3: mov bx,-1 ; request maximum memory
mov ah,48h ; allocate memory block
int 21h
mov cs:[rcode],7
jmp fnish7
size4: mov cs:[last],1 ; not last block swap
size5: sub bx,dx ; subtract PSP segment
mov ax,cx ; last owned block
mov es,cx
inc ax
add ax,es:[siz] ; block size
sub ax,dx ; subtract PSP segment
mov cs:[parsz],ax ; parent size
sub ax,10h ; subtract PSP size
xor dx,dx ; convert to bytes
mov cx,4
size6: shl ax,1
rcl dx,1
loop size6
IFDEF LDATA
lds si,dword ptr [bp+ARG_1+2]
ELSE
mov si,word ptr [bp+ARG_1+2]
ENDIF
mov ds:[si],ax ; swap size requirement
mov ds:[si+2],dx
mov cs:[cntl],ax ; count low
mov cs:[cnth],dx ; count high
mov cx,offset slidebot - offset slidetop
sub ax,cx
sbb dx,0
mov cs:[cntsvl],ax ; count save low
mov cs:[cntsvh],dx ; count save high
mov cs:[ttlsz],bx ; total size
xor dx,dx ; convert to bytes
mov cx,4
size7: shl bx,1
rcl dx,1
loop size7
IFDEF LDATA
lds si,dword ptr [bp+ARG_1+6]
ELSE
mov si,word ptr [bp+ARG_1+4]
ENDIF
mov ds:[si],bx ; parent and free memory
mov ds:[si+2],dx
pop ds
pop si ; restore register variables
pop di
pop bp
xor ax,ax
ret
__xsize ENDP
;
; int _chkems( char *, int * );
;
PUBLIC __chkems
IFDEF LCODE
__chkems PROC far
ELSE
__chkems PROC near
ENDIF
push bp
mov bp,sp
; determine whether expanded memory is available
IFDEF LDATA
push ds
lds dx,dword ptr [bp+ARG_1] ; EMM device driver name
ELSE
mov dx,word ptr [bp+ARG_1] ; EMM device driver name
ENDIF
mov ax,3D00h ; open file read only
int 21h
IFDEF LDATA
pop ds
ENDIF
jc check2 ; expanded memory unavailable
; determine whether we opened the EMM device driver or a file
mov bx,ax ; handle
mov ax,4400h ; IOCTL - get device info
int 21h
jc check1 ; expanded memory unavailable
test dx,80h ; test bit 7
jz check1 ; expanded memory unavailable
mov ax,4407h ; IOCTL - get output status
int 21h
jc check1 ; expanded memory unavailable
or al,al
jz check1 ; expanded memory unavailable
; close EMM device driver to reclaim handle
mov ah,3Eh ; close file
int 21h
; determine whether the EMM is functional
mov ah,40h ; get manager status
int 67h
or ah,ah
jnz check2 ; expanded memory unavailable
; check EMM version
mov ah,46h ; get EMM version
int 67h
or ah,ah
jnz check2 ; expanded memory unavailable
cmp al,32h ; version 3.2
jb check2 ; expanded memory unavailable
; get page frame segment
mov ah,41h ; get page frame segment
int 67h
or ah,ah
jnz check2 ; expanded memory unavailable
mov cs:[emsseg],bx ; segment
; get size of page map information
mov ax,4E03h ; get size of page map info
int 67h
or ah,ah
jnz check2 ; expanded memory unavailable
IFDEF LDATA
les bx,dword ptr [bp+ARG_1+4] ; mapsize address
mov es:[bx],ax
ELSE
mov bx,word ptr [bp+ARG_1+2] ; mapsize address
mov ds:[bx],ax
ENDIF
xor ax,ax ; expanded memory available
pop bp
ret
; close EMM device driver or file to reclaim handle
check1: mov ah,3Eh ; close file
int 21h
check2: mov ax,1 ; expanded memory unavailable
pop bp
ret
__chkems ENDP
;
; int _savemap( char * );
;
PUBLIC __savemap
IFDEF LCODE
__savemap PROC far
ELSE
__savemap PROC near
ENDIF
push bp
mov bp,sp
push di ; preserve register variable
IFDEF LDATA
les di,dword ptr [bp+ARG_1] ; buffer address
ELSE
mov di,word ptr [bp+ARG_1] ; buffer address
push ds
pop es
ENDIF
mov ax,4E00h ; save page map
int 67h
pop di ; restore register variable
pop bp
ret
__savemap ENDP
;
; int _restmap( char * );
;
PUBLIC __restmap
IFDEF LCODE
__restmap PROC far
ELSE
__restmap PROC near
ENDIF
push bp
mov bp,sp
push ds
push si ; preserve register variable
IFDEF LDATA
lds si,dword ptr [bp+ARG_1] ; buffer address
ELSE
mov si,word ptr [bp+ARG_1] ; buffer address
ENDIF
mov ax,4E01h ; restore page map
int 67h
xor al,al
pop si ; restore register variable
pop ds
pop bp
ret
__restmap ENDP
;
; int _getems( int, int * );
;
PUBLIC __getems
IFDEF LCODE
__getems PROC far
ELSE
__getems PROC near
ENDIF
push bp
mov bp,sp
mov bx,word ptr [bp+ARG_1] ; number of pages
mov ah,43h ; get handle and allocate
; memory
int 67h
IFDEF LDATA
les bx,dword ptr [bp+ARG_1+2] ; handle address
mov es:[bx],dx ; handle
ELSE
mov bx,word ptr [bp+ARG_1+2] ; handle address
mov ds:[bx],dx ; handle
ENDIF
xor al,al
pop bp
ret
__getems ENDP
;
; int _dskspace( int, unsigned int *, unsigned int * );
;
PUBLIC __dskspace
IFDEF LCODE
__dskspace PROC far
ELSE
__dskspace PROC near
ENDIF
push bp
mov bp,sp
push di ; preserve register variable
mov ah,36h ; get free disk space
mov dl,byte ptr [bp+ARG_1] ; drive code (0=default, 1=A)
int 21h
cmp ax,0FFFFh ; was drive invalid?
je space1 ; yes, jump
mul cx ; bytes per sector *
; sectors per cluster
IFDEF LDATA
les di,dword ptr [bp+ARG_1+2]
mov es:[di],ax ; bytes per cluster
ELSE
mov di,word ptr [bp+ARG_1+2]
mov ds:[di],ax ; bytes per cluster
ENDIF
IFDEF LDATA
les di,dword ptr [bp+ARG_1+6]
mov es:[di],bx ; number of available clusters
ELSE
mov di,word ptr [bp+ARG_1+4]
mov ds:[di],bx ; number of available clusters
ENDIF
xor ax,ax
space1: pop di ; restore register variable
pop bp
ret
__dskspace ENDP
;
; int _getrc( void );
;
PUBLIC __getrc
IFDEF LCODE
__getrc PROC far
ELSE
__getrc PROC near
ENDIF
mov ah,4Dh ; get child return code
int 21h
ret
__getrc ENDP
;
; int _create( char *, int * );
;
PUBLIC __create
IFDEF LCODE
__create PROC far
ELSE
__create PROC near
ENDIF
push bp
mov bp,sp
IFDEF LDATA
push ds
ENDIF
mov ax,3000h ; get DOS version number
int 21h
IFDEF LDATA
lds dx,dword ptr [bp+ARG_1] ; file
ELSE
mov dx,word ptr [bp+ARG_1] ; file
ENDIF
xor cx,cx ; normal attribute
mov ah,5Bh ; create new file
cmp al,3 ; major version number
jae create1
mov ah,3Ch ; create file
create1: int 21h
jc create2
IFDEF LDATA
lds bx,dword ptr [bp+ARG_1+4] ; handle address
ELSE
mov bx,word ptr [bp+ARG_1+2] ; handle address
ENDIF
mov ds:[bx],ax
xor ax,ax
create2:
IFDEF LDATA
pop ds
ENDIF
pop bp
ret
__create ENDP
;
; int _getcd( int, char * );
;
PUBLIC __getcd
IFDEF LCODE
__getcd PROC far
ELSE
__getcd PROC near
ENDIF
push bp
mov bp,sp
push si ; preserve register variable
IFDEF LDATA
push ds
ENDIF
mov dl,byte ptr [bp+ARG_1] ; drive code (0=default, 1=A)
IFDEF LDATA
lds si,dword ptr [bp+ARG_1+2] ; buffer
ELSE
mov si,word ptr [bp+ARG_1+2] ; buffer
ENDIF
mov ah,47h ; get current directory
int 21h
jc getcd1
xor ax,ax
getcd1:
IFDEF LDATA
pop ds
ENDIF
pop si ; restore register variable
pop bp
ret
__getcd ENDP
;
; int _getdrv( void );
;
PUBLIC __getdrv
IFDEF LCODE
__getdrv PROC far
ELSE
__getdrv PROC near
ENDIF
mov ah,19h ; get default disk drive
int 21h
xor ah,ah
; AX = drive (0 = A, 1 = B, etc.)
ret
__getdrv ENDP
;
; void _getvect( int, unsigned int *, unsigned int * );
;
PUBLIC __getvect
IFDEF LCODE
__getvect PROC far
ELSE
__getvect PROC near
ENDIF
push bp
mov bp,sp
push ds
push si ; preserve register variable
mov ah,35h ; get interrupt vector
mov al,byte ptr [bp+ARG_1] ; interrupt number
int 21h
IFDEF LDATA
lds si,dword ptr [bp+ARG_1+2]
ELSE
mov si,word ptr [bp+ARG_1+2]
ENDIF
mov ds:[si],es ; segment
IFDEF LDATA
lds si,dword ptr [bp+ARG_1+6]
ELSE
mov si,word ptr [bp+ARG_1+4]
ENDIF
mov ds:[si],bx ; offset
pop si ; restore register variable
pop ds
pop bp
ret
__getvect ENDP
;
; void _setvect( VECTOR * );
;
PUBLIC __setvect
IFDEF LCODE
__setvect PROC far
ELSE
__setvect PROC near
ENDIF
push bp
mov bp,sp
push ds ; modified in setvectsub
IFDEF LDATA
les bx,dword ptr [bp+ARG_1] ; vector table
ELSE
mov bx,word ptr [bp+ARG_1] ; vector table
push ds
pop es
ENDIF
call setvectsub
pop ds
pop bp
ret
__setvect ENDP
;
; void _setdrvcd(int drive, char * string);
;
PUBLIC __setdrvcd
IFDEF LCODE
__setdrvcd PROC far
ELSE
__setdrvcd PROC near
ENDIF
push bp
mov bp,sp
IFDEF LDATA
push ds
ENDIF
mov dl,byte ptr [bp+ARG_1] ; drive code (0=A, 1=B)
mov ah,0eh
int 21h
IFDEF LDATA
lds dx,dword ptr [bp+ARG_1+2] ; buffer
ELSE
mov dx,word ptr [bp+ARG_1+2] ; buffer
ENDIF
mov ah,3bh ; set current directory
int 21h
IFDEF LDATA
pop ds
ENDIF
pop bp
ret
__setdrvcd ENDP
_TEXT ENDS
END