No description
Find a file
2026-05-25 20:13:41 +02:00
_attic new try 2026-05-25 20:13:41 +02:00
_swsetup new try 2026-05-25 20:13:41 +02:00
build new try 2026-05-25 20:13:41 +02:00
ddk-headers new try 2026-05-25 20:13:41 +02:00
dist new try 2026-05-25 20:13:41 +02:00
docs new try 2026-05-25 20:13:41 +02:00
include new try 2026-05-25 20:13:41 +02:00
res new try 2026-05-25 20:13:41 +02:00
src new try 2026-05-25 20:13:41 +02:00
tests new try 2026-05-25 20:13:41 +02:00
tools new try 2026-05-25 20:13:41 +02:00
vendor new try 2026-05-25 20:13:41 +02:00
.dockerignore new try 2026-05-25 20:13:41 +02:00
.gitignore new try 2026-05-25 20:13:41 +02:00
build.sh new try 2026-05-25 20:13:41 +02:00
Dockerfile new try 2026-05-25 20:13:41 +02:00
Makefile new try 2026-05-25 20:13:41 +02:00
README.md new version with rewrote driver 2026-05-21 15:46:31 +02:00

SideWinder 3D Pro Timing Fix Installer

Automated installer for the Microsoft SideWinder 3D Pro VXD driver timing fix on Windows 95/98/ME.

What This Does

The Microsoft SideWinder 3D Pro driver (SW3DPRO.VXD Version 3.00.00) has timing loops that fail on systems faster than 66 MHz FSB. This causes the joystick to show "Not Connected" in the Game Devices control panel. The original fix (by Stewart Todd Morgan, sw3dp10.zip) provided 48 pre-patched driver variants that users had to test one by one.

This installer automates the entire process:

  1. Benchmarks your CPU speed using RDTSC (or multimedia timer fallback)
  2. Calculates the correct timing divisor via linear interpolation
  3. Patches the VXD binary with the right values
  4. Installs the patched driver with automatic backup
  5. Lets you verify the joystick works immediately

No more trial and error across 48 driver variants.

Requirements

  • Operating System: Windows 95, Windows 98, or Windows ME
  • CPU: Pentium 1 (233 MHz) through Athlon XP (2200+ MHz)
  • RAM: 16 MB minimum
  • Joystick: Microsoft SideWinder 3D Pro connected to the game port
  • Driver: SideWinder Software 3.02 installed (provides the original SW3DPRO.VXD)

Note: This tool does NOT work on Windows NT/2000/XP/Vista or later. VXD drivers are only supported on Windows 9x.

Usage

Quick Start

  1. Copy sw3dfix.exe to your Windows 9x machine
  2. Run sw3dfix.exe
  3. Click Next on the Welcome page
  4. Wait for the CPU speed benchmark to complete (~2 seconds)
  5. Review the recommended settings (divisor, timeout variant)
  6. Click Next to install the patched driver
  7. Click Test to verify the joystick works

Step-by-Step

1. Welcome

The installer checks that you're running Windows 9x and locates the original SW3DPRO.VXD in your \WINDOWS\SYSTEM directory. If the driver isn't found, you'll be prompted to browse for it.

2. Detect Speed

The installer measures your CPU speed using the RDTSC instruction (Pentium and newer). On older CPUs without RDTSC, it falls back to the Windows multimedia timer. The measurement takes about 2 seconds (3 samples, median selected).

3. Review Settings

You'll see:

  • Detected CPU speed (MHz)
  • Recommended divisor (124, calculated via linear interpolation)
  • Timeout variant (Standard or Extended)

For most users, the defaults are correct. Click Advanced if you want to:

  • Manually enter a divisor value (124)
  • Switch between standard and extended timeouts

Extended timeouts are automatically recommended for CPUs above 1500 MHz. They use 10x longer timeout values in certain timing loops, which helps on very fast systems but can slightly impact performance.

4. Install

The installer:

  1. Creates a backup (SW3DPRO.VXD.BAK) in your system directory
  2. Patches the driver to a temporary file
  3. Copies the patched driver to \WINDOWS\SYSTEM

If anything fails, the original driver is automatically restored.

5. Verify

Click Test to check if the joystick responds. You'll see live axis data (X, Y, throttle, hat switch) updating at 4+ Hz. If the joystick shows "Not Connected", try divisor values 1 above or 1 below the recommended value.

Restoring the Original Driver

If you need to undo the patch:

  1. Run sw3dfix.exe
  2. Use the Restore function from the interface
  3. The original SW3DPRO.VXD is restored from the .BAK file

You can also manually copy SW3DPRO.VXD.BAK back to SW3DPRO.VXD in your \WINDOWS\SYSTEM directory.

How the Divisor Calculation Works

The installer uses linear interpolation from tested reference points:

CPU Speed Divisor System Tested
233 MHz 24 Pentium MMX, 66 MHz FSB
800 MHz 22 Pentium III, 100 MHz FSB
933 MHz 21 Pentium III, 133 MHz FSB

Formula: divisor = 24 - ((speed_mhz - 233) × 3) / 700

The result is rounded to the nearest integer and clamped to [1, 24]. Higher CPU speeds get lower divisor values (faster timing loops need less delay).

Bit Count Parameter

Most divisor values use a bit count of 0x1E (30). Two special cases:

  • Divisor 6 → bit count 0x1C (28)
  • Divisor 8 → bit count 0x1D (29)

Timeout Variants

Setting Standard ("0") Extended ("99")
10 standard timeouts 300 (0x012C) 2973 (0x0B9D)
Timeout at 0x2636 1600 (0x0640) 15856 (0x3DF0)
Timeout at 0x2695 3000 (0x0BB8) 29730 (0x7422)
Timeout at 0x26B0 10 (0x0A) 99 (0x63)

Extended timeouts are ~10x the standard values. Use them only if the standard variant doesn't work on your system.

Building from Source

Prerequisites

To build a Windows 95/98/ME compatible binary, you need one of:

  • Docker (recommended — easiest, works on any OS)
  • Open Watcom V2 (native cross-compiler)
  • Microsoft Visual C++ 6.0 (native build on Windows)

Important: MinGW-w64 (brew install mingw-w64) produces binaries that require Windows XP or later. It will NOT work on Windows 9x due to api-ms-win-* DLL dependencies. Use it only for development/testing on modern Windows.

# Build the container image with Open Watcom
finch build -t sw3dfix-builder .

# Extract the Win9x-compatible EXE
mkdir -p build
finch run --rm -v $(pwd)/build:/out sw3dfix-builder

Output: build/sw3dfix.exe — runs on Windows 95/98/ME, no external dependencies.

Works with docker too — just replace finch with docker in the commands above.

Build with Open Watcom (manual)

# Download Open Watcom V2 from:
# https://github.com/open-watcom/open-watcom-v2/releases

# Set environment
export WATCOM=/path/to/watcom
export PATH=$WATCOM/binl64:$PATH

# Build
make win32

Output: build/win32/sw3dfix.exe

Build with MSVC 6.0

From a Visual Studio 6.0 command prompt on Windows:

nmake /f Makefile.msvc

Output: build\win32\sw3dfix.exe

Build with MinGW (development/testing only)

brew install mingw-w64
make mingw

Output: build/mingw/sw3dfix.exeruns on Windows XP+ only, not Win9x. Use for testing the UI on modern Windows.

Running Tests (Development Machine)

The pure logic modules (divisor.c, patcher.c) can be tested on any platform. Tests use the theft property-based testing library.

# Install theft library first, then:
make test

This builds and runs 10 property-based tests covering:

  • Divisor range invariant (always 124)
  • Divisor monotonicity (higher speed → lower divisor)
  • Bit count mapping completeness
  • Divisor validation correctness
  • Timeout recommendation threshold
  • Out-of-range speed warning
  • File size validation
  • Patch writes correct values
  • Patch frame condition (non-patched bytes preserved)
  • PatchConfig round-trip consistency

Project Structure

├── src/                       # Win32 installer EXE source (Open Watcom + MinGW)
│   ├── main.c                 # WinMain, PropertySheet wizard setup
│   ├── benchmark.c            # CPU speed measurement (RDTSC + fallback)
│   ├── divisor.c              # Divisor calculation, linear interpolation
│   ├── patcher.c              # VXD binary validation and patching
│   ├── installer.c            # Backup, install, restore operations
│   ├── joystick.c             # Joystick detection and live testing
│   ├── ui_pages.c             # Dialog procedures for wizard pages
│   └── platform.c             # OS version detection
├── include/
│   ├── app_state.h            # Application state struct
│   ├── benchmark.h            # Benchmark module interface
│   ├── compat.h               # Cross-platform type compatibility
│   ├── divisor.h              # Divisor calculator interface
│   ├── installer.h            # Installer module interface
│   ├── joystick.h             # Joystick verifier interface
│   ├── patcher.h              # Patcher module interface
│   └── platform.h             # Platform detection interface
├── res/
│   ├── resource.rc            # Dialog templates, icons, strings
│   └── resource.h             # Resource IDs
├── tests/                     # Host-side property tests (112/112 passing)
│   ├── test_divisor_props.c
│   ├── test_patcher_props.c
│   ├── test_benchmark.c
│   ├── test_installer.c
│   ├── test_joystick.c
│   ├── test_integration.c
│   ├── test_sw3dfix_install_path.c
│   ├── test_sw3dpro_pit.c
│   ├── test_sw3dpro_vjoyd.c
│   ├── test_sw_protocol.c
│   └── test_main.c            # Test runner entry point
├── vxd/                       # SW3DFIX replacement VxD (see vxd/README.md)
│   ├── sw3dpro.c              # PIT calibration, bit reader, VxD scaffolding
│   ├── sw3dpro_pit.c          # Pure-arithmetic loops/us helper
│   ├── sw3dpro_vjoyd.c        # VJOYD glue + JOYOEMPOLLDATA translator
│   ├── sw_protocol.c          # 3D Pro packet parser (host-testable)
│   ├── gen_lnk.sh             # wlink directive-file generator
│   ├── README.md
│   ├── DDK_SETUP.md
│   └── VALIDATION.md
├── ddk-headers/               # Vendored Win9x VxD toolchain headers
│   ├── jhdk/                  # JHRobotics' clean-room vmm.h shadow (MIT)
│   ├── fixlink/fixlink.c      # Post-link LE32 header patcher (MIT)
│   └── joyreg.h               # Clean-room Win9x joystick minidriver ABI
├── tools/                     # Host-side build helpers
│   └── analyze_vxd_le_header.py   # LE32 header validator
├── ddk-extract/inc/           # Microsoft Win9x DDK headers (extracted on demand
│                              # by ddk-extract.sh from WMEDDK.ZIP)
├── sw3dp10_extracted/         # Original 48 pre-patched drivers (reference)
├── Makefile                   # Open Watcom + MinGW + test build
├── Makefile.msvc              # MSVC 6.0 build (alternative)
├── Dockerfile                 # Docker build with Open Watcom (Win9x-compatible)
├── build.sh                   # One-stop wrapper around finch/docker build
├── ddk-extract.sh             # Extract Win9x DDK from WMEDDK.ZIP
└── README.md                  # This file

Troubleshooting

Problem Solution
"Not Connected" after patching Try divisor ±1 from the recommended value
Speed detection shows 0 MHz Your CPU may not support RDTSC; use manual divisor entry
"File is not the expected version" You need SW3DPRO.VXD from SideWinder Software 3.02 (exactly 12,346 bytes)
"VXD drivers not supported" You're running Windows NT/2000/XP — this tool is for Win9x only
Joystick works but is erratic Try the next higher divisor value, or switch to extended timeouts
All divisors fail Try extended timeout ("99") variants — your system may be too fast for standard timeouts

Credits

  • Original timing fix research: Stewart Todd Morgan (sw3dp10.zip, February 2008)
  • Vojtech Pavlik — Linux drivers/input/joystick/sidewinder.c (1998-2003), GPL-2.0-or-later
  • Jaroslav Hensl — JHRobotics vmm.h + fixlink (vmdisp9x), MIT
  • SideWinder community: Grendel and KoolBear at DescentBB.net

License

This software is provided "as is" without warranty. The patched driver is based on Microsoft's SW3DPRO.VXD Version 3.00.00 from the SideWinder Software 3.02 package. This tool automates the same binary patching process documented in the original sw3dp10.zip archive.