alinebee / Boxer

The DOS game emulator that's fit for your Mac.
http://boxerapp.com/
770 stars 139 forks source link

Privateer in-game music slowdown #28

Open isrob opened 10 years ago

isrob commented 10 years ago

A bug exists in Privateer running on Boxer (including the GOG version) that replicates perfectly an issue in the original code, running on metal. In-game music (MIDI or SB16) music runs at half-speed (or thereabouts) when the game is run without a joystick connected. This is best demonstrated by launching your ship, listening to the music and then hitting Alt-O to open the Options panel in-game - the speed dramatically increases.

In DosBox directly, a joysticktype=2axis enables fake emulation, which prompts Privateer to calibrate the joystick. Providing a fake JOYA.DAT file in the game directory bypasses this, and results in smooth playback of music. http://isrob.com/files/JOYA.DAT

Boxer, however, seems not to respect the joysticktype (or overrides it if none is detected attached to the underlying system) - the problem is resolved if I use Joypad on iOS to simulate.

Laughably I remember noticing this slowdown as a kid on my 486, but didn't know enough to realise it wasn't by design. As a separate initiative it would be great to analyse what's causing it and whether it could be patched out of the game rather than any kind of Boxer workaround.

alinebee commented 10 years ago

As you've observed, if no controller is connected then Boxer disables gameport emulation and reports no joystick device to the game. This differs from DOSBox by design: in fact Boxer does this precisely because of Privateer, and games like it, because otherwise users wouldn't be able to start up Privateer at all without having a controller or a fake JOYA.DAT file - making the game otherwise unplayable out-of-the-box.

This behaviour does get in the way of a user-applied workaround for this MIDI bug however, since there is currently no way to force Boxer to present a joystick to the DOS game without having a controller attached. Boxer could selectively override its behaviour for Privateer, but that would then rely on the user having a JOYA.DAT file in place, and would break the game for everybody who doesn't.

So, a truly automatic workaround for this bug would require Boxer to:

Boxer could do the former without much trouble, but it has no functionality for the latter at the moment; I have been planning to implement such a system for handling problems like this though. (Such a system would be most useful if it could also patch DOS binaries in memory, but that's a whole other kettle of fish.)

One question: does your fake JOYA.DAT contain valid calibration data that results in usable joystick control if one later connects a real controller? The game will not ask the user to recalibrate if JOYA.DAT is present, so it's vital that the calibration data in the file is valid.

isrob commented 10 years ago

A good analysis of the impact of some of the workarounds, thank you. There's real calibration data in that JOYA.DAT file, yes, but who knows if that would be appropriate for different controllers so it certainly isn't a solution in itself. I don't know the details of Privateer's calibration data, but unfortunately I would assume as a file it's only useful in the absence of an actual controller and calibration data.

alinebee commented 10 years ago

Well helpfully modern USB and bluetooth game controllers provide consistent inputs that Boxer can reliably normalize, so calibration data that's accurate for one controller is also accurate for any other.

(In practice there's one or two exceptions to this: principally when calibrating on a controller with square axis travel, like a PC gamepad, then using the same calibration data with a controller with circular travel, like a console gamepad - they can't reach the same diagonal extents, so the game doesn't think they're pushing all the way. That's not a major problem with Privateer though.)

isrob commented 10 years ago

I see. The file's taken from somewhere floating around the web, so if this was something that ended up as a bundled workaround I would recommend recalibrating with an actual controller connected to OS X and Boxer as I can't vouch for its accuracy. Unfortunately I don't have one.

isrob commented 10 years ago

Bit more info:

I got in touch with Mario Brito (of http://hcl.solsector.net/), who has been in the Wing Commander modding scene for literally decades. Asked him about the issue and he was aware of it, so poked at the executable and actually came up with a fix. In short, the game tells the CPU to ignore interrupts during reads of the joystick; this would generally be good (guarantees timing accuracy) but the game doesn't re-enable interrupts when it's done. They get re-enabled 'at some point' later, messing the music timing.

Patch out the interrupt ignore instruction and bam, solved. Mario's going to revisit the patch at a later date to look into making the joystick reading generally more robust (read: timed), but cursory checks don't suggest any issues (either with or without a joystick attached).

BSDiff patch for PRCD.exe: http://isrob.com/files/prcd_patch.bdf

alinebee commented 10 years ago

Oh nice catch! That explanation does make a lot of sense. I'll test this myself and will let GOG know of the fix so hopefully they'll integrate it into the copy of Privateer they're selling.

(If the diff could get weaponised as a patcher exe, that could go up on wcnews.com as well - I dunno what tools are available for wrapping bspatches though.)