Vanilla Doom's external control API

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):

  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?

Share this post


Link to post
fraggle said:

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

Automated strafe running and other player movement scripting?

Holding down the fire button on slaughter maps while I go make a cuppa?

Share this post


Link to post

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).

Share this post


Link to post
DaniJ said:

Automated strafe running and other player movement scripting?

Holding down the fire button on slaughter maps while I go make a cuppa?

I thought about things like these; unfortunately, the ticcmd structure doesn't capture the "run held" or "strafe held" actions, so because of the level it works at, it can't really inject them.

chungy said:

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

Doom doesn't really have much problem playing back long demos, only recording them.

Also, I might be missing something obvious, but what did you use to compile it?

It's compiled with Borland Turbo C.

Share this post


Link to post
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).


He used tcc...

edit: wait no. so how will the batch file work?

edit2: nevermind, I got it to compile :)

Share this post


Link to post
fraggle said:

  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


Vanilla TAS! Run for cover everybody! :p

Share this post


Link to post

Just wanted to say that this is massively cool! I'm slightly disappointed that I didn't know about it. Awesome work!

Share this post


Link to post

Final version is here, and I've uploaded it to /idgames/incoming. I made some minor changes and enhancements: the most significant one being that replay.exe also supports Strife playback now.

Thanks for your comments, everyone!

Share this post


Link to post

uhhhhhhhh

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.

Share this post


Link to post

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).

Share this post


Link to post

Relevant necro-bump!

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.

Share this post


Link to post

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.

Share this post


Link to post

Does Chocolate Doom support the -control command?

Share this post


Link to post
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.

Yep. Identical to this, no doubt.

Sodaholic said:

Does Chocolate Doom support the -control command?

No, and it wouldn't be technically feasible for it to do so.

Share this post


Link to post

Is there any chance for the control API to be tested on DOS? The original release had problems there, and so did the second.

Share this post


Link to post

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.

Share this post


Link to post

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.

Share this post


Link to post
myk said:

...within Windows 98...

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

Share this post


Link to post

I did try by booting to DOS now and replay.exe and statdump.exe both worked, although having to boot to full DOS makes them just a curiosity rather than a more useful tool.

Can my problem be bypassed by using other -cvector values? If so, where could I check to see what Windows is using?

Share this post


Link to post
myk said:

I did try by booting to DOS now and replay.exe and statdump.exe both worked, although having to boot to full DOS makes them just a curiosity rather than a more useful tool.

Can my problem be bypassed by using other -cvector values? If so, where could I check to see what Windows is using?


For memory protection's sake, it's best just to try plain old MS-DOS mode or Dosbox for this. What you are using in Windows is pretty much a VM.

Share this post


Link to post
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.

Share this post


Link to post
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.

This might be a long shot, but does soulsphere.org/random/forward.exe]this work any better?

Share this post


Link to post

Yes, that does work within Windows!

Share this post


Link to post
myk said:

Yes, that does work within Windows!

Excellent. Would you also be able to test this updated package, which contains updated versions of statdump.exe and replay.exe? Your assistance is much appreciated.

Quasar said:

Now I am curious about what change you made :>

Integer overflow. I did this:

    sprintf(addr_string, "%li", 
            (long) (_DS * 16) + (unsigned) (&control_buf));
instead of this:
    long flataddr;
    [...]
    flataddr = (long) _DS * 16 + (unsigned) (&control_buf);
    sprintf(addr_string, "%li", flataddr);
Working on a 16-bit architecture is kind of annoying like that :) Presumably it works in DOSbox because the upper bits of DS are zero.

Share this post


Link to post

The good news is that Replay is now working properly on Windows! Statdump is still capturing stats for 0 levels and writing an empty text file, though.

Share this post


Link to post
myk said:

The good news is that Replay is now working properly on Windows!

Great!

Statdump is still capturing stats for 0 levels and writing an empty text file, though.

D'oh. Turns out I made the same mistake in generating the -statdump parameter as I did in generating the -control parameter.

I've uploaded soulsphere.org/random/ctrlapi.zip]another version that hopefully fixes this too. Could you try again?

Share this post


Link to post

Hurray, Statdump also works now, thanks!

Share this post


Link to post

Excellent. I'll upload the updated version to the idgames archive.

Share this post


Link to post

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%).

P_LoadSideDefs2: sidedef 97 has out-of-range sector num 65535
P_LoadSideDefs2: sidedef 2152 has out-of-range sector num 65535
P_LoadSideDefs2: sidedef 2153 has out-of-range sector num 65535
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.

4_41°00.zip

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now