VOGONS

Common searches


Driving Glidos from DOSBox

Topic actions

  • This topic is locked. You cannot reply or edit posts.

First post, by Glidos

User metadata
Rank l33t
Rank
l33t

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.

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);
Show last 2 lines
 //	Bit32u err=errno;

Reply 1 of 16, by Glidos

User metadata
Rank l33t
Rank
l33t

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.

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 */

Reply 3 of 16, by Glidos

User metadata
Rank l33t
Rank
l33t

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.

Reply 4 of 16, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

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!

Reply 5 of 16, by Glidos

User metadata
Rank l33t
Rank
l33t
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.

Reply 7 of 16, by Glidos

User metadata
Rank l33t
Rank
l33t

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.

Reply 8 of 16, by Glidos

User metadata
Rank l33t
Rank
l33t

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.

Reply 10 of 16, by Glidos

User metadata
Rank l33t
Rank
l33t

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.

Reply 11 of 16, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

maybe the
SDL_SYSWMEVENT


/* 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!

Reply 15 of 16, by Glidos

User metadata
Rank l33t
Rank
l33t
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.

Reply 16 of 16, by Glidos

User metadata
Rank l33t
Rank
l33t

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.

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
Show last 150 lines
+ *  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);
+}
+