Thanks to some helpfully-provided information from Quasar, over the past few days I've been playing with Doom's external control API. This is a little-known command line parameter in Vanilla Doom (-control), which I think was added so that manufacturers of controllers (gamepads, joysticks, etc) could write special drivers to control the game.

What I have so far is here. It's essentially possible to inject any ticcmd into the game. These are the demo programs I've put together so far (copy+pasting from the text file):

code: forward.exe
- The most simple (and most boring) example. This program simply
makes the player move forward constantly. To run:
forward.exe doom2.exe -warp 1
replay.exe
- This program replays a previously recorded demo. This is useful
because it allows a demo to be partially recorded and then
continued at a later date. To run:
replay.exe -playdemo olddemo.lmp doom2.exe -warp 1
Or to continue recording:
replay.exe -playdemo olddemo.lmp doom2.exe -warp 1 -record newdemo
statdump.exe
- This is a refactored version of my external statistics driver
which I previously released as statdump.zip. Problems were reported
with that program because it replaced the mouse interrupt, and
as a result, worked under DOSbox but not under real DOS systems.
Hopefully this should work better.
This does not actually make use of the control API to inject any
events, it just take advantage of the fact that it provides a
regular interrupt. To run:
statdump.exe doom2.exe -warp 1
Or for statistics for a demo:
statdump.exe -o mydemo.txt doom2.exe -playdemo mydemo

Feedback is welcome. Any suggestions for other things this might be useful for?

This is pretty cool, I wonder if replay.exe could be used to play back demos larger than Doom allows ...

Also, I might be missing something obvious, but what did you use to compile it? I seriously doubt this TCC has a DOS port, and I already have DJGPP in DOSEMU but gcc can't compile the code either (this probably isn't hard to fix, I'm thinking).

chungy said:
This is pretty cool, I wonder if replay.exe could be used to play back demos larger than Doom allows ...

Also, I might be missing something obvious, but what did you use to compile it? I seriously doubt this TCC has a DOS port, and I already have DJGPP in DOSEMU but gcc can't compile the code either (this probably isn't hard to fix, I'm thinking).

code: replay.exe
- This program replays a previously recorded demo. This is useful
because it allows a demo to be partially recorded and then
continued at a later date. To run:
replay.exe -playdemo olddemo.lmp doom2.exe -warp 1
Or to continue recording:
replay.exe -playdemo olddemo.lmp doom2.exe -warp 1 -record newdemo

Doesn't the Heretic source code contain a lot of device-dependent defines which allowed using some exotic controllers like Cyberman to control the character? Those worked at the G_BuildTicCmd level, by directly "injecting" in the input.

Indeed, it seems that it does! The "-externdriver" command line parameter seems to do something similar to -control.

Looks slightly more elaborate than -control, though. It seems that with -externdriver you can do the strafe down/speed down thing that isn't possible with -control.

Looking at the code it seems like Raven put a lot more effort into it than Id did with -control, to the extent that I suspect they must have had something they used to test it. I wonder what they added it for?

Cyberman support is separate, by the way. It's built in to the program. The Cyberman API worked through an extended DOS mouse API, which is why you always get a "wrong mouse driver - no SWIFT support" message on startup. I had a crazy idea a while back to make a modified version of DOSbox which used a Wii remote to emulate a Cyberman, to see if I could use it to control Vanilla Doom (and other games, like Descent).

I've uploaded a file to idgames that includes a Logitech implementation of an external control driver, apparently written for their "Wingman Warrior" joystick. The same driver supports a bunch of other games as well, including Quake (which supports the -control parameter as well). So it seems that this was actually used for something after all, and explains the efforts that Raven went to when implementing -externdriver. I wonder if any other manufacturers used this, or if it was just Logitech.

I can give you some info on a bit of your speculation in the text file - the -control parameter does not support the Cyberman. Instead, vanilla DOOM has dedicated code to detect and directly interact with the Cyberman mouse by querying its interrupt API. I found the code for it in strife1.exe during the Chocolate Strife reverse engineering.

Quasar said:
I can give you some info on a bit of your speculation in the text file - the -control parameter does not support the Cyberman. Instead, vanilla DOOM has dedicated code to detect and directly interact with the Cyberman mouse by querying its interrupt API. I found the code for it in strife1.exe during the Chocolate Strife reverse engineering.

I remember hearing that there were problems with the original statdump.exe due to the perverse things it did with the DOS mouse interrupt handler. Were there problems with this as well? I only tested in DOSbox.

I tested again in DOS within Windows 98 and forward.exe made a beep after which it closed with a "was terminated unexpectedly" message, replay.exe closed with an illegal operation message when I tried to "rerecord" on a short demo I had just recorded, and statdump.exe ran 30bt0941.lmp all the way but said that it captured statistics for 0 levels and left a blank text file.

Quasar said:
Expecting DOS programs that directly hook interrupts to work under Win98 is a bit of a crapshoot.

I see no reason why it shouldn't be able work on Windows 98 (Microsoft put a lot of effort into ensuring DOS programs worked). I suspect I've probably screwed something up in the interrupt handler.

Checking through the code, it's essentially almost identical to the same things that ipxsetup.exe and sersetup.exe do to hook vectors and communicate with Doom. So I'm kind of stumped as to why it doesn't work.

myk said:
I tested again in DOS within Windows 98 and forward.exe made a beep after which it closed with a "was terminated unexpectedly" message, replay.exe closed with an illegal operation message when I tried to "rerecord" on a short demo I had just recorded, and statdump.exe ran 30bt0941.lmp all the way but said that it captured statistics for 0 levels and left a blank text file.

Here's an oddity related to Statdump. It may not be a bug in Statdump itself, I suppose, if Doom is passing weird info to it. While the numbers in monsters seem fine (359/373), I got a strange negative kills percentage (-79%). The ZIP contains the demo plus the a REJECT lump for the WAD, MHS Doom II. I had to edit REJECT because it's missing one byte and otherwise crashed vanilla with a numlumps error. The included lump is needed for vanilla, but PrBoom+ won't need it, with its automatic REJECT padding. PrBoom+ also detected some other bugs in the level. Maybe they have something to do with the odd kills percentage? Yet, the percentage on the ingame stats screen is correct (96%).

The demo is 35:02 minutes long, so -timedemo or PrBoom+'s fast forward or -skipsec may come in handy for anyone not watching it for the popcorn and the giggles. The text file is a stats dump of the play-through/demo. The edited.lmp demo is a copy of 4_41°00.lmp without firing tics at the end, padded with 2 seconds of wait tics, so that it will display the stats screen long enough. (I didn't expect an exit line there, which is stupid; I thought the actual exit was a switch in the room.) So it may be better to watch this than the original demo.

The 0:00 par time in the stats dump text file is nothing unusual. Unless the IWAD is run, or I add a patch with par times, my batch file applies a patch that gives every level a par time of 0.