From f0998e650479b01cdc5f9b85fbe1a823bdede7cb Mon Sep 17 00:00:00 2001 From: Sjoerd van der Berg Date: Wed, 31 Mar 2004 14:43:50 +0000 Subject: [PATCH] internal dpmi not needed anymore Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1744 --- src/dosbox.cpp | 12 +- src/ints/dpmi.cpp | 3233 --------------------------------------------- 2 files changed, 1 insertion(+), 3244 deletions(-) delete mode 100644 src/ints/dpmi.cpp diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 69bce9c4..88c1fc1f 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dosbox.cpp,v 1.66 2004-03-10 13:49:30 qbix79 Exp $ */ +/* $Id: dosbox.cpp,v 1.67 2004-03-31 14:43:50 harekiet Exp $ */ #include #include @@ -91,7 +91,6 @@ void MSCDEX_Init(Section*); /* Dos Internal mostly */ void EMS_Init(Section*); void XMS_Init(Section*); -void DPMI_Init(Section*); void AUTOEXEC_Init(Section*); void SHELL_Init(void); @@ -350,18 +349,9 @@ void DOSBOX_Init(void) { secprop->Add_bool("xms",true); secprop->AddInitFunction(&EMS_Init); secprop->Add_bool("ems",true); -#if (C_DEBUG) - secprop->AddInitFunction(&DPMI_Init); - secprop->Add_bool("dpmi",false); -#endif MSG_Add("DOS_CONFIGFILE_HELP", "xms -- Enable XMS support.\n" "ems -- Enable EMS support.\n" -#if (C_DEBUG) - "dpmi -- Enable builtin DPMI host support.\n" - " This might help in getting some games to work, but might crash others.\n" - " So be sure to try both settings.\n" -#endif ); // Mscdex secprop->AddInitFunction(&MSCDEX_Init); diff --git a/src/ints/dpmi.cpp b/src/ints/dpmi.cpp deleted file mode 100644 index dbbe45f2..00000000 --- a/src/ints/dpmi.cpp +++ /dev/null @@ -1,3233 +0,0 @@ -/* - * Copyright (C) 2002-2004 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -// Pharlap Special Infos: -// - Dont hook hardware ints -// - CMOS Memory Size has to return 0 otherwise it tries to map physical memory -// - Set PM Int Vector : Use it on current idt, not only dpmi one (ultima 8 mouse check fails otherwise) -// - Ultima 8 wants 40 Files (Hack in PSP::SetNumFiles -// - Ultima 8 and Bioforge work with DPL 3 -// - Crusaders 1+2 seem to need DPL 0, which is bad... -// - Bioforge uses more than 2048 descriptos in ldt (4096) - -#include -#include -#include -#include "dosbox.h" -#include "dos_inc.h" -#include "callback.h" -#include "mem.h" -#include "regs.h" -#include "dos_system.h" -#include "setup.h" -#include "inout.h" -#include "cpu.h" -#include "bios.h" -#include "paging.h" - -#include "debug.h" - -//#define DPMI_LOG LOG(LOG_MISC,LOG_ERROR) -#define DPMI_LOG - -#define DPMI_LOG_ERROR LOG(LOG_MISC,LOG_ERROR) -//#define DPMI_LOG_ERROR - -#define DPMI_ALLOC_NEEDEDMEM_HIGH 1 - -#define DPMI_DPL 3 - -#define GDT_ZERO 0 -#define GDT_LDT ((0x1 << 3) | DPMI_DPL) -#define GDT_CODE ((0x2 << 3) | DPMI_DPL) -#define GDT_PROTCODE ((0x3 << 3) | DPMI_DPL) -#define GDT_DOSDATA ((0x4 << 3) | DPMI_DPL) -#define GDT_ENVIRONMENT ((0x5 << 3) | DPMI_DPL) - -#define GDT_DOSSEG40 (0x40) - -/* Amount of descriptors in each table */ -#define GDT_SIZE 32 -#define IDT_SIZE 256 -#define LDT_SIZE 4096 -#define INT_SIZE 256 - -#define TOTAL_SIZE ((GDT_SIZE+IDT_SIZE+LDT_SIZE+INT_SIZE)*8) - -#define LDT_ENTRY(BLAH_) (BLAH_ << 3) - -#define LDT_FIRSTSELECTOR 16 - -#define DPMI_ERROR_UNSUPPORTED 0x8001 -#define DPMI_ERROR_DESCRIPTOR_UNAVAILABLE 0x8011 -#define DPMI_ERROR_LINEAR_MEMORY_UNAVAILABLE 0x8012 -#define DPMI_ERROR_PHYSICAL_MEMORY_UNAVAILABLE 0x8013 -#define DPMI_ERROR_CALLBACK_UNAVAILABLE 0x8015 -#define DPMI_ERROR_INVALID_SELECTOR 0x8022 -#define DPMI_ERROR_INVALID_VALUE 0x8022 -#define DPMI_ERROR_INVALID_HANDLE 0x8023 -#define DPMI_ERROR_INVALID_CALLBACK 0x8024 -#define DPMI_ERROR_INVALID_LINEAR_ADDRESS 0x8025 - -#define DPMI_XMSHANDLES_MAX 256 -#define DPMI_XMSHANDLE_FREE 0xFFFF -#define DPMI_EXCEPTION_MAX 0x20 -#define DPMI_PAGE_SIZE (4*1024) -#define DPMI_REALMODE_CALLBACK_MAX 32 -#define DPMI_REALMODE_STACKSIZE 4096 -#define DPMI_PROTMODE_STACK_MAX 3 -#define DPMI_PROTMODE_STACKSIZE (4*1024) -#define DPMI_REALVEC_MAX 17 -#define DPMI_SAVESTACK_MAX 1024 - -#define DPMI_CB_APIMSDOSENTRY_OFFSET 256*8 -#define DPMI_CB_ENTERREALMODE_OFFSET 257*8 -#define DPMI_CB_SAVESTATE_OFFSET 258*8 -#define DPMI_CB_EXCEPTION_OFFSET 259*8 -#define DPMI_CB_EXCEPTIONRETURN_OFFSET 260*8 -#define DPMI_CB_VENDORENTRY_OFFSET 261*8 - -static bool g_hookHardwareInts = true; - -void CMOS_SetRegister(Bitu regNr, Bit8u val); - -static Bitu rmIndexToInt[DPMI_REALVEC_MAX] = -{ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x1C }; - -// General functions -void CALLBACK32_SCF(bool val) -{ - Bitu v_esp = 0; - if (cpu.stack.big) v_esp = reg_esp; else v_esp = reg_sp; - Bit32u tempf=mem_readd(SegPhys(ss)+v_esp+8) & 0xFFFFFFFE; - Bit32u newCF=(val==true); - mem_writed(SegPhys(ss)+v_esp+8,(tempf | newCF)); -}; - -#define DPMI_CALLBACK_SCF(b) if (dpmi.client.bit32) CALLBACK32_SCF(b); else CALLBACK_SCF(b) - -// ********************************************** -// SetDescriptor Class -// ********************************************** - -#pragma pack(1) -class SetDescriptor : public Descriptor { -public: - void Save(PhysPt address) { - Bit32u* data = (Bit32u*)&saved; - mem_writed(address,*data); - mem_writed(address+4,*(data+1)); - } - - void SetBase(Bitu _base) { - saved.seg.base_24_31=_base >> 24; - saved.seg.base_16_23=_base >> 16; - saved.seg.base_0_15=_base; - } - void SetLimit (Bitu _limit) { - if (_limit<1048576) saved.seg.g=false; - else { - saved.seg.g=true; - _limit>>=12; - } - saved.seg.limit_0_15=_limit; - saved.seg.limit_16_19=_limit>>16; - } - void SetOffset(Bitu _offset) { - saved.gate.offset_0_15=_offset; - saved.gate.offset_16_31=(_offset>>16); - } - void SetSelector(Bitu _selector) { - saved.gate.selector=_selector; - } - void SetType(Bitu _type) { - saved.seg.type=_type; - } - void Clear(void) { - saved.fill[0]=saved.fill[1]=0; - } -}; -#pragma pack() - -// ********************************************** -// Shared Memory -// ********************************************** - -typedef struct SSharedMem { - - std::string name; - Bitu handle; - Bitu pages; - -} TSharedMem; - -std::list g_sharedMemList; - -// ********************************************** -// DPMI Class -// ********************************************** - -class DPMI { - -public: - DPMI (void); - ~DPMI (void); - - // Settp/Startup methods - void Setup (void); - Bitu Entrypoint (void); - RealPt HookInterrupt (Bitu num, Bitu intHandler); - void RestoreHookedInterrupt (Bitu num, RealPt oldVec); - void CreateStackSpace (void); - bool HasClient (void) { return dpmi.client.have; }; - void Terminate (void); - void Reactivate (void); - - // DPMI Services - Bitu AllocateLDTDescriptor (Bitu count,Bitu & base); - Bitu AllocateLDTDescriptor2 (Bitu count,Bitu & base); // TEMP - bool AllocateMem (Bitu size, Bitu& outHandle, Bitu& linear); - Bitu CreateAlias (Bitu selector, Bit16u& alias); - void ReloadSegments (Bitu selector); - bool SetAccessRights (Bitu selector, SetDescriptor& desc, Bitu rights); - bool SetProtInterrupt (Bitu num, Bitu selector, Bitu offset); - - // Special Interrupt handlers - Bitu Int2fHandler (void); - Bitu Int31Handler (void); - - // Exceptions - Bitu CreateException (void); - void CreateException (Bitu num, Bitu errorCode); - Bitu ExceptionReturn (void); - - // Realmode callbacks - bool AllocateRealModeCallback(Bitu codeSel,Bitu codeOff,Bitu dataSel, Bitu dataOff, Bitu& segment, Bitu& offset); - Bitu RealModeCallback (void); - Bitu RealModeCallbackReturn (void); - - // Real mode reflection callbacks - void PrepareReflectToReal (Bitu num); - Bitu CallRealIRETFrame (bool callAsInt); - Bitu CallRealIRETFrameReturn (void); - Bitu SimulateInt (void); - Bitu SimulateIntReturn (void); - Bitu ptorHandler (void); - Bitu ptorHandlerReturn (void); - Bitu Int21Handler (void); - Bitu Int21HandlerReturn (void); - Bitu HWIntDefaultHandler (void); - void RemoveIntCallbacks (void); - void RestoreIntCallbacks (void); - - // Switching modes - void SaveRegisterState (Bitu num); - void LoadRegisterState (Bitu num); - Bitu EnterProtMode (void); - Bitu EnterRealMode (void); - Bitu RealSaveState (void); - Bitu ProtSaveState (void); - - // virtual interrupt flag - bool GetVirtualIntFlag (void); - void SetVirtualIntFlag (bool on); - - // Internal Stack for saving processor status - void PushStack (Bitu val) { saveStack[savePtr++] = val; }; - Bitu PopStack (void) { return saveStack[--savePtr]; }; - void SaveSegments (void); - void SaveRegister (void); - void RestoreSegments (void); - void RestoreRegister (void); - - void CopyRegistersToBuffer (PhysPt data); - void LoadRegistersFromBuffer (PhysPt data); - - void ProvideRealModeStack (PhysPt prStack, Bitu toCopy); - void UpdateRealModeStack (void); - - // xms handle information - void SetXMSHandle (Bitu handle); - void ClearXMSHandles (void); - void FreeXMSHandle (Bitu handle); - - // shared memory - void SetSharedMem (const char* name, Bitu handle, Bitu pages); - bool GetSharedMem (const char* name, Bitu& handle, Bitu& pages); - bool IsSharedMem (Bitu handle); - bool RemoveSharedMem (Bitu handle); - - // special msdos api stuff - void SetupPharlapSelectors (void); - bool Pharlap_AllocateMem (Bitu size, Bitu& outHandle, Bitu& linear); - Bitu GetSegmentFromSelector (Bitu selector); - bool GetMsdosSelector (Bitu realseg, Bitu realoff, Bitu &protsel, Bitu &protoff); - void API_Init_MSDOS (void); - Bitu API_Entry_MSDOS (void); - Bitu API_Int21_MSDOS (void); - - // debug - void Debug_ShowDescriptors (void); - -private: - Bitu Mask (Bitu value); - - Bitu saveStack[DPMI_SAVESTACK_MAX]; - Bitu savePtr; - Bitu rm_ss, rm_sp; - - struct { - struct { - bool have; - bool bit32; - Bitu psp; - } client; - Bit32s mem_handle; /* Handle for GDT/IDT */ - Bitu idtBase,idtLimit; - struct { - PhysPt base; - Bitu limit; - } gdt,idt,ldt; - struct { - bool inCall; - bool inUse; - bool stop; - Bitu callCount; - Bitu id; - Bitu dataSelector,dataOffset; - Bitu codeSelector,codeOffset; - Bitu realSegment ,realOffset; - } rmCallback[DPMI_REALMODE_CALLBACK_MAX]; - - RealPt realModeVec [DPMI_REALVEC_MAX]; - Bitu oldRealVec [DPMI_REALVEC_MAX]; - Bitu defaultHWIntFromProtMode[DPMI_REALVEC_MAX]; - - PhysPt ptorint_base; /* Base of pmode int handlers that reflect to realmode */ - Bitu exceptionSelector[DPMI_EXCEPTION_MAX],exceptionOffset[DPMI_EXCEPTION_MAX]; - - Bitu xmsHandles[DPMI_XMSHANDLES_MAX]; - Bitu protStack; - - Bitu protStackSelector[DPMI_PROTMODE_STACK_MAX]; - Bitu realStackSelector[DPMI_PROTMODE_STACK_MAX]; - Bitu dataSelector [DPMI_PROTMODE_STACK_MAX]; - Bitu protStackCurrent; - - Bitu vIntFlag; - - bool pharlap; - bool suppressRMCB; - - // Pharlap stuff - Bitu initialcs,initialds; - Bitu initialenv; - } dpmi; - - Bit32u* modIntTable; - DPMI* prevDPMI; - std::vector dosSelectorList; - - Bitu dtaAddress; - Bitu save_cs[2],save_ds[2],save_es[2],save_fs[2],save_gs[2],save_ss[2]; - Bitu save_eax[2],save_ebx[2],save_ecx[2],save_edx[2],save_esi[2],save_edi[2]; - Bitu save_ebp[2],save_esp[2],save_eip[2],save_fl[2]; -}; - -struct { - Bitu entry; - Bitu ptorint; - Bitu ptorintReturn; - Bitu int31; - Bitu int21; - Bitu int21Return; - Bitu int2f; - Bitu enterpmode; - Bitu enterrmode; - Bitu protsavestate; - Bitu realsavestate; - Bitu simint; - Bitu simintReturn; - Bitu rmIntFrame; - Bitu rmIntFrameReturn; - Bitu rmCallbackReturn; - Bitu exception; - Bitu exceptionret; - // Special callbacks for special dos extenders - Bitu apimsdosentry; - Bitu int21msdos; -} callback; - -// ************************************************ -// DPMI static functions -// ************************************************ - -#define SWITCH_TO_REALMODE CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); \ - CPU_SIDT(dpmi.idtLimit,dpmi.idtBase); \ - CPU_LIDT(256*4,0); - -#define SWITCH_TO_PROTMODE CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); \ - CPU_LIDT(dpmi.idtLimit,dpmi.idtBase); - - -static DPMI* activeDPMI = 0; -static Bit32u originalIntTable[256]; - -bool DPMI_IsActive(void) -{ - return (cpu.cr0 & CR0_PROTECTION) && activeDPMI && activeDPMI->HasClient(); -} - -void DPMI_SetVirtualIntFlag(bool on) -{ - if (activeDPMI) activeDPMI->SetVirtualIntFlag(on); -} - -void DPMI_CreateException(Bitu num, Bitu errorCode) -{ - if (activeDPMI) activeDPMI->CreateException(num,errorCode); -} - -// ************************************************ -// DPMI Methods -// ************************************************ - -DPMI::DPMI(void) -{ - memset(&dpmi,0,sizeof(dpmi)); - savePtr = 0; - dtaAddress = 0; - rm_ss = rm_sp = 0; - modIntTable = 0; - prevDPMI = activeDPMI; -}; - -DPMI::~DPMI(void) -{ - MEM_ReleasePages(dpmi.mem_handle); - dosSelectorList.clear(); - // TODO: Free all memory allocated with DOS_GetMemory - // Activate previous dpmi - activeDPMI = prevDPMI; - // Restore hookHardwareInts ability which may be changed by a pharlap program - if (!activeDPMI) g_hookHardwareInts = true; -}; - -void DPMI::ClearXMSHandles(void) -{ - for (Bitu i=0; iname = name; - smem->handle= handle; - smem->pages = pages; - g_sharedMemList.push_back(smem); -}; - -bool DPMI::GetSharedMem(const char* name, Bitu& handle, Bitu& pages) -{ - TSharedMem* smem; - std::list::iterator i; - for(i = g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) { - smem = static_cast(*i); - if (smem->name.compare(name)==0) { - handle = smem->handle; - pages = smem->pages; - return true; - } - - }; - return false; -}; - -bool DPMI::IsSharedMem(Bitu handle) -{ - std::list::iterator i; - for(i = g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) { - if ((*i)->handle==handle) return true; - }; - return false; -}; - -bool DPMI::RemoveSharedMem(Bitu handle) -{ - TSharedMem* smem; - std::list::iterator i; - for(i = g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) { - smem = static_cast(*i); - if (smem->handle==handle) { - g_sharedMemList.remove(*i); - delete smem; - return true; - } - - }; - return false; -}; - -void DPMI::SetXMSHandle(Bitu handle) { - for (Bitu i=0; i=DPMI_SAVESTACK_MAX) E_Exit("DPMI: Stack too small."); - saveStack[savePtr++] = SegValue(ds); - saveStack[savePtr++] = SegValue(es); - saveStack[savePtr++] = SegValue(fs); - saveStack[savePtr++] = SegValue(gs); - saveStack[savePtr++] = SegValue(ss); -} - -void DPMI::SaveRegister(void) -{ - SaveSegments(); - if (savePtr+8>=DPMI_SAVESTACK_MAX) E_Exit("DPMI: Stack too small."); - saveStack[savePtr++] = reg_eax; - saveStack[savePtr++] = reg_ebx; - saveStack[savePtr++] = reg_ecx; - saveStack[savePtr++] = reg_edx; - saveStack[savePtr++] = reg_esi; - saveStack[savePtr++] = reg_edi; - saveStack[savePtr++] = reg_ebp; - saveStack[savePtr++] = reg_esp; -}; - -void DPMI::RestoreSegments(void) -{ - CPU_SetSegGeneral(ss,saveStack[--savePtr]); - CPU_SetSegGeneral(gs,saveStack[--savePtr]); - CPU_SetSegGeneral(fs,saveStack[--savePtr]); - CPU_SetSegGeneral(es,saveStack[--savePtr]); - CPU_SetSegGeneral(ds,saveStack[--savePtr]); -}; - -void DPMI::RestoreRegister(void) -{ - reg_esp = saveStack[--savePtr]; - reg_ebp = saveStack[--savePtr]; - reg_edi = saveStack[--savePtr]; - reg_esi = saveStack[--savePtr]; - reg_edx = saveStack[--savePtr]; - reg_ecx = saveStack[--savePtr]; - reg_ebx = saveStack[--savePtr]; - reg_eax = saveStack[--savePtr]; - RestoreSegments(); -}; - -void DPMI::CopyRegistersToBuffer(PhysPt data) -{ - // Save Values in structure - mem_writed(data+0x00, reg_edi); - mem_writed(data+0x04, reg_esi); - mem_writed(data+0x08, reg_ebp); - mem_writed(data+0x0C, 0x0000); - mem_writed(data+0x10, reg_ebx); - mem_writed(data+0x14, reg_edx); - mem_writed(data+0x18, reg_ecx); - mem_writed(data+0x1C, reg_eax); - mem_writew(data+0x20, reg_flags); - mem_writew(data+0x22, SegValue(es)); - mem_writew(data+0x24, SegValue(ds)); - mem_writew(data+0x26, SegValue(fs)); - mem_writew(data+0x28, SegValue(gs)); - mem_writew(data+0x2A, reg_ip); - mem_writew(data+0x2C, SegValue(cs)); - mem_writew(data+0x2E, reg_sp); - mem_writew(data+0x30, SegValue(ss)); -} - -void DPMI::LoadRegistersFromBuffer(PhysPt data) -{ - reg_edi = mem_readd(data+0x00); - reg_esi = mem_readd(data+0x04); - reg_ebp = mem_readd(data+0x08); - reg_ebx = mem_readd(data+0x10); - reg_edx = mem_readd(data+0x14); - reg_ecx = mem_readd(data+0x18); - reg_eax = mem_readd(data+0x1C); - CPU_SetFlagsw(mem_readw(data+0x20)); - SegSet16(es,mem_readw(data+0x22)); - SegSet16(ds,mem_readw(data+0x24)); - SegSet16(fs,mem_readw(data+0x26)); - SegSet16(gs,mem_readw(data+0x28)); - reg_esp = mem_readw(data+0x2E); - SegSet16(ss,mem_readw(data+0x30)); - if (!dpmi.client.bit32) { - reg_eax &= 0xFFFF; - reg_ebx &= 0xFFFF; - reg_ecx &= 0xFFFF; - reg_edx &= 0xFFFF; - reg_edi &= 0xFFFF; - reg_esi &= 0xFFFF; - reg_ebp &= 0xFFFF; - reg_esp &= 0xFFFF; - }; -}; - -void DPMI::ProvideRealModeStack(PhysPt prStack, Bitu toCopy) -{ - // Check stack, if zero provide it - if ((SegValue(ss)==0) && (reg_sp==0)) { - SegSet16(ss,rm_ss); - reg_esp = rm_sp; - } else { - if (SegValue(ss)==rm_ss) reg_esp = rm_sp; - }; - // We have to be in realmode here - if (toCopy>0) { - Bitu numBytes = toCopy*2; - if (reg_espDPMI_REALMODE_STACKSIZE) E_Exit("DPMI:Realmode stack out of range: %04X",reg_esp); - rm_sp = reg_sp; - } -}; - -Bitu DPMI::AllocateLDTDescriptor(Bitu count,Bitu & base) { - - SetDescriptor test; - Bitu i=16, found=0; - PhysPt address = dpmi.ldt.base + LDT_FIRSTSELECTOR*8; - while (i0;found--) { - test.Save(address); - address+=8; - } - return true; - } - } - return false; -} - -Bitu DPMI::AllocateLDTDescriptor2(Bitu count,Bitu & base) { - - static Bitu allocated = 0; - - SetDescriptor desc; - Bitu nr = LDT_FIRSTSELECTOR + allocated; - if (nr+count < LDT_SIZE) { - desc.Clear(); - desc.SetType(DESC_DATA_EU_RW_NA); - desc.saved.seg.p = 1; - desc.saved.seg.big = dpmi.client.bit32; - desc.saved.seg.dpl = DPMI_DPL; - base = (nr << 3)|(4|DPMI_DPL); /* Make it an LDT Entry */ - allocated += count; - Bitu address = dpmi.ldt.base+(base & ~7); - for (;count>0;count--) { - desc.Save(address); - address+=8; - } - return true; - }; - return false; -} - -Bitu DPMI::CreateAlias(Bitu selector, Bit16u& alias) -{ - Descriptor oldDesc; - Bitu base; - if (!cpu.gdt.GetDescriptor(selector,oldDesc)) { alias = DPMI_ERROR_INVALID_SELECTOR; return false; }; - if (!AllocateLDTDescriptor(1,base)) { alias = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; return false; }; - SetDescriptor desc; - desc.Clear(); - desc.SetLimit(oldDesc.GetLimit()); - desc.SetBase (oldDesc.GetBase()); - desc.SetType (DESC_DATA_ED_RW_A); - desc.saved.seg.p=1; - desc.saved.seg.dpl = DPMI_DPL; - desc.Save (dpmi.ldt.base+(base & ~7)); - alias = base; - return true; -}; - -void DPMI::ReloadSegments(Bitu selector) -{ - if (SegValue(cs)==selector) CPU_SetSegGeneral(cs,selector); - if (SegValue(ds)==selector) CPU_SetSegGeneral(ds,selector); - if (SegValue(es)==selector) CPU_SetSegGeneral(es,selector); - if (SegValue(fs)==selector) CPU_SetSegGeneral(fs,selector); - if (SegValue(gs)==selector) CPU_SetSegGeneral(gs,selector); - if (SegValue(ss)==selector) CPU_SetSegGeneral(ss,selector); -}; - -Bitu DPMI::CreateException(void) -{ - // Division by Zero - CreateException(0,0); - return CBRET_NONE; -}; - -void DPMI::CreateException(Bitu num, Bitu errorCode) -{ - // Assuming Stack looks like a int has occured - Bitu stack_eip,stack_cs,stack_flags; - if (dpmi.client.bit32) { - // Clean up stack - stack_eip = CPU_Pop32(); - stack_cs = CPU_Pop32(); - stack_flags = CPU_Pop32(); - // Push values for exception handler - CPU_Push32(SegValue(ss)); - CPU_Push32(reg_esp); - CPU_Push32(stack_flags); - CPU_Push32(stack_cs); - CPU_Push32(stack_eip); - CPU_Push32(errorCode); - CPU_Push32(GDT_PROTCODE); // return cs - CPU_Push32(DPMI_CB_EXCEPTIONRETURN_OFFSET); // return eip - } else { - // Clean up stack - stack_eip = CPU_Pop16(); - stack_cs = CPU_Pop16(); - stack_flags = CPU_Pop16(); - // Push values for exception handler - CPU_Push16(SegValue(ss)); - CPU_Push16(reg_sp); - CPU_Push16(stack_flags); - CPU_Push16(stack_cs); - CPU_Push16(stack_eip); - CPU_Push16(errorCode); - CPU_Push16(GDT_PROTCODE); // return cs - CPU_Push16(DPMI_CB_EXCEPTIONRETURN_OFFSET); // return eip - }; - DPMI_LOG("DPMI: Exception occured : %04X (%04X:%08X)",num,dpmi.exceptionSelector[num],dpmi.exceptionOffset[num]); - CPU_JMP(dpmi.client.bit32,dpmi.exceptionSelector[num],dpmi.exceptionOffset[num]); -}; - -Bitu DPMI::ExceptionReturn(void) -{ - Bitu error; - // Restore Registers - Bitu newcs; - if (dpmi.client.bit32) { - error = CPU_Pop32(); - reg_eip = CPU_Pop32(); - newcs = CPU_Pop32(); - CPU_SetFlagsd(CPU_Pop32()); - reg_esp = CPU_Pop32(); - CPU_SetSegGeneral(ss,CPU_Pop32()); - } else { - error = CPU_Pop16(); - reg_eip = CPU_Pop16(); - newcs = CPU_Pop16(); - CPU_SetFlagsw(CPU_Pop16()); - reg_esp = CPU_Pop16(); - CPU_SetSegGeneral(ss,CPU_Pop16()); - }; - DPMI_LOG("DPMI: Return from Exception. Jump to %04X:%08X",SegValue(cs),reg_eip); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - return 0; -}; - -void DPMI::RemoveIntCallbacks() -// When switching dpmi clients, remove active callbacks from hardware int -{ - Bitu i; - modIntTable = new Bit32u[256]; - // read and store interrupt table - for (i=0; i<256; i++) modIntTable[i] = mem_readd(i*4); - // set a clean interrupt table - for (i=0; i<256; i++) mem_writed(i*4,originalIntTable[i]); -}; - -void DPMI::RestoreIntCallbacks() -{ - if (modIntTable) { - // restore modified interrupt table - for (int i=0; i<256; i++) mem_writed(i*4,modIntTable[i]); - delete[] modIntTable; modIntTable = 0; - } -}; - -bool DPMI::AllocateRealModeCallback(Bitu codeSel,Bitu codeOff,Bitu dataSel, Bitu dataOff, Bitu& segment, Bitu& offset) -{ - Bitu num = 0; - for (Bitu i=0; i=DPMI_REALMODE_CALLBACK_MAX) || !dpmi.rmCallback[num].inUse) E_Exit("DPMI: Illegal Realmode callback %02X.",num); - - if (dpmi.rmCallback[num].inCall) DPMI_LOG("DPMI: Recursive Realmode callback %02X",num); - if (dpmi.protStackCurrent>DPMI_PROTMODE_STACK_MAX) E_Exit("DPMI: Too many recursive Realmode callbacks. Stack failure."); - - PushStack(num); - - DPMI_LOG("DPMI: Realmode Callback %02X (%04X:%08X) enter",num,dpmi.rmCallback[num].codeSelector,dpmi.rmCallback[num].codeOffset); - dpmi.rmCallback[num].inCall= true; - dpmi.rmCallback[num].callCount++; - - // Important! Update realmode stack - UpdateRealModeStack(); - // Setup stack selector of real mode stack - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(dpmi.realStackSelector[dpmi.protStackCurrent],desc)) { - desc.SetBase (SegValue(ss)<<4); - desc.SetLimit(0xFFFF); - desc.Save (dpmi.ldt.base+(dpmi.realStackSelector[dpmi.protStackCurrent] & ~7)); - } else E_Exit("DPMI: RealmodeCB: Could not provide real mode stack descriptor."); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Setup dataSelector - Descriptor data; - Bitu dataSelector; - if (dpmi.rmCallback[num].dataSelector==0x0000) dataSelector = dpmi.dataSelector[dpmi.protStackCurrent]; - else dataSelector = dpmi.rmCallback[num].dataSelector; - if (!cpu.gdt.GetDescriptor(dataSelector,data)) E_Exit("DPMI: Init RM-Callback failed."); - - DPMI_LOG("DPMI: CB: Writing RegData at = %04X:%04X",dataSelector,dpmi.rmCallback[num].dataOffset); - // Prepare data buffer - CopyRegistersToBuffer(PhysPt(data.GetBase()+dpmi.rmCallback[num].dataOffset)); - DPMI_LOG("DPMI: CB: Stored cs:ip = %04X:%04X",SegValue(cs),reg_ip); - // setup registers for protected mode func - CPU_SetSegGeneral(ds,dpmi.realStackSelector[dpmi.protStackCurrent]); // DS:ESI = RM Stack - reg_esi = reg_esp; - CPU_SetSegGeneral(es,dataSelector); // ES:EDI = RM Register data - reg_edi = dpmi.rmCallback[num].dataOffset; - // SS:ESP = API stack - CPU_SetSegGeneral(ss,dpmi.protStackSelector[dpmi.protStackCurrent++]); - reg_esp = DPMI_PROTMODE_STACKSIZE; - // prepare stack for iret - if (dpmi.client.bit32) CPU_Push32(reg_flags); else CPU_Push16(reg_flags); - // Setup cs:ip to return to DPMI_ReturnFromRealModeCallback - CPU_SetSegGeneral(cs,GDT_CODE); - reg_eip = RealOff(CALLBACK_RealPointer(callback.rmCallbackReturn)); - // call protected mode func - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_Push32(reg_flags); - CPU_CALL(dpmi.client.bit32,dpmi.rmCallback[num].codeSelector,dpmi.rmCallback[num].codeOffset); - return 0; -}; - -Bitu DPMI::RealModeCallbackReturn(void) -{ - // returning from protected mode function, now back to real mode - Bitu num = PopStack(); - DPMI_LOG("DPMI: Realmode Callback leave %02X",num); - dpmi.suppressRMCB = false; - dpmi.rmCallback[num].inCall = false; - dpmi.rmCallback[num].stop = false; - dpmi.rmCallback[num].callCount--; - PhysPt data = PhysPt(SegPhys(es)+reg_edi); - DPMI_LOG("DPMI: CB: Reading RegData at = %04X:%04X",SegValue(es),reg_edi); - /* Swtich to real mode */ - SWITCH_TO_REALMODE - dpmi.protStackCurrent--; - // Restore Registers - LoadRegistersFromBuffer(data); - Bitu newCS = mem_readw(data+0x2C); - Bitu newIP = mem_readw(data+0x2A); - UpdateRealModeStack(); - SetVirtualIntFlag(true); - DPMI_LOG("DPMI: CB: Retored cs:ip = %04X:%04X (%d)",newCS,newIP); - CPU_JMP(false,newCS,newIP); - return 0; -}; - -static Bitu count = 0; - -Bitu DPMI::CallRealIRETFrame(bool callAsInt) -{ - Bitu calledIP = mem_readd(SegPhys(ss)+reg_esp); - Bitu calledCS = mem_readd(SegPhys(ss)+reg_esp+4); - DPMI_LOG("DPMI: ENTER REAL PROC IRETF %04X:%08X",calledCS,calledIP); - // Save changed registers - PushStack(SegValue(cs)); - SaveRegister(); - Bitu toCopy = reg_cx; - // Load Registers - PhysPt data = SegPhys(es) + reg_edi; - PhysPt prStack = SegPhys(ss) + reg_esp; - LoadRegistersFromBuffer(data); - PushStack(data); - /* Switch to real mode */ - SWITCH_TO_REALMODE - // Provide Stack - ProvideRealModeStack(prStack,toCopy); - // Push flags - if (callAsInt) CPU_Push16(reg_flags); - // Setup IP - Bitu newCS = mem_readw(data+0x2C); - Bitu newIP = mem_readw(data+0x2A); - // Setup cs:ip to return to DPMI_CallRealIRETFrame callback - SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.rmIntFrameReturn))); - reg_ip = RealOff(CALLBACK_RealPointer(callback.rmIntFrameReturn)); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_CALL(false,newCS,newIP); - return 0; -} - -Bitu DPMI::CallRealIRETFrameReturn(void) -{ - UpdateRealModeStack(); - // returning from realmode func - DPMI_LOG("DPMI: LEAVE REAL PROC IRETF %d",count); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Save registers into real mode structure - CopyRegistersToBuffer(PopStack()); - // Restore changed Resgisters - RestoreRegister(); - Bitu newcs = PopStack(); - - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - - SetVirtualIntFlag(true); - DPMI_CALLBACK_SCF(false); - return 0; -}; - -Bitu DPMI::SimulateInt(void) -{ - Bitu num = reg_bl; - DPMI_LOG("DPMI: SIM INT %02X %04X called. cs = %04X",num,reg_ax,SegValue(cs)); - // Save changed registers - PushStack(SegValue(cs)); - SaveRegister(); - Bitu toCopy = reg_cx; - // Load Registers - PhysPt data = SegPhys(es) + reg_edi; - PhysPt prStack = SegPhys(ss) + reg_esp; - LoadRegistersFromBuffer(data); - PushStack(data); - /* Switch to real mode */ - SWITCH_TO_REALMODE - // Provide Stack - ProvideRealModeStack(prStack,toCopy); - // prepare for return - SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.simintReturn))); - reg_ip = RealOff(CALLBACK_RealPointer(callback.simintReturn)); - // Push flags from structure on stack - DPMI_LOG("DPMI: SimInt1: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); - reg_flags = mem_readw(data+0x20); - CPU_SW_Interrupt(num,0); - DPMI_LOG("DPMI: SimInt2: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); - return 0; -}; - -Bitu DPMI::SimulateIntReturn(void) -{ - // returning from realmode func - DPMI_LOG("DPMI: SIM INT return"); - DPMI_LOG("DPMI: SimIntRet1: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); - - UpdateRealModeStack(); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Save registers into real mode structure - CopyRegistersToBuffer(PopStack()); - // Restore changed Resgisters - RestoreRegister(); - Bitu newcs = PopStack(); - DPMI_LOG("DPMI: SimIntRet: JUMP to %04X:%08X",newcs,reg_eip); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - SetVirtualIntFlag(true); - // Free last realmode stack - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: SimIntRet2: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); - return 0; -}; - -void DPMI::PrepareReflectToReal(Bitu num) -{ - // Save segment and stack register - SaveSegments(); - PushStack(reg_esp); - PushStack(num); - PushStack(reg_eip); - PushStack(SegValue(cs)); - /* Swtich to real mode */ - SWITCH_TO_REALMODE - // Setup cs:ip to return to intreturn - Bitu retcs = RealSeg(CALLBACK_RealPointer(callback.ptorintReturn)); - Bitu retip = RealOff(CALLBACK_RealPointer(callback.ptorintReturn)); - - SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.ptorintReturn))); - reg_ip = RealOff(CALLBACK_RealPointer(callback.ptorintReturn)); - // setup stack - SegSet16(ss,rm_ss); - reg_esp = rm_sp; -} - -Bitu DPMI::ptorHandler(void) -{ - /* Pmode interrupt handler that maps the interrupt to realmode */ - Bitu num = reg_eip >> 3; -// if (!dpmi.vIntFlag) { -// if ((num>=0x08) && (num<=0x0F)) return 0; -// if ((num>=0x70) && (num<=0x77)) return 0; -// }; - PrepareReflectToReal(num); -// if (num==0x0F) - DPMI_LOG("DPMI: INT %02X %04X called.",num,reg_ax); - // Prepare flags for real int - // CPU_SetFlagsw(reg_flags & 0x3ED5); // 0011111011010101b - CPU_SW_Interrupt(num,0); - return 0; -} - -Bitu DPMI::ptorHandlerReturn(void) -// Return from reflected real mode int -{ - UpdateRealModeStack(); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Restore Registers - Bitu newcs = PopStack(); - reg_eip = PopStack(); - Bitu num = PopStack(); - reg_esp = PopStack(); - RestoreSegments(); -// if (num==0x0F) - DPMI_LOG("DPMI: INT %02X RETURN",num); - // hardware ints exit here - if (((num>=0x08) && (num<=0x0F)) || ((num>=0x70) && (num<=0x77))) { - SetVirtualIntFlag(true); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - return 0; - } - // Change flags on stack to reflect possible results from ints - if (dpmi.client.bit32) { - Bit32u oldFlags = mem_readd(SegPhys(ss)+reg_esp+8) & ~FMASK_TEST; // leave only flags that cannot be changed by int - Bit32u userFlags = reg_flags & FMASK_NORMAL; // Mask out illegal flags not to change by int (0011111011010101b) - mem_writed(SegPhys(ss)+reg_esp+8,oldFlags|userFlags); - } else { - Bit16u oldFlags = mem_readw(SegPhys(ss)+reg_sp+4) & ~FMASK_TEST; // leave only flags that cannot be changed by int - Bit16u userFlags = reg_flags & FMASK_NORMAL; // Mask out illegal flags not to change by int (0011111011010101b) - mem_writew(SegPhys(ss)+reg_sp+4,oldFlags|userFlags); - }; - SetVirtualIntFlag(true); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - return 0; -} - -Bitu DPMI::Int21Handler(void) -{ - // Check for exit - if (reg_ah==0x4C) { - DPMI_LOG("DPMI: INT 21: Terminating."); - Terminate(); - } - // Save segment and stack register - PushStack(SegValue(ss)); - PushStack(reg_esp); - PushStack(SegValue(ds)); - PushStack(SegValue(es)); - PushStack(SegValue(cs)); - - /* Swtich to real mode */ - SWITCH_TO_REALMODE - // Setup cs:ip to return to intreturn - SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.int21Return))); - reg_ip = RealOff(CALLBACK_RealPointer(callback.int21Return)); - // setup stack - SegSet16(ss,rm_ss); - reg_esp = rm_sp; - // Call realmode interrupt - DPMI_LOG("DPMI: INT 21 %04X called.",reg_ax); - CPU_SW_Interrupt(0x21,0); - if (reg_ah==0x4C) { - // Shut doen dpmi and restore previous one - delete this; - if (activeDPMI) activeDPMI->Reactivate(); - } - return 0; -}; - -Bitu DPMI::Int21HandlerReturn(void) -{ - UpdateRealModeStack(); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Restore Registers - Bitu newcs = PopStack(); - CPU_SetSegGeneral(es,PopStack()); - CPU_SetSegGeneral(ds,PopStack()); - reg_esp = PopStack(); - CPU_SetSegGeneral(ss,PopStack()); - // Set carry flag - DPMI_CALLBACK_SCF(reg_flags & 1); - DPMI_LOG("DPMI: INT 21 RETURN"); - SetVirtualIntFlag(true); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - return 0; -} - -Bitu DPMI::HWIntDefaultHandler() -// Wir sind hier im Protected mode -// a) durch einen INTerrupt im protected mode -// b) durch einen INTerrupt im real mode (durch RMCB) -{ - Bitu index = mem_readw(PhysPt(SegPhys(cs)+reg_eip-2)) - dpmi.defaultHWIntFromProtMode[0]; - if (index>=DPMI_REALVEC_MAX) E_Exit("DPMI: Illegal realmode interrupt callback: %02X",index); - Bitu num = rmIndexToInt[index]; - - RealPt vec = RealGetVec(num); - - if (dpmi.rmCallback[index].callCount==0) { - // INT PROT (Use Handler is already done). - // Wenn rmcb noch in Realmode Int table installiert, dann originalMethode aufrufef - if (vec==dpmi.realModeVec[index]) { - // originalroutine aufrufen - dpmi.rmCallback[index].stop = false; - PrepareReflectToReal(num); - CPU_Push16(reg_flags); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_CALL(false,RealSeg(dpmi.oldRealVec[index]),RealOff(dpmi.oldRealVec[index])); - } else { - // user real mode handler in real mode int table aktiv. - // Moeglich, dass dieser den RMCB von Hand noch aufruft - // dann wird aber callCount>0 sein (da RMCB aktiv) und - // dann die alte Routine aufgerufen... - // RMCB sperren, um einen erneuten Aufruf des User Handlers zu vermeiden,.. - - // This is a hack for cybermage wich wont work otherwise. But why ? - if (num==0x0F) { - if (dpmi.suppressRMCB) { - dpmi.suppressRMCB = false; - return 0; - } else { - dpmi.suppressRMCB = true; - } - }; - PrepareReflectToReal(num); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_Push16(reg_flags); - CPU_CALL(false,RealSeg(vec),RealOff(vec)); - } - } else { - // INT REAL (vom RMCB aktiviert) - // Falls user handler schon aktiv war (int von prot->reflected to real) - // rufe original routine auf - if (dpmi.rmCallback[index].stop) { - dpmi.rmCallback[index].stop = false; - PrepareReflectToReal(num); - CPU_Push16(reg_flags); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_CALL(false,RealSeg(dpmi.oldRealVec[index]),RealOff(dpmi.oldRealVec[index])); - } else { - // User routine wurde noch nicht aktiviert, callback aber ausgeführt - // falls spezieller protected mode handler aktiviert wurde, - // wird dieser jetzt aufgerufen (user routine im protected mode) - Descriptor gate; - gate.Load(dpmi.idt.base+num*8); - if ((gate.GetSelector()!=GDT_CODE) || (gate.GetOffset()!=RealOff(dpmi.defaultHWIntFromProtMode[index]))) { - dpmi.rmCallback[index].stop = true; // vermeide rekursion - CPU_JMP(dpmi.client.bit32,gate.GetSelector(),gate.GetOffset()); - } else { - // kein spezieller Protmode handler - Rufe originalroutine auf - PrepareReflectToReal(num); - CPU_Push16(reg_flags); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_CALL(false,RealSeg(dpmi.oldRealVec[index]),RealOff(dpmi.oldRealVec[index])); - }; - }; - } - return 0; -}; - -void DPMI::SaveRegisterState(Bitu num) -// Copy Current Registers to structure -{ - return; - save_cs[num] = SegValue(cs); - save_ds[num] = SegValue(ds); - save_es[num] = SegValue(es); - save_fs[num] = SegValue(fs); - save_gs[num] = SegValue(gs); - save_ss[num] = SegValue(ss); - save_eip[num] = reg_eip; - save_eax[num] = reg_eax; - save_ebx[num] = reg_ebx; - save_ecx[num] = reg_ecx; - save_edx[num] = reg_edx; - save_esi[num] = reg_esi; - save_edi[num] = reg_edi; - save_ebp[num] = reg_ebp; - save_esp[num] = reg_esp; - save_fl [num] = reg_flags; -}; - -void DPMI::LoadRegisterState(Bitu num) -// Copy Current Registers to structure -{ - return; - CPU_SetSegGeneral(fs,save_fs[num]); - CPU_SetSegGeneral(gs,save_gs[num]); - reg_eax = save_eax[num]; - reg_ebx = save_ebx[num]; - reg_ecx = save_ecx[num]; - reg_edx = save_edx[num]; - reg_esi = save_esi[num]; - reg_edi = save_edi[num]; - reg_flags = save_fl [num]; -}; - -Bitu DPMI::EnterProtMode(void) { - - /* Save real mode register state */ - SaveRegisterState(0); - - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - - CPU_SetSegGeneral(ds,reg_ax); - CPU_SetSegGeneral(es,reg_cx); - CPU_SetSegGeneral(ss,reg_dx); - CPU_SetSegGeneral(ds,reg_ax); - - if (dpmi.client.bit32) { - reg_esp = reg_ebx; - CPU_JMP(true,reg_si,reg_edi); - } else { - reg_sp = reg_bx; - CPU_JMP(false,reg_si,reg_di); - }; - - /* Load prot mode register state (all other unchanged registers */ - LoadRegisterState(1); - - DPMI_LOG("DPMI: Switch to protected mode."); - return 0; -} - -Bitu DPMI::EnterRealMode(void) { - - /* Save Prot Mode Registers */ - SaveRegisterState(1); - - /* Swtich to real mode */ - SWITCH_TO_REALMODE - // (E)BP will be preserved across the mode switch call so it can be used as a pointer. - // TODO: If interrupts are disabled when the mode switch procedure is invoked, - // they will not be re-enabled by the DPMI host (even temporarily). - SegSet16(ds,reg_ax); - SegSet16(es,reg_cx); - SegSet16(ss,reg_dx); - SegSet16(fs,0); - SegSet16(gs,0); - if (dpmi.client.bit32) { - reg_esp = reg_ebx; - CPU_JMP(true,reg_si,reg_edi); - } else { - reg_sp = reg_bx; - CPU_JMP(false,reg_si,reg_di); - }; - - /* Load real mode register state (all other unchanged registers) */ - LoadRegisterState(0); - DPMI_LOG("DPMI: Switch to real mode."); - return CBRET_NONE; -}; - -Bitu DPMI::RealSaveState(void) -{ - return CBRET_NONE; - /* Save Protected mode state */ - if (reg_al==0) { - PhysPt data = SegPhys(es) + reg_edi; - mem_writew(data+ 0,save_cs[1]); - mem_writew(data+ 2,save_ds[1]); - mem_writew(data+ 4,save_es[1]); - mem_writew(data+ 6,save_fs[1]); - mem_writew(data+ 8,save_gs[1]); - mem_writew(data+10,save_ss[1]); - mem_writed(data+12,save_eax[1]); - mem_writed(data+16,save_ebx[1]); - mem_writed(data+20,save_ecx[1]); - mem_writed(data+24,save_edx[1]); - mem_writed(data+28,save_esi[1]); - mem_writed(data+32,save_edi[1]); - mem_writed(data+36,save_ebp[1]); - mem_writed(data+40,save_esp[1]); - mem_writed(data+44,save_fl [1]); - DPMI_LOG("DPMI: Prot Save State."); - } else if (reg_al==1) { - /* restore state of prot mode registers */ - PhysPt data = SegPhys(es) + reg_edi; - save_cs [1] = mem_readw(data+ 0); - save_ds [1] = mem_readw(data+ 2); - save_es [1] = mem_readw(data+ 4); - save_fs [1] = mem_readw(data+ 6); - save_gs [1] = mem_readw(data+ 8); - save_ss [1] = mem_readw(data+10); - save_eax[1] = mem_readd(data+12); - save_ebx[1] = mem_readd(data+16); - save_ecx[1] = mem_readd(data+20); - save_edx[1] = mem_readd(data+24); - save_edi[1] = mem_readd(data+28); - save_esi[1] = mem_readd(data+32); - save_ebp[1] = mem_readd(data+36); - save_esp[1] = mem_readd(data+40); -// save_eip[1] = mem_readd(data+44); - save_fl [1] = mem_readd(data+44); - DPMI_LOG("DPMI: Prot Restore State."); - }; - return CBRET_NONE; -}; - -Bitu DPMI::ProtSaveState(void) -{ - return CBRET_NONE; - if (reg_al==0) { - /* Save State of real mode registers */ - PhysPt data = SegPhys(es) + reg_edi; - mem_writew(data+ 0,save_cs[0]); - mem_writew(data+ 2,save_ds[0]); - mem_writew(data+ 4,save_es[0]); - mem_writew(data+ 6,save_fs[0]); - mem_writew(data+ 8,save_gs[0]); - mem_writew(data+10,save_ss[0]); - mem_writed(data+12,save_eax[0]); - mem_writed(data+16,save_ebx[0]); - mem_writed(data+20,save_ecx[0]); - mem_writed(data+24,save_edx[0]); - mem_writed(data+28,save_esi[0]); - mem_writed(data+32,save_edi[0]); - mem_writed(data+36,save_ebp[0]); - mem_writed(data+40,save_esp[0]); - mem_writed(data+44,save_eip[0]); - mem_writed(data+48,save_fl [0]); - DPMI_LOG("DPMI: Real Save State."); - } else if (reg_al==1) { - /* restore state of real mode registers */ - PhysPt data = SegPhys(es) + reg_edi; - save_cs [0] = mem_readw(data+ 0); - save_ds [0] = mem_readw(data+ 2); - save_es [0] = mem_readw(data+ 4); - save_fs [0] = mem_readw(data+ 6); - save_gs [0] = mem_readw(data+ 8); - save_ss [0] = mem_readw(data+10); - save_eax[0] = mem_readd(data+12); - save_ebx[0] = mem_readd(data+16); - save_ecx[0] = mem_readd(data+20); - save_edx[0] = mem_readd(data+24); - save_edi[0] = mem_readd(data+28); - save_esi[0] = mem_readd(data+32); - save_ebp[0] = mem_readd(data+36); - save_esp[0] = mem_readd(data+40); - save_eip[0] = mem_readd(data+44); - save_fl [0] = mem_readd(data+48); - DPMI_LOG("DPMI: Real Restore State."); - }; - return CBRET_NONE; -}; - -bool DPMI::GetVirtualIntFlag(void) -// only to call from int 31 cos it uses the pushed flags on int stack -{ - if (dpmi.client.bit32) return (mem_readd(SegPhys(ss)+reg_esp+8) & FLAG_IF)>0; - else return (mem_readd(SegPhys(ss)+reg_sp+4) & FLAG_IF)>0; -}; - -void DPMI::SetVirtualIntFlag(bool on) -{ - dpmi.vIntFlag = 1; //on; -}; - -bool DPMI::AllocateMem(Bitu size, Bitu& outHandle, Bitu& linear) -{ - Bitu pages = (size/DPMI_PAGE_SIZE) + ((size%DPMI_PAGE_SIZE)>0); // Convert to 4KB pages - outHandle = MEM_AllocatePages(pages,true); - linear = outHandle*DPMI_PAGE_SIZE; - if (outHandle!=0) SetXMSHandle(outHandle); - return (outHandle!=0); -}; - -bool DPMI::SetAccessRights(Bitu selector, SetDescriptor& desc, Bitu rights) -{ - // must equal caller DPL - if (((rights & 0x60)>>5)!=DPMI_DPL) { - DPMI_LOG("DPMI: Set Rights %04X : %04X failure (dpl=%02X)",selector,rights,(rights & 0x60)>>5); -// return false; - } - // must be 1 - if ((rights & 0x10)==0) { - DPMI_LOG_ERROR("DPMI: Set Rights %04X : %04X failure (must be 1)",selector,rights); - return false; - }; - // must be 0 - if (dpmi.client.bit32 && desc.saved.seg.p && (rights & 0x2000)) { - DPMI_LOG_ERROR("DPMI: Set Rights %04X : %04X failure (must be 0)",selector,rights); - return false; - }; - // all tests passed, set rights for 16 + 32 Bit - desc.SetType (rights&0x1F); - desc.saved.seg.dpl = (rights&0x60)>>5; - desc.saved.seg.dpl = DPMI_DPL; - desc.saved.seg.p = (rights&0x80)>0; - // extended rights for 32 Bit apps - if (dpmi.client.bit32) { - desc.saved.seg.avl = (rights&0x1000)>0; - desc.saved.seg.r = (rights&0x2000)>0; - desc.saved.seg.big = (rights&0x4000)>0; - desc.saved.seg.g = (rights&0x8000)>0; - }; - return true; -}; - -Bitu DPMI::Int31Handler(void) -{ - switch (reg_ax) { - - case 0x0000:{// Allocate LDT Descriptors - Bitu base; - Descriptor desc; - if (AllocateLDTDescriptor(reg_cx,base)) { - reg_ax = base; - DPMI_LOG("DPMI: 0000: Allocate %d descriptors: %04X",reg_cx,base); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG_ERROR("DPMI: 0000: Allocate %d descriptors failure",reg_cx); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0001:{// Free Descriptor - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - desc.saved.seg.p = 0; - desc.Save (dpmi.ldt.base+(reg_bx & ~7)); - DPMI_LOG("DPMI: 0001: Free Descriptor: %04X",reg_bx); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG_ERROR("DPMI: 0001: Free Descriptor failure : %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0002:{// Segment to Descriptor - SetDescriptor desc; Bitu base; - if (AllocateLDTDescriptor(1,base)) { - desc.Load (dpmi.ldt.base+(base & ~7)); - desc.SetLimit(0xFFFF); - desc.SetBase (reg_bx<<4); - desc.saved.seg.dpl=3; - desc.Save (dpmi.ldt.base+(base & ~7)); - reg_ax = base; - DPMI_LOG("DPMI: 0000: Seg %04X to Desc: %04X",reg_bx,base); - DPMI_CALLBACK_SCF(false); - } else { - // No more Descriptors available - DPMI_LOG_ERROR("DPMI: 0002: No more Descriptors available."); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0003:// Get Next Selector Increment Value - reg_ax = 8; - DPMI_LOG("DPMI: 0003: Get Selector Inc Value: %04X",reg_ax); - DPMI_CALLBACK_SCF(false); - break; - case 0x0004:// undocumented (reserved) lock selector - case 0x0005:// undocumented (reserved) unlock selector - DPMI_LOG("DPMI: 0004: Undoc: (un)lock selector",reg_ax); - DPMI_CALLBACK_SCF(true); - break; - case 0x0006:{ // Get Segment Base Address - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - DPMI_LOG("DPMI: 0006: Get Base %04X : B:%08X",reg_bx,desc.GetBase()); - reg_cx = (Bit16u)(desc.GetBase()>>16); - reg_dx = (Bit16u)(desc.GetBase()&0xFFFF); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG_ERROR("DPMI: 0006: Invalid Selector: %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0007:{// Set Segment base address - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - Bitu base; - if (!dpmi.client.bit32) base = (reg_cl<<16)+reg_dx; - else base = (reg_cx<<16)+reg_dx; - desc.SetBase(base); - desc.Save (dpmi.ldt.base+(reg_bx & ~7)); - ReloadSegments(reg_bx); - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 0007: Set Base %04X : B:%08X",reg_bx,base); - } else { - DPMI_LOG_ERROR("DPMI: 0007: Invalid Selector: %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0008:{// Set Segment limit - SetDescriptor desc; - if ((!dpmi.client.bit32) && (reg_cx!=0)) { - // 16-bit DPMI implementations can not set segment limits greater - // than 0FFFFh (64K) so CX must be zero when calling - DPMI_LOG_ERROR("DPMI: 0008: Set Segment Limit invalid: %04X (%04X%04X)",reg_bx,reg_cx,reg_dx); - reg_ax = DPMI_ERROR_INVALID_VALUE; - DPMI_CALLBACK_SCF(true); - } else if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - desc.SetLimit((reg_cx<<16)+reg_dx); - desc.Save (dpmi.ldt.base+(reg_bx & ~7)); - ReloadSegments(reg_bx); - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 0008: Set Limit %08X",(reg_cx<<16)+reg_dx); - } else { - DPMI_LOG_ERROR("DPMI: 0008: Invalid Selector: %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0009:{// Set Descriptor Access Rights - SetDescriptor desc; - Bit8u rcl = reg_cl; - Bit8u rch = reg_ch; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - if (!SetAccessRights(reg_bx,desc,reg_cx)) { - DPMI_LOG_ERROR("DPMI: 0009: Set Rights %04X : failure",reg_bx); - reg_ax = DPMI_ERROR_INVALID_VALUE; - DPMI_CALLBACK_SCF(true); - break; - }; - desc.Save(dpmi.ldt.base+(reg_bx & ~7)); - ReloadSegments(reg_bx); - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 0009: Set Rights %04X : %04X",reg_bx,reg_cx); - } else { - DPMI_LOG_ERROR("DPMI: 0009: Set Rights %04X : invalid selector",reg_bx); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x000A:{// Create Alias Descriptor - Descriptor desc; - if (CreateAlias(reg_bx, reg_ax)) { - DPMI_LOG("DPMI: 000A: Create Alias : %04X - %04X",reg_bx,reg_ax); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_CALLBACK_SCF(true); - DPMI_LOG_ERROR("DPMI: 000A: Invalid Selector: %04X",reg_bx); - }; }; break; - case 0x000B:{//Get Descriptor - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - desc.Save(SegPhys(es)+Mask(reg_edi)); - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 000B: Get Descriptor %04X : B:%08X L:%08X",reg_bx,desc.GetBase(),desc.GetLimit()); - } else { - DPMI_LOG_ERROR("DPMI: 000B: Get Descriptor %04X : failure",reg_bx); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x000C:{//Set Descriptor - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - desc.Load (SegPhys(es)+Mask(reg_edi)); - Bitu rights = (mem_readb(SegPhys(es)+Mask(reg_edi)+6)<<8) + mem_readb(SegPhys(es)+Mask(reg_edi)+5); - if (!SetAccessRights(reg_bx,desc,rights)) { - DPMI_LOG_ERROR("DPMI: 000C: Set Rights %04X : failure",reg_bx); - reg_ax = DPMI_ERROR_INVALID_VALUE; - DPMI_CALLBACK_SCF(true); - break; - }; - // TEMP : Test -/* if (!dpmi.client.bit32) { - if (desc.GetLimit()>0xFFFF) { - DPMI_LOG_ERROR("DPMI: 000C: Set Limit %04X : failure (%08X)",reg_bx,desc.GetLimit()); - desc.SetLimit(0xFFFF); - } - if (desc.GetBase ()>0xFFFFFF) { - DPMI_LOG_ERROR("DPMI: 000C: Set Base %04X : failure (%08X)",reg_bx,desc.GetBase()); - desc.SetBase(desc.GetBase() % 0xFFFFFF); - } - }*/ - desc.Save(dpmi.ldt.base+(reg_bx & ~7)); - ReloadSegments(reg_bx); - DPMI_LOG("DPMI: 000B: Set Descriptor %04X : B:%08X L:%08X : P %01X",reg_bx,desc.GetBase(),desc.GetLimit(),desc.saved.seg.p); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG_ERROR("DPMI: 000C: Set Descriptor %04X failed",reg_bx); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x000D:{ // Allocate specific LDT Descriptor : TODO: Support it - DPMI_LOG("DPMI: 000D: Alloc Specific LDT Selector: %04X",reg_bx); - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { -// if (!desc.saved.seg.p) { - desc.saved.seg.p = 1; -// desc.SetLimit(0xDEADAAAA); -// desc.SetBase (0xDEADBBBB); - desc.Save (dpmi.ldt.base+(reg_bx & ~7)); - DPMI_CALLBACK_SCF(false); - break; -// } else { -// DPMI_LOG_ERROR("DPMI: 000D: Invalid Selector: %04X",reg_bx); -// reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; -// }; - } else reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; break; - case 0x0100:{// Allocate DOS Memory Block - Bit16u blocks = reg_bx; - DPMI_LOG("DPMI: 0100: Allocate DOS Mem: (%04X Blocks)",blocks); - if (DOS_AllocateMemory(®_ax,&blocks)) { - // Allocate Selector for block - SetDescriptor desc; Bitu base; Bitu numDesc; - numDesc = reg_bx/0x1000 + ((reg_bx%0x1000)>0); - if (AllocateLDTDescriptor(numDesc,base)) { - reg_dx = base; - // First selector - if (numDesc>1) { - Bitu descBase = reg_ax*16; - Bitu length = reg_bx*16; - desc.Load (dpmi.ldt.base+(base & ~7)); - desc.SetBase (descBase); - desc.SetLimit(dpmi.client.bit32?length:0xFFFF); - desc.Save (dpmi.ldt.base+(base & ~7)); - for (Bitu i=1; i>4; - DOS_MCB mcb(seg-1); - Bitu size = mcb.GetSize()*16; - if (DOS_FreeMemory(seg)) { - while (size>0) { - desc.Load(dpmi.ldt.base+(sel & ~7)); - desc.saved.seg.p = 0; - desc.Save(dpmi.ldt.base+(sel & ~7)); - size -= (size>=0x10000)?0x10000:size; - sel+=8; - }; - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 0101: Free Dos Mem: %04X",reg_dx); - break; - } - } - DPMI_LOG_ERROR("DPMI: 0101: Invalid Selector: %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - };break; - case 0x0200:{// Get Real Mode Interrupt Vector - RealPt vec = RealGetVec(reg_bl); - reg_cx = RealSeg(vec); - reg_dx = RealOff(vec); - DPMI_LOG("DPMI: 0200: Get Real Int Vector %02X (%04X:%04X)",reg_bl,reg_cx,reg_dx); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0201:{// Set Real Mode Interrupt Vector - DPMI_LOG("DPMI: 0201: Set Real Int Vector %02X (%04X:%04X)",reg_bl,reg_cx,reg_dx); - RealSetVec(reg_bl,RealMake(reg_cx,reg_dx)); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0202:// Get Processor Exception Handler Vector - if (reg_bl>16; - reg_di = handle&0xFFFF; - reg_bx = linear>>16; - reg_cx = linear&0xFFFF; - DPMI_CALLBACK_SCF(false); - // TEMP -// Bitu total = MEM_FreeLargest(); // in KB -// DPMI_LOG_ERROR("DPMI: 0501: Allocation success: H:%04X%04X (%d KB) (R:%d KB)",reg_si,reg_di,length/1024 + ((length%1024)>0),total*4); - } else { - reg_ax = DPMI_ERROR_PHYSICAL_MEMORY_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - // TEMP - Bitu total = MEM_FreeLargest(); // in KB - DPMI_LOG("DPMI: 0501: Allocation failure (%d KB) (R:%d KB)",length/1024 + ((length%1024)>0),total*4); - }; - }; break; - case 0x0502://Free Memory Block - DPMI_LOG("DPMI: 0502: Free Mem: H:%04X%04X",reg_si,reg_di); - MEM_ReleasePages((reg_si<<16)+reg_di); - FreeXMSHandle((reg_si<<16)+reg_di); - DPMI_CALLBACK_SCF(false); - break; - case 0x0503:{//Resize Memory Block - Bitu linear,newHandle; - Bitu newByte = (reg_bx<<16)+reg_cx; - Bitu newSize = (newByte/DPMI_PAGE_SIZE)+((newByte & (DPMI_PAGE_SIZE-1))>0); - MemHandle handle = (reg_si<<16)+reg_di; - DPMI_LOG("DPMI: 0503: Resize Memory: H:%08X (%d KB)",handle,newSize*4); - if (MEM_ReAllocatePages(handle,newSize,true)) { - linear = handle * DPMI_PAGE_SIZE; - reg_si = (Bit16u)(handle>>16); - reg_di = (Bit16u)(handle&0xFFFF); - reg_bx = (Bit16u)(linear>>16); - reg_cx = (Bit16u)(linear&0xFFFF); - DPMI_CALLBACK_SCF(false); - } else if (AllocateMem(newByte,newHandle,linear)) { - // Not possible, try to allocate - DPMI_LOG("DPMI: 0503: Reallocated Memory: %d KB",newSize*4); - reg_si = (Bit16u)(newHandle>>16); - reg_di = (Bit16u)(newHandle&0xFFFF); - reg_bx = (Bit16u)(linear>>16); - reg_cx = (Bit16u)(linear&0xFFFF); - // copy contents - Bitu size = MEM_AllocatedPages(handle); - if (newSize>16; - reg_cx = linear & 0xFFFF; - DPMI_LOG_ERROR("DPMI: 0800: Phys-adr-map not supported : Start:%08X (Size:%08X) - Linear:%08X.",phys,size,linear); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0801:// Free physical address mapping - DPMI_LOG("DPMI: 0801: Free physical address mapping"); - DPMI_CALLBACK_SCF(false); - break; - case 0x0900://Get and Disable Virtual Interrupt State - reg_al = dpmi.vIntFlag; - dpmi.vIntFlag = 0; - DPMI_LOG("DPMI: 0900: Get and disbale vi : %01X",reg_al); - DPMI_CALLBACK_SCF(false); - break; - case 0x0901://Get and Enable Virtual Interrupt State - reg_al = dpmi.vIntFlag; - dpmi.vIntFlag = 1; - DPMI_LOG("DPMI: 0901: Get and enable vi : %01X",reg_al); - DPMI_CALLBACK_SCF(false); - break; - case 0x0902:{//Get Virtual Interrupt State - reg_al = 0; //dpmi.vIntFlag; - DPMI_LOG("DPMI: 0902: Get vi : %01X",reg_al); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0A00:{//Get Vendor Specific API Entry Point - char name[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_esi),name,255); - LOG(LOG_MISC,LOG_WARN)("DPMI: Get API: %s",name); - if (strcmp(name,"MS-DOS")==0) { - CPU_SetSegGeneral(es,GDT_PROTCODE); - if (dpmi.client.bit32) reg_edi = DPMI_CB_APIMSDOSENTRY_OFFSET; - else reg_di = DPMI_CB_APIMSDOSENTRY_OFFSET; - API_Init_MSDOS(); - DPMI_CALLBACK_SCF(false); - } else if (strstr(name,"HWINT_SUPPORT")!=0) { - reg_ax = DPMI_ERROR_UNSUPPORTED; - DPMI_CALLBACK_SCF(true); - } else if (strstr(name,"CE_SUPPORT")!=0) { - reg_ax = DPMI_ERROR_UNSUPPORTED; - DPMI_CALLBACK_SCF(true); - } else if (strstr(name,"PHARLAP")!=0) { - CPU_SetSegGeneral(es,GDT_PROTCODE); - if (dpmi.client.bit32) reg_edi = DPMI_CB_APIMSDOSENTRY_OFFSET; - else reg_di = DPMI_CB_APIMSDOSENTRY_OFFSET; - API_Init_MSDOS(); - DPMI_CALLBACK_SCF(false); - dpmi.pharlap = true; - } else { - reg_ax = DPMI_ERROR_UNSUPPORTED; - DPMI_CALLBACK_SCF(true); - } - }; break; - case 0x0D00:{//Allocate Shared Memory - char name[256]; - PhysPt data = SegPhys(es)+Mask(reg_edi); - Bitu length = mem_readd(data); - Bitu pages = (length/DPMI_PAGE_SIZE)+((length%DPMI_PAGE_SIZE)>0); - Bitu handle = mem_readd(data+0x08); - Bitu linear = mem_readd(data+0x0C); - Bitu strOffset = mem_readd(data+0x10); - Bitu strSelect = mem_readw(data+0x14); - - Descriptor desc; - if (!cpu.gdt.GetDescriptor(strSelect,desc)) { - DPMI_LOG_ERROR("DPMI: 0D00: shared memory: invalid name selector"); - reg_ax = DPMI_ERROR_INVALID_VALUE; - DPMI_CALLBACK_SCF(true); - return false; - }; - MEM_StrCopy(desc.GetBase()+strOffset,name,256); - - // Already allocated ? - if (!GetSharedMem(name,handle,pages)) { - if (!AllocateMem(length,handle,linear)) { - DPMI_LOG_ERROR("DPMI: 0D00: Allocation shared failure %s (%d KB)",name,pages*4); - reg_ax = DPMI_ERROR_PHYSICAL_MEMORY_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - break; - }; - // Init first paragraph with zeros - for (Bitu i=0; i<16; i++) mem_writeb(linear+i,0); - SetSharedMem(name,handle,pages); - DPMI_LOG("DPMI: 0D00: Allocate shared memory %s (%d KB) ",name,pages*4); - } else { - linear = handle*DPMI_PAGE_SIZE; - DPMI_LOG("DPMI: 0D00: Reuse shared memory %s (%d KB) ",name,pages*4); - }; - - mem_writed(data+0x04,pages*DPMI_PAGE_SIZE); - mem_writed(data+0x08,handle); - mem_writed(data+0x0C,linear); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0B00:// Set debug watchpoint - case 0x0B01:// Clear debug watchpoint - DPMI_CALLBACK_SCF(true); - break; - case 0x0E00:// Get Coprocessor Status - DPMI_LOG("DPMI: 0E00: Get Coprocessor status"); - reg_ax = 0x45; // nope, no coprocessor - DPMI_CALLBACK_SCF(false); - break; - case 0x0E01:// Set Coprocessor Emulation - DPMI_LOG("DPMI: 0E01: Set Coprocessor emulation"); - DPMI_CALLBACK_SCF(true); // failure - break; - default :LOG(LOG_MISC,LOG_ERROR)("DPMI: Unsupported func %04X",reg_ax); - reg_ax = DPMI_ERROR_UNSUPPORTED; - DPMI_CALLBACK_SCF(true); // failure - break; - }; - return 0; -} - -Bitu DPMI::Int2fHandler(void) -{ - // Only available in ProtectedMode - // LOG(LOG_MISC,LOG_WARN)("DPMI: 0x2F %04x",reg_ax); - switch (reg_ax) { - case 0x1686: /* Get CPU Mode */ - reg_ax = 0; - break; - case 0x168A: // Only available in protected mode - // Get Vendor-Specific API Entry Point - char name[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_esi),name,255); - LOG(LOG_MISC,LOG_WARN)("DPMI: 0x2F 0x168A: Get Specific API :%s",name); - if (strcmp(name,"MS-DOS")==0) { - CPU_SetSegGeneral(es,GDT_PROTCODE); - if (dpmi.client.bit32) reg_edi = DPMI_CB_APIMSDOSENTRY_OFFSET; - else reg_di = DPMI_CB_APIMSDOSENTRY_OFFSET; - reg_al = 0x00; // Success, whatever they want... - API_Init_MSDOS(); - }; - break; - default : // reflect to real - ptorHandler(); - break; - } - return 0; -}; - -// ********************************************************************* -// Callbacks and Callback-Returns -// ********************************************************************* - -static Bitu DPMI_Exception(void) { if (activeDPMI) return activeDPMI->CreateException(); return 0;}; -static Bitu DPMI_ExceptionReturn(void) { if (activeDPMI) return activeDPMI->ExceptionReturn(); return 0;}; -static Bitu DPMI_RealModeCallback(void) { if (activeDPMI) return activeDPMI->RealModeCallback(); return 0;}; -static Bitu DPMI_RealModeCallbackReturn(void) { if (activeDPMI) return activeDPMI->RealModeCallbackReturn(); return 0;}; -static Bitu DPMI_CallRealIRETFrame(void) { if (activeDPMI) return activeDPMI->CallRealIRETFrame(true); return 0;}; -static Bitu DPMI_CallRealIRETFrameReturn(void) { if (activeDPMI) return activeDPMI->CallRealIRETFrameReturn(); return 0;}; -static Bitu DPMI_SimulateInt(void) { if (activeDPMI) return activeDPMI->SimulateInt(); return 0;}; -static Bitu DPMI_SimulateIntReturn(void) { if (activeDPMI) return activeDPMI->SimulateIntReturn(); return 0;}; -static Bitu DPMI_ptorHandler(void) { if (activeDPMI) return activeDPMI->ptorHandler(); return 0;}; -static Bitu DPMI_ptorHandlerReturn(void) { if (activeDPMI) return activeDPMI->ptorHandlerReturn(); return 0;}; -static Bitu DPMI_Int21Handler(void) { if (activeDPMI) return activeDPMI->Int21Handler(); return 0;}; -static Bitu DPMI_Int21HandlerReturn(void) { if (activeDPMI) return activeDPMI->Int21HandlerReturn(); return 0;}; -static Bitu DPMI_HWIntDefaultHandler(void) { if (activeDPMI) return activeDPMI->HWIntDefaultHandler(); return 0;}; -static Bitu DPMI_EnterProtMode(void) { if (activeDPMI) return activeDPMI->EnterProtMode(); return 0;}; -static Bitu DPMI_EnterRealMode(void) { if (activeDPMI) return activeDPMI->EnterRealMode(); return 0;}; -static Bitu DPMI_RealSaveState(void) { if (activeDPMI) return activeDPMI->RealSaveState(); return 0;}; -static Bitu DPMI_ProtSaveState(void) { if (activeDPMI) return activeDPMI->ProtSaveState(); return 0;}; -static Bitu DPMI_Int2fHandler(void) { if (activeDPMI) return activeDPMI->Int2fHandler(); return 0;}; -static Bitu DPMI_Int31Handler(void) { if (activeDPMI) return activeDPMI->Int31Handler(); return 0;}; -static Bitu DPMI_API_Int21_MSDOS(void) { if (activeDPMI) return activeDPMI->API_Int21_MSDOS(); return 0;}; -static Bitu DPMI_API_Entry_MSDOS(void) { if (activeDPMI) return activeDPMI->API_Entry_MSDOS(); return 0;}; - - -// **************************************************************** -// Setup stuff -// **************************************************************** - -bool DPMI::SetProtInterrupt(Bitu num, Bitu selector, Bitu offset) -{ - // Nobody messes with the div0 vector - if (num==0) return true; - - SetDescriptor gate; - gate.Clear(); - gate.saved.seg.p=1; - gate.SetSelector(selector); - gate.SetOffset (Mask(offset)); - gate.SetType (dpmi.client.bit32?DESC_386_INT_GATE:DESC_286_INT_GATE); - gate.saved.seg.dpl = DPMI_DPL; - gate.Save(dpmi.idt.base+num*8); - // Special Pharlap stuff - if (dpmi.pharlap) { - gate.Save(cpu.idt.GetBase()+num*8); - DPMI_LOG("DPMI: 0205: Pharlap: Set Prot Int Vector %02X (%04X:%08X)",reg_bl,reg_cx,reg_edx); - } - return true; -}; - -RealPt DPMI::HookInterrupt(Bitu num, Bitu intHandler) -{ - // Setup realmode hook - RealPt oldVec; - Bitu segment, offset; - // Allocate Realmode callback - RealPt func = CALLBACK_RealPointer(intHandler); - if (AllocateRealModeCallback(GDT_CODE,RealOff(func),0x0000,0x0000,segment,offset)) { - oldVec = RealGetVec(num); - RealSetVec(num,RealMake(segment,offset)); - } else E_Exit("DPMI: Couldnt allocate Realmode-Callback for INT %04X",num); - // Setup protmode hook - func = CALLBACK_RealPointer(intHandler); - SetProtInterrupt(num,GDT_CODE,RealOff(func)); - return oldVec; -} - -void DPMI::RestoreHookedInterrupt(Bitu num, RealPt oldVec) -{ - //.Restore hooked int - RealSetVec(num,oldVec); - RealPt func = CALLBACK_RealPointer(callback.ptorint); - SetDescriptor gate; - gate.Load (dpmi.idt.base+num*8); - gate.SetSelector(GDT_CODE); - gate.SetOffset (RealOff(func)); - gate.Save (dpmi.idt.base+num*8); -} - -void DPMI::Debug_ShowDescriptors(void) -{ - char out1[512]; - SetDescriptor desc; - Bitu i=0; - PhysPt address = dpmi.ldt.base; - while (iRemoveIntCallbacks(); - } - activeDPMI = new DPMI(); - return activeDPMI->Entrypoint(); -} - -Bitu DPMI::Entrypoint(void) -{ - /* This should switch to pmode */ - if (dpmi.client.have) E_Exit("DPMI:Already have a client"); - - LOG(LOG_MISC,LOG_ERROR)("DPMI: Entrypoint (%d Bit)",(reg_ax & 1) ? 32:16); - - MEM_A20_Enable(true); - // Create gdt, ldt, idt and other stuff - Setup(); - - // Save Realmode Registers - SaveRegisterState(0); - - dpmi.client.have = true; - dpmi.client.bit32 = reg_ax & 1; - - // Clear XMS Handles - ClearXMSHandles(); - /* Clear the LDT */ - Bitu i; - for (i=0;i::iterator i; - for(i=g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) - delete static_cast(*i); - (g_sharedMemList.clear)(); -}; - -void DPMI_Init(Section* sec) -{ - Section_prop * section=static_cast(sec); - if (!section->Get_bool("dpmi")) return; - - BIOS_ZeroExtendedSize(); - memset(&callback,0,sizeof(callback)); - - /* setup Real mode Callbacks */ - callback.entry=CALLBACK_Allocate(); - CALLBACK_Setup(callback.entry,DPMI_EntryPoint,CB_RETF,"Entrypoint"); - callback.enterpmode=CALLBACK_Allocate(); - CALLBACK_Setup(callback.enterpmode,DPMI_EnterProtMode,CB_RETF,"Enter PMode"); - callback.realsavestate=CALLBACK_Allocate(); - CALLBACK_Setup(callback.realsavestate,DPMI_RealSaveState,CB_RETF,"Save RealState"); - callback.simint=CALLBACK_Allocate(); - CALLBACK_Setup(callback.simint,DPMI_SimulateInt,CB_IRET,"Sim INT"); - callback.simintReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.simintReturn,DPMI_SimulateIntReturn,CB_IRET,"Sim INT RET"); - callback.rmIntFrame=CALLBACK_Allocate(); - CALLBACK_Setup(callback.rmIntFrame,DPMI_CallRealIRETFrame,CB_IRET,"Call REAL IRET"); - callback.rmIntFrameReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.rmIntFrameReturn,DPMI_CallRealIRETFrameReturn,CB_IRET,"Call REAL IRET RET"); - callback.ptorint=CALLBACK_Allocate(); - CALLBACK_Setup(callback.ptorint,DPMI_ptorHandler,CB_IRET,"INT Handler"); - callback.ptorintReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.ptorintReturn,DPMI_ptorHandlerReturn,CB_IRET,"INT Handler RET"); - callback.int21Return=CALLBACK_Allocate(); - CALLBACK_Setup(callback.int21Return,DPMI_Int21HandlerReturn,CB_IRET,"INT 21 RET"); - callback.rmCallbackReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.rmCallbackReturn,DPMI_RealModeCallbackReturn,CB_IRET,"RMCB RET"); - callback.int21msdos=CALLBACK_Allocate(); - CALLBACK_Setup(callback.int21msdos,DPMI_API_Int21_MSDOS,CB_IRET,"MSDOS INT 21 API"); - - /* Setup multiplex */ - DOS_AddMultiplexHandler(DPMI_Multiplex); - - /* shutdown function */ - sec->AddDestroyFunction(&DPMI_ShutDown); -} - -void DPMI::Reactivate() -{ - /* Load GDT and IDT */ - CPU_LIDT(dpmi.idt.limit,dpmi.idt.base); - CPU_LGDT(dpmi.gdt.limit,dpmi.gdt.base); - CPU_LLDT(GDT_LDT); - cpu.cpl = DPMI_DPL; - RestoreIntCallbacks(); -}; - -void DPMI::Setup() -{ - Bitu i; - Bitu xmssize = (TOTAL_SIZE|(DPMI_PAGE_SIZE-1))+1; - Bitu protStackSize = ((DPMI_PROTMODE_STACK_MAX*DPMI_PROTMODE_STACKSIZE)|(DPMI_PAGE_SIZE-1))+1; - Bitu numPages = ((xmssize+protStackSize) >> 12); - -#if DPMI_ALLOC_NEEDEDMEM_HIGH - // Allocate the GDT,LDT,IDT Stack space (High Mem) - Bitu max = MEM_FreeLargest(); - Bitu temphandle = MEM_AllocatePages(max-numPages,true); - dpmi.mem_handle = MEM_AllocatePages(numPages,true); - if (dpmi.mem_handle==0) { - LOG_MSG("DPMI:Can't allocate XMS memory, disabling dpmi support."); - return; - } - Bitu address = dpmi.mem_handle*DPMI_PAGE_SIZE;; - MEM_ReleasePages(temphandle); -#else - // load LDT and stuff in low mem ( - Bit16u segment; - Bit16u blocks = numPages*4096/16; - if (!DOS_AllocateMemory(&segment,&blocks)) { - LOG_MSG("DPMI:Can't allocate XMS memory, disabling dpmi support."); - return; - }; - Bitu address = segment * 16; -#endif - // Allocate real mode stack space - rm_ss = DOS_GetMemory(DPMI_REALMODE_STACKSIZE/16); - rm_sp = DPMI_REALMODE_STACKSIZE; - // Get Begin of protected mode stack - dpmi.protStack = address + xmssize; - /* Clear the memory */ - PhysPt w; - for (w=address;w0); // Convert to 4KB pages - Bitu maxPages = MEM_FreeLargest(); - if (maxPages0xFFFFF) || (base & 0x0F)) E_Exit("DPMI:MSDOS: Invalid Selector (convert to segment not possible)"); - base >>= 4; - } else E_Exit("DPMI:MSDOS: Invalid Selector (not found)"); - return base; -}; - -bool DPMI::GetMsdosSelector(Bitu realseg, Bitu realoff, Bitu &protsel, Bitu &protoff) -{ - // Check if selector is already in list - for (Bitu i=0; i0xFFFF) E_Exit("DPMI:DOS: Read file size > 0xffff"); - - Bit16u toread = Mask(reg_ecx); - dos.echo = true; - if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) { - MEM_BlockWrite(SegPhys(ds)+Mask(reg_edx),dos_copybuf,toread); - if (dpmi.client.bit32) reg_eax=toread; else reg_ax=toread; -// LOG(LOG_MISC,LOG_ERROR)("READ FILE Handle:%d Size:%d Read:%d",reg_bx,toread,reg_eax); - DPMI_CALLBACK_SCF(false); - - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: Read file %d failed",reg_bx); - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - dos.echo=false; - break; - } - case 0x40: {/* WRITE Write to file or device */ - Bit16u towrite = Mask(reg_ecx); - MEM_BlockRead(SegPhys(ds)+Mask(reg_edx),dos_copybuf,towrite); -// if (reg_bx<=5) LOG(LOG_MISC,LOG_ERROR)("INT 21 40: %s",(char *)dos_copybuf); - if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) { - if (dpmi.client.bit32) reg_eax=towrite; - else reg_ax =towrite; - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG("DPMI:MSDOS:Write %d file failure.",reg_bx); - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - }; break; - case 0x41: { /* UNLINK Delete file */ - char name1[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,255); - if (DOS_UnlinkFile(name1)) { - DPMI_CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - }; break; - case 0x42: /* LSEEK Set current file position */ - { - Bit32u pos=(reg_cx<<16) + reg_dx; - Bit32u topos = pos; - if (DOS_SeekFile(reg_bx,&pos,reg_al)) { - reg_dx=(Bit16u)(pos >> 16); - reg_ax=(Bit16u)(pos & 0xFFFF); - DPMI_CALLBACK_SCF(false); - if ((reg_al==0) && (topos!=pos)) { - LOG(LOG_MISC,LOG_ERROR)("SEEK FILE Handle:%d Seek:%d Pos:%d",reg_bx,topos,pos); - LOG(LOG_MISC,LOG_ERROR)("SEEK FILE ERROR : Pos differs"); - } - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: Seek file %d failed",reg_bx); - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - break; - } - case 0x43: { /* Get/Set file attributes */ - char name1[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,255); - switch (reg_al) - case 0x00: /* Get */ - { - if (DOS_GetFileAttr(name1,®_cx)) { - DPMI_CALLBACK_SCF(false); - } else { - DPMI_CALLBACK_SCF(true); - reg_ax=dos.errorcode; - } - break; - case 0x01: /* Set */ - DPMI_LOG("DOS:Set File Attributes for %s not supported",name1); - DPMI_CALLBACK_SCF(false); - break; - default: - E_Exit("DOS:0x43:Illegal subfunction %2X",reg_al); - } - }; break; - - case 0x47: { /* CWD Get current directory */ - char name1[256]; - if (DOS_GetCurrentDir(reg_dl,name1)) { - MEM_BlockWrite(SegPhys(ds)+Mask(reg_esi),name1,strlen(name1)+1); - LOG(LOG_MISC,LOG_ERROR)("DOS: Get Dir %s ",name1); - reg_ax=0x0100; - CALLBACK_SCF(false); - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: Get Dir failed %s ",name1); - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - }; break; - - case 0x4E: {/* Get first dir entry */ - char name1[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,255); - if (DOS_FindFirst(name1,reg_cx)) { - LOG(LOG_MISC,LOG_ERROR)("DOS: Find Dir entry %s success",name1); - DPMI_CALLBACK_SCF(false); - // Copy result to internal dta - if (dtaAddress) MEM_BlockCopy(dtaAddress,PhysMake(RealSeg(dos.dta),RealOff(dos.dta)),dpmi.pharlap?43:128); - reg_ax=0; /* Undocumented */ - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: Find Dir entry %s failure",name1); - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x4f: /* FINDNEXT Find next matching file */ - // Copy data to dos dta - if (dtaAddress) MEM_BlockCopy(PhysMake(RealSeg(dos.dta),RealOff(dos.dta)),dtaAddress,dpmi.pharlap?43:128); - if (DOS_FindNext()) { - LOG(LOG_MISC,LOG_ERROR)("DOS: FindNext Dir entry success"); - CALLBACK_SCF(false); - // Copy result to internal dta - if (dtaAddress) MEM_BlockCopy(dtaAddress,PhysMake(RealSeg(dos.dta),RealOff(dos.dta)),dpmi.pharlap?43:128); - reg_ax=0xffff; /* Undocumented */ - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: FindNext Dir entry failure"); - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - }; - break; - case 0x50: /* Set current PSP */ - if (dpmi.pharlap) dos.psp = reg_bx; // pharlap uses real mode paragraph address - else - dos.psp = GetSegmentFromSelector(reg_bx); - DPMI_LOG("DPMI:MSDOS:0x50:Set current psp:%04X",reg_bx); - break; - case 0x51: /* Get current PSP */ - if (dpmi.pharlap) reg_bx = dos.psp; // pharlap uses real mode paragraph address - else { - GetMsdosSelector(dos.psp,0x0000,protsel,protoff); - reg_bx = protsel; - }; - DPMI_LOG("DPMI:MSDOS:0x51:Get current psp:%04X",reg_bx); - break; - case 0x55 : { // Neuen PSP erstellen - Bitu segment = GetSegmentFromSelector(reg_dx); - DOS_ChildPSP(segment,reg_si); - dos.psp = segment; - DPMI_LOG("DPMI:MSDOS:0x55:Create new psp:%04X",segment); - }; break; - case 0x56: { /* RENAME Rename file */ - char name1[256+1]; - char name2[256+1]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,256); - MEM_StrCopy(SegPhys(es)+Mask(reg_edi),name2,256); - if (DOS_Rename(name1,name2)) { - DPMI_CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - }; break; - case 0x5D : // Get Address of dos swappable area - // FIXME: This is totally faked... - // FIXME: Add size in bytes (at least pharlap) - // FIXME: Depending on al, two functions (pharlap) - GetMsdosSelector(0xDEAD,0xDEAD,protsel,protoff); - CPU_SetSegGeneral(ds,protsel); - reg_si = protoff; - DPMI_LOG("DPMI:MSDOS:0x5D:Get Addres of DOS SwapArea:%04X",reg_si); - break; - case 0x62 : /* Get Current PSP Address */ - GetMsdosSelector(dos.psp,0x0000,protsel,protoff); - reg_bx = protsel; - DPMI_LOG("DPMI:MSDOS:0x62:Get current psp:%04X",reg_bx); - break; - case 0x68: // Flush file to disc - DPMI_CALLBACK_SCF(false); - break; - - case 0x09: - case 0x0A: - case 0x0C: - case 0x1B: - case 0x1C: - case 0x26: // Pharlap != MS-DOS -// case 0x30: // Pharlap extended information - case 0x31: - case 0x32: - case 0x3A: - case 0x48: // Pharlap = 4KB mem pages - case 0x49: - case 0x4A: // Pharlap = 4KB mem pages - case 0x4B: - case 0x52: - case 0x53: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5E: - case 0x5F: - case 0x60: -// case 0x62: - case 0x65: - case 0x6C: - E_Exit("DPMI:MSDOS-API:function %04X not yet supported.",reg_ax); - break; - - // *** PASS THROUGH *** - case 0x44: if ((reg_al==0x02) || (reg_al==0x03) || (reg_al==0x04) || (reg_al==0x05) || (reg_al==0x0C) || (reg_al==0x0D)) { - E_Exit("DPMI:MSDOS-API:function %04X not yet supported.",reg_ax); - }; - case 0x07: case 0x0B: case 0x0E: case 0x19: case 0x2A: case 0x2C: case 0x2D: case 0x30: - case 0x36: case 0x3E: case 0x4C: case 0x58: case 0x67: - { - // reflect to real mode - DPMI_Int21Handler(); - }; - break; - default: E_Exit("DPMI:MSDOS-API:Missing function %04X",reg_ax); - - }; - return 0; -};