;
; SUBROUTINE INT86QQ( intnum, inregs, outregs )
;
; Inputs: intnum - interrupt number to be executed (integer*2 value)
;         inregs - pointer to REGINFO structure, contains input register
;                  values for interrupt
;
; Outputs: outregs - pointer to REGINFO structure, contains the return
;                    registers for the interrupt
;


	.386

      .MODEL  flat, stdcall

REGINFO         STRUCT  4      ; Register structure used in application

   RegEAX       DWORD   0
   RegEBX       DWORD   0
   RegECX       DWORD   0
   RegEDX       DWORD   0
   RegESI       DWORD   0
   RegEDI       DWORD   0
   RegCFLAG      WORD   0

REGINFO         ENDS


REG_BLOCK      STRUCT          ; Register structure used by Phar Lap

   IntNum      WORD     ?
   RealDS      WORD     ?
   RealES      WORD     ?
   RealFS      WORD     ?
   RealGS      WORD     ?
   RealEAX     DWORD    ?
   RealEDX     DWORD    ?
   
REG_BLOCK      ENDS  
                                               

TRANS_BLOCK    STRUCT          ; Register structure used by DPMI

   RegEDI      DWORD    ?
   RegESI      DWORD    ?
   RegEBP      DWORD    ?
   Reserv1     DWORD    ?
   RegEBX      DWORD    ?
   RegEDX      DWORD    ?
   RegECX      DWORD    ?
   RegEAX      DWORD    ?
   FlagReg      WORD    ?
   RegES        WORD    ?
   RegDS        WORD    ?
   RegFS        WORD    ?
   RegGS        WORD    ?
   RegIP        WORD    ?
   RegCS        WORD    ?
   RegSP        WORD    ?
   RegSS        WORD    ?


TRANS_BLOCK    ENDS


INT86QQ PROTO   STDCALL, intnum:WORD, inregs:PTR REGINFO, outregs:PTR REGINFO

      .DATA               

DPMI_block     TRANS_BLOCK <?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?>
Parm_block     REG_BLOCK   <?,?,?,?,?,?,?>      
check_DPMI     dd          0
DPMI_avail     dd          0
   
      .CODE

                            
INT86QQ   PROC STDCALL USES ebx esi edi,
                            intnum:WORD,         ; interrupt number
                            inregs:PTR REGINFO,  ; input registers
                            outregs:PTR REGINFO  ; output registers
                            
      .IF   !check_DPMI           ; have we checked yet for DPMI?
            mov   check_DPMI,1
            mov   ax,1686H
            int   2fH             ; check for DMPI here
            or    ax,ax
            jnz   no_DPMI
            mov   DPMI_avail,1    ; We have DPMI, so set flag
      .ELSE
           .IF    !DPMI_avail
                  jmp   no_DPMI
           .ENDIF
      .ENDIF
            
use_DPMI:

      mov    ecx,inregs      ; Load registers into DPMI structure
      lea    edx,DPMI_block       
      
      mov    eax,[ecx]       ; EAX
      mov    [edx+28],eax
      
      mov    eax,[ecx+4]     ; EBX
      mov    [edx+16],eax
      
      mov    eax,[ecx+8]     ; ECX
      mov    [edx+24],eax
      
      mov    eax,[ecx+12]    ; EDX
      mov    [edx+20],eax
     
      mov    eax,[ecx+16]    ; ESI
      mov    [edx+4],eax
     
      mov    eax,[ecx+20]    ; EDI
      mov    [edx],eax
     
                            
      mov    ax,0300h           ; simulate real mode interrupt
      lea    edi,DPMI_block
      mov    bx,intnum
      mov    bh,1
      sub    cx,cx
      int    31H
                            
      mov    ecx,outregs                                    
      
      .IF    CARRY?                       ; store carry flag
             mov    WORD PTR [ecx+22],1
      .ELSE
             mov    WORD PTR [ecx+22],0
      .ENDIF        
      
      lea    edx,DPMI_block  ; Store registers into REGINFO structure
      
      mov    eax,[edx+28]
      mov    [ecx],eax       ; EAX
      
      mov    eax,[edx+16]
      mov    [ecx+4],eax     ; EBX
      
      mov    eax,[edx+24]
      mov    [ecx+8],eax     ; ECX
      
      mov    eax,[edx+20]
      mov    [ecx+12],eax    ; EDX
     
      mov    eax,[edx+4]
      mov    [ecx+16],eax    ; ESI
     
      mov    eax,[edx]
      mov    [ecx+20],eax    ; EDI
     
      jmp   We_are_done                                       

no_DPMI:               
                                   
      mov    cx,intnum     ; LOAD PARAMETER BLOCK
      mov    Parm_block.Intnum,cx
      
      
      mov    ecx,inregs    ; LOAD REGISTERS
      mov    eax,[ecx+8]   ; get ecx register
      push   eax           ;  and save
      
      mov    eax,[ecx]     ; load registers
      mov    Parm_block.RealEAX,eax
      mov    ebx,[ecx+4]
      mov    edx,[ecx+12]
      mov    Parm_block.RealEDX,edx
      mov    esi,[ecx+16]
      mov    edi,[ecx+20]
      pop    ecx
      
      LEA    edx, Parm_block          
      mov    ax,2511h      ; Issue real mode interrupt (Phar Lap)
      int    21H           ; system call
      
      push   ecx
      mov    ecx,outregs                                    
      
      .IF    CARRY?                       ; store carry flag
             mov    WORD PTR [ecx+22],1
      .ELSE
             mov    WORD PTR [ecx+22],0
      .ENDIF
                                   
      mov    [ecx],eax     ; store return registers
      mov    [ecx+4],ebx
      mov    edx,Parm_block.RealEDX
      mov    [ecx+12],edx
      mov    [ecx+16],esi
      mov    [ecx+20],edi
      
      pop    ecx         
      
We_are_done:
      
      ret
            
INT86QQ ENDP

      
      END
