;; This is the biggest damned hack I've ever seen under DPMI.  As if there
;; aren't enough hacks as it is.  Since it is required that we be able
;; to execute some real-mode code (like DIGPAK and MIDPAK) even though
;; we are in proteted mode, it is necessary to get into real-mode.
;; The problem is that DIGPAK and MIDPAK are initialized and de-initialized
;; through a indirect far call to a jump table.  Normal funtion 301h of
;; the DPMI services int 31h would take care of this.  But the 4GW 'royalty
;; free' DOS extender that comes with Watcom doesn't support this most basic
;; function.  Meaning there is no way, from protected mode, that we can call
;; a real-mode far procedure.  Therefor I have created, as a place holder, the
;; 'vector manager'.  This attaches to the INT 66h vector PRIOR!!!! to any
;; DIGPAK/MIDPAK installation.	      This is accomplished by stomping on the INT
;; 66h vector and simulating a real-mode interrupt, which 4GW supports.
;; However, even this method of installing the interupt is dangerous.
;; It is only a placeholder until a better system can be devised.  Once
;; installed the VECTOR manager now provides a service that will let us
;; peform a far real-mode procedure call.
;; The vector manager requires the presence of VECTOR.COM in the directory
;; which is the tiny real-mode interrupt vector hook.  This is all black
;; boxed and handled by the LOADER.C program which handles dynamically
;; loading and unloading DIGPAK and MIDPAK drivers.
;; Note: both DIGPAK and MIDPAK are capable of operating as a DOS real-mode
;; TSR.  If LOADER finds both DIGPAK and MIDPAK in memory as a TSR it will
;; use the resident portion rather than trying to dynamicall load the
;; versions specified.
;; extern int cdecl InstallVector(char *vect); // Install far call vector manager.
;; extern int cdecl RemoveVector(void); // Remove vector manager.
;;																																					 */
;;		Written by John W. Ratcliff (c) 1994
;;			 Compuserve: 70253,3237
;;			 Genie: J.RATCLIFF3
;;			 BBS: 1-314-939-0200
;;			 Addresss:
;;			    747 Napa Lane
;;			    St. Charles, MO 63304
;;																																					 */

	IDEAL
	P386
	JUMPS
	MODEL FLAT,C

Struc   PREGS

R_EDI   dd      ?       ; The EDI register.
R_ESI   dd      ?       ; The ESI register.
R_EBP   dd      ?       ; The EBP register.
R_RESERVED dd   ?       ; reserved, should be zero.
R_EBX   dd      ?       ; The EBX register.
R_EDX   dd      ?       ; The EDX register.
R_ECX   dd      ?       ; The ECX register.
R_EAX   dd      ?       ; The EAX register.
R_FLAGS dw      ?       ; The CPU flags register.
R_ES    dw      ?       ; The ES register.
R_DS    dw      ?       ; The DS register.
R_FS    dw      ?       ; The FS register.
R_GS    dw      ?       ; The GS register.
R_IP    dw      ?       ; Reserved
R_CS    dw      ?       ; Reserved
R_SP    dw      ?       ; Stack pointer
R_SS    dw      ?       ; Stack segment.

        Ends


	CODESEG

	public	InstallVector
	public	RemoveVector

SIMREGS PREGS <>

OLDOFF	dw	0
OLDSEG	dw	0

Proc	C	InstallVector
	ARG	VECTOR:DWORD
	uses	ebx,ecx,esi,edi

	lea	edi,[SIMREGS]		; Get the address of the registers
	mov	ecx,size SIMREGS	; for size of the register region.
	xor	eax,eax
	rep	stosb			; Zero out register region.

	mov	ebx,[VECTOR]	; Get the address of the 'supposed' DIGPAK.
	cmp	[byte ebx+3],'V'        ; Does it say digpak?
	jne	@@FREE
	cmp	[byte ebx+4],'E'        ;
	jne	@@FREE
	cmp	[byte ebx+5],'C'
	jne	@@FREE
	cmp	[byte ebx+6],'T'
	jne	@@FREE
	cmp	[byte ebx+7],'O'
	jne	@@FREE
	cmp	[byte ebx+8],'R'
	jne	@@FREE
;; Ok, it SAY's VECTOR.
	shr	ebx,4		; segment.
	sub	bx,10h		; less 10 paragraphs.

	push	ebx
	mov	ebx,66h
	mov	eax,200h
	int	31h
	mov	[OLDSEG],cx	; Save original segment
	mov	[OLDOFF],dx	; Save original offset.
	pop	ebx

	mov	ecx,ebx 	; CX=segment.
	mov	edx,200h	; Offset.
	mov	ebx,66h 	; Install interrupt.
	mov	eax,201h	; Intall real-mode interrupt vector.
	int	31h		; install it.

	lea	edi,[SIMREGS]	; Get address.
	xor	ecx,ecx 	; Don't copy anything on the stack.
	xor	ebx,ebx 	; Zero out flags.
	mov	eax,0300h	; simulate realmode interrupt
	mov	bl,66h
	int	31h		; Do it!
	jc	@@FREE		; Failed.
	mov	ax,1		; Worked!
@@RET:
	ret
@@FREE:
	xor	ax,ax	; Zero failed return code
	jmp short @@RET
	endp

Proc	C	RemoveVector
	uses	ebx,ecx,edx
	cmp	[OLDSEG],0
	je	@@NOTIN
	movsx	ecx,[OLDSEG]	; CX=segment.
	movsx	edx,[OLDOFF]	; Offset.
	mov	ebx,66h 	; Install interrupt.
	mov	eax,201h	; Intall real-mode interrupt vector.
	int	31h		; install it.
	mov	[OLDSEG],0
	mov	[OLDOFF],0
@@NOTIN:
	ret
	endp

	ends
	end
