Driving Glidos from DOSBox

Here you can discuss the development of patches.

Driving Glidos from DOSBox

Postby Glidos » 2009-8-17 @ 16:29

I've been working towards getting Glidos to support DOSBox (which I really should have looked at years ago). My first throughts were to add VDD support to DOSBox, but that's looking hard (it's unclear without some reverse engineering where VDDs expect the DOS registers to be stashed while "DispatchCall" is executed).

Glidos used not to use a VDD, instead communicating via a named pipe. I've reenstated that as an option, and now have something partly working (TR1 works at least in some configurations).

I've had to patch DOSBox a little just to avoid it translating the name of the named pipe. Here's the patch. It's slightly hacky.


Code: Select all
Index: src/dos/dos_files.cpp
===================================================================
RCS file: /cvsroot/dosbox/dosbox/src/dos/dos_files.cpp,v
retrieving revision 1.112
diff -u -r1.112 dos_files.cpp
--- src/dos/dos_files.cpp   9 Jul 2009 20:06:57 -0000   1.112
+++ src/dos/dos_files.cpp   17 Aug 2009 16:12:01 -0000
@@ -63,6 +63,19 @@
       DOS_SetError(DOSERR_FILE_NOT_FOUND);
       return false;
    }
+   if(strlen(name) > 4 && memcmp(name, "\\\\.\\", 4) == 0)
+   {
+      /* The program is opening a Windows device or pipe.
+       * Either we are running under Windows, in which case
+       * no translation should be applied to the name, or
+       * we are running under some other OS, in which case
+       * no tranlation will help. */
+      strcpy(fullname, name);
+      /* Trickery: pretend the path valid for the default
+       * drive */
+      *drive = DOS_GetDefaultDrive();
+      return true;
+   }
    const char * name_int = name;
    char tempdir[DOS_PATHLENGTH];
    char upname[DOS_PATHLENGTH];
Index: src/dos/drive_local.cpp
===================================================================
RCS file: /cvsroot/dosbox/dosbox/src/dos/drive_local.cpp,v
retrieving revision 1.82
diff -u -r1.82 drive_local.cpp
--- src/dos/drive_local.cpp   18 Jul 2009 18:42:55 -0000   1.82
+++ src/dos/drive_local.cpp   17 Aug 2009 16:10:07 -0000
@@ -90,10 +90,22 @@
       return false;
    }
    char newname[CROSS_LEN];
-   strcpy(newname,basedir);
-   strcat(newname,name);
-   CROSS_FILENAME(newname);
-   dirCache.ExpandName(newname);
+   if(strlen(name) > 4 && memcmp(name, "\\\\.\\", 4) ==0)
+   {
+      /* The program is opening a Windows device or pipe.
+       * Either we are running under Windows, in which case
+       * no translation should be applied to the name, or
+       * we are running under some other OS, in which case
+       * no tranlation will help. */
+       strcpy(newname,name);
+   }
+   else
+   {
+       strcpy(newname,basedir);
+       strcat(newname,name);
+       CROSS_FILENAME(newname);
+       dirCache.ExpandName(newname);
+   }
 
    FILE * hand=fopen(newname,type);
 //   Bit32u err=errno;
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55

Re: Driving Glidos from DOSBox

Postby Glidos » 2009-8-17 @ 16:32

Here's another patch, which stops Glidos being fooled into thinking it's running under Window 98. It's not really needed for what I'm doing, but I thought it worth posting, because it is probably preferable behaviour.

Code: Select all
Index: src/dos/dos_misc.cpp
===================================================================
RCS file: /cvsroot/dosbox/dosbox/src/dos/dos_misc.cpp,v
retrieving revision 1.23
diff -u -r1.23 dos_misc.cpp
--- src/dos/dos_misc.cpp   27 May 2009 09:15:41 -0000   1.23
+++ src/dos/dos_misc.cpp   13 Aug 2009 11:16:05 -0000
@@ -186,6 +186,10 @@
       //TODO Maybe do some idling but could screw up other systems :)
       reg_al=0;   
       return true;
+   case 0x1684:    /* MS Windows - GET DEVICE API ENTRY POINT */
+      SegSet16(es,0);   /* Report device not present */
+      reg_edi=0;
+      return true;
    case 0x1689:   /*  Kernel IDLE CALL */
    case 0x168f:   /*  Close awareness crap */
       /* Removing warning */
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55

Re: Driving Glidos from DOSBox

Postby wd » 2009-8-17 @ 17:25

1684 is not handled in msdos (6.22 tested).
wd
DOSBox Author
 
Posts: 10818
Joined: 2003-12-03 @ 21:23

Re: Driving Glidos from DOSBox

Postby Glidos » 2009-8-17 @ 18:50

Not surprising. It's for communication with Windows 9X/ME. If the VxD referred to isn't present then it sets ES:DI to 0:0. Under Windows NT/2000/XP it also sets ES:DI to 0:0, probably in all cases.

What that means for DOSBox, I don't really know.

Anyway, just mentioning it in case it was of some use.
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55

Re: Driving Glidos from DOSBox

Postby Qbix » 2009-8-17 @ 18:58

not handles means that the doing nothing of DOSBox is correct, when comparing it with msdos 6.22

According to the intlist you need set es:di to 0:0 before calling and check if they changed afterwards. but multiplex stuff is tricky
I see we "handle" a few of the 16* calls, but don't handle the 16 installation check. Nor we should I think, but the 1607 is handled anyway... Our idling call 1680 (by modifying reg_al is a bit of a hack though)
Water flows down the stream
How to ask questions the smart way!
User avatar
Qbix
DOSBox Author
 
Posts: 10696
Joined: 2002-11-27 @ 14:50
Location: Fryslan

Re: Driving Glidos from DOSBox

Postby Glidos » 2009-8-17 @ 19:58

Qbix wrote:not handles means that the doing nothing of DOSBox is correct, when comparing it with msdos 6.22

Yeah, I see what you mean, but I would have thought that a program intended for msdos 6.22 would never call int 2f ax=1684. So any behaviour for that interrupt is consistent with intended usage under 6.22. If you set ES:DI to 0:0 then you may also support a few programs intended to run under various versions of Windows.
According to the intlist you need set es:di to 0:0 before calling and check if they changed afterwards.

Yes, that's what intlist says, but Windows 95 VxD documentation also mentions the case of requesting the API of a named VxD, which involves setting ES:DI to point to the name before the call, but where ES:DI still returns ES:DI = 0:0 for device not found.
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55

Re: Driving Glidos from DOSBox

Postby robertmo » 2009-8-18 @ 05:50

would there be any difference between glidos supporting dosbox and gulikoza's glide patch for dosbox?
User avatar
robertmo
l33t
 
Posts: 4416
Joined: 2003-6-18 @ 10:35

Re: Driving Glidos from DOSBox

Postby Glidos » 2009-8-18 @ 09:30

Yes, there's a number of extras that I've put into Glidos over the years.

1. TRX textures for Tombraider.

2. Stereo 3D support.

3. Full set of PS1 version audio tracks for TR1 via MP3.

4. Support for resolutions higher than the game uses, including mapping to a subarea of a widescreen display.

It's only a few things, but I have people asking me for a way to run Glidos on 64bit OS's.

Also I'm looking for a way to do it that doesn't add anything Glide specific to DOSBox, adding either support for accessing named pipes or VDDs, which might be useful for other applications.
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55

Re: Driving Glidos from DOSBox

Postby Glidos » 2009-8-18 @ 09:43

Anyway, I've run into problems. I'm often seeing deadlocks. I think I remember having similar problems with VDos32: while blocked in a read from a pipe, there's no pumping of window messages. Anyone know if SDL supports a call to wait on an event while pumping window messages?

I might have another go at the VDD version because, with that method, the DOS side of Glidos polls rather than blocking during communication, which presumably would lead to DOSBox continuing to pump window messages.
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55

Re: Driving Glidos from DOSBox

Postby Qbix » 2009-8-18 @ 10:32

our event interface with sdl in src/gui/sdlmain.
Water flows down the stream
How to ask questions the smart way!
User avatar
Qbix
DOSBox Author
 
Posts: 10696
Joined: 2002-11-27 @ 14:50
Location: Fryslan

Re: Driving Glidos from DOSBox

Postby Glidos » 2009-8-18 @ 11:16

Hmmm, looks like it might not be possible. I need to pump messages while blocked reading from a pipe. Of course you can't do that while ACTUALLY blocked.

One possibility was that SDL mgiht have explicit support for this, but I can't see it, and it did seem unlikely to be there.

The other possibility (since this needs work only in the WIN32 version), was to use overlapped IO. With overlapped IO, a WIN32 event is associated with the read. The idea then is to wait on the event while pumping messages. But to do that, you need a function that returns if either the event is signalled or if a message comes in. Again SDL would have to provide support for that, and I can't see it: as far as I can see there's no platform specific APIs in SDL, so no way to talk about the WIN32 event in SDL speak.

... maybe it would be sufficient to use MsgWaitForMultipleObjects, and pump messages each time it returns.
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55

Re: Driving Glidos from DOSBox

Postby Qbix » 2009-8-18 @ 11:27

maybe the
SDL_SYSWMEVENT

Code: Select all

/* The windows custom event structure */
struct SDL_SysWMmsg {
        SDL_version version;
        HWND hwnd;                      /* The window for the message */
        UINT msg;                       /* The type of message */
        WPARAM wParam;                  /* WORD message parameter */
        LPARAM lParam;                  /* LONG message parameter */
};

/* The windows custom window manager information structure */
typedef struct SDL_SysWMinfo {
        SDL_version version;
        HWND window;                    /* The Win32 display window */
        HGLRC hglrc;                    /* The OpenGL context, if any */
} SDL_SysWMinfo;

Water flows down the stream
How to ask questions the smart way!
User avatar
Qbix
DOSBox Author
 
Posts: 10696
Joined: 2002-11-27 @ 14:50
Location: Fryslan

Re: Driving Glidos from DOSBox

Postby Glidos » 2009-8-18 @ 12:45

Thanks. Can't immediately see how to use that, but it does show there are some platform specific defs.
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55

Re: Driving Glidos from DOSBox

Postby robertmo » 2009-8-18 @ 14:26

Glidos wrote:1. TRX textures for Tombraider.
4. Support for resolutions higher than the game uses, including mapping to a subarea of a widescreen display.

I think dosbox may not be fast enough for these features.
User avatar
robertmo
l33t
 
Posts: 4416
Joined: 2003-6-18 @ 10:35

Re: Driving Glidos from DOSBox

Postby h-a-l-9000 » 2009-8-18 @ 14:30

Why, DOSBox doesn't have to draw pixel by pixel, Glidos is doing that.
1+1=10
h-a-l-9000
DOSBox Author
 
Posts: 4512
Joined: 2005-2-23 @ 00:14

Re: Driving Glidos from DOSBox

Postby Glidos » 2009-8-18 @ 14:34

robertmo wrote:
Glidos wrote:1. TRX textures for Tombraider.
4. Support for resolutions higher than the game uses, including mapping to a subarea of a widescreen display.

I think dosbox may not be fast enough for these features.


From my experiments so far, it's fine when Glidos is using OpenGLide, but struggles a little when using psVoodoo. That's on a 2.4GHz Core2 Duo, and a GF GTX 280.
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55

Re: Driving Glidos from DOSBox

Postby Glidos » 2009-9-05 @ 12:34

Here's a cleaner patch, with named pipes implemented via their own DOS_File subclass, and using overlapped IO while keeping windows messages pumping.

There is still work to do to make Glidos work seemlessly with DOSBox. Glidos uses a slightly nasty trick to handle key presses. Key events received by Glidos's display window are posted to the DOS window (in this case DOSBox's window). That works ok with ntvdm and VDos32, but - as far as I can tell - DOSBox ignores key events when it doesn't have the focus (which is probably quite reasonable). Because of this, I have it working only with Glidos in Windowed mode, and even then the keyboard goes dead if I click on the Glidos display window.
Code: Select all
diff -ruN old/src/dos/dos_files.cpp new/src/dos/dos_files.cpp
--- old/src/dos/dos_files.cpp   Sat Sep  5 13:12:33 2009
+++ new/src/dos/dos_files.cpp   Sat Sep  5 13:03:06 2009
@@ -29,6 +29,7 @@
 #include "regs.h"
 #include "dos_inc.h"
 #include "drives.h"
+#include "named_pipe.h"
 #include "cross.h"
 
 #define DOS_FILESTART 4
@@ -540,6 +541,11 @@
       return false;
    }
    bool exists=false;
+#if defined (WIN32)
+   if (NamedPipe_isNamedPipe(name)) {
+      exists = NamedPipe_Open(name, &Files[handle]);
+   } else
+#endif
    if (device) {
       Files[handle]=new DOS_Device(*Devices[devnum]);
    } else {
diff -ruN old/src/dos/named_pipe.h new/src/dos/named_pipe.h
--- old/src/dos/named_pipe.h   Thu Jan  1 00:00:00 1970
+++ new/src/dos/named_pipe.h   Fri Aug 21 11:20:33 2009
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (C) 2002-2009  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "dosbox.h"
+#include "dos_system.h"
+
+bool NamedPipe_isNamedPipe(const char * name);
+
+bool NamedPipe_Open(const char * name, DOS_File * * file);
diff -ruN old/src/dos/named_pipe_win32.cpp new/src/dos/named_pipe_win32.cpp
--- old/src/dos/named_pipe_win32.cpp   Thu Jan  1 00:00:00 1970
+++ new/src/dos/named_pipe_win32.cpp   Sat Sep  5 12:59:16 2009
@@ -0,0 +1,154 @@
+/*
+ *  Copyright (C) 2002-2009  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <windows.h>
+
+#include "sdl.h"
+
+#include "dosbox.h"
+#include "dos_system.h"
+
+#include "named_pipe.h"
+
+class NamedPipe : public DOS_File {
+public:
+   NamedPipe();
+   ~NamedPipe();
+   bool Read(Bit8u * data,Bit16u * size);
+   bool Write(Bit8u * data,Bit16u * size);
+   bool Seek(Bit32u * pos,Bit32u type);
+   bool Open(const char *name);
+   bool Close();
+   Bit16u GetInformation(void);
+private:
+   HANDLE    m_pipe;
+   OVERLAPPED m_overlapped;
+   void PumpWhileWaiting(HANDLE event);
+};
+
+NamedPipe::NamedPipe() {
+   m_pipe           = INVALID_HANDLE_VALUE;
+   m_overlapped.hEvent = INVALID_HANDLE_VALUE;
+}
+
+NamedPipe::~NamedPipe() {
+   void Close();
+}
+
+bool NamedPipe::Open(const char *name) {
+   Close();
+   m_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+   if(m_overlapped.hEvent == INVALID_HANDLE_VALUE)
+      return false;
+   m_pipe = CreateFile(name,
+                 GENERIC_READ|GENERIC_WRITE,
+                 0,    /* Don't share */
+                 NULL,  /* No Security */
+                 OPEN_EXISTING,
+                 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
+                 NULL);
+   return (m_pipe != INVALID_HANDLE_VALUE);
+}
+
+bool NamedPipe::Close(){
+   if(m_pipe != INVALID_HANDLE_VALUE)
+      CloseHandle(m_pipe);
+   if(m_overlapped.hEvent != INVALID_HANDLE_VALUE)
+      CloseHandle(m_overlapped.hEvent);
+   return true;
+}
+
+bool NamedPipe::Read(Bit8u * data,Bit16u * size) {
+   DWORD returned;
+   DWORD len = *size;
+   while(len > 0) {
+      m_overlapped.Offset = 0;
+      m_overlapped.OffsetHigh = 0;
+      if(ReadFile(m_pipe, (LPVOID)data, len, NULL, &m_overlapped)) {
+         GetOverlappedResult(m_pipe, &m_overlapped, &returned, FALSE);
+      } else {
+         if(GetLastError() != ERROR_IO_PENDING)
+            return false;
+         PumpWhileWaiting(m_overlapped.hEvent);
+         GetOverlappedResult(m_pipe, &m_overlapped, &returned, FALSE);
+         ResetEvent(m_overlapped.hEvent);
+      }
+      data += returned;
+      len  -= returned;
+   }
+   return true;
+}
+
+bool NamedPipe::Write(Bit8u * data,Bit16u * size){
+   DWORD returned;
+   DWORD len = *size;
+   while(len > 0) {
+      m_overlapped.Offset = 0;
+      m_overlapped.OffsetHigh = 0;
+      if(WriteFile(m_pipe, (LPVOID)data, len, NULL, &m_overlapped)) {
+         GetOverlappedResult(m_pipe, &m_overlapped, &returned, FALSE);
+      } else {
+         if(GetLastError() != ERROR_IO_PENDING)
+            return false;
+         PumpWhileWaiting(m_overlapped.hEvent);
+         GetOverlappedResult(m_pipe, &m_overlapped, &returned, FALSE);
+         ResetEvent(m_overlapped.hEvent);
+      }
+      data += returned;
+      len  -= returned;
+   }
+   return true;
+}
+
+void NamedPipe::PumpWhileWaiting(HANDLE event)
+{
+   bool going = true;
+
+   while(going) {
+      SDL_PumpEvents();
+      if(MsgWaitForMultipleObjects(1, &event, false, INFINITE, QS_ALLINPUT) == 0)
+         going = false;
+   }
+}
+
+bool NamedPipe::Seek(Bit32u * new_pos,Bit32u type){
+   /* Not seekable */
+   return false;
+}
+
+Bit16u NamedPipe::GetInformation(void) {
+   return 2;
+}
+
+bool NamedPipe_isNamedPipe(const char * name) {
+   return strlen(name) > 4 && memcmp(name, "\\\\.\\", 4) ==0;
+}
+
+bool NamedPipe_Open(const char * name, DOS_File * * file) {
+   NamedPipe *pipe = new NamedPipe();
+   if(pipe != NULL) {
+      if(!pipe->Open(name)) {
+         delete pipe;
+         pipe=NULL;
+      }
+   }
+   *file = pipe;
+   return (pipe != NULL);
+}
+
User avatar
Glidos
l33t
 
Posts: 3116
Joined: 2002-8-08 @ 02:55


Return to DOSBox Patches

Who is online

Users browsing this forum: lmerckx and 1 guest