Moved most of the real-mode stuff to dlls/winedos.

diff --git a/dlls/kernel/kernel_main.c b/dlls/kernel/kernel_main.c
index 229dcc0..649c051 100644
--- a/dlls/kernel/kernel_main.c
+++ b/dlls/kernel/kernel_main.c
@@ -76,9 +76,6 @@
     /* Force loading of some dlls */
     if (LoadLibrary16( "system" ) < 32) return FALSE;
 
-    /* Read DOS config.sys */
-    if (!DOSCONF_ReadConfig()) return FALSE;
-
     /* Create 16-bit task */
     TASK_CreateMainTask();
 
diff --git a/dlls/kernel/wprocs.spec b/dlls/kernel/wprocs.spec
index 8af24f0..eeafdf5 100644
--- a/dlls/kernel/wprocs.spec
+++ b/dlls/kernel/wprocs.spec
@@ -4,7 +4,6 @@
 
 # Interrupt vectors 0-255 are ordinals 100-355
 # The 'interrupt' keyword takes care of the flags pushed on the stack by the interrupt
-116 interrupt INT_Int10Handler() INT_Int10Handler
 117 interrupt INT_Int11Handler() INT_Int11Handler
 118 interrupt INT_Int12Handler() INT_Int12Handler
 119 interrupt INT_Int13Handler() INT_Int13Handler
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index f43f755..3d7058a 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -28,7 +28,6 @@
 	wcstring.c
 
 EXTRA_OBJS = \
-	$(TOPOBJDIR)/console/console.o \
 	$(TOPOBJDIR)/files/files.o \
 	$(TOPOBJDIR)/if1632/if1632.o \
 	$(TOPOBJDIR)/loader/loader.o \
@@ -42,7 +41,6 @@
 	$(TOPOBJDIR)/win32/win32.o
 
 SUBDIRS = \
-	$(TOPOBJDIR)/console \
 	$(TOPOBJDIR)/files \
 	$(TOPOBJDIR)/if1632 \
 	$(TOPOBJDIR)/loader \
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 2cc319b..f9dfbb1 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1,11 +1,11 @@
 name	ntdll
 type	win32
 
-debug_channels (aspi atom cdrom console ddraw debug delayhlp dll dosfs dosmem
-                file fixup global heap int int10 int16 int17 int19 int21 int31
-                io loaddll local module ntdll process profile reg relay resource
-                segment seh selector server snoop string system tape task thread
-                thunk tid timer toolhelp ver virtual vxd win32)
+debug_channels (atom cdrom console debug delayhlp dll dosfs dosmem file fixup
+                global heap int int21 int31 io loaddll local module ntdll process
+                profile reg relay resource segment seh selector server snoop
+                string system tape task thread thunk tid timer toolhelp ver
+                virtual vxd win32)
 
 #note that the Zw... functions are alternate names for the 
 #Nt... functions.  (see www.sysinternals.com for details)
diff --git a/dlls/winedos/Makefile.in b/dlls/winedos/Makefile.in
index d1a0534..c910069 100644
--- a/dlls/winedos/Makefile.in
+++ b/dlls/winedos/Makefile.in
@@ -7,10 +7,33 @@
 IMPORTS   = user32 kernel32 ntdll
 
 C_SRCS = \
+	dosaspi.c \
+	devices.c \
 	dosvm.c \
 	int09.c \
-	module.c
+	int10.c \
+	int16.c \
+	int17.c \
+	int19.c \
+	int20.c \
+	int21.c \
+	int29.c \
+	int31.c \
+	int33.c \
+	ioports.c \
+	module.c \
+	vga.c \
+	xms.c
+
+EXTRA_OBJS = \
+	$(TOPOBJDIR)/console/console.o
+
+SUBDIRS = \
+	$(TOPOBJDIR)/console
 
 @MAKE_DLL_RULES@
 
+$(EXTRA_OBJS): dummy
+	@cd `dirname $@` && $(MAKE) `basename $@`
+
 ### Dependencies:
diff --git a/msdos/devices.c b/dlls/winedos/devices.c
similarity index 98%
rename from msdos/devices.c
rename to dlls/winedos/devices.c
index 45e5166..451e7bf 100644
--- a/msdos/devices.c
+++ b/dlls/winedos/devices.c
@@ -10,7 +10,6 @@
 #include "msdos.h"
 #include "miscemu.h"
 #include "dosexe.h"
-#include "callback.h"
 #include "debugtools.h"
 
 #include "pshpack1.h"
@@ -107,7 +106,6 @@
     WORD attr;
     RMCBPROC strategy;
     RMCBPROC interrupt;
-    
 } WINEDEV;
 
 static WINEDEV devs[] = 
@@ -136,7 +134,11 @@
 
 #define DOS_DATASEG_OFF(xxx) FIELD_OFFSET(DOS_DATASEG, xxx)
 
-DWORD DOS_LOLSeg;
+struct _DOS_LISTOFLISTS * DOSMEM_LOL()
+{
+    return (struct _DOS_LISTOFLISTS *)DOSMEM_MapRealToLinear
+      (MAKESEGPTR(HIWORD(DOS_LOLSeg),0));
+}
 
 
 /* the device implementations */
@@ -265,7 +267,7 @@
 	  /* check for new keyboard input */
 	  while (CurOfs == bios->FirstKbdCharPtr) {
 	    /* no input available yet, so wait... */
-	    Dosvm.Wait( -1, 0 );
+	    DOSVM_Wait( -1, 0 );
 	  }
 	  /* read from keyboard queue (call int16?) */
 	  data = ((WORD*)bios)[CurOfs];
@@ -284,7 +286,7 @@
 	  /* check for new keyboard input */
 	  while (CurOfs == bios->FirstKbdCharPtr) {
 	    /* no input available yet, so wait... */
-	    Dosvm.Wait( -1, 0 );
+	    DOSVM_Wait( -1, 0 );
 	  }
 	  /* read from keyboard queue (call int16?) */
 	  data = ((WORD*)bios)[CurOfs];
diff --git a/msdos/dosaspi.c b/dlls/winedos/dosaspi.c
similarity index 95%
rename from msdos/dosaspi.c
rename to dlls/winedos/dosaspi.c
index a7bb3be..140e8ca 100644
--- a/msdos/dosaspi.c
+++ b/dlls/winedos/dosaspi.c
@@ -167,8 +167,12 @@
 }
 
 
-/* returns the address of a real mode callback to ASPI_DOS_func() */
-void ASPI_DOS_HandleInt(CONTEXT86 *context)
+/**********************************************************************
+ *	    DOSVM_ASPIHandler  (WINEDOS.@)
+ *
+ * returns the address of a real mode callback to ASPI_DOS_func()
+ */
+void WINAPI DOSVM_ASPIHandler( CONTEXT86 *context )
 {
 	FARPROC16 *p = (FARPROC16 *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
 	TRACE("DOS ASPI opening\n");
diff --git a/dlls/winedos/dosexe.h b/dlls/winedos/dosexe.h
new file mode 100644
index 0000000..60fbd01
--- /dev/null
+++ b/dlls/winedos/dosexe.h
@@ -0,0 +1,98 @@
+/*
+ * DOS EXE loader
+ *
+ * Copyright 1998 Ove Kåven
+ */
+
+#ifndef __WINE_DOSEXE_H
+#define __WINE_DOSEXE_H
+
+#include "wine/windef16.h"
+#include "winbase.h"   /* for LPSTARTUPINFO32A */
+#include "winnt.h"     /* for PCONTEXT */
+
+struct _DOSEVENT;
+
+typedef void (*DOSRELAY)(CONTEXT86*,void*);
+
+#define DOS_PRIORITY_REALTIME 0  /* IRQ0 */
+#define DOS_PRIORITY_KEYBOARD 1  /* IRQ1 */
+#define DOS_PRIORITY_VGA      2  /* IRQ9 */
+#define DOS_PRIORITY_MOUSE    5  /* IRQ12 */
+#define DOS_PRIORITY_SERIAL   10 /* IRQ4 */
+
+extern WORD DOSVM_psp;     /* psp of current DOS task */
+extern WORD DOSVM_retval;  /* return value of previous DOS task */
+
+#if defined(linux) && defined(__i386__)
+#define MZ_SUPPORTED
+#endif /* linux-i386 */
+
+#define V86_FLAG 0x00020000
+
+extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile );
+extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
+extern void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval );
+extern BOOL WINAPI MZ_Current( void );
+extern void WINAPI MZ_AllocDPMITask( void );
+extern void WINAPI MZ_RunInThread( PAPCFUNC proc, ULONG_PTR arg );
+extern INT WINAPI DOSVM_Enter( CONTEXT86 *context );
+extern void WINAPI DOSVM_Wait( INT read_pipe, HANDLE hObject );
+extern DWORD WINAPI DOSVM_Loop( LPVOID lpExtra );
+extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data );
+extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val );
+extern void WINAPI DOSVM_SetTimer( UINT ticks );
+extern UINT WINAPI DOSVM_GetTimer( void );
+extern FARPROC16 DOSVM_GetRMHandler( BYTE intnum );
+extern void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler );
+extern void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context );
+
+/* devices.c */
+extern void DOSDEV_InstallDOSDevices(void);
+extern DWORD DOSDEV_Console(void);
+extern DWORD DOSDEV_FindCharDevice(char*name);
+extern int DOSDEV_Peek(DWORD dev, BYTE*data);
+extern int DOSDEV_Read(DWORD dev, DWORD buf, int buflen);
+extern int DOSDEV_Write(DWORD dev, DWORD buf, int buflen, int verify);
+extern int DOSDEV_IoctlRead(DWORD dev, DWORD buf, int buflen);
+extern int DOSDEV_IoctlWrite(DWORD dev, DWORD buf, int buflen);
+
+/* int09.c */
+extern void WINAPI DOSVM_Int09Handler(CONTEXT86*);
+extern void WINAPI DOSVM_Int09SendScan(BYTE scan,BYTE ascii);
+extern BYTE WINAPI DOSVM_Int09ReadScan(BYTE*ascii);
+
+/* int10.c */
+extern void WINAPI DOSVM_Int10Handler(CONTEXT86*);
+
+/* int16.c */
+extern void WINAPI DOSVM_Int16Handler(CONTEXT86*);
+extern int WINAPI DOSVM_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek);
+extern int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan);
+
+/* int17.c */
+extern void WINAPI DOSVM_Int17Handler(CONTEXT86*);
+
+/* int19.c */
+extern void WINAPI DOSVM_Int19Handler(CONTEXT86*);
+
+/* int20.c */
+extern void WINAPI DOSVM_Int20Handler(CONTEXT86*);
+
+/* int21.c */
+extern void WINAPI DOSVM_Int21Handler(CONTEXT86*);
+
+/* int29.c */
+extern void WINAPI DOSVM_Int29Handler(CONTEXT86*);
+
+/* int31.c */
+extern void WINAPI DOSVM_Int31Handler(CONTEXT86*);
+
+/* int33.c */
+extern void WINAPI DOSVM_Int33Handler(CONTEXT86*);
+extern void WINAPI DOSVM_Int33Message(UINT,WPARAM,LPARAM);
+
+/* xms.c */
+extern void WINAPI XMS_Handler(CONTEXT86*);
+
+#endif /* __WINE_DOSEXE_H */
diff --git a/dlls/winedos/dosvm.c b/dlls/winedos/dosvm.c
index 6d23f36..f8338b9 100644
--- a/dlls/winedos/dosvm.c
+++ b/dlls/winedos/dosvm.c
@@ -35,10 +35,13 @@
 #include "stackframe.h"
 #include "debugtools.h"
 
-DECLARE_DEBUG_CHANNEL(int);
+DEFAULT_DEBUG_CHANNEL(int);
 DECLARE_DEBUG_CHANNEL(module);
 DECLARE_DEBUG_CHANNEL(relay);
 
+WORD DOSVM_psp = 0;
+WORD DOSVM_retval = 0;
+
 #ifdef MZ_SUPPORTED
 
 #ifdef HAVE_SYS_VM86_H
@@ -128,7 +131,7 @@
 
 static int DOSVM_SimulateInt( int vect, CONTEXT86 *context, BOOL inwine )
 {
-  FARPROC16 handler=INT_GetRMHandler(vect);
+  FARPROC16 handler=DOSVM_GetRMHandler(vect);
 
   /* check for our real-mode hooks */
   if (vect==0x31) {
@@ -141,16 +144,16 @@
   /* check if the call is from our fake BIOS interrupt stubs */
   if ((context->SegCs==0xf000) && !inwine) {
     if (vect != (context->Eip/4)) {
-      TRACE_(int)("something fishy going on here (interrupt stub is %02lx)\n", context->Eip/4);
+      TRACE("something fishy going on here (interrupt stub is %02lx)\n", context->Eip/4);
     }
-    TRACE_(int)("builtin interrupt %02x has been branched to\n", vect);
-    INT_RealModeInterrupt(vect, context);
+    TRACE("builtin interrupt %02x has been branched to\n", vect);
+    DOSVM_RealModeInterrupt(vect, context);
   }
   /* check if the call goes to an unhooked interrupt */
   else if (SELECTOROF(handler)==0xf000) {
     /* if so, call it directly */
-    TRACE_(int)("builtin interrupt %02x has been invoked (through vector %02x)\n", OFFSETOF(handler)/4, vect);
-    INT_RealModeInterrupt(OFFSETOF(handler)/4, context);
+    TRACE("builtin interrupt %02x has been invoked (through vector %02x)\n", OFFSETOF(handler)/4, vect);
+    DOSVM_RealModeInterrupt(OFFSETOF(handler)/4, context);
   }
   /* the interrupt is hooked, simulate interrupt in DOS space */
   else {
@@ -186,19 +189,19 @@
       /* it's an IRQ, move it to "current" list */
       event->next = current_event;
       current_event = event;
-      TRACE_(int)("dispatching IRQ %d\n",event->irq);
+      TRACE("dispatching IRQ %d\n",event->irq);
       /* note that if DOSVM_SimulateInt calls an internal interrupt directly,
        * current_event might be cleared (and event freed) in this very call! */
       DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context,TRUE);
     } else {
       /* callback event */
-      TRACE_(int)("dispatching callback event\n");
+      TRACE("dispatching callback event\n");
       (*event->relay)(context,event->data);
       free(event);
     }
   }
   if (!SHOULD_PEND(pending_event)) {
-    TRACE_(int)("clearing Pending flag\n");
+    TRACE("clearing Pending flag\n");
     CLR_PEND(context);
   }
 }
@@ -221,7 +224,7 @@
   if (entered) {
     event = malloc(sizeof(DOSEVENT));
     if (!event) {
-      ERR_(int)("out of memory allocating event entry\n");
+      ERR("out of memory allocating event entry\n");
       return;
     }
     event->irq = irq; event->priority = priority;
@@ -240,11 +243,11 @@
     
     /* get dosmod's attention to the new event, if necessary */
     if (!sig_sent) {
-      TRACE_(int)("new event queued, signalling dosmod\n");
+      TRACE("new event queued, signalling dosmod\n");
       kill(dosmod_pid,SIGUSR2);
       sig_sent++;
     } else {
-      TRACE_(int)("new event queued\n");
+      TRACE("new event queued\n");
     }
   } else {
     /* DOS subsystem not running */
@@ -256,7 +259,7 @@
       memset(&context,0,sizeof(context));
       (*relay)(&context,data);
     } else {
-      ERR_(int)("IRQ without DOS task: should not happen");
+      ERR("IRQ without DOS task: should not happen");
     }
   }
 }
@@ -299,19 +302,19 @@
 
  switch (VM86_TYPE(fn)) {
   case VM86_SIGNAL:
-   TRACE_(int)("DOS module caught signal %d\n",sig);
+   TRACE("DOS module caught signal %d\n",sig);
    if ((sig==SIGALRM) || (sig==SIGUSR2)) {
      if (sig==SIGALRM) {
        sig_sent++;
        DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL);
      }
      if (pending_event) {
-       TRACE_(int)("setting Pending flag, interrupts are currently %s\n",
+       TRACE("setting Pending flag, interrupts are currently %s\n",
                  IF_ENABLED(&context) ? "enabled" : "disabled");
        SET_PEND(&context);
        DOSVM_SendQueuedEvents(&context);
      } else {
-       TRACE_(int)("no events are pending, clearing Pending flag\n");
+       TRACE("no events are pending, clearing Pending flag\n");
        CLR_PEND(&context);
      }
      sig_sent--;
@@ -337,7 +340,7 @@
   case VM86_STI:
     IF_SET(&context);
   /* case VM86_PICRETURN: */
-    TRACE_(int)("DOS task enabled interrupts %s events pending, sending events\n", IS_PEND(&context)?"with":"without");
+    TRACE("DOS task enabled interrupts %s events pending, sending events\n", IS_PEND(&context)?"with":"without");
     DOSVM_SendQueuedEvents(&context);
     break;
   case VM86_TRAP:
@@ -375,12 +378,12 @@
       /* check whether extended bit is set,
        * and if so, queue the extension prefix */
       if (msg.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY) {
-        INT_Int09SendScan(0xE0,0);
+        DOSVM_Int09SendScan(0xE0,0);
       }
-      INT_Int09SendScan(scan,msg.Event.KeyEvent.uChar.AsciiChar);
+      DOSVM_Int09SendScan(scan,msg.Event.KeyEvent.uChar.AsciiChar);
       break;
     default:
-      FIXME_(int)("unhandled console event: %d\n", msg.EventType);
+      FIXME("unhandled console event: %d\n", msg.EventType);
     }
   }
 }
@@ -389,10 +392,10 @@
 {
   BYTE scan = 0;
 
-  TRACE_(int)("got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam);
+  TRACE("got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam);
   if ((msg->message>=WM_MOUSEFIRST)&&
       (msg->message<=WM_MOUSELAST)) {
-    INT_Int33Message(msg->message,msg->wParam,msg->lParam);
+    DOSVM_Int33Message(msg->message,msg->wParam,msg->lParam);
   } else {
     switch (msg->message) {
     case WM_KEYUP:
@@ -406,9 +409,9 @@
 	/* FIXME: some keys (function keys) have
 	 * extended bit set even when they shouldn't,
 	 * should check for them */
-	INT_Int09SendScan(0xE0,0);
+	DOSVM_Int09SendScan(0xE0,0);
       }
-      INT_Int09SendScan(scan,0);
+      DOSVM_Int09SendScan(scan,0);
       break;
     }
   }
@@ -571,7 +574,7 @@
     if ((port==0x20) && (val==0x20)) {
       if (current_event) {
 	/* EOI (End Of Interrupt) */
-	TRACE_(int)("received EOI for current IRQ, clearing\n");
+	TRACE("received EOI for current IRQ, clearing\n");
 	event = current_event;
 	current_event = event->next;
 	if (event->relay)
@@ -582,15 +585,15 @@
 	    !sig_sent) {
 	  /* another event is pending, which we should probably
 	   * be able to process now, so tell dosmod about it */
-	  TRACE_(int)("another event pending, signalling dosmod\n");
+	  TRACE("another event pending, signalling dosmod\n");
 	  kill(dosmod_pid,SIGUSR2);
 	  sig_sent++;
 	}
       } else {
-	WARN_(int)("EOI without active IRQ\n");
+	WARN("EOI without active IRQ\n");
       }
     } else {
-      FIXME_(int)("unrecognized PIC command %02x\n",val);
+      FIXME("unrecognized PIC command %02x\n",val);
     }
 }
 
@@ -602,7 +605,7 @@
   int stat=DOSMOD_SET_TIMER;
   struct timeval tim;
 
-  if (MZ_Current()) {
+  if (write_pipe != -1) {
     /* the PC clocks ticks at 1193180 Hz */
     tim.tv_sec=0;
     tim.tv_usec=MulDiv(ticks,1000000,1193180);
@@ -629,7 +632,7 @@
   int stat=DOSMOD_GET_TIMER;
   struct timeval tim;
 
-  if (MZ_Current()) {
+  if (write_pipe != -1) {
     if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
       ERR_(module)("dosmod sync lost, errno=%d\n",errno);
       return 0;
@@ -688,23 +691,82 @@
     memset(&context,0,sizeof(context));
     (*relay)(&context,data);
   } else {
-    ERR_(int)("IRQ without DOS task: should not happen");
+    ERR("IRQ without DOS task: should not happen");
   }
 }
 
 #endif
 
+/**********************************************************************
+ *	    DOSVM_GetRMHandler
+ *
+ * Return the real mode interrupt vector for a given interrupt.
+ */
+FARPROC16 DOSVM_GetRMHandler( BYTE intnum )
+{
+    return ((FARPROC16*)DOSMEM_SystemBase())[intnum];
+}
+
+
+/**********************************************************************
+ *	    DOSVM_SetRMHandler
+ *
+ * Set the real mode interrupt handler for a given interrupt.
+ */
+void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler )
+{
+    TRACE("Set real mode interrupt vector %02x <- %04x:%04x\n",
+                 intnum, HIWORD(handler), LOWORD(handler) );
+    ((FARPROC16*)DOSMEM_SystemBase())[intnum] = handler;
+}
+
+
+static const INTPROC real_mode_handlers[] =
+{
+    /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0,
+    /* 08 */ 0, DOSVM_Int09Handler, 0, 0, 0, 0, 0, 0,
+    /* 10 */ DOSVM_Int10Handler, INT_Int11Handler, INT_Int12Handler, INT_Int13Handler,
+             0, INT_Int15Handler, DOSVM_Int16Handler, DOSVM_Int17Handler,
+    /* 18 */ 0, 0, INT_Int1aHandler, 0, 0, 0, 0, 0,
+    /* 20 */ DOSVM_Int20Handler, DOSVM_Int21Handler, 0, 0, 0, INT_Int25Handler, 0, 0,
+    /* 28 */ 0, DOSVM_Int29Handler, INT_Int2aHandler, 0, 0, 0, 0, INT_Int2fHandler,
+    /* 30 */ 0, DOSVM_Int31Handler, 0, DOSVM_Int33Handler
+};
+
+
+/**********************************************************************
+ *	    DOSVM_RealModeInterrupt
+ *
+ * Handle real mode interrupts
+ */
+void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context )
+{
+    if (intnum < sizeof(real_mode_handlers)/sizeof(INTPROC) && real_mode_handlers[intnum])
+        (*real_mode_handlers[intnum])(context);
+    else
+    {
+        FIXME("Unknown Interrupt in DOS mode: 0x%x\n", intnum);
+        FIXME("    eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx\n",
+              context->Eax, context->Ebx, context->Ecx, context->Edx);
+        FIXME("    esi=%08lx edi=%08lx ds=%04lx es=%04lx\n",
+              context->Esi, context->Edi, context->SegDs, context->SegEs );
+    }
+}
+
+
+/**********************************************************************
+ *	    DOSVM_Init
+ */
 BOOL WINAPI DOSVM_Init( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
 {
-  TRACE_(module)("(0x%08x,%ld,%p)\n", hinstDLL, fdwReason, lpvReserved);
+    TRACE_(module)("(0x%08x,%ld,%p)\n", hinstDLL, fdwReason, lpvReserved);
 
-  if (fdwReason == DLL_PROCESS_ATTACH) {
-    INT_SetWineHandler(9, INT_Int09Handler);
-  }
-  else if (fdwReason == DLL_PROCESS_DETACH)
-  {
-    INT_SetWineHandler(9, NULL);
-  }
-
-  return TRUE;
+    if (fdwReason == DLL_PROCESS_ATTACH)
+    {
+        /* initialize the memory */
+        TRACE("Initializing DOS memory structures\n");
+        DOSMEM_Init( TRUE );
+        DOSDEV_InstallDOSDevices();
+    }
+    return TRUE;
 }
diff --git a/dlls/winedos/int09.c b/dlls/winedos/int09.c
index d281670..96f65e4 100644
--- a/dlls/winedos/int09.c
+++ b/dlls/winedos/int09.c
@@ -11,7 +11,6 @@
 #include "winuser.h"
 #include "miscemu.h"
 #include "debugtools.h"
-#include "callback.h"
 #include "dosexe.h"
 
 DEFAULT_DEBUG_CHANNEL(int);
@@ -25,13 +24,13 @@
 
 
 /**********************************************************************
- *	    INT_Int09Handler
+ *	    DOSVM_Int09Handler
  *
  * Handler for int 09h.
  */
-void WINAPI INT_Int09Handler( CONTEXT86 *context )
+void WINAPI DOSVM_Int09Handler( CONTEXT86 *context )
 {
-  BYTE ascii, scan = INT_Int09ReadScan(&ascii);
+  BYTE ascii, scan = DOSVM_Int09ReadScan(&ascii);
   BYTE ch[2];
   int cnt, c2;
 
@@ -49,21 +48,21 @@
     }
     if (cnt>0) {
       for (c2=0; c2<cnt; c2++)
-        INT_Int16AddChar(ch[c2], scan);
+        DOSVM_Int16AddChar(ch[c2], scan);
     } else
     if (cnt==0) {
       /* FIXME: need to handle things like shift-F-keys,
        * 0xE0 extended keys, etc */
-      INT_Int16AddChar(0, scan);
+      DOSVM_Int16AddChar(0, scan);
     }
   }
-  Dosvm.OutPIC(0x20, 0x20); /* send EOI */
+  DOSVM_PIC_ioport_out( 0x20, 0x20 ); /* send EOI */
 }
 
 static void KbdRelay( CONTEXT86 *context, void *data )
 {
   if (kbdinfo.queuelen) {
-    /* cleanup operation, called from Dosvm.OutPIC:
+    /* cleanup operation, called from DOSVM_PIC_ioport_out:
      * we'll remove current scancode from keyboard buffer here,
      * rather than in ReadScan, because some DOS apps depend on
      * the scancode being available for reading multiple times... */
@@ -74,7 +73,7 @@
   }
 }
 
-void WINAPI INT_Int09SendScan( BYTE scan, BYTE ascii )
+void WINAPI DOSVM_Int09SendScan( BYTE scan, BYTE ascii )
 {
   if (kbdinfo.queuelen == QUEUELEN) {
     ERR("keyboard queue overflow\n");
@@ -84,13 +83,13 @@
   kbdinfo.queue[kbdinfo.queuelen] = scan;
   kbdinfo.ascii[kbdinfo.queuelen++] = ascii;
   /* tell app to read it by triggering IRQ 1 (int 09) */
-  Dosvm.QueueEvent(1,DOS_PRIORITY_KEYBOARD,KbdRelay,NULL);
+  DOSVM_QueueEvent(1,DOS_PRIORITY_KEYBOARD,KbdRelay,NULL);
 }
 
 /**********************************************************************
  *	    KbdReadScan (WINEDOS.@)
  */
-BYTE WINAPI INT_Int09ReadScan( BYTE*ascii )
+BYTE WINAPI DOSVM_Int09ReadScan( BYTE*ascii )
 {
     if (ascii) *ascii = kbdinfo.ascii[0];
     return kbdinfo.queue[0];
diff --git a/msdos/int10.c b/dlls/winedos/int10.c
similarity index 99%
rename from msdos/int10.c
rename to dlls/winedos/int10.c
index ffa9755..390b6d9 100644
--- a/msdos/int10.c
+++ b/dlls/winedos/int10.c
@@ -11,7 +11,7 @@
 #include "debugtools.h"
 #include "console.h"
 
-DEFAULT_DEBUG_CHANNEL(int10);
+DEFAULT_DEBUG_CHANNEL(int);
 
 static void conv_text_mode_attributes(char attribute, int *fg, int *bg,
        int *wattribute);
@@ -37,7 +37,7 @@
 }
 
 /**********************************************************************
- *	    INT_Int10Handler (WPROCS.116)
+ *	    DOSVM_Int10Handler (WPROCS.116)
  *
  * Handler for int 10h (video).
  * 
@@ -70,7 +70,7 @@
  *      Added additional vga graphic support - 3/99
  */
 
-void WINAPI INT_Int10Handler( CONTEXT86 *context )
+void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
 {
     static int registered_colors = FALSE;
     BIOSDATA *data = DOSMEM_BiosData();
diff --git a/msdos/int16.c b/dlls/winedos/int16.c
similarity index 84%
rename from msdos/int16.c
rename to dlls/winedos/int16.c
index 6194974..c25e1e1 100644
--- a/msdos/int16.c
+++ b/dlls/winedos/int16.c
@@ -9,7 +9,6 @@
 #include <unistd.h>
 
 #include "module.h"
-#include "callback.h"
 #include "dosexe.h"
 #include "wincon.h"
 #include "debugtools.h"
@@ -18,10 +17,10 @@
 #include "winuser.h"
 #include "miscemu.h"
 
-DEFAULT_DEBUG_CHANNEL(int16);
+DEFAULT_DEBUG_CHANNEL(int);
 
 /**********************************************************************
- *	    INT_Int16Handler
+ *	    DOSVM_Int16Handler
  *
  * Handler for int 16h (keyboard)
  *
@@ -31,15 +30,15 @@
  *    not currently listed here.
  */
 
-void WINAPI INT_Int16Handler( CONTEXT86 *context )
+void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
 {
    switch AH_reg(context) {
 
    case 0x00: /* Get Keystroke */
       /* Returns: AH = Scan code
-                  AL = ASCII character */   
+                  AL = ASCII character */
       TRACE("Get Keystroke\n");
-      INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
+      DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
       break;
 
    case 0x01: /* Check for Keystroke */
@@ -47,7 +46,7 @@
       /*          AH = Scan code */
       /*          AL = ASCII character */
       TRACE("Check for Keystroke\n");
-      if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
+      if (!DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
       {
           SET_ZFLAG(context);
       }
@@ -57,10 +56,9 @@
       }
       break;
 
-   case 0x02: /* Get Shift Flags */      
+   case 0x02: /* Get Shift Flags */
       AL_reg(context) = 0;
 
-#if 0  /* FIXME: cannot call USER functions here */
       if (GetAsyncKeyState(VK_RSHIFT))
           AL_reg(context) |= 0x01;
       if (GetAsyncKeyState(VK_LSHIFT))
@@ -77,7 +75,6 @@
           AL_reg(context) |= 0x40;
       if (GetAsyncKeyState(VK_INSERT))
           AL_reg(context) |= 0x80;
-#endif
       TRACE("Get Shift Flags: returning 0x%02x\n", AL_reg(context));
       break;
 
@@ -98,17 +95,17 @@
    case 0x10: /* Get Enhanced Keystroke */
       TRACE("Get Enhanced Keystroke - Partially supported\n");
       /* Returns: AH = Scan code
-                  AL = ASCII character */   
-      INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
+                  AL = ASCII character */
+      DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
       break;
-  
+
 
    case 0x11: /* Check for Enhanced Keystroke */
       /* Returns: ZF set if no keystroke */
       /*          AH = Scan code */
       /*          AL = ASCII character */
       TRACE("Check for Enhanced Keystroke - Partially supported\n");
-      if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
+      if (!DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
       {
           SET_ZFLAG(context);
       }
@@ -121,15 +118,15 @@
    case 0x12: /* Get Extended Shift States */
       FIXME("Get Extended Shift States - Not Supported\n");
       break;
- 
+
    default:
-      FIXME("Unknown INT 16 function - 0x%x\n", AH_reg(context));   
+      FIXME("Unknown INT 16 function - 0x%x\n", AH_reg(context));
       break;
 
    }
 }
 
-int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek)
+int WINAPI DOSVM_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek)
 {
   BIOSDATA *data = DOSMEM_BiosData();
   WORD CurOfs = data->NextKbdCharPtr;
@@ -141,7 +138,7 @@
   } else {
     while (CurOfs == data->FirstKbdCharPtr) {
       /* no input available yet, so wait... */
-      Dosvm.Wait( -1, 0 );
+      DOSVM_Wait( -1, 0 );
     }
   }
   /* read from keyboard queue */
@@ -156,7 +153,7 @@
   return 1;
 }
 
-int WINAPI INT_Int16AddChar(BYTE ascii,BYTE scan)
+int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan)
 {
   BIOSDATA *data = DOSMEM_BiosData();
   WORD CurOfs = data->FirstKbdCharPtr;
diff --git a/msdos/int17.c b/dlls/winedos/int17.c
similarity index 85%
rename from msdos/int17.c
rename to dlls/winedos/int17.c
index 48c0212..5324e53 100644
--- a/msdos/int17.c
+++ b/dlls/winedos/int17.c
@@ -9,14 +9,14 @@
 #include "msdos.h"
 #include "winnt.h"
 
-DEFAULT_DEBUG_CHANNEL(int17);
+DEFAULT_DEBUG_CHANNEL(int);
 
 /**********************************************************************
- *          INT_Int17Handler
+ *          DOSVM_Int17Handler
  *
  * Handler for int 17h (printer - output character).
  */
-void WINAPI INT_Int17Handler( CONTEXT86 *context )
+void WINAPI DOSVM_Int17Handler( CONTEXT86 *context )
 {
     switch( AH_reg(context) )
     {
diff --git a/msdos/int19.c b/dlls/winedos/int19.c
similarity index 69%
rename from msdos/int19.c
rename to dlls/winedos/int19.c
index 966afc4..d92daab 100644
--- a/msdos/int19.c
+++ b/dlls/winedos/int19.c
@@ -6,15 +6,15 @@
 #include "miscemu.h"
 #include "debugtools.h"
 
-DEFAULT_DEBUG_CHANNEL(int19);
+DEFAULT_DEBUG_CHANNEL(int);
 
 
 /**********************************************************************
- *          INT_Int19Handler
+ *          DOSVM_Int19Handler
  *
  * Handler for int 19h (Reboot).
  */
-void WINAPI INT_Int19Handler( CONTEXT86 *context )
+void WINAPI DOSVM_Int19Handler( CONTEXT86 *context )
 {
     WARN("Attempted Reboot\n");
 }
diff --git a/dlls/winedos/int20.c b/dlls/winedos/int20.c
new file mode 100644
index 0000000..bb6cef3
--- /dev/null
+++ b/dlls/winedos/int20.c
@@ -0,0 +1,18 @@
+/*
+ * DOS interrupt 20h handler (TERMINATE PROGRAM)
+ */
+
+#include <stdlib.h>
+#include "winbase.h"
+#include "dosexe.h"
+#include "miscemu.h"
+
+/**********************************************************************
+ *	    DOSVM_Int20Handler
+ *
+ * Handler for int 20h.
+ */
+void WINAPI DOSVM_Int20Handler( CONTEXT86 *context )
+{
+    MZ_Exit( context, TRUE, 0 );
+}
diff --git a/dlls/winedos/int21.c b/dlls/winedos/int21.c
new file mode 100644
index 0000000..e0dfda4
--- /dev/null
+++ b/dlls/winedos/int21.c
@@ -0,0 +1,187 @@
+/*
+ * DOS interrupt 21h handler
+ */
+
+#include "config.h"
+
+#include "windef.h"
+#include "winbase.h"
+#include "ntddk.h"
+#include "wine/winbase16.h"
+#include "dosexe.h"
+#include "miscemu.h"
+#include "msdos.h"
+#include "console.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(int21);
+
+
+/***********************************************************************
+ *           DOSVM_Int21Handler
+ *
+ * int 21h real-mode handler. Most calls are passed directly to DOS3Call.
+ */
+void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
+{
+    RESET_CFLAG(context);  /* Not sure if this is a good idea */
+
+    switch(AH_reg(context))
+    {
+    case 0x00: /* TERMINATE PROGRAM */
+        TRACE("TERMINATE PROGRAM\n");
+        MZ_Exit( context, FALSE, 0 );
+        break;
+
+    case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
+        TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
+	AL_reg(context) = CONSOLE_GetCharacter();
+	/* FIXME: no echo */
+	break;
+
+    case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
+        TRACE("Write Character to Standard Output\n");
+    	CONSOLE_Write(DL_reg(context), 0, 0, 0);
+        break;
+
+    case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
+        /* FIXME: Use DOSDEV_Peek/Read/Write(DOSDEV_Console(),...) !! */
+        if (DL_reg(context) == 0xff) {
+            static char scan = 0;
+            TRACE("Direct Console Input\n");
+            if (scan) {
+                /* return pending scancode */
+                AL_reg(context) = scan;
+                RESET_ZFLAG(context);
+                scan = 0;
+            } else {
+                char ascii;
+                if (DOSVM_Int16ReadChar(&ascii,&scan,TRUE)) {
+                    DOSVM_Int16ReadChar(&ascii,&scan,FALSE);
+                    /* return ASCII code */
+                    AL_reg(context) = ascii;
+                    RESET_ZFLAG(context);
+                    /* return scan code on next call only if ascii==0 */
+                    if (ascii) scan = 0;
+                } else {
+                    /* nothing pending, clear everything */
+                    AL_reg(context) = 0;
+                    SET_ZFLAG(context);
+                    scan = 0; /* just in case */
+                }
+            }
+        } else {
+            TRACE("Direct Console Output\n");
+            CONSOLE_Write(DL_reg(context), 0, 0, 0);
+        }
+        break;
+
+    case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
+        /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
+        TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
+        DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
+        break;
+
+    case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
+        /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
+        TRACE("CHARACTER INPUT WITHOUT ECHO\n");
+        DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
+        break;
+
+    case 0x0b: /* GET STDIN STATUS */
+        {
+            char x1,x2;
+
+            if (CONSOLE_CheckForKeystroke(&x1,&x2))
+                AL_reg(context) = 0xff;
+            else
+                AL_reg(context) = 0;
+        }
+        break;
+
+    case 0x25: /* SET INTERRUPT VECTOR */
+        DOSVM_SetRMHandler( AL_reg(context),
+                            (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
+        break;
+
+    case 0x35: /* GET INTERRUPT VECTOR */
+        TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
+        {
+            FARPROC16 addr = DOSVM_GetRMHandler( AL_reg(context) );
+            context->SegEs = SELECTOROF(addr);
+            BX_reg(context) = OFFSETOF(addr);
+        }
+        break;
+
+    case 0x44: /* IOCTL */
+        switch (AL_reg(context))
+        {
+        case 0x0b:   /* SET SHARING RETRY COUNT */
+            TRACE("IOCTL - SET SHARING RETRY COUNT pause %d retries %d\n",
+                  CX_reg(context), DX_reg(context));
+            if (!CX_reg(context))
+            {
+                AX_reg(context) = 1;
+                SET_CFLAG(context);
+                break;
+            }
+            DOSMEM_LOL()->sharing_retry_delay = CX_reg(context);
+            if (!DX_reg(context))
+                DOSMEM_LOL()->sharing_retry_count = DX_reg(context);
+            RESET_CFLAG(context);
+            break;
+        }
+        break;
+
+    case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
+        TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
+        if (!MZ_Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx),
+                      AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) ))
+        {
+            AX_reg(context) = GetLastError();
+            SET_CFLAG(context);
+        }
+        break;
+
+    case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
+        TRACE("EXIT with return code %d\n",AL_reg(context));
+        MZ_Exit( context, FALSE, AL_reg(context) );
+        break;
+
+    case 0x4d: /* GET RETURN CODE */
+        TRACE("GET RETURN CODE (ERRORLEVEL)\n");
+        AX_reg(context) = DOSVM_retval;
+        DOSVM_retval = 0;
+        break;
+
+    case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
+        TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n");
+        DOSVM_psp = BX_reg(context);
+        break;
+
+    case 0x51: /* GET PSP ADDRESS */
+        TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n");
+        /* FIXME: should we return the original DOS PSP upon */
+        /*        Windows startup ? */
+        BX_reg(context) = DOSVM_psp;
+        break;
+
+    case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
+        TRACE("SYSVARS - GET LIST OF LISTS\n");
+        {
+            context->SegEs = HIWORD(DOS_LOLSeg);
+            BX_reg(context) = FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB);
+        }
+        break;
+
+    case 0x62: /* GET PSP ADDRESS */
+        TRACE("GET CURRENT PSP ADDRESS\n");
+        /* FIXME: should we return the original DOS PSP upon */
+        /*        Windows startup ? */
+        BX_reg(context) = DOSVM_psp;
+        break;
+
+    default:
+        DOS3Call( context );
+    }
+}
diff --git a/msdos/int29.c b/dlls/winedos/int29.c
similarity index 81%
rename from msdos/int29.c
rename to dlls/winedos/int29.c
index 8ffaa56..65d20a2 100644
--- a/msdos/int29.c
+++ b/dlls/winedos/int29.c
@@ -10,11 +10,11 @@
 #include "miscemu.h"
 
 /**********************************************************************
- *	    INT_Int29Handler
+ *	    DOSVM_Int29Handler
  *
  * Handler for int 29h (fast console output)
  */
-void WINAPI INT_Int29Handler( CONTEXT86 *context )
+void WINAPI DOSVM_Int29Handler( CONTEXT86 *context )
 {
    /* Yes, it seems that this is really all this interrupt does. */
    CONSOLE_Write(AL_reg(context), 0, 0, 0);
diff --git a/dlls/winedos/int31.c b/dlls/winedos/int31.c
new file mode 100644
index 0000000..3efc177
--- /dev/null
+++ b/dlls/winedos/int31.c
@@ -0,0 +1,634 @@
+/*
+ * DPMI 0.9 emulation
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#include "config.h"
+
+#include "windef.h"
+#include "wine/winbase16.h"
+#include "miscemu.h"
+#include "task.h"
+#include "msdos.h"
+#include "dosexe.h"
+
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(int31);
+
+/* Structure for real-mode callbacks */
+typedef struct
+{
+    DWORD edi;
+    DWORD esi;
+    DWORD ebp;
+    DWORD reserved;
+    DWORD ebx;
+    DWORD edx;
+    DWORD ecx;
+    DWORD eax;
+    WORD  fl;
+    WORD  es;
+    WORD  ds;
+    WORD  fs;
+    WORD  gs;
+    WORD  ip;
+    WORD  cs;
+    WORD  sp;
+    WORD  ss;
+} REALMODECALL;
+
+typedef struct tagRMCB {
+    DWORD address;
+    DWORD proc_ofs,proc_sel;
+    DWORD regs_ofs,regs_sel;
+    struct tagRMCB *next;
+} RMCB;
+
+static RMCB *FirstRMCB = NULL;
+static WORD dpmi_flag;
+
+/**********************************************************************
+ *	    INT_GetRealModeContext
+ */
+static void INT_GetRealModeContext( REALMODECALL *call, CONTEXT86 *context )
+{
+    context->Eax    = call->eax;
+    context->Ebx    = call->ebx;
+    context->Ecx    = call->ecx;
+    context->Edx    = call->edx;
+    context->Esi    = call->esi;
+    context->Edi    = call->edi;
+    context->Ebp    = call->ebp;
+    context->EFlags = call->fl | V86_FLAG;
+    context->Eip    = call->ip;
+    context->Esp    = call->sp;
+    context->SegCs  = call->cs;
+    context->SegDs  = call->ds;
+    context->SegEs  = call->es;
+    context->SegFs  = call->fs;
+    context->SegGs  = call->gs;
+    context->SegSs  = call->ss;
+}
+
+
+/**********************************************************************
+ *	    INT_SetRealModeContext
+ */
+static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT86 *context )
+{
+    call->eax = context->Eax;
+    call->ebx = context->Ebx;
+    call->ecx = context->Ecx;
+    call->edx = context->Edx;
+    call->esi = context->Esi;
+    call->edi = context->Edi;
+    call->ebp = context->Ebp;
+    call->fl  = LOWORD(context->EFlags);
+    call->ip  = LOWORD(context->Eip);
+    call->sp  = LOWORD(context->Esp);
+    call->cs  = context->SegCs;
+    call->ds  = context->SegDs;
+    call->es  = context->SegEs;
+    call->fs  = context->SegFs;
+    call->gs  = context->SegGs;
+    call->ss  = context->SegSs;
+}
+
+
+#ifdef __i386__
+
+void DPMI_CallRMCB32(RMCB *rmcb, UINT16 ss, DWORD esp, UINT16*es, DWORD*edi)
+#if 0 /* original code, which early gccs puke on */
+{
+    int _clobber;
+    __asm__ __volatile__(
+        "pushl %%ebp\n"
+        "pushl %%ebx\n"
+        "pushl %%es\n"
+        "pushl %%ds\n"
+        "pushfl\n"
+        "mov %7,%%es\n"
+        "mov %5,%%ds\n"
+        ".byte 0x36, 0xff, 0x18\n" /* lcall *%ss:(%eax) */
+        "popl %%ds\n"
+        "mov %%es,%0\n"
+        "popl %%es\n"
+        "popl %%ebx\n"
+        "popl %%ebp\n"
+    : "=d" (*es), "=D" (*edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber)
+    : "0" (ss), "2" (esp),
+      "4" (rmcb->regs_sel), "1" (rmcb->regs_ofs),
+      "3" (&rmcb->proc_ofs) );
+}
+#else /* code generated by a gcc new enough */
+;
+__ASM_GLOBAL_FUNC(DPMI_CallRMCB32,
+    "pushl %ebp\n\t"
+    "movl %esp,%ebp\n\t"
+    "pushl %edi\n\t"
+    "pushl %esi\n\t"
+    "movl 0x8(%ebp),%eax\n\t"
+    "movl 0x10(%ebp),%esi\n\t"
+    "movl 0xc(%ebp),%edx\n\t"
+    "movl 0x10(%eax),%ecx\n\t"
+    "movl 0xc(%eax),%edi\n\t"
+    "addl $0x4,%eax\n\t"
+    "pushl %ebp\n\t"
+    "pushl %ebx\n\t"
+    "pushl %es\n\t"
+    "pushl %ds\n\t"
+    "pushfl\n\t"
+    "mov %cx,%es\n\t"
+    "mov %dx,%ds\n\t"
+    ".byte 0x36, 0xff, 0x18\n\t" /* lcall *%ss:(%eax) */
+    "popl %ds\n\t"
+    "mov %es,%dx\n\t"
+    "popl %es\n\t"
+    "popl %ebx\n\t"
+    "popl %ebp\n\t"
+    "movl 0x14(%ebp),%eax\n\t"
+    "movw %dx,(%eax)\n\t"
+    "movl 0x18(%ebp),%edx\n\t"
+    "movl %edi,(%edx)\n\t"
+    "popl %esi\n\t"
+    "popl %edi\n\t"
+    "leave\n\t"
+    "ret")
+#endif
+
+#endif /* __i386__ */
+
+/**********************************************************************
+ *	    DPMI_CallRMCBProc
+ *
+ * This routine does the hard work of calling a callback procedure.
+ */
+static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
+{
+    if (IS_SELECTOR_SYSTEM( rmcb->proc_sel )) {
+        /* Wine-internal RMCB, call directly */
+        ((RMCBPROC)rmcb->proc_ofs)(context);
+    } else {
+#ifdef __i386__
+        UINT16 ss,es;
+        DWORD esp,edi;
+
+        INT_SetRealModeContext(MapSL(MAKESEGPTR( rmcb->regs_sel, rmcb->regs_ofs )), context);
+        ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, WINE_LDT_FLAGS_DATA );
+        esp = context->Esp;
+
+        FIXME("untested!\n");
+
+        /* The called proc ends with an IRET, and takes these parameters:
+         * DS:ESI = pointer to real-mode SS:SP
+         * ES:EDI = pointer to real-mode call structure
+         * It returns:
+         * ES:EDI = pointer to real-mode call structure (may be a copy)
+         * It is the proc's responsibility to change the return CS:IP in the
+         * real-mode call structure. */
+        if (flag & 1) {
+            /* 32-bit DPMI client */
+            DPMI_CallRMCB32(rmcb, ss, esp, &es, &edi);
+        } else {
+            /* 16-bit DPMI client */
+            CONTEXT86 ctx = *context;
+            ctx.SegCs = rmcb->proc_sel;
+            ctx.Eip   = rmcb->proc_ofs;
+            ctx.SegDs = ss;
+            ctx.Esi   = esp;
+            ctx.SegEs = rmcb->regs_sel;
+            ctx.Edi   = rmcb->regs_ofs;
+            /* FIXME: I'm pretty sure this isn't right - should push flags first */
+            wine_call_to_16_regs_short(&ctx, 0);
+            es = ctx.SegEs;
+            edi = ctx.Edi;
+        }
+	FreeSelector16(ss);
+        INT_GetRealModeContext( MapSL( MAKESEGPTR( es, edi )), context);
+#else
+        ERR("RMCBs only implemented for i386\n");
+#endif
+    }
+}
+
+
+/**********************************************************************
+ *	    DPMI_CallRMProc
+ *
+ * This routine does the hard work of calling a real mode procedure.
+ */
+int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret )
+{
+    LPWORD stack16;
+    LPVOID addr = NULL; /* avoid gcc warning */
+    RMCB *CurrRMCB;
+    int alloc = 0, already = 0;
+    BYTE *code;
+
+    TRACE("EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
+                 context->Eax, context->Ebx, context->Ecx, context->Edx );
+    TRACE("ESI=%08lx EDI=%08lx ES=%04lx DS=%04lx CS:IP=%04lx:%04x, %d WORD arguments, %s\n",
+                 context->Esi, context->Edi, context->SegEs, context->SegDs,
+                 context->SegCs, LOWORD(context->Eip), args, iret?"IRET":"FAR" );
+
+callrmproc_again:
+
+/* there might be some code that just jumps to RMCBs or the like,
+   in which case following the jumps here might get us to a shortcut */
+    code = CTX_SEG_OFF_TO_LIN(context, context->SegCs, context->Eip);
+    switch (*code) {
+    case 0xe9: /* JMP NEAR */
+      context->Eip += 3 + *(WORD *)(code+1);
+      /* yeah, I know these gotos don't look good... */
+      goto callrmproc_again;
+    case 0xea: /* JMP FAR */
+      context->Eip = *(WORD *)(code+1);
+      context->SegCs = *(WORD *)(code+3);
+      /* ...but since the label is there anyway... */
+      goto callrmproc_again;
+    case 0xeb: /* JMP SHORT */
+      context->Eip += 2 + *(signed char *)(code+1);
+      /* ...because of other gotos below, so... */
+      goto callrmproc_again;
+    }
+
+/* shortcut for chaining to internal interrupt handlers */
+    if ((context->SegCs == 0xF000) && iret)
+    {
+        DOSVM_RealModeInterrupt( LOWORD(context->Eip)/4, context);
+        return 0;
+    }
+
+/* shortcut for RMCBs */
+    CurrRMCB = FirstRMCB;
+
+    while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs))
+        CurrRMCB = CurrRMCB->next;
+
+    if (!CurrRMCB && !MZ_Current())
+    {
+        FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n");
+        TRACE("creating VM86 task\n");
+        MZ_AllocDPMITask();
+    }
+    if (!already) {
+        if (!context->SegSs) {
+            alloc = 1; /* allocate default stack */
+            stack16 = addr = DOSMEM_GetBlock( 64, (UINT16 *)&(context->SegSs) );
+            context->Esp = 64-2;
+            stack16 += 32-1;
+            if (!addr) {
+                ERR("could not allocate default stack\n");
+                return 1;
+            }
+        } else {
+            stack16 = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
+        }
+        context->Esp -= (args + (iret?1:0)) * sizeof(WORD);
+        stack16 -= args;
+        if (args) memcpy(stack16, stack, args*sizeof(WORD) );
+        /* push flags if iret */
+        if (iret) {
+            stack16--; args++;
+            *stack16 = LOWORD(context->EFlags);
+        }
+        /* push return address (return to interrupt wrapper) */
+        *(--stack16) = DOSMEM_wrap_seg;
+        *(--stack16) = 0;
+        /* adjust stack */
+        context->Esp -= 2*sizeof(WORD);
+        already = 1;
+    }
+
+    if (CurrRMCB) {
+        /* RMCB call, invoke protected-mode handler directly */
+        DPMI_CallRMCBProc(context, CurrRMCB, dpmi_flag);
+        /* check if we returned to where we thought we would */
+        if ((context->SegCs != DOSMEM_wrap_seg) ||
+            (LOWORD(context->Eip) != 0)) {
+            /* we need to continue at different address in real-mode space,
+               so we need to set it all up for real mode again */
+            goto callrmproc_again;
+        }
+    } else {
+        TRACE("entering real mode...\n");
+        DOSVM_Enter( context );
+        TRACE("returned from real-mode call\n");
+    }
+    if (alloc) DOSMEM_FreeBlock( addr );
+    return 0;
+}
+
+
+/**********************************************************************
+ *	    DOSVM_CallRMInt   (WINEDOS.@)
+ */
+void WINAPI DOSVM_CallRMInt( CONTEXT86 *context )
+{
+    CONTEXT86 realmode_ctx;
+    FARPROC16 rm_int = DOSVM_GetRMHandler( BL_reg(context) );
+    REALMODECALL *call = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) ));
+    INT_GetRealModeContext( call, &realmode_ctx );
+
+    /* we need to check if a real-mode program has hooked the interrupt */
+    if (HIWORD(rm_int)!=0xF000) {
+        /* yup, which means we need to switch to real mode... */
+        realmode_ctx.SegCs = HIWORD(rm_int);
+        realmode_ctx.Eip   = LOWORD(rm_int);
+        if (DPMI_CallRMProc( &realmode_ctx, NULL, 0, TRUE))
+          SET_CFLAG(context);
+    } else {
+        RESET_CFLAG(context);
+        /* use the IP we have instead of BL_reg, in case some apps
+           decide to move interrupts around for whatever reason... */
+        DOSVM_RealModeInterrupt( LOWORD(rm_int)/4, &realmode_ctx );
+    }
+    INT_SetRealModeContext( call, &realmode_ctx );
+}
+
+
+/**********************************************************************
+ *	    DOSVM_CallRMProc   (WINEDOS.@)
+ */
+void WINAPI DOSVM_CallRMProc( CONTEXT86 *context, int iret )
+{
+    REALMODECALL *p = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) ));
+    CONTEXT86 context16;
+
+    TRACE("RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
+          p->eax, p->ebx, p->ecx, p->edx);
+    TRACE("              ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments, %s\n",
+          p->esi, p->edi, p->es, p->ds, p->cs, p->ip, CX_reg(context), iret?"IRET":"FAR" );
+
+    if (!(p->cs) && !(p->ip)) { /* remove this check
+                                   if Int21/6501 case map function
+                                   has been implemented */
+        SET_CFLAG(context);
+        return;
+     }
+    INT_GetRealModeContext(p, &context16);
+    DPMI_CallRMProc( &context16, ((LPWORD)MapSL(MAKESEGPTR(context->SegSs, LOWORD(context->Esp))))+3,
+                     CX_reg(context), iret );
+    INT_SetRealModeContext(p, &context16);
+}
+
+
+/* (see dosmem.c, function DOSMEM_InitDPMI) */
+static void StartPM( CONTEXT86 *context )
+{
+    UINT16 cs, ss, ds, es;
+    CONTEXT86 pm_ctx;
+    DWORD psp_ofs = (DWORD)(DOSVM_psp<<4);
+    PDB16 *psp = (PDB16 *)psp_ofs;
+    HANDLE16 env_seg = psp->environment;
+    unsigned char selflags = WINE_LDT_FLAGS_DATA;
+
+    RESET_CFLAG(context);
+    dpmi_flag = AX_reg(context);
+/* our mode switch wrapper have placed the desired CS into DX */
+    cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, WINE_LDT_FLAGS_CODE );
+/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
+   can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
+   ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
+   32-bit code using this stack. */
+    if (dpmi_flag & 1) selflags |= WINE_LDT_FLAGS_32BIT;
+    ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, selflags );
+/* do the same for the data segments, just in case */
+    if (context->SegDs == context->SegSs) ds = ss;
+    else ds = SELECTOR_AllocBlock( (void *)(context->SegDs<<4), 0x10000, selflags );
+    es = SELECTOR_AllocBlock( psp, 0x100, selflags );
+/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
+    psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4), 0x10000, WINE_LDT_FLAGS_DATA );
+
+    pm_ctx = *context;
+    pm_ctx.SegCs = DOSMEM_dpmi_sel;
+/* our mode switch wrapper expects the new CS in DX, and the new SS in AX */
+    pm_ctx.Eax   = ss;
+    pm_ctx.Edx   = cs;
+    pm_ctx.SegDs = ds;
+    pm_ctx.SegEs = es;
+    pm_ctx.SegFs = 0;
+    pm_ctx.SegGs = 0;
+
+    TRACE("DOS program is now entering protected mode\n");
+    wine_call_to_16_regs_short(&pm_ctx, 0);
+
+    /* in the current state of affairs, we won't ever actually return here... */
+    /* we should have int21/ah=4c do it someday, though... */
+
+    FreeSelector16(psp->environment);
+    psp->environment = env_seg;
+    FreeSelector16(es);
+    if (ds != ss) FreeSelector16(ds);
+    FreeSelector16(ss);
+    FreeSelector16(cs);
+}
+
+static RMCB *DPMI_AllocRMCB( void )
+{
+    RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB));
+    UINT16 uParagraph;
+
+    if (NewRMCB)
+    {
+	LPVOID RMCBmem = DOSMEM_GetBlock(4, &uParagraph);
+	LPBYTE p = RMCBmem;
+
+	*p++ = 0xcd; /* RMCB: */
+	*p++ = 0x31; /* int $0x31 */
+/* it is the called procedure's task to change the return CS:EIP
+   the DPMI 0.9 spec states that if it doesn't, it will be called again */
+	*p++ = 0xeb;
+	*p++ = 0xfc; /* jmp RMCB */
+	NewRMCB->address = MAKELONG(0, uParagraph);
+	NewRMCB->next = FirstRMCB;
+	FirstRMCB = NewRMCB;
+    }
+    return NewRMCB;
+}
+
+
+FARPROC16 WINAPI DPMI_AllocInternalRMCB( RMCBPROC proc )
+{
+    RMCB *NewRMCB = DPMI_AllocRMCB();
+
+    if (NewRMCB) {
+        NewRMCB->proc_ofs = (DWORD)proc;
+        NewRMCB->proc_sel = 0;
+        NewRMCB->regs_ofs = 0;
+        NewRMCB->regs_sel = 0;
+        return (FARPROC16)(NewRMCB->address);
+    }
+    return NULL;
+}
+
+
+static int DPMI_FreeRMCB( DWORD address )
+{
+    RMCB *CurrRMCB = FirstRMCB;
+    RMCB *PrevRMCB = NULL;
+
+    while (CurrRMCB && (CurrRMCB->address != address))
+    {
+	PrevRMCB = CurrRMCB;
+	CurrRMCB = CurrRMCB->next;
+    }
+    if (CurrRMCB)
+    {
+	if (PrevRMCB)
+	PrevRMCB->next = CurrRMCB->next;
+	    else
+	FirstRMCB = CurrRMCB->next;
+	DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(CurrRMCB->address));
+	HeapFree(GetProcessHeap(), 0, CurrRMCB);
+	return 0;
+    }
+    return 1;
+}
+
+
+void WINAPI DPMI_FreeInternalRMCB( FARPROC16 proc )
+{
+    DPMI_FreeRMCB( (DWORD)proc );
+}
+
+
+/* DPMI Raw Mode Switch handler */
+
+#if 0
+void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context )
+{
+  LPDOSTASK lpDosTask = MZ_Current();
+  CONTEXT86 rm_ctx;
+  int ret;
+
+  if (!lpDosTask) {
+    /* we could probably start a DPMI-only dosmod task here, but I doubt
+       anything other than real DOS apps want to call raw mode switch */
+    ERR("attempting raw mode switch without DOS task!\n");
+    ExitProcess(1);
+  }
+  /* initialize real-mode context as per spec */
+  memset(&rm_ctx, 0, sizeof(rm_ctx));
+  rm_ctx.SegDs  = AX_sig(context);
+  rm_ctx.SegEs  = CX_sig(context);
+  rm_ctx.SegSs  = DX_sig(context);
+  rm_ctx.Esp    = EBX_sig(context);
+  rm_ctx.SegCs  = SI_sig(context);
+  rm_ctx.Eip    = EDI_sig(context);
+  rm_ctx.Ebp    = EBP_sig(context);
+  rm_ctx.SegFs  = 0;
+  rm_ctx.SegGs  = 0;
+  rm_ctx.EFlags = EFL_sig(context); /* at least we need the IF flag */
+
+  /* enter real mode again */
+  TRACE("re-entering real mode at %04lx:%04lx\n",rm_ctx.SegCs,rm_ctx.Eip);
+  ret = DOSVM_Enter( &rm_ctx );
+  /* when the real-mode stuff call its mode switch address,
+     DOSVM_Enter will return and we will continue here */
+
+  if (ret<0) {
+    /* if the sync was lost, there's no way to recover */
+    ExitProcess(1);
+  }
+
+  /* alter protected-mode context as per spec */
+  DS_sig(context)  = LOWORD(rm_ctx.Eax);
+  ES_sig(context)  = LOWORD(rm_ctx.Ecx);
+  SS_sig(context)  = LOWORD(rm_ctx.Edx);
+  ESP_sig(context) = rm_ctx.Ebx;
+  CS_sig(context)  = LOWORD(rm_ctx.Esi);
+  EIP_sig(context) = rm_ctx.Edi;
+  EBP_sig(context) = rm_ctx.Ebp;
+  FS_sig(context) = 0;
+  GS_sig(context) = 0;
+
+  /* Return to new address and hope that we didn't mess up */
+  TRACE("re-entering protected mode at %04x:%08lx\n",
+	CS_sig(context), EIP_sig(context));
+}
+#endif
+
+
+/**********************************************************************
+ *	    DOSVM_AllocRMCB   (WINEDOS.@)
+ */
+void WINAPI DOSVM_AllocRMCB( CONTEXT86 *context )
+{
+    RMCB *NewRMCB = DPMI_AllocRMCB();
+
+    TRACE("Function to call: %04x:%04x\n", (WORD)context->SegDs, SI_reg(context) );
+
+    if (NewRMCB)
+    {
+	/* FIXME: if 32-bit DPMI client, use ESI and EDI */
+	NewRMCB->proc_ofs = LOWORD(context->Esi);
+	NewRMCB->proc_sel = context->SegDs;
+	NewRMCB->regs_ofs = LOWORD(context->Edi);
+	NewRMCB->regs_sel = context->SegEs;
+	SET_LOWORD( context->Ecx, HIWORD(NewRMCB->address) );
+	SET_LOWORD( context->Edx, LOWORD(NewRMCB->address) );
+    }
+    else
+    {
+	SET_LOWORD( context->Eax, 0x8015 ); /* callback unavailable */
+	SET_CFLAG(context);
+    }
+}
+
+
+/**********************************************************************
+ *	    DOSVM_FreeRMCB   (WINEDOS.@)
+ */
+void WINAPI DOSVM_FreeRMCB( CONTEXT86 *context )
+{
+    FIXME("callback address: %04x:%04x\n",
+          CX_reg(context), DX_reg(context));
+
+    if (DPMI_FreeRMCB(MAKELONG(DX_reg(context), CX_reg(context)))) {
+	SET_LOWORD( context->Eax, 0x8024 ); /* invalid callback address */
+	SET_CFLAG(context);
+    }
+}
+
+
+/**********************************************************************
+ *	    DOSVM_Int31Handler
+ *
+ * Handler for real-mode int 31h (DPMI).
+ */
+void WINAPI DOSVM_Int31Handler( CONTEXT86 *context )
+{
+    /* check if it's our wrapper */
+    TRACE("called from real mode\n");
+    if (context->SegCs==DOSMEM_dpmi_seg) {
+        /* This is the protected mode switch */
+        StartPM(context);
+        return;
+    }
+    else if (context->SegCs==DOSMEM_xms_seg)
+    {
+        /* This is the XMS driver entry point */
+        XMS_Handler(context);
+        return;
+    }
+    else
+    {
+        /* Check for RMCB */
+        RMCB *CurrRMCB = FirstRMCB;
+
+        while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs))
+            CurrRMCB = CurrRMCB->next;
+
+        if (CurrRMCB) {
+            /* RMCB call, propagate to protected-mode handler */
+            DPMI_CallRMCBProc(context, CurrRMCB, dpmi_flag);
+            return;
+        }
+    }
+
+    /* chain to protected mode handler */
+    INT_Int31Handler( context );
+}
diff --git a/msdos/int33.c b/dlls/winedos/int33.c
similarity index 93%
rename from msdos/int33.c
rename to dlls/winedos/int33.c
index 944db4d..9693d73 100644
--- a/msdos/int33.c
+++ b/dlls/winedos/int33.c
@@ -10,7 +10,6 @@
 #include "wingdi.h"
 #include "winuser.h"
 #include "miscemu.h"
-#include "callback.h"
 #include "dosexe.h"
 #include "vga.h"
 #include "debugtools.h"
@@ -25,11 +24,11 @@
 } mouse_info;
 
 /**********************************************************************
- *	    INT_Int33Handler
+ *	    DOSVM_Int33Handler
  *
  * Handler for int 33h (MS MOUSE).
  */
-void WINAPI INT_Int33Handler( CONTEXT86 *context )
+void WINAPI DOSVM_Int33Handler( CONTEXT86 *context )
 {
   switch (LOWORD(context->Eax)) {
   case 0x00:
@@ -100,7 +99,7 @@
   DPMI_CallRMProc(&ctx, NULL, 0, 0);
 }
 
-void WINAPI INT_Int33Message(UINT message,WPARAM wParam,LPARAM lParam)
+void WINAPI DOSVM_Int33Message(UINT message,WPARAM wParam,LPARAM lParam)
 {
   WORD mask = 0;
   unsigned Height, Width, SX=1, SY=1;
@@ -152,6 +151,6 @@
     data->but = mouse_info.but;
     data->x = mouse_info.x;
     data->y = mouse_info.y;
-    Dosvm.QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data);
+    DOSVM_QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data);
   }
 }
diff --git a/dlls/winedos/ioports.c b/dlls/winedos/ioports.c
new file mode 100644
index 0000000..b63e1ad
--- /dev/null
+++ b/dlls/winedos/ioports.c
@@ -0,0 +1,54 @@
+/*
+ * Emulation of processor ioports.
+ *
+ * Copyright 1995 Morten Welinder
+ * Copyright 1998 Andreas Mohr, Ove Kaaven
+ */
+
+#include "config.h"
+
+#include "windef.h"
+#include "dosexe.h"
+#include "vga.h"
+
+
+/**********************************************************************
+ *	    DOSVM_inport
+ */
+BOOL WINAPI DOSVM_inport( int port, int size, DWORD *res )
+{
+    switch (port)
+    {
+    case 0x60:
+        *res = DOSVM_Int09ReadScan(NULL);
+        break;
+    case 0x3ba:
+    case 0x3da:
+        *res = (DWORD)VGA_ioport_in( port );
+        break;
+    default:
+        return FALSE;  /* not handled */
+    }
+    return TRUE;  /* handled */
+}
+
+
+/**********************************************************************
+ *	    DOSVM_outport
+ */
+BOOL WINAPI DOSVM_outport( int port, int size, DWORD value )
+{
+    switch (port)
+    {
+    case 0x20:
+        DOSVM_PIC_ioport_out( port, (BYTE)value );
+        break;
+    case 0x3c8:
+    case 0x3c9:
+        VGA_ioport_out( port, (BYTE)value );
+        break;
+    default:
+        return FALSE;  /* not handled */
+    }
+    return TRUE;  /* handled */
+}
diff --git a/dlls/winedos/module.c b/dlls/winedos/module.c
index 70c7154..a01118c 100644
--- a/dlls/winedos/module.c
+++ b/dlls/winedos/module.c
@@ -33,8 +33,6 @@
 
 DEFAULT_DEBUG_CHANNEL(module);
 
-static LPDOSTASK dos_current;
-
 #ifdef MZ_SUPPORTED
 
 #ifdef HAVE_SYS_MMAN_H
@@ -74,7 +72,7 @@
 static WORD init_cs,init_ip,init_ss,init_sp;
 static char mm_name[128];
 
-int read_pipe, write_pipe;
+int read_pipe = -1, write_pipe = -1;
 HANDLE hReadPipe, hWritePipe;
 pid_t dosmod_pid;
 
@@ -90,9 +88,9 @@
   /* some programs use this to calculate how much memory they need */
   psp->nextParagraph=0x9FFF; /* FIXME: use a real value */
   /* FIXME: dispatcher */
-  psp->savedint22 = INT_GetRMHandler(0x22);
-  psp->savedint23 = INT_GetRMHandler(0x23);
-  psp->savedint24 = INT_GetRMHandler(0x24);
+  psp->savedint22 = DOSVM_GetRMHandler(0x22);
+  psp->savedint23 = DOSVM_GetRMHandler(0x23);
+  psp->savedint24 = DOSVM_GetRMHandler(0x24);
   psp->parentPSP=par;
   psp->environment=env;
   /* FIXME: more PSP stuff */
@@ -175,10 +173,6 @@
     int mm_fd;
     void *img_base;
 
-    /* initialize the memory */
-    TRACE("Initializing DOS memory structures\n");
-    DOSMEM_Init(TRUE);
-
     /* allocate 1MB+64K shared memory */
     tmpnam(mm_name);
     /* strcpy(mm_name,"/tmp/mydosimage"); */
@@ -201,7 +195,6 @@
 
 static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
 {
-  LPDOSTASK lpDosTask = dos_current;
   IMAGE_DOS_HEADER mz_header;
   DWORD image_start,image_size,min_size,max_size,avail;
   BYTE*psp_start,*load_start,*oldenv;
@@ -210,17 +203,15 @@
   WORD env_seg, load_seg, rel_seg, oldpsp_seg;
   DWORD len;
 
-  if (lpDosTask) {
+  if (DOSVM_psp) {
     /* DOS process already running, inherit from it */
-    PDB16* par_psp = (PDB16*)((DWORD)lpDosTask->psp_seg << 4);
+    PDB16* par_psp = (PDB16*)((DWORD)DOSVM_psp << 4);
     alloc=0;
     oldenv = (LPBYTE)((DWORD)par_psp->environment << 4);
-    oldpsp_seg = lpDosTask->psp_seg;
+    oldpsp_seg = DOSVM_psp;
   } else {
     /* allocate new DOS process, inheriting from Wine environment */
     alloc=1;
-    lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
-    dos_current = lpDosTask;
     oldenv = GetEnvironmentStringsA();
     oldpsp_seg = 0;
   }
@@ -272,13 +263,13 @@
       goto load_error;
     }
     if (avail>max_size) avail=max_size;
-    psp_start=DOSMEM_GetBlock(avail,&lpDosTask->psp_seg);
+    psp_start=DOSMEM_GetBlock(avail,&DOSVM_psp);
     if (!psp_start) {
       ERR("error allocating DOS memory\n");
       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
       goto load_error;
     }
-    load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE);
+    load_seg=DOSVM_psp+(old_com?0:PSP_SIZE);
     rel_seg=load_seg;
     load_start=psp_start+(PSP_SIZE<<4);
     MZ_CreatePSP(psp_start, env_seg, oldpsp_seg);
@@ -324,9 +315,8 @@
   return TRUE;
 
 load_error:
-  lpDosTask->psp_seg = oldpsp_seg;
+  DOSVM_psp = oldpsp_seg;
   if (alloc) {
-    dos_current = NULL;
     if (mm_name[0]!=0) unlink(mm_name);
   }
 
@@ -342,7 +332,7 @@
 }
 
 /***********************************************************************
- *		Exec (WINEDOS.@)
+ *		MZ_Exec
  */
 BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
 {
@@ -350,7 +340,6 @@
    * (i.e. one DOS app spawning another) */
   /* FIXME: do we want to check binary type first, to check
    * whether it's a NE/PE executable? */
-  LPDOSTASK lpDosTask = MZ_Current();
   HFILE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
 			     NULL, OPEN_EXISTING, 0, 0);
   BOOL ret = FALSE;
@@ -360,19 +349,19 @@
   case 1: /* load but don't execute */
     {
       /* save current process's return SS:SP now */
-      LPBYTE psp_start = (LPBYTE)((DWORD)lpDosTask->psp_seg << 4);
+      LPBYTE psp_start = (LPBYTE)((DWORD)DOSVM_psp << 4);
       PDB16 *psp = (PDB16 *)psp_start;
       psp->saveStack = (DWORD)MAKESEGPTR(context->SegSs, LOWORD(context->Esp));
     }
     ret = MZ_DoLoadImage( hFile, filename, NULL );
     if (ret) {
-      /* MZ_LoadImage created a new PSP and loaded new values into lpDosTask,
+      /* MZ_LoadImage created a new PSP and loaded new values into it,
        * let's work on the new values now */
-      LPBYTE psp_start = (LPBYTE)((DWORD)lpDosTask->psp_seg << 4);
+      LPBYTE psp_start = (LPBYTE)((DWORD)DOSVM_psp << 4);
       ExecBlock *blk = (ExecBlock *)paramblk;
       MZ_FillPSP(psp_start, DOSMEM_MapRealToLinear(blk->cmdline));
       /* the lame MS-DOS engineers decided that the return address should be in int22 */
-      INT_SetRMHandler(0x22, (FARPROC16)MAKESEGPTR(context->SegCs, LOWORD(context->Eip)));
+      DOSVM_SetRMHandler(0x22, (FARPROC16)MAKESEGPTR(context->SegCs, LOWORD(context->Eip)));
       if (func) {
 	/* don't execute, just return startup state */
 	blk->init_cs = init_cs;
@@ -385,8 +374,8 @@
 	context->Eip   = init_ip;
 	context->SegSs = init_ss;
 	context->Esp   = init_sp;
-	context->SegDs = lpDosTask->psp_seg;
-	context->SegEs = lpDosTask->psp_seg;
+	context->SegDs = DOSVM_psp;
+	context->SegEs = DOSVM_psp;
 	context->Eax   = 0;
       }
     }
@@ -407,22 +396,16 @@
 }
 
 /***********************************************************************
- *		LoadDPMI (WINEDOS.@)
+ *		MZ_AllocDPMITask
  */
-LPDOSTASK WINAPI MZ_AllocDPMITask( void )
+void WINAPI MZ_AllocDPMITask( void )
 {
-  LPDOSTASK lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
-
-  if (lpDosTask) {
-    dos_current = lpDosTask;
     MZ_InitMemory();
     MZ_InitTask();
-  }
-  return lpDosTask;
 }
 
 /***********************************************************************
- *		RunInThread (WINEDOS.@)
+ *		MZ_RunInThread
  */
 void WINAPI MZ_RunInThread( PAPCFUNC proc, ULONG_PTR arg )
 {
@@ -536,10 +519,9 @@
 
 static void MZ_Launch(void)
 {
-  LPDOSTASK lpDosTask = MZ_Current();
   CONTEXT context;
-  TDB *pTask = TASK_GetCurrent();
-  BYTE *psp_start = PTR_REAL_TO_LIN( lpDosTask->psp_seg, 0 );
+  TDB *pTask = GlobalLock16( GetCurrentTask() );
+  BYTE *psp_start = PTR_REAL_TO_LIN( DOSVM_psp, 0 );
 
   MZ_FillPSP(psp_start, GetCommandLineA());
   pTask->flags |= TDBF_WINOLDAP;
@@ -549,8 +531,8 @@
   context.Eip    = init_ip;
   context.SegSs  = init_ss;
   context.Esp    = init_sp;
-  context.SegDs  = lpDosTask->psp_seg;
-  context.SegEs  = lpDosTask->psp_seg;
+  context.SegDs  = DOSVM_psp;
+  context.SegEs  = DOSVM_psp;
   context.EFlags = 0x00080000;  /* virtual interrupt flag */
   _LeaveWin16Lock();
   DOSVM_Enter( &context );
@@ -564,34 +546,33 @@
 }
 
 /***********************************************************************
- *		Exit (WINEDOS.@)
+ *		MZ_Exit
  */
 void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
 {
-  LPDOSTASK lpDosTask = MZ_Current();
-  if (lpDosTask) {
-    WORD psp_seg = cs_psp ? context->SegCs : lpDosTask->psp_seg;
+  if (DOSVM_psp) {
+    WORD psp_seg = cs_psp ? context->SegCs : DOSVM_psp;
     LPBYTE psp_start = (LPBYTE)((DWORD)psp_seg << 4);
     PDB16 *psp = (PDB16 *)psp_start;
     WORD parpsp = psp->parentPSP; /* check for parent DOS process */
     if (parpsp) {
       /* retrieve parent's return address */
-      FARPROC16 retaddr = INT_GetRMHandler(0x22);
+      FARPROC16 retaddr = DOSVM_GetRMHandler(0x22);
       /* restore interrupts */
-      INT_SetRMHandler(0x22, psp->savedint22);
-      INT_SetRMHandler(0x23, psp->savedint23);
-      INT_SetRMHandler(0x24, psp->savedint24);
+      DOSVM_SetRMHandler(0x22, psp->savedint22);
+      DOSVM_SetRMHandler(0x23, psp->savedint23);
+      DOSVM_SetRMHandler(0x24, psp->savedint24);
       /* FIXME: deallocate file handles etc */
       /* free process's associated memory
        * FIXME: walk memory and deallocate all blocks owned by process */
       DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,psp->environment)));
-      DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,lpDosTask->psp_seg)));
+      DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,DOSVM_psp)));
       /* switch to parent's PSP */
-      lpDosTask->psp_seg = parpsp;
+      DOSVM_psp = parpsp;
       psp_start = (LPBYTE)((DWORD)parpsp << 4);
       psp = (PDB16 *)psp_start;
       /* now return to parent */
-      lpDosTask->retval = retval;
+      DOSVM_retval = retval;
       context->SegCs = SELECTOROF(retaddr);
       context->Eip   = OFFSETOF(retaddr);
       context->SegSs = SELECTOROF(psp->saveStack);
@@ -615,7 +596,7 @@
 }
 
 /***********************************************************************
- *		Exec (WINEDOS.@)
+ *		MZ_Exec
  */
 BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
 {
@@ -625,16 +606,16 @@
 }
 
 /***********************************************************************
- *		LoadDPMI (WINEDOS.@)
+ *		MZ_AllocDPMITask
  */
-LPDOSTASK WINAPI MZ_AllocDPMITask( void )
+void WINAPI MZ_AllocDPMITask( void )
 {
     ERR("Actual real-mode calls not supported on this platform!\n");
     return NULL;
 }
 
 /***********************************************************************
- *		Exit (WINEDOS.@)
+ *		MZ_Exit
  */
 void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
 {
@@ -644,9 +625,9 @@
 #endif /* !MZ_SUPPORTED */
 
 /***********************************************************************
- *		GetCurrent (WINEDOS.@)
+ *		MZ_Current
  */
-LPDOSTASK WINAPI MZ_Current( void )
+BOOL WINAPI MZ_Current( void )
 {
-  return dos_current;
+    return (write_pipe != -1); /* FIXME: do a better check */
 }
diff --git a/msdos/vga.c b/dlls/winedos/vga.c
similarity index 90%
rename from msdos/vga.c
rename to dlls/winedos/vga.c
index 8175fa1..dc682a3 100644
--- a/msdos/vga.c
+++ b/dlls/winedos/vga.c
@@ -11,7 +11,7 @@
 #include "winuser.h"
 #include "wincon.h"
 #include "miscemu.h"
-#include "callback.h"
+#include "dosexe.h"
 #include "vga.h"
 #include "ddraw.h"
 #include "services.h"
@@ -29,9 +29,6 @@
 typedef HRESULT WINAPI (*DirectDrawCreateProc)(LPGUID,LPDIRECTDRAW *,LPUNKNOWN);
 static DirectDrawCreateProc pDirectDrawCreate;
 
-typedef HWND WINAPI (*CreateWindowExAProc)(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT, INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
-static CreateWindowExAProc pCreateWindowExA;
-
 static PALETTEENTRY vga_def_palette[256]={
 /* red  green  blue */
   {0x00, 0x00, 0x00}, /* 0 - Black */
@@ -105,25 +102,12 @@
 		return;
 	    }
         }
-        if (!pCreateWindowExA)
-	{
-            HMODULE hmod = LoadLibraryA( "user32.dll" );
-	    if (!hmod) {
-		ERR("Can't load user32.dll.\n");
-		return;
-	    }
-            if (hmod) pCreateWindowExA = (CreateWindowExAProc)GetProcAddress( hmod, "CreateWindowExA" );
-	    if (!pCreateWindowExA) {
-		ERR("Can't lookup CreateWindowExA from user32.dll.\n");
-		return;
-	    }
-	}
         res = pDirectDrawCreate(NULL,&lpddraw,NULL);
         if (!lpddraw) {
             ERR("DirectDraw is not available (res = %lx)\n",res);
             return;
         }
-	hwnd = pCreateWindowExA(0,"STATIC","WINEDOS VGA",WS_POPUP|WS_BORDER|WS_CAPTION|WS_SYSMENU,0,0,par->Xres,par->Yres,0,0,0,NULL);
+	hwnd = CreateWindowExA(0,"STATIC","WINEDOS VGA",WS_POPUP|WS_BORDER|WS_CAPTION|WS_SYSMENU,0,0,par->Xres,par->Yres,0,0,0,NULL);
 	if (!hwnd) {
 	    ERR("Failed to create user window.\n");
 	}
@@ -174,8 +158,7 @@
     par.Xres = Xres;
     par.Yres = Yres;
     par.Depth = Depth;
-    if (Dosvm.RunInThread) Dosvm.RunInThread(VGA_DoSetMode, (ULONG_PTR)&par);
-    else VGA_DoSetMode((ULONG_PTR)&par);
+    MZ_RunInThread(VGA_DoSetMode, (ULONG_PTR)&par);
     return par.ret;
 }
 
@@ -203,10 +186,7 @@
 
 void VGA_Exit(void)
 {
-    if (lpddraw) {
-        if (Dosvm.RunInThread) Dosvm.RunInThread(VGA_DoExit, 0);
-        else VGA_DoExit(0);
-    }
+    if (lpddraw) MZ_RunInThread(VGA_DoExit, 0);
 }
 
 void VGA_SetPalette(PALETTEENTRY*pal,int start,int len)
@@ -352,8 +332,7 @@
                   ch[X].Attributes = *dat++;
               }
               dest.Left=0; dest.Right=Width+1;
-              FIXME("output commented out for now, should be moved to winedos.dll\n");
-              /*WriteConsoleOutputA(con, ch, siz, off, &dest);*/
+              WriteConsoleOutputA(con, ch, siz, off, &dest);
           }
         }
         vga_refresh=1;
diff --git a/include/vga.h b/dlls/winedos/vga.h
similarity index 100%
rename from include/vga.h
rename to dlls/winedos/vga.h
diff --git a/dlls/winedos/winedos.spec b/dlls/winedos/winedos.spec
index cb21131..7030cbe 100644
--- a/dlls/winedos/winedos.spec
+++ b/dlls/winedos/winedos.spec
@@ -6,20 +6,19 @@
 import kernel32.dll
 import ntdll.dll
 
-debug_channels (int module relay)
+debug_channels (aspi console ddraw int int21 int31 module relay)
 
-@ stdcall GetCurrent() MZ_Current
-@ stdcall LoadDPMI() MZ_AllocDPMITask
 @ stdcall LoadDosExe(str long) MZ_LoadImage
-@ stdcall Exec(ptr str long ptr) MZ_Exec
-@ stdcall Exit(ptr long long) MZ_Exit
-@ stdcall RunInThread(ptr long) MZ_RunInThread
 
-@ stdcall Enter(ptr) DOSVM_Enter
-@ stdcall Wait(long long) DOSVM_Wait
-@ stdcall QueueEvent(long long ptr ptr) DOSVM_QueueEvent
-@ stdcall OutPIC(long long) DOSVM_PIC_ioport_out
+# DPMI functions
+@ stdcall CallRMInt(ptr) DOSVM_CallRMInt
+@ stdcall CallRMProc(ptr ptr long long) DOSVM_CallRMProc
+@ stdcall AllocRMCB(ptr) DOSVM_AllocRMCB
+@ stdcall FreeRMCB(ptr) DOSVM_FreeRMCB
+
+# I/O functions
 @ stdcall SetTimer(long) DOSVM_SetTimer
 @ stdcall GetTimer() DOSVM_GetTimer
-
-@ stdcall KbdReadScan(ptr) INT_Int09ReadScan
+@ stdcall inport(long long ptr) DOSVM_inport
+@ stdcall outport(long long long) DOSVM_outport
+@ stdcall ASPIHandler(ptr) DOSVM_ASPIHandler
diff --git a/msdos/xms.c b/dlls/winedos/xms.c
similarity index 100%
rename from msdos/xms.c
rename to dlls/winedos/xms.c
diff --git a/graphics/dispdib.c b/graphics/dispdib.c
index e6e3f9a..92b63c9 100644
--- a/graphics/dispdib.c
+++ b/graphics/dispdib.c
@@ -9,13 +9,13 @@
 #include "windef.h"
 #include "wingdi.h"
 #include "wine/wingdi16.h"
-#include "miscemu.h"
 #include "dispdib.h"
-#include "vga.h"
 #include "debugtools.h"
 
 DEFAULT_DEBUG_CHANNEL(ddraw);
 
+#if 0
+
 static int dispdib_multi = 0;
 
 static WORD DISPDIB_Begin(WORD wFlags)
@@ -80,6 +80,8 @@
 
     VGA_Poll(0);
 }
+#endif
+
 
 /*********************************************************************
  *	DisplayDib	(DISPDIB.1)
@@ -115,6 +117,7 @@
 		WORD wFlags        /* [in] */
 	)
 {
+#if 0
     WORD ret;
 
     if (wFlags&DISPLAYDIB_END) {
@@ -138,5 +141,7 @@
         FIXME("wait not implemented\n");
     }
     if (!dispdib_multi) DISPDIB_End();
+#endif
+    FIXME( "broken, should be rewritten using ddraw\n" );
     return DISPLAYDIB_NOERROR;
 }
diff --git a/include/callback.h b/include/callback.h
index a93dc4d..23b63bf 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -31,19 +31,20 @@
 
 
 typedef struct {
-    struct _DOSTASK* WINAPI (*Current)( void );
-    struct _DOSTASK* WINAPI (*LoadDPMI)( void );
     void WINAPI             (*LoadDosExe)( LPCSTR filename, HANDLE hFile );
-    BOOL WINAPI             (*Exec)( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
-    void WINAPI             (*Exit)( CONTEXT86 *context, BOOL cs_psp, WORD retval );
-    int WINAPI              (*Enter)( CONTEXT86 *context );
-    void WINAPI             (*RunInThread)( PAPCFUNC proc, ULONG_PTR arg );
-    void WINAPI             (*Wait)( int read_pipe, HANDLE hObject );
-    void WINAPI             (*QueueEvent)( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data );
-    void WINAPI             (*OutPIC)( WORD port, BYTE val );
+
+    /* DPMI functions */
+    void WINAPI             (*CallRMInt)( CONTEXT86 *context );
+    void WINAPI             (*CallRMProc)( CONTEXT86 *context, int iret );
+    void WINAPI             (*AllocRMCB)( CONTEXT86 *context );
+    void WINAPI             (*FreeRMCB)( CONTEXT86 *context );
+
+    /* I/O functions */
     void WINAPI             (*SetTimer)( unsigned ticks );
     unsigned WINAPI         (*GetTimer)( void );
-    BYTE WINAPI             (*KbdReadScan)( BYTE *ascii );
+    BOOL WINAPI             (*inport)( int port, int size, DWORD *res );
+    BOOL WINAPI             (*outport)( int port, int size, DWORD val );
+    void WINAPI             (*ASPIHandler)( CONTEXT86 *context );
 } DOSVM_TABLE;
 
 extern DOSVM_TABLE Dosvm;
diff --git a/include/dosexe.h b/include/dosexe.h
deleted file mode 100644
index 5e0fefd..0000000
--- a/include/dosexe.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * DOS EXE loader
- *
- * Copyright 1998 Ove Kåven
- */
-
-#ifndef __WINE_DOSEXE_H
-#define __WINE_DOSEXE_H
-
-#include <sys/types.h> /* pid_t */
-#include "winbase.h"   /* for LPSTARTUPINFO32A */
-#include "winnt.h"     /* for PCONTEXT */
-
-struct _DOSEVENT;
-
-typedef void (*DOSRELAY)(CONTEXT86*,void*);
-
-typedef struct _DOSTASK {
- WORD psp_seg, retval;
- WORD dpmi_flag;
-} DOSTASK, *LPDOSTASK;
-
-#define DOS_PRIORITY_REALTIME 0  /* IRQ0 */
-#define DOS_PRIORITY_KEYBOARD 1  /* IRQ1 */
-#define DOS_PRIORITY_VGA      2  /* IRQ9 */
-#define DOS_PRIORITY_MOUSE    5  /* IRQ12 */
-#define DOS_PRIORITY_SERIAL   10 /* IRQ4 */
-
-#if defined(linux) && defined(__i386__)
-#define MZ_SUPPORTED
-#endif /* linux-i386 */
-
-#define V86_FLAG 0x00020000
-
-extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile );
-extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
-extern void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval );
-extern LPDOSTASK WINAPI MZ_Current( void );
-extern LPDOSTASK WINAPI MZ_AllocDPMITask( void );
-extern void WINAPI MZ_RunInThread( PAPCFUNC proc, ULONG_PTR arg );
-extern INT WINAPI DOSVM_Enter( CONTEXT86 *context );
-extern void WINAPI DOSVM_Wait( INT read_pipe, HANDLE hObject );
-extern DWORD WINAPI DOSVM_Loop( LPVOID lpExtra );
-extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data );
-extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val );
-extern void WINAPI DOSVM_SetTimer( UINT ticks );
-extern UINT WINAPI DOSVM_GetTimer( void );
-
-#endif /* __WINE_DOSEXE_H */
diff --git a/include/miscemu.h b/include/miscemu.h
index bd32ca7..e1dd3e1 100644
--- a/include/miscemu.h
+++ b/include/miscemu.h
@@ -155,40 +155,15 @@
 /* memory/instr.c */
 extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context );
 
-/* msdos/devices.c */
-extern void DOSDEV_InstallDOSDevices(void);
-extern DWORD DOSDEV_Console(void);
-extern DWORD DOSDEV_FindCharDevice(char*name);
-extern int DOSDEV_Peek(DWORD dev, BYTE*data);
-extern int DOSDEV_Read(DWORD dev, DWORD buf, int buflen);
-extern int DOSDEV_Write(DWORD dev, DWORD buf, int buflen, int verify);
-extern int DOSDEV_IoctlRead(DWORD dev, DWORD buf, int buflen);
-extern int DOSDEV_IoctlWrite(DWORD dev, DWORD buf, int buflen);
-
 /* msdos/interrupts.c */
 typedef void WINAPI (*INTPROC)(CONTEXT86*);
 extern FARPROC16 INT_GetPMHandler( BYTE intnum );
 extern void INT_SetPMHandler( BYTE intnum, FARPROC16 handler );
-extern FARPROC16 INT_GetRMHandler( BYTE intnum );
-extern void INT_SetRMHandler( BYTE intnum, FARPROC16 handler );
-extern FARPROC16 INT_CtxGetHandler( CONTEXT86 *context, BYTE intnum );
-extern void INT_CtxSetHandler( CONTEXT86 *context, BYTE intnum, FARPROC16 handler );
-extern int INT_RealModeInterrupt( BYTE intnum, CONTEXT86 *context );
-extern INTPROC INT_GetWineHandler( BYTE intnum );
-extern void INT_SetWineHandler( BYTE intnum, INTPROC proc );
 
 /* msdos/ioports.c */
 extern DWORD IO_inport( int port, int count );
 extern void IO_outport( int port, int count, DWORD value );
 
-/* msdos/int09.c */
-extern void WINAPI INT_Int09Handler(CONTEXT86*);
-extern void WINAPI INT_Int09SendScan(BYTE scan,BYTE ascii);
-extern BYTE WINAPI INT_Int09ReadScan(BYTE*ascii);
-
-/* msdos/int10.c */
-extern void WINAPI INT_Int10Handler(CONTEXT86*);
-
 /* msdos/int11.c */
 extern void WINAPI INT_Int11Handler(CONTEXT86*);
 
@@ -201,17 +176,6 @@
 /* msdos/int15.c */
 extern void WINAPI INT_Int15Handler(CONTEXT86*);
 
-/* msdos/int16.c */
-extern void WINAPI INT_Int16Handler(CONTEXT86*);
-extern int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek);
-extern int WINAPI INT_Int16AddChar(BYTE ascii,BYTE scan);
-
-/* msdos/int17.c */
-extern void WINAPI INT_Int17Handler(CONTEXT86*);
-
-/* msdos/int19.c */
-extern void WINAPI INT_Int19Handler(CONTEXT86*);
-
 /* msdos/int1a.c */
 extern DWORD INT1A_GetTicksSinceMidnight(void);
 extern void WINAPI INT_Int1aHandler(CONTEXT86*);
@@ -225,19 +189,12 @@
 /* msdos/int26.c */
 extern void WINAPI INT_Int26Handler(CONTEXT86*);
 
-/* msdos/int29.c */
-extern void WINAPI INT_Int29Handler(CONTEXT86*);
-
 /* msdos/int2a.c */
 extern void WINAPI INT_Int2aHandler(CONTEXT86*);
 
 /* msdos/int2f.c */
 extern void WINAPI INT_Int2fHandler(CONTEXT86*);
 
-/* msdos/int33.c */
-extern void WINAPI INT_Int33Handler(CONTEXT86*);
-extern void WINAPI INT_Int33Message(UINT,WPARAM,LPARAM);
-
 /* msdos/dpmi.c */
 typedef void WINAPI (*RMCBPROC)(CONTEXT86*);
 extern void WINAPI INT_Int31Handler(CONTEXT86*);
@@ -246,12 +203,6 @@
 extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16);
 extern int DPMI_CallRMProc(CONTEXT86*,LPWORD,int,int);
 
-/* msdos/xms.c */
-extern void WINAPI XMS_Handler(CONTEXT86*);
-
-/* misc/aspi.c */
-extern void ASPI_DOS_HandleInt(CONTEXT86 *context);
-
 /* misc/ppdev.c */
 
 extern BOOL IO_pp_outp(int port, DWORD* res);
diff --git a/miscemu/main.c b/miscemu/main.c
index aad576c..ececb2e 100644
--- a/miscemu/main.c
+++ b/miscemu/main.c
@@ -11,7 +11,6 @@
 #include "miscemu.h"
 #include "callback.h"
 #include "options.h"
-#include "dosexe.h"
 #include "debugtools.h"
 
 static char main_exe_name[MAX_PATH];
diff --git a/msdos/Makefile.in b/msdos/Makefile.in
index 617b42a..4fc628b 100644
--- a/msdos/Makefile.in
+++ b/msdos/Makefile.in
@@ -6,29 +6,20 @@
 MODULE    = msdos
 
 C_SRCS = \
-	devices.c \
-	dosaspi.c \
 	dosconf.c \
 	dosmem.c \
 	dpmi.c \
-	xms.c \
-	int10.c \
 	int11.c \
 	int12.c \
 	int13.c \
 	int15.c \
-	int16.c \
-	int17.c \
-	int19.c \
 	int1a.c \
 	int20.c \
 	int21.c \
 	int25.c \
 	int26.c \
-	int29.c \
 	int2a.c \
 	int2f.c \
-	int33.c \
 	int3d.c \
 	int41.c \
 	int4b.c \
@@ -36,7 +27,6 @@
 	interrupts.c \
 	ioports.c \
 	ppdev.c \
-	vga.c \
 	vxd.c
 
 all: $(MODULE).o
diff --git a/msdos/dosmem.c b/msdos/dosmem.c
index 55e8008..56604d6 100644
--- a/msdos/dosmem.c
+++ b/msdos/dosmem.c
@@ -22,8 +22,6 @@
 #include "global.h"
 #include "selectors.h"
 #include "miscemu.h"
-#include "vga.h"
-#include "dosexe.h"
 #include "debugtools.h"
 
 DEFAULT_DEBUG_CHANNEL(dosmem);
@@ -76,6 +74,8 @@
 WORD DOSMEM_dpmi_seg;
 WORD DOSMEM_dpmi_sel;
 
+DWORD DOS_LOLSeg;
+
 /***********************************************************************
  *           DOSMEM_SystemBase
  *
@@ -225,12 +225,6 @@
     return DOSMEM_dosmem+0xf0000;
 }
 
-struct _DOS_LISTOFLISTS * DOSMEM_LOL()
-{
-    return (struct _DOS_LISTOFLISTS *)DOSMEM_MapRealToLinear
-      (MAKESEGPTR(HIWORD(DOS_LOLSeg),0));
-}
-
 /***********************************************************************
  *           DOSMEM_FillBiosSegments
  *
@@ -516,7 +510,6 @@
         DOSMEM_InitCollateTable();
         DOSMEM_InitErrorTable();
         DOSMEM_InitDPMI();
-        DOSDEV_InstallDOSDevices();
         already_done = 1;
     }
     else if (dos_init && !already_mapped)
diff --git a/msdos/dpmi.c b/msdos/dpmi.c
index 00d9c1b..d8687d5 100644
--- a/msdos/dpmi.c
+++ b/msdos/dpmi.c
@@ -15,7 +15,6 @@
 #include "builtin16.h"
 #include "miscemu.h"
 #include "msdos.h"
-#include "dosexe.h"
 #include "task.h"
 #include "toolhelp.h"
 #include "selectors.h"
@@ -30,42 +29,8 @@
 
 static void* lastvalloced = NULL;
 
-/* Structure for real-mode callbacks */
-typedef struct
-{
-    DWORD edi;
-    DWORD esi;
-    DWORD ebp;
-    DWORD reserved;
-    DWORD ebx;
-    DWORD edx;
-    DWORD ecx;
-    DWORD eax;
-    WORD  fl;
-    WORD  es;
-    WORD  ds;
-    WORD  fs;
-    WORD  gs;
-    WORD  ip;
-    WORD  cs;
-    WORD  sp;
-    WORD  ss;
-} REALMODECALL;
 
-
-
-typedef struct tagRMCB {
-    DWORD address;
-    DWORD proc_ofs,proc_sel;
-    DWORD regs_ofs,regs_sel;
-    struct tagRMCB *next;
-} RMCB;
-
-static RMCB *FirstRMCB = NULL;
-
-
-static LPDOSTASK WINAPI DPMI_NoCurrent(void) { return NULL; }
-DOSVM_TABLE Dosvm = { DPMI_NoCurrent };
+DOSVM_TABLE Dosvm = { NULL, };
 
 static HMODULE DosModule;
 
@@ -80,19 +45,19 @@
         ERR("could not load winedos.dll, DOS subsystem unavailable\n");
         return FALSE;
     }
-    Dosvm.Current     = (void *)GetProcAddress(DosModule, "GetCurrent");
-    Dosvm.LoadDPMI    = (void *)GetProcAddress(DosModule, "LoadDPMI");
-    Dosvm.LoadDosExe  = (void *)GetProcAddress(DosModule, "LoadDosExe");
-    Dosvm.Exec        = (void *)GetProcAddress(DosModule, "Exec");
-    Dosvm.Exit        = (void *)GetProcAddress(DosModule, "Exit");
-    Dosvm.Enter       = (void *)GetProcAddress(DosModule, "Enter");
-    Dosvm.RunInThread = (void *)GetProcAddress(DosModule, "RunInThread");
-    Dosvm.Wait        = (void *)GetProcAddress(DosModule, "Wait");
-    Dosvm.QueueEvent  = (void *)GetProcAddress(DosModule, "QueueEvent");
-    Dosvm.OutPIC      = (void *)GetProcAddress(DosModule, "OutPIC");
-    Dosvm.SetTimer    = (void *)GetProcAddress(DosModule, "SetTimer");
-    Dosvm.GetTimer    = (void *)GetProcAddress(DosModule, "GetTimer");
-    Dosvm.KbdReadScan = (void *)GetProcAddress(DosModule, "KbdReadScan");
+#define GET_ADDR(func)  Dosvm.func = (void *)GetProcAddress(DosModule, #func);
+
+    GET_ADDR(LoadDosExe);
+    GET_ADDR(CallRMInt);
+    GET_ADDR(CallRMProc);
+    GET_ADDR(AllocRMCB);
+    GET_ADDR(FreeRMCB);
+    GET_ADDR(SetTimer);
+    GET_ADDR(GetTimer);
+    GET_ADDR(inport);
+    GET_ADDR(outport);
+    GET_ADDR(ASPIHandler);
+#undef GET_ADDR
     return TRUE;
 }
 
@@ -167,552 +132,52 @@
 	}
 	return newptr;
 }
-/**********************************************************************
- *	    INT_GetRealModeContext
- */
-static void INT_GetRealModeContext( REALMODECALL *call, CONTEXT86 *context )
-{
-    context->Eax    = call->eax;
-    context->Ebx    = call->ebx;
-    context->Ecx    = call->ecx;
-    context->Edx    = call->edx;
-    context->Esi    = call->esi;
-    context->Edi    = call->edi;
-    context->Ebp    = call->ebp;
-    context->EFlags = call->fl | V86_FLAG;
-    context->Eip    = call->ip;
-    context->Esp    = call->sp;
-    context->SegCs  = call->cs;
-    context->SegDs  = call->ds;
-    context->SegEs  = call->es;
-    context->SegFs  = call->fs;
-    context->SegGs  = call->gs;
-    context->SegSs  = call->ss;
-}
-
-
-/**********************************************************************
- *	    INT_SetRealModeContext
- */
-static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT86 *context )
-{
-    call->eax = context->Eax;
-    call->ebx = context->Ebx;
-    call->ecx = context->Ecx;
-    call->edx = context->Edx;
-    call->esi = context->Esi;
-    call->edi = context->Edi;
-    call->ebp = context->Ebp;
-    call->fl  = LOWORD(context->EFlags);
-    call->ip  = LOWORD(context->Eip);
-    call->sp  = LOWORD(context->Esp);
-    call->cs  = context->SegCs;
-    call->ds  = context->SegDs;
-    call->es  = context->SegEs;
-    call->fs  = context->SegFs;
-    call->gs  = context->SegGs;
-    call->ss  = context->SegSs;
-}
-
-#ifdef __i386__
-
-void DPMI_CallRMCB32(RMCB *rmcb, UINT16 ss, DWORD esp, UINT16*es, DWORD*edi)
-#if 0 /* original code, which early gccs puke on */
-{
-    int _clobber;
-    __asm__ __volatile__(
-        "pushl %%ebp\n"
-        "pushl %%ebx\n"
-        "pushl %%es\n"
-        "pushl %%ds\n"
-        "pushfl\n"
-        "mov %7,%%es\n"
-        "mov %5,%%ds\n"
-        ".byte 0x36, 0xff, 0x18\n" /* lcall *%ss:(%eax) */
-        "popl %%ds\n"
-        "mov %%es,%0\n"
-        "popl %%es\n"
-        "popl %%ebx\n"
-        "popl %%ebp\n"
-    : "=d" (*es), "=D" (*edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber)
-    : "0" (ss), "2" (esp),
-      "4" (rmcb->regs_sel), "1" (rmcb->regs_ofs),
-      "3" (&rmcb->proc_ofs) );
-}
-#else /* code generated by a gcc new enough */
-;
-__ASM_GLOBAL_FUNC(DPMI_CallRMCB32,
-    "pushl %ebp\n\t"
-    "movl %esp,%ebp\n\t"
-    "pushl %edi\n\t"
-    "pushl %esi\n\t"
-    "movl 0x8(%ebp),%eax\n\t"
-    "movl 0x10(%ebp),%esi\n\t"
-    "movl 0xc(%ebp),%edx\n\t"
-    "movl 0x10(%eax),%ecx\n\t"
-    "movl 0xc(%eax),%edi\n\t"
-    "addl $0x4,%eax\n\t"
-    "pushl %ebp\n\t"
-    "pushl %ebx\n\t"
-    "pushl %es\n\t"
-    "pushl %ds\n\t"
-    "pushfl\n\t"
-    "mov %cx,%es\n\t"
-    "mov %dx,%ds\n\t"
-    ".byte 0x36, 0xff, 0x18\n\t" /* lcall *%ss:(%eax) */
-    "popl %ds\n\t"
-    "mov %es,%dx\n\t"
-    "popl %es\n\t"
-    "popl %ebx\n\t"
-    "popl %ebp\n\t"
-    "movl 0x14(%ebp),%eax\n\t"
-    "movw %dx,(%eax)\n\t"
-    "movl 0x18(%ebp),%edx\n\t"
-    "movl %edi,(%edx)\n\t"
-    "popl %esi\n\t"
-    "popl %edi\n\t"
-    "leave\n\t"
-    "ret")
-#endif
-
-#endif /* __i386__ */
-
-/**********************************************************************
- *	    DPMI_CallRMCBProc
- *
- * This routine does the hard work of calling a callback procedure.
- */
-static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
-{
-    if (IS_SELECTOR_SYSTEM( rmcb->proc_sel )) {
-        /* Wine-internal RMCB, call directly */
-        ((RMCBPROC)rmcb->proc_ofs)(context);
-    } else {
-#ifdef __i386__
-        UINT16 ss,es;
-        DWORD esp,edi;
-
-        INT_SetRealModeContext(MapSL(MAKESEGPTR( rmcb->regs_sel, rmcb->regs_ofs )), context);
-        ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, WINE_LDT_FLAGS_DATA );
-        esp = context->Esp;
-
-        FIXME("untested!\n");
-
-        /* The called proc ends with an IRET, and takes these parameters:
-         * DS:ESI = pointer to real-mode SS:SP
-         * ES:EDI = pointer to real-mode call structure
-         * It returns:
-         * ES:EDI = pointer to real-mode call structure (may be a copy)
-         * It is the proc's responsibility to change the return CS:IP in the
-         * real-mode call structure. */
-        if (flag & 1) {
-            /* 32-bit DPMI client */
-            DPMI_CallRMCB32(rmcb, ss, esp, &es, &edi);
-        } else {
-            /* 16-bit DPMI client */
-            CONTEXT86 ctx = *context;
-            ctx.SegCs = rmcb->proc_sel;
-            ctx.Eip   = rmcb->proc_ofs;
-            ctx.SegDs = ss;
-            ctx.Esi   = esp;
-            ctx.SegEs = rmcb->regs_sel;
-            ctx.Edi   = rmcb->regs_ofs;
-            /* FIXME: I'm pretty sure this isn't right - should push flags first */
-            wine_call_to_16_regs_short(&ctx, 0);
-            es = ctx.SegEs;
-            edi = ctx.Edi;
-        }
-	FreeSelector16(ss);
-        INT_GetRealModeContext( MapSL( MAKESEGPTR( es, edi )), context);
-#else
-        ERR("RMCBs only implemented for i386\n");
-#endif
-    }
-}
-
-
-/**********************************************************************
- *	    DPMI_CallRMProc
- *
- * This routine does the hard work of calling a real mode procedure.
- */
-int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret )
-{
-    LPWORD stack16;
-    LPVOID addr = NULL; /* avoid gcc warning */
-    LPDOSTASK lpDosTask = Dosvm.Current();
-    RMCB *CurrRMCB;
-    int alloc = 0, already = 0;
-    BYTE *code;
-
-    TRACE("EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
-                 context->Eax, context->Ebx, context->Ecx, context->Edx );
-    TRACE("ESI=%08lx EDI=%08lx ES=%04lx DS=%04lx CS:IP=%04lx:%04x, %d WORD arguments, %s\n",
-                 context->Esi, context->Edi, context->SegEs, context->SegDs,
-                 context->SegCs, LOWORD(context->Eip), args, iret?"IRET":"FAR" );
-
-callrmproc_again:
-
-/* there might be some code that just jumps to RMCBs or the like,
-   in which case following the jumps here might get us to a shortcut */
-    code = CTX_SEG_OFF_TO_LIN(context, context->SegCs, context->Eip);
-    switch (*code) {
-    case 0xe9: /* JMP NEAR */
-      context->Eip += 3 + *(WORD *)(code+1);
-      /* yeah, I know these gotos don't look good... */
-      goto callrmproc_again;
-    case 0xea: /* JMP FAR */
-      context->Eip = *(WORD *)(code+1);
-      context->SegCs = *(WORD *)(code+3);
-      /* ...but since the label is there anyway... */
-      goto callrmproc_again;
-    case 0xeb: /* JMP SHORT */
-      context->Eip += 2 + *(signed char *)(code+1);
-      /* ...because of other gotos below, so... */
-      goto callrmproc_again;
-    }
-
-/* shortcut for chaining to internal interrupt handlers */
-    if ((context->SegCs == 0xF000) && iret) {
-        return INT_RealModeInterrupt( LOWORD(context->Eip)/4, context);
-    }
-
-/* shortcut for RMCBs */
-    CurrRMCB = FirstRMCB;
-
-    while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs))
-        CurrRMCB = CurrRMCB->next;
-
-    if (!(CurrRMCB || lpDosTask)) {
-        FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n");
-        TRACE("creating VM86 task\n");
-        if ((!DPMI_LoadDosSystem()) || !(lpDosTask = Dosvm.LoadDPMI() )) {
-            ERR("could not setup VM86 task\n");
-            return 1;
-        }
-    }
-    if (!already) {
-        if (!context->SegSs) {
-            alloc = 1; /* allocate default stack */
-            stack16 = addr = DOSMEM_GetBlock( 64, (UINT16 *)&(context->SegSs) );
-            context->Esp = 64-2;
-            stack16 += 32-1;
-            if (!addr) {
-                ERR("could not allocate default stack\n");
-                return 1;
-            }
-        } else {
-            stack16 = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
-        }
-        context->Esp -= (args + (iret?1:0)) * sizeof(WORD);
-        stack16 -= args;
-        if (args) memcpy(stack16, stack, args*sizeof(WORD) );
-        /* push flags if iret */
-        if (iret) {
-            stack16--; args++;
-            *stack16 = LOWORD(context->EFlags);
-        }
-        /* push return address (return to interrupt wrapper) */
-        *(--stack16) = DOSMEM_wrap_seg;
-        *(--stack16) = 0;
-        /* adjust stack */
-        context->Esp -= 2*sizeof(WORD);
-        already = 1;
-    }
-
-    if (CurrRMCB) {
-        /* RMCB call, invoke protected-mode handler directly */
-        DPMI_CallRMCBProc(context, CurrRMCB, lpDosTask ? lpDosTask->dpmi_flag : 0);
-        /* check if we returned to where we thought we would */
-        if ((context->SegCs != DOSMEM_wrap_seg) ||
-            (LOWORD(context->Eip) != 0)) {
-            /* we need to continue at different address in real-mode space,
-               so we need to set it all up for real mode again */
-            goto callrmproc_again;
-        }
-    } else {
-        TRACE("entering real mode...\n");
-        Dosvm.Enter( context );
-        TRACE("returned from real-mode call\n");
-    }
-    if (alloc) DOSMEM_FreeBlock( addr );
-    return 0;
-}
-
 
 /**********************************************************************
  *	    CallRMInt
  */
 static void CallRMInt( CONTEXT86 *context )
 {
-    CONTEXT86 realmode_ctx;
-    FARPROC16 rm_int = INT_GetRMHandler( BL_reg(context) );
-    REALMODECALL *call = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) ));
-    INT_GetRealModeContext( call, &realmode_ctx );
-
-    /* we need to check if a real-mode program has hooked the interrupt */
-    if (HIWORD(rm_int)!=0xF000) {
-        /* yup, which means we need to switch to real mode... */
-        realmode_ctx.SegCs = HIWORD(rm_int);
-        realmode_ctx.Eip   = LOWORD(rm_int);
-        if (DPMI_CallRMProc( &realmode_ctx, NULL, 0, TRUE))
-          SET_CFLAG(context);
-    } else {
-        RESET_CFLAG(context);
-        /* use the IP we have instead of BL_reg, in case some apps
-           decide to move interrupts around for whatever reason... */
-        if (INT_RealModeInterrupt( LOWORD(rm_int)/4, &realmode_ctx ))
-          SET_CFLAG(context);
-        if (context->EFlags & 1) {
-          FIXME("%02x: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
-                BL_reg(context), realmode_ctx.Eax, realmode_ctx.Ebx,
-                realmode_ctx.Ecx, realmode_ctx.Edx);
-          FIXME("      ESI=%08lx EDI=%08lx DS=%04lx ES=%04lx\n",
-                realmode_ctx.Esi, realmode_ctx.Edi,
-                realmode_ctx.SegDs, realmode_ctx.SegEs );
-        }
+    if (!Dosvm.CallRMInt && !DPMI_LoadDosSystem())
+    {
+        ERR("could not setup real-mode calls\n");
+        return;
     }
-    INT_SetRealModeContext( call, &realmode_ctx );
+    Dosvm.CallRMInt( context );
 }
 
 
 static void CallRMProc( CONTEXT86 *context, int iret )
 {
-    REALMODECALL *p = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) ));
-    CONTEXT86 context16;
-
-    TRACE("RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
-	p->eax, p->ebx, p->ecx, p->edx);
-    TRACE("              ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments, %s\n",
-	p->esi, p->edi, p->es, p->ds, p->cs, p->ip, CX_reg(context), iret?"IRET":"FAR" );
-
-    if (!(p->cs) && !(p->ip)) { /* remove this check
-                                   if Int21/6501 case map function
-                                   has been implemented */
-	SET_CFLAG(context);
-	return;
-    }
-    INT_GetRealModeContext(p, &context16);
-    DPMI_CallRMProc( &context16, ((LPWORD)MapSL(MAKESEGPTR(context->SegSs, LOWORD(context->Esp))))+3,
-                     CX_reg(context), iret );
-    INT_SetRealModeContext(p, &context16);
-}
-
-
-static RMCB *DPMI_AllocRMCB( void )
-{
-    RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB));
-    UINT16 uParagraph;
-
-    if (NewRMCB)
+    if (!Dosvm.CallRMProc && !DPMI_LoadDosSystem())
     {
-	LPVOID RMCBmem = DOSMEM_GetBlock(4, &uParagraph);
-	LPBYTE p = RMCBmem;
-
-	*p++ = 0xcd; /* RMCB: */
-	*p++ = 0x31; /* int $0x31 */
-/* it is the called procedure's task to change the return CS:EIP
-   the DPMI 0.9 spec states that if it doesn't, it will be called again */
-	*p++ = 0xeb;
-	*p++ = 0xfc; /* jmp RMCB */
-	NewRMCB->address = MAKELONG(0, uParagraph);
-	NewRMCB->next = FirstRMCB;
-	FirstRMCB = NewRMCB;
+        ERR("could not setup real-mode calls\n");
+        return;
     }
-    return NewRMCB;
+    Dosvm.CallRMProc( context, iret );
 }
 
-
 static void AllocRMCB( CONTEXT86 *context )
 {
-    RMCB *NewRMCB = DPMI_AllocRMCB();
-
-    TRACE("Function to call: %04x:%04x\n", (WORD)context->SegDs, SI_reg(context) );
-
-    if (NewRMCB)
+    if (!Dosvm.AllocRMCB && !DPMI_LoadDosSystem())
     {
-	/* FIXME: if 32-bit DPMI client, use ESI and EDI */
-	NewRMCB->proc_ofs = LOWORD(context->Esi);
-	NewRMCB->proc_sel = context->SegDs;
-	NewRMCB->regs_ofs = LOWORD(context->Edi);
-	NewRMCB->regs_sel = context->SegEs;
-	SET_LOWORD( context->Ecx, HIWORD(NewRMCB->address) );
-	SET_LOWORD( context->Edx, LOWORD(NewRMCB->address) );
+        ERR("could not setup real-mode calls\n");
+        return;
     }
-    else
-    {
-	SET_LOWORD( context->Eax, 0x8015 ); /* callback unavailable */
-	SET_CFLAG(context);
-    }
+    Dosvm.AllocRMCB( context );
 }
 
-
-FARPROC16 WINAPI DPMI_AllocInternalRMCB( RMCBPROC proc )
-{
-    RMCB *NewRMCB = DPMI_AllocRMCB();
-
-    if (NewRMCB) {
-        NewRMCB->proc_ofs = (DWORD)proc;
-        NewRMCB->proc_sel = 0;
-        NewRMCB->regs_ofs = 0;
-        NewRMCB->regs_sel = 0;
-        return (FARPROC16)(NewRMCB->address);
-    }
-    return NULL;
-}
-
-
-static int DPMI_FreeRMCB( DWORD address )
-{
-    RMCB *CurrRMCB = FirstRMCB;
-    RMCB *PrevRMCB = NULL;
-
-    while (CurrRMCB && (CurrRMCB->address != address))
-    {
-	PrevRMCB = CurrRMCB;
-	CurrRMCB = CurrRMCB->next;
-    }
-    if (CurrRMCB)
-    {
-	if (PrevRMCB)
-	PrevRMCB->next = CurrRMCB->next;
-	    else
-	FirstRMCB = CurrRMCB->next;
-	DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(CurrRMCB->address));
-	HeapFree(GetProcessHeap(), 0, CurrRMCB);
-	return 0;
-    }
-    return 1;
-}
-
-
 static void FreeRMCB( CONTEXT86 *context )
 {
-    FIXME("callback address: %04x:%04x\n",
-          CX_reg(context), DX_reg(context));
-
-    if (DPMI_FreeRMCB(MAKELONG(DX_reg(context), CX_reg(context)))) {
-	SET_LOWORD( context->Eax, 0x8024 ); /* invalid callback address */
-	SET_CFLAG(context);
+    if (!Dosvm.FreeRMCB)  /* cannot have allocated one if dosvm not loaded */
+    {
+        SET_LOWORD( context->Eax, 0x8024 ); /* invalid callback address */
+        SET_CFLAG( context );
     }
+    else Dosvm.FreeRMCB( context );
 }
 
 
-void WINAPI DPMI_FreeInternalRMCB( FARPROC16 proc )
-{
-    DPMI_FreeRMCB( (DWORD)proc );
-}
-
-
-/* (see dosmem.c, function DOSMEM_InitDPMI) */
-
-static void StartPM( CONTEXT86 *context, LPDOSTASK lpDosTask )
-{
-    UINT16 cs, ss, ds, es;
-    CONTEXT86 pm_ctx;
-    DWORD psp_ofs = (DWORD)(lpDosTask->psp_seg<<4);
-    PDB16 *psp = (PDB16 *)psp_ofs;
-    HANDLE16 env_seg = psp->environment;
-    unsigned char selflags = WINE_LDT_FLAGS_DATA;
-
-    RESET_CFLAG(context);
-    lpDosTask->dpmi_flag = AX_reg(context);
-/* our mode switch wrapper have placed the desired CS into DX */
-    cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, WINE_LDT_FLAGS_CODE );
-/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
-   can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
-   ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
-   32-bit code using this stack. */
-    if (lpDosTask->dpmi_flag & 1) selflags |= WINE_LDT_FLAGS_32BIT;
-    ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, selflags );
-/* do the same for the data segments, just in case */
-    if (context->SegDs == context->SegSs) ds = ss;
-    else ds = SELECTOR_AllocBlock( (void *)(context->SegDs<<4), 0x10000, selflags );
-    es = SELECTOR_AllocBlock( psp, 0x100, selflags );
-/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
-    psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4), 0x10000, WINE_LDT_FLAGS_DATA );
-
-    pm_ctx = *context;
-    pm_ctx.SegCs = DOSMEM_dpmi_sel;
-/* our mode switch wrapper expects the new CS in DX, and the new SS in AX */
-    pm_ctx.Eax   = ss;
-    pm_ctx.Edx   = cs;
-    pm_ctx.SegDs = ds;
-    pm_ctx.SegEs = es;
-    pm_ctx.SegFs = 0;
-    pm_ctx.SegGs = 0;
-
-    TRACE("DOS program is now entering protected mode\n");
-    wine_call_to_16_regs_short(&pm_ctx, 0);
-
-    /* in the current state of affairs, we won't ever actually return here... */
-    /* we should have int21/ah=4c do it someday, though... */
-
-    FreeSelector16(psp->environment);
-    psp->environment = env_seg;
-    FreeSelector16(es);
-    if (ds != ss) FreeSelector16(ds);
-    FreeSelector16(ss);
-    FreeSelector16(cs);
-}
-
-/* DPMI Raw Mode Switch handler */
-
-#if 0
-void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context )
-{
-  LPDOSTASK lpDosTask = Dosvm.Current();
-  CONTEXT86 rm_ctx;
-  int ret;
-
-  if (!lpDosTask) {
-    /* we could probably start a DPMI-only dosmod task here, but I doubt
-       anything other than real DOS apps want to call raw mode switch */
-    ERR("attempting raw mode switch without DOS task!\n");
-    ExitProcess(1);
-  }
-  /* initialize real-mode context as per spec */
-  memset(&rm_ctx, 0, sizeof(rm_ctx));
-  rm_ctx.SegDs  = AX_sig(context);
-  rm_ctx.SegEs  = CX_sig(context);
-  rm_ctx.SegSs  = DX_sig(context);
-  rm_ctx.Esp    = EBX_sig(context);
-  rm_ctx.SegCs  = SI_sig(context);
-  rm_ctx.Eip    = EDI_sig(context);
-  rm_ctx.Ebp    = EBP_sig(context);
-  rm_ctx.SegFs  = 0;
-  rm_ctx.SegGs  = 0;
-  rm_ctx.EFlags = EFL_sig(context); /* at least we need the IF flag */
-
-  /* enter real mode again */
-  TRACE("re-entering real mode at %04lx:%04lx\n",rm_ctx.SegCs,rm_ctx.Eip);
-  ret = Dosvm.Enter( &rm_ctx );
-  /* when the real-mode stuff call its mode switch address,
-     Dosvm.Enter will return and we will continue here */
-
-  if (ret<0) {
-    /* if the sync was lost, there's no way to recover */
-    ExitProcess(1);
-  }
-
-  /* alter protected-mode context as per spec */
-  DS_sig(context)  = LOWORD(rm_ctx.Eax);
-  ES_sig(context)  = LOWORD(rm_ctx.Ecx);
-  SS_sig(context)  = LOWORD(rm_ctx.Edx);
-  ESP_sig(context) = rm_ctx.Ebx;
-  CS_sig(context)  = LOWORD(rm_ctx.Esi);
-  EIP_sig(context) = rm_ctx.Edi;
-  EBP_sig(context) = rm_ctx.Ebp;
-  FS_sig(context) = 0;
-  GS_sig(context) = 0;
-
-  /* Return to new address and hope that we didn't mess up */
-  TRACE("re-entering protected mode at %04x:%08lx\n",
-	CS_sig(context), EIP_sig(context));
-}
-#endif
-
-
 /**********************************************************************
  *	    INT_Int31Handler (WPROCS.149)
  *
@@ -729,36 +194,6 @@
     DWORD dw;
     BYTE *ptr;
 
-    LPDOSTASK lpDosTask = Dosvm.Current();
-
-    if (ISV86(context) && lpDosTask) {
-        /* Called from real mode, check if it's our wrapper */
-        TRACE("called from real mode\n");
-        if (context->SegCs==DOSMEM_dpmi_seg) {
-            /* This is the protected mode switch */
-            StartPM(context,lpDosTask);
-            return;
-        } else
-        if (context->SegCs==DOSMEM_xms_seg) {
-            /* This is the XMS driver entry point */
-            XMS_Handler(context);
-            return;
-        } else
-        {
-            /* Check for RMCB */
-            RMCB *CurrRMCB = FirstRMCB;
-            
-            while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs))
-                CurrRMCB = CurrRMCB->next;
-            
-            if (CurrRMCB) {
-                /* RMCB call, propagate to protected-mode handler */
-                DPMI_CallRMCBProc(context, CurrRMCB, lpDosTask->dpmi_flag);
-                return;
-            }
-        }
-    }
-
     RESET_CFLAG(context);
     switch(AX_reg(context))
     {
@@ -851,8 +286,8 @@
                      W32S_APP2WINE(MAKELONG(DX_reg(context),CX_reg(context))));
         dw = W32S_APP2WINE(MAKELONG(DX_reg(context), CX_reg(context)));
         if (dw < 0x10000)
-            /* app wants to access lower 64K of DOS memory, map it in now */
-            DOSMEM_Init(TRUE);
+            /* app wants to access lower 64K of DOS memory, load DOS subsystem */
+            DPMI_LoadDosSystem();
         SetSelectorBase(BX_reg(context), dw);
         break;
 
diff --git a/msdos/int20.c b/msdos/int20.c
index 9964033..e98c438 100644
--- a/msdos/int20.c
+++ b/msdos/int20.c
@@ -5,9 +5,6 @@
 #include <stdlib.h>
 #include "winbase.h"
 #include "miscemu.h"
-/* #define DEBUG_INT */
-#include "debugtools.h"
-#include "callback.h"
 
 /**********************************************************************
  *	    INT_Int20Handler (WPROCS.132)
@@ -16,6 +13,5 @@
  */
 void WINAPI INT_Int20Handler( CONTEXT86 *context )
 {
-        if (Dosvm.Exit) Dosvm.Exit( context, TRUE, 0 );
-        else ExitThread( 0 );
+    ExitThread( 0 );
 }
diff --git a/msdos/int21.c b/msdos/int21.c
index e9db39d..e0ca2cb 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -26,12 +26,11 @@
 #include "winerror.h"
 #include "drive.h"
 #include "file.h"
+#include "callback.h"
 #include "msdos.h"
 #include "options.h"
 #include "miscemu.h"
 #include "task.h"
-#include "dosexe.h"
-#include "callback.h"
 #include "debugtools.h"
 #include "console.h"
 
@@ -111,6 +110,13 @@
 
 extern char TempDirectory[];
 
+static void INT21_ReadConfigSys(void)
+{
+    static int done;
+    if (!done) DOSCONF_ReadConfig();
+    done = 1;
+}
+
 static BOOL INT21_CreateHeap(void)
 {
     if (!(DosHeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct DosHeap))))
@@ -944,32 +950,15 @@
      }
 }
 
-static void INT21_SetCurrentPSP(WORD psp)
-{
-    LPDOSTASK lpDosTask = Dosvm.Current();
-    if (lpDosTask)
-        lpDosTask->psp_seg = psp;
-    else
-        ERR("Cannot change PSP for non-DOS task!\n");
-}
-    
-static WORD INT21_GetCurrentPSP(void)
-{
-    LPDOSTASK lpDosTask = Dosvm.Current();
-    if (lpDosTask)
-        return lpDosTask->psp_seg;
-    else
-        return GetCurrentPDB16();
-}
 
-static WORD INT21_GetReturnCode(void)
+static void ASPI_DOS_HandleInt( CONTEXT86 *context )
 {
-    LPDOSTASK lpDosTask = Dosvm.Current();
-    if (lpDosTask) {
-        WORD ret = lpDosTask->retval;
-        lpDosTask->retval = 0;
-        return ret;
-    } else return 0;
+    if (!Dosvm.ASPIHandler && !DPMI_LoadDosSystem())
+    {
+        ERR("could not setup ASPI handler\n");
+        return;
+    }
+    Dosvm.ASPIHandler( context );
 }
 
 /***********************************************************************
@@ -1125,9 +1114,15 @@
 
     switch(AH_reg(context)) 
     {
+    case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
+    case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
     case 0x03: /* READ CHARACTER FROM STDAUX  */
     case 0x04: /* WRITE CHARACTER TO STDAUX */
     case 0x05: /* WRITE CHARACTER TO PRINTER */
+    case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
+    case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
+    case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
+    case 0x0b: /* GET STDIN STATUS */
     case 0x0f: /* OPEN FILE USING FCB */
     case 0x10: /* CLOSE FILE USING FCB */
     case 0x14: /* SEQUENTIAL READ FROM FCB FILE */		
@@ -1140,68 +1135,14 @@
     case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
     case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
     case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
+    case 0x4d: /* GET RETURN CODE */
+    case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
         INT_BARF( context, 0x21 );
         break;
 
     case 0x00: /* TERMINATE PROGRAM */
         TRACE("TERMINATE PROGRAM\n");
-        if (Dosvm.Exit) Dosvm.Exit( context, FALSE, 0 );
-        else ExitThread( 0 );
-        break;
-
-    case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
-        TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
-	AL_reg(context) = CONSOLE_GetCharacter();
-	/* FIXME: no echo */
-	break;
-
-    case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
-        TRACE("Write Character to Standard Output\n");
-    	CONSOLE_Write(DL_reg(context), 0, 0, 0);
-        break;
-
-    case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
-        /* FIXME: Use DOSDEV_Peek/Read/Write(DOSDEV_Console(),...) !! */
-        if (DL_reg(context) == 0xff) {
-            static char scan = 0;
-            TRACE("Direct Console Input\n");
-            if (scan) {
-                /* return pending scancode */
-                AL_reg(context) = scan;
-                RESET_ZFLAG(context);
-                scan = 0;
-            } else {
-                char ascii;
-                if (INT_Int16ReadChar(&ascii,&scan,TRUE)) {
-                    INT_Int16ReadChar(&ascii,&scan,FALSE);
-                    /* return ASCII code */
-                    AL_reg(context) = ascii;
-                    RESET_ZFLAG(context);
-                    /* return scan code on next call only if ascii==0 */
-                    if (ascii) scan = 0;
-                } else {
-                    /* nothing pending, clear everything */
-                    AL_reg(context) = 0;
-                    SET_ZFLAG(context);
-                    scan = 0; /* just in case */
-                }
-            }
-        } else {
-            TRACE("Direct Console Output\n");
-    	    CONSOLE_Write(DL_reg(context), 0, 0, 0);
-    	}
-        break;
-
-    case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
-        /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
-        TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
-        INT_Int16ReadChar(&AL_reg(context), NULL, FALSE);
-        break;
-
-    case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
-        /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
-        TRACE("CHARACTER INPUT WITHOUT ECHO\n");
-        INT_Int16ReadChar(&AL_reg(context), NULL, FALSE);
+        ExitThread( 0 );
         break;
 
     case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
@@ -1235,15 +1176,6 @@
 	break;
       }
 
-    case 0x0b: {/* GET STDIN STATUS */
-    		char x1,x2;
-
-		if (CONSOLE_CheckForKeystroke(&x1,&x2))
-		    AL_reg(context) = 0xff; 
-		else
-		    AL_reg(context) = 0; 
-		break;
-	}
     case 0x2e: /* SET VERIFY FLAG */
         TRACE("SET VERIFY FLAG ignored\n");
     	/* we cannot change the behaviour anyway, so just ignore it */
@@ -1320,8 +1252,7 @@
         break;
 		
     case 0x25: /* SET INTERRUPT VECTOR */
-        INT_CtxSetHandler( context, AL_reg(context),
-                           (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
+        INT_SetPMHandler( AL_reg(context), (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
         break;
 
     case 0x29: /* PARSE FILENAME INTO FCB */
@@ -1387,16 +1318,19 @@
         {
 	      case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
 		TRACE("GET CURRENT EXTENDED BREAK STATE\n");
+                INT21_ReadConfigSys();
                 DL_reg(context) = DOSCONF_config.brk_flag;
 		break;
 
 	      case 0x01: /* SET EXTENDED BREAK STATE */
 		TRACE("SET CURRENT EXTENDED BREAK STATE\n");
+                INT21_ReadConfigSys();
 		DOSCONF_config.brk_flag = (DL_reg(context) > 0);
 		break;		
 		
 	      case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE*/
 		TRACE("GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE\n");
+                INT21_ReadConfigSys();
 		/* ugly coding in order to stay reentrant */
 		if (DL_reg(context))
 		{
@@ -1439,7 +1373,7 @@
     case 0x35: /* GET INTERRUPT VECTOR */
         TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
         {
-            FARPROC16 addr = INT_CtxGetHandler( context, AL_reg(context) );
+            FARPROC16 addr = INT_GetPMHandler( AL_reg(context) );
             context->SegEs = SELECTOROF(addr);
             BX_reg(context) = OFFSETOF(addr);
         }
@@ -1691,21 +1625,6 @@
             DX_reg(context) = 0;
             break;
 
-        case 0x0b:   /* SET SHARING RETRY COUNT */
-            TRACE("IOCTL - SET SHARING RETRY COUNT pause %d retries %d\n",
-		 CX_reg(context), DX_reg(context));
-            if (!CX_reg(context))
-            { 
-                AX_reg(context) = 1;
-                SET_CFLAG(context);
-                break;
-            }
-            DOSMEM_LOL()->sharing_retry_delay = CX_reg(context);
-            if (!DX_reg(context))
-                DOSMEM_LOL()->sharing_retry_count = DX_reg(context);
-            RESET_CFLAG(context);
-            break;
-
         case 0x0d:
             TRACE("IOCTL - GENERIC BLOCK DEVICE REQUEST %s\n",
 		  INT21_DriveName( BL_reg(context)));
@@ -1842,29 +1761,15 @@
         break;
 
     case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
-        TRACE("EXEC %s\n",
-	      (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
-	if (ISV86(context)) {
-            if (!Dosvm.Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx),
-                         AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) ))
-                bSetDOSExtendedError = TRUE;
-	} else {
-            AX_reg(context) = WinExec16( CTX_SEG_OFF_TO_LIN(context,  context->SegDs,
-                                                             context->Edx ),
-                                         SW_NORMAL );
-            if (AX_reg(context) < 32) SET_CFLAG(context);
-        }
-        break;		
-	
-    case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
-        TRACE("EXIT with return code %d\n",AL_reg(context));
-        if (Dosvm.Exit) Dosvm.Exit( context, FALSE, AL_reg(context) );
-        else ExitThread( AL_reg(context) );
+        TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
+        AX_reg(context) = WinExec16( CTX_SEG_OFF_TO_LIN(context,  context->SegDs, context->Edx ),
+                                     SW_NORMAL );
+        if (AX_reg(context) < 32) SET_CFLAG(context);
         break;
 
-    case 0x4d: /* GET RETURN CODE */
-        TRACE("GET RETURN CODE (ERRORLEVEL)\n");
-        AX_reg(context) = INT21_GetReturnCode();
+    case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
+        TRACE("EXIT with return code %d\n",AL_reg(context));
+        ExitThread( AL_reg(context) );
         break;
 
     case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
@@ -1883,27 +1788,22 @@
         }
         else AX_reg(context) = 0;  /* OK */
         break;
-    case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
-        TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n");
-        INT21_SetCurrentPSP(BX_reg(context));
-        break;
     case 0x51: /* GET PSP ADDRESS */
         TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n");
         /* FIXME: should we return the original DOS PSP upon */
         /*        Windows startup ? */
-        BX_reg(context) = INT21_GetCurrentPSP();
+        BX_reg(context) = GetCurrentPDB16();
         break;
     case 0x62: /* GET PSP ADDRESS */
-        TRACE("GET CURRENT PSP ADDRESS\n");
         /* FIXME: should we return the original DOS PSP upon */
         /*        Windows startup ? */
-        BX_reg(context) = INT21_GetCurrentPSP();
+        BX_reg(context) = GetCurrentPDB16();
         break;
 
     case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
         TRACE("SYSVARS - GET LIST OF LISTS\n");
         {
-	    context->SegEs = ISV86(context) ? HIWORD(DOS_LOLSeg) : LOWORD(DOS_LOLSeg);
+            context->SegEs = LOWORD(DOS_LOLSeg);
             BX_reg(context) = FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB);
         }
         break;
diff --git a/msdos/int2f.c b/msdos/int2f.c
index 88dc312..ed6fffb 100644
--- a/msdos/int2f.c
+++ b/msdos/int2f.c
@@ -11,7 +11,6 @@
 
 #include <string.h>
 #include "wine/winbase16.h"
-#include "dosexe.h"
 #include "miscemu.h"
 #include "module.h"
 /* #define DEBUG_INT */
diff --git a/msdos/interrupts.c b/msdos/interrupts.c
index 618a573..4abf2e1 100644
--- a/msdos/interrupts.c
+++ b/msdos/interrupts.c
@@ -14,17 +14,6 @@
 
 DEFAULT_DEBUG_CHANNEL(int);
 
-static INTPROC INT_WineHandler[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- INT_Int10Handler, INT_Int11Handler, INT_Int12Handler, INT_Int13Handler,
- 0, INT_Int15Handler, INT_Int16Handler, INT_Int17Handler,
- 0, 0, INT_Int1aHandler, 0, 0, 0, 0, 0,
- INT_Int20Handler, DOS3Call, 0, 0, 0, INT_Int25Handler, 0, 0,
- 0, INT_Int29Handler, INT_Int2aHandler, 0, 0, 0, 0, INT_Int2fHandler,
- 0, INT_Int31Handler, 0, INT_Int33Handler
-};
-
 static FARPROC16 INT_Vectors[256];
 
 /* Ordinal number for interrupt 0 handler in WPROCS.DLL */
@@ -74,97 +63,6 @@
 
 
 /**********************************************************************
- *	    INT_GetRMHandler
- *
- * Return the real mode interrupt vector for a given interrupt.
- */
-FARPROC16 INT_GetRMHandler( BYTE intnum )
-{
-    return ((FARPROC16*)DOSMEM_SystemBase())[intnum];
-}
-
-
-/**********************************************************************
- *	    INT_SetRMHandler
- *
- * Set the real mode interrupt handler for a given interrupt.
- */
-void INT_SetRMHandler( BYTE intnum, FARPROC16 handler )
-{
-    TRACE("Set real mode interrupt vector %02x <- %04x:%04x\n",
-                 intnum, HIWORD(handler), LOWORD(handler) );
-    ((FARPROC16*)DOSMEM_SystemBase())[intnum] = handler;
-}
-
-
-/**********************************************************************
- *	    INT_CtxGetHandler
- *
- * Return the interrupt vector for a given interrupt.
- */
-FARPROC16 INT_CtxGetHandler( CONTEXT86 *context, BYTE intnum )
-{
-    if (ISV86(context))
-        return INT_GetRMHandler(intnum);
-    else
-        return INT_GetPMHandler(intnum);
-}
-
-
-/**********************************************************************
- *	    INT_CtxSetHandler
- *
- * Set the interrupt handler for a given interrupt.
- */
-void INT_CtxSetHandler( CONTEXT86 *context, BYTE intnum, FARPROC16 handler )
-{
-    if (ISV86(context))
-        INT_SetRMHandler(intnum, handler);
-    else
-        INT_SetPMHandler(intnum, handler);
-}
-
-
-/**********************************************************************
- *	    INT_GetWineHandler
- *
- * Return the Wine interrupt handler for a given interrupt.
- */
-INTPROC INT_GetWineHandler( BYTE intnum )
-{
-    return INT_WineHandler[intnum];
-}
-
-
-/**********************************************************************
- *	    INT_SetWineHandler
- *
- * Set the Wine interrupt handler for a given interrupt.
- */
-void INT_SetWineHandler( BYTE intnum, INTPROC handler )
-{
-    TRACE("Set Wine interrupt vector %02x <- %p\n", intnum, handler );
-    INT_WineHandler[intnum] = handler;
-}
-
-
-/**********************************************************************
- *	    INT_RealModeInterrupt
- *
- * Handle real mode interrupts
- */
-int INT_RealModeInterrupt( BYTE intnum, CONTEXT86 *context )
-{
-    if (INT_WineHandler[intnum]) {
-        (*INT_WineHandler[intnum])(context);
-        return 0;
-    }
-    FIXME("Unknown Interrupt in DOS mode: 0x%x\n", intnum);
-    return 1;
-}
-
-
-/**********************************************************************
  *         INT_DefaultHandler (WPROCS.356)
  *
  * Default interrupt handler.
diff --git a/msdos/ioports.c b/msdos/ioports.c
index 24450f0..235b1e1 100644
--- a/msdos/ioports.c
+++ b/msdos/ioports.c
@@ -20,9 +20,7 @@
 #include <time.h>
 #include <unistd.h>
 #include "windef.h"
-#include "vga.h"
 #include "callback.h"
-#include "dosexe.h"
 #include "options.h"
 #include "miscemu.h"
 #include "debugtools.h"
@@ -98,8 +96,7 @@
 {
     switch (timer) {
         case 0: /* System timer counter divisor */
-            if (Dosvm.Current())
-	      Dosvm.SetTimer(maxval);
+            if (Dosvm.SetTimer) Dosvm.SetTimer(maxval);
             break;
         case 1: /* RAM refresh */
             FIXME("RAM refresh counter handling not implemented !\n");
@@ -292,6 +289,9 @@
     }
 #endif
 
+    /* first give the DOS VM a chance to handle it */
+    if (Dosvm.inport && Dosvm.inport( port, size, &res )) return res;
+
     switch (port)
     {
     case 0x40:
@@ -308,7 +308,7 @@
 	    if (chan == 0) /* System timer counter divisor */
 	    {
 		/* FIXME: Dosvm.GetTimer() returns quite rigid values */
-	        if (Dosvm.Current())
+	        if (Dosvm.GetTimer)
 		  tempval = dummy_ctr + (WORD)Dosvm.GetTimer();
 		else
 		  tempval = dummy_ctr;
@@ -345,7 +345,6 @@
     }
     break;
     case 0x60:
-        res = Dosvm.KbdReadScan ? Dosvm.KbdReadScan(NULL) : 0;
 #if 0 /* what's this port got to do with parport ? */
         res = (DWORD)parport_8255[0];
 #endif
@@ -366,10 +365,6 @@
     case 0x201:
         res = 0xffffffff; /* no joystick */
         break;
-    case 0x3ba:
-    case 0x3da:
-        res = (DWORD)VGA_ioport_in( port );
-        break;
     default:
         WARN("Direct I/O read attempted from port %x\n", port);
         res = 0xffffffff;
@@ -416,12 +411,11 @@
     }
 #endif
 
+    /* first give the DOS VM a chance to handle it */
+    if (Dosvm.outport && Dosvm.outport( port, size, value )) return;
+
     switch (port)
     {
-    case 0x20:
-        if (Dosvm.Current())
-	  Dosvm.OutPIC( port, (BYTE)value );
-        break;
     case 0x40:
     case 0x41:
     case 0x42:
@@ -477,7 +471,7 @@
 	    tmr_8253[chan].latched = TRUE;
 	    dummy_ctr -= 1 + (int)(10.0 * rand() / (RAND_MAX + 1.0));
 	    if (chan == 0) /* System timer divisor */
-	        if (Dosvm.Current())
+	        if (Dosvm.GetTimer)
 		  tmr_8253[chan].latch = dummy_ctr + (WORD)Dosvm.GetTimer();
 	        else
 		  tmr_8253[chan].latch = dummy_ctr;
@@ -511,10 +505,6 @@
     case 0x71:
         cmosimage[cmosaddress & 0x3f] = (BYTE)value;
         break;
-    case 0x3c8:
-    case 0x3c9:
-        VGA_ioport_out( port, (BYTE)value );
-        break;
     default:
         WARN("Direct I/O write attempted to port %x\n", port );
         break;