[PATCH 2/3] winedos: better MSCDEX emulation

Petr Tesarik hat at tesarici.cz
Fri Mar 31 06:36:46 CST 2006


Hi,

while I was trying to make Kindler Literaturlexikon work in Wine, I
found out that this program uses a DOS program to access the CDROM,
and that it requires a real working MSCDEX device driver (and not only
that, the driver has to reside in a different segment than the DOS
core).

To make the patches as small as possible, I've split the patch into
several parts.

This part moves device driver setup to a new function which can be
used from other files (that will be needed later).

ChangeLog:

* dlls/winedos/devices.c, dlls/winedos/dosexe.h:
winedos: add init routine to the WINEDEV structure

* dlls/winedos/devices.c, dlls/winedos/dosexe.h:
winedos: move all device driver initialization code to
a newly written function DOSDEV_SetupDevice()
-------------- next part --------------
Index: devices.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/devices.c,v
retrieving revision 1.14
diff -u -r1.14 devices.c
--- devices.c	21 Jun 2005 20:53:14 -0000	1.14
+++ devices.c	31 Mar 2006 10:29:37 -0000
@@ -158,25 +81,18 @@
 static void WINAPI nul_interrupt(CONTEXT86*ctx);
 static void WINAPI con_strategy(CONTEXT86*ctx);
 static void WINAPI con_interrupt(CONTEXT86*ctx);
+static void con_init(SEGPTR ptr_dev);
 
 /* devices */
-typedef struct
-{
-    char name[8];
-    WORD attr;
-    RMCBPROC strategy;
-    RMCBPROC interrupt;
-} WINEDEV;
-
 static WINEDEV devs[] =
 {
   { "NUL     ",
     ATTR_CHAR|ATTR_NUL|ATTR_DEVICE,
-    nul_strategy, nul_interrupt },
+    nul_strategy, nul_interrupt, NULL },
 
   { "CON     ",
     ATTR_CHAR|ATTR_STDIN|ATTR_STDOUT|ATTR_FASTCON|ATTR_NOTEOF|ATTR_DEVICE,
-    con_strategy, con_interrupt }
+    con_strategy, con_interrupt, con_init }
 };
 
 #define NR_DEVS (sizeof(devs)/sizeof(WINEDEV))
@@ -189,7 +105,7 @@
     WINEDEV_THUNK      thunk[NR_DEVS];
     REQ_IO             req;
     BYTE               buffer[CON_BUFFER];
-
+    DOS_DEVICE_HEADER *last_dev;
 } DOS_DATASEG;
 
 #define DOS_DATASEG_OFF(xxx) FIELD_OFFSET(DOS_DATASEG, xxx)
@@ -256,6 +172,11 @@
   do_lret(ctx);
 }
 
+static void con_init(SEGPTR ptr_dev)
+{
+  DOSMEM_LOL()->ptr_CON_dev_hdr = ptr_dev;
+}
+
 static void WINAPI con_strategy(CONTEXT86*ctx)
 {
   do_strategy(ctx, SYSTEM_STRATEGY_CON, sizeof(int));
@@ -500,6 +421,32 @@
   DOS_LOL->size_extended_mem		= 0xf000; /* very high value */
 }
 
+void DOSDEV_SetupDevice(const WINEDEV * devinfo,
+			WORD seg, WORD off_dev, WORD off_thunk)
+{
+  DOS_DEVICE_HEADER *dev = PTR_REAL_TO_LIN(seg, off_dev);
+  WINEDEV_THUNK *thunk = PTR_REAL_TO_LIN(seg, off_thunk);
+  DOS_DATASEG *dataseg = (DOS_DATASEG*)DOSMEM_LOL();
+
+  dev->attr = devinfo->attr;
+  dev->strategy  = off_thunk + FIELD_OFFSET(WINEDEV_THUNK, ljmp1);
+  dev->interrupt = off_thunk + FIELD_OFFSET(WINEDEV_THUNK, ljmp2);
+  memcpy(dev->name, devinfo->name, 8);
+
+  thunk->ljmp1     = LJMP;
+  thunk->strategy  = DPMI_AllocInternalRMCB(devinfo->strategy);
+  thunk->ljmp2     = LJMP;
+  thunk->interrupt = DPMI_AllocInternalRMCB(devinfo->interrupt);
+
+  dev->next_dev = NONEXT;
+  if (dataseg->last_dev)
+      dataseg->last_dev->next_dev = MAKESEGPTR(seg, off_dev);
+  dataseg->last_dev = dev;
+
+  if (devinfo->init)
+	  devinfo->init( MAKESEGPTR(seg, off_dev) );
+}
+
 void DOSDEV_InstallDOSDevices(void)
 {
   DOS_DATASEG *dataseg;
@@ -520,34 +467,18 @@
   InitListOfLists(&dataseg->lol);
 
   /* Set up first device (NUL) */
-  dataseg->lol.NUL_dev.next_dev  = MAKESEGPTR(seg, DOS_DATASEG_OFF(dev[0]));
-  dataseg->lol.NUL_dev.attr      = devs[0].attr;
-  dataseg->lol.NUL_dev.strategy  = DOS_DATASEG_OFF(thunk[0].ljmp1);
-  dataseg->lol.NUL_dev.interrupt = DOS_DATASEG_OFF(thunk[0].ljmp2);
-  memcpy(dataseg->lol.NUL_dev.name, devs[0].name, 8);
+  dataseg->last_dev = NULL;
+  DOSDEV_SetupDevice( &devs[0],
+		      seg,
+		      DOS_DATASEG_OFF(lol.NUL_dev),
+		      DOS_DATASEG_OFF(thunk[0]) );
 
   /* Set up the remaining devices */
   for (n = 1; n < NR_DEVS; n++)
-  {
-    dataseg->dev[n-1].next_dev  = (n+1) == NR_DEVS ? NONEXT :
-                                  MAKESEGPTR(seg, DOS_DATASEG_OFF(dev[n]));
-    dataseg->dev[n-1].attr      = devs[n].attr;
-    dataseg->dev[n-1].strategy  = DOS_DATASEG_OFF(thunk[n].ljmp1);
-    dataseg->dev[n-1].interrupt = DOS_DATASEG_OFF(thunk[n].ljmp2);
-    memcpy(dataseg->dev[n-1].name, devs[n].name, 8);
-  }
-
-  /* Set up thunks */
-  for (n = 0; n < NR_DEVS; n++)
-  {
-    dataseg->thunk[n].ljmp1     = LJMP;
-    dataseg->thunk[n].strategy  = (RMCBPROC)DPMI_AllocInternalRMCB(devs[n].strategy);
-    dataseg->thunk[n].ljmp2     = LJMP;
-    dataseg->thunk[n].interrupt = (RMCBPROC)DPMI_AllocInternalRMCB(devs[n].interrupt);
-  }
-
-  /* CON is device 1 */
-  dataseg->lol.ptr_CON_dev_hdr = MAKESEGPTR(seg, DOS_DATASEG_OFF(dev[0]));
+    DOSDEV_SetupDevice( &devs[n],
+			seg,
+			DOS_DATASEG_OFF(dev[n-1]),
+			DOS_DATASEG_OFF(thunk[n]) );
 }
 
 DWORD DOSDEV_Console(void)
Index: dosexe.h
===================================================================
RCS file: /home/wine/wine/dlls/winedos/dosexe.h,v
retrieving revision 1.38
diff -u -r1.38 dosexe.h
--- dosexe.h	27 Mar 2006 11:30:41 -0000	1.38
+++ dosexe.h	31 Mar 2006 10:29:37 -0000
@@ -245,3 +245,16 @@
+#include <poppack.h>
+
+/* Device driver info (used for initialization) */
+
+typedef struct
+{
+    char name[8];
+    WORD attr;
+    RMCBPROC strategy;
+    RMCBPROC interrupt;
+    void (*init)(SEGPTR ptr_dev);
+} WINEDEV;
+
 /* module.c */
 extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile );
 extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
@@ -267,6 +373,8 @@
 
 /* devices.c */
 extern void DOSDEV_InstallDOSDevices(void);
+extern void DOSDEV_SetupDevice(const WINEDEV * devinfo,
+                               WORD seg, WORD off_dev, WORD off_thunk);
 extern DWORD DOSDEV_Console(void);
 extern DWORD DOSDEV_FindCharDevice(char*name);
 extern int DOSDEV_Peek(DWORD dev, BYTE*data);


More information about the wine-patches mailing list