#ifdef WINDOWS #include #include #include "dpmi.h" #define MAKEP(seg, ofs) ((void far *)MAKELONG((ofs), (seg))) static unsigned __0000H; dpmi_rmode_intr(unsigned intno, unsigned flags, unsigned copywords, RMODE_CALL far *rmode_call) { /* Copying won't work here - fail if they try it. */ if(copywords) return 0; /* To make DPMI reset the 8259's and A20 for real mode, set BH=1 */ if (flags) intno |= 0x100; _asm { push di mov ax, 0300h /* simulate real-mode interrupt */ mov bx, word ptr intno /* interrupt number, flags */ mov cx, 0 /* words to copy from pmode to rmode stack */ les di, dword ptr rmode_call /* ES:DI = addr of rmode call struct */ int 31h /* call DPMI */ jc error mov ax, 1 /* return TRUE */ jmp short done } error: _asm xor ax, ax /* return FALSE */ done: _asm pop di } unsigned dpmi_sel(void) { asm { xor ax, ax mov cx, 1 int 31h jc error jmp short done } error: asm xor ax, ax done:; } dpmi_set_descriptor(unsigned pmodesel, DESCRIPTOR far *d) { asm { push di mov ax, 0ch mov bx, word ptr pmodesel les di, dword ptr d int 31h jc error mov ax, 1 jmp short done } error: asm xor ax, ax done: asm pop di } dpmi_get_descriptor(unsigned pmodesel, DESCRIPTOR far *d) { asm { push di mov ax, 0bh mov bx, word ptr pmodesel les di, dword ptr d int 31h jc error mov ax, 1 jmp short done } error: asm xor ax, ax done: asm pop di } void far (*dpmi_make_callback(void far (*p)(), RMODE_CALL far *rc))() { _asm { push ds push si push di lds si, dword ptr p /* pmode call-back procedure address */ les di, dword ptr rc /* pmode address of static stuct to use */ mov ax, 0303h /* allocate call-back address */ int 31h /* call DPMI */ pop di pop si pop ds jc error mov ax, dx /* return rmode seg:ofs on success */ mov dx, cx jmp short done } error: _asm xor ax, ax _asm mov dx, ax done:; } int dpmi_free_callback(void far (*p)()) { _asm { mov dx, word ptr p mov cx, word ptr p+2 mov ax, 0304h int 31h mov ax, 0 jc done inc ax } done:; } unsigned verw(unsigned sel) { asm mov ax, 1 asm verw sel asm je short ok asm xor ax, ax ok:; } unsigned MapRealSeg(unsigned rpara, DWORD size, unsigned far *psel) { DESCRIPTOR d; unsigned long addr; unsigned sel = dpmi_sel(); if(!sel) return 0; if(!verw(FP_SEG(psel))) return(490); dpmi_get_descriptor(FP_SEG(psel), &d); d.limit = (unsigned)size - 1; addr = ((unsigned long)rpara) << 4; d.addr_lo = (unsigned)addr; d.addr_hi = (unsigned char)(addr >> 16); d.res1 = d.addr_xhi = 0; dpmi_set_descriptor(sel, &d); *psel = sel; return 0; } void far * ProtToReal(void far *prot) { unsigned long base = GetSelectorBase(FP_SEG(prot)); if(base >= 0x100000L) return NULL; else return MAKEP(base >> 4, (base & 0x0f) + FP_OFF(prot)); } void far * map_real(void far *rptr, unsigned long size) { unsigned seg, ofs, sel; /* If not running standard or enhanced, nothing more to do */ if(!(GetWinFlags() & WF_PMODE)) return rptr; if(!__0000H) __0000H = LOWORD(GetProcAddress(GetModuleHandle("KERNEL"), "__0000H")); seg = FP_SEG(rptr); ofs = FP_OFF(rptr); if((seg < 0x1000) && ((ofs + size) < 0xffff)) return(MAKEP(__0000H, (seg << 4) + ofs)); if(MapRealSeg(seg, size + ofs, &sel) != 0) return 0; return(MAKEP(sel, ofs)); } void unmap_real(void far *p) { unsigned sel = FP_SEG(p); /* If not running standard or enhanced, nothing more to do */ if(!(GetWinFlags() & WF_PMODE)) return; if(sel != __0000H) { asm { mov ax, 1 mov bx, word ptr sel int 31h jc error mov ax, 1 jmp short done } error: asm xor ax, ax done:; } } /* * Replacement intr() function to perform a real-mode software * interrupt under DPMI. */ void pmode_intr(int intno, struct REGPACK _FAR *regs) { RMODE_CALL pregs; register RMODE_CALL *pp = &pregs; register struct REGPACK far *rp = regs; pp->res1 = 0; pp->flags = rp->r_flags; pp->eax = rp->r_ax; pp->ebx = rp->r_bx; pp->ecx = rp->r_cx; pp->edx = rp->r_dx; pp->esi = rp->r_si; pp->edi = rp->r_di; pp->ebp = rp->r_bp; pp->ds = rp->r_ds; pp->es = rp->r_es; pp->ss = pp->sp = 0; /* 0:0 -> DPMI provides a 30-word stack */ pp->fs = pp->gs = pp->ds; dpmi_rmode_intr(intno, 0, 0, (RMODE_CALL far *)pp); rp->r_ax = pp->eax; rp->r_bx = pp->ebx; rp->r_cx = pp->ecx; rp->r_dx = pp->edx; rp->r_si = pp->esi; rp->r_di = pp->edi; rp->r_bp = pp->ebp; rp->r_ds = pp->ds; rp->r_es = pp->es; rp->r_flags = pp->flags; } #endif