245 lines
13 KiB
Markdown
Executable File
245 lines
13 KiB
Markdown
Executable File
# Necroware's GamePort Adapter
|
|
|
|

|
|
|
|
Many people from the retro community still have their beloved joysticks and
|
|
gamepads from the early days. These devices often live their lives somewhere in
|
|
the dark corners of our basements and we don't dare to throw them away, because
|
|
of nostalgic reasons. They remind us so much of our childhoods, where we played
|
|
our Wing Commanders, X-Wings, Descents and many other games. These old joysticks
|
|
were all made to be connected to the game port, usually on a sound card. But
|
|
by the end of 90's and beginning of 2000's game ports vanished from our
|
|
computers and were replaced by USB and our old joysticks disappeared into the
|
|
past. Today not everybody has a full retro PC and many people are using their
|
|
modern computer with DOSBox to play the old games, sometimes with a modern
|
|
USB joystick. But wouldn't it be great to play the old games with the same
|
|
joystick which we used back then? And this is where this adapter comes into
|
|
play. It can be used to connect gameport joysticks to a USB port.
|
|
|
|
GamePort Adapter Videos:
|
|
* [Part 1: Introduction](https://youtu.be/tSJLgCD8jeM)
|
|
* [Part 2: Updates](https://youtu.be/947DewHwbsE)
|
|
|
|
## How does it work?
|
|
|
|
The adapter is built around Arduino Pro Micro, which uses the same ATmega32U4
|
|
microcontroller as Leonardo. This microcontroller has built-in USB HID
|
|
capabilities and can be used to build HID input devices, like joysticks. The
|
|
adapter itself is super simple, the main brainwork was invested into the
|
|
software. Very much simplified, it reads the joystick states and sends the data,
|
|
via USB, to the computer, which thinks that it is communicating with a USB
|
|
joystick.
|
|
|
|
## What is special about this one?
|
|
|
|
There are already plenty of gameport to USB adapters for basic analog joysticks
|
|
and, as far as I know, there were some efforts to communicate with Sidewinder
|
|
joysticks by Microsoft as well. But there is no universal adapter, which would
|
|
work with different types of joysticks. This adapter implements multiple drivers
|
|
for various analog and digital joysticks, with an option to add more, in the
|
|
future.
|
|
|
|
Features overview:
|
|
* Support for generic analog joysticks with 2/4 buttons and 2/4 axes
|
|
* Four switches to select joystick type
|
|
* Autodetection for various digital protocol joysticks
|
|
* Auto-Calibration
|
|
* Very low input lag
|
|
|
|
## What is the difference between analog and digital joystick?
|
|
|
|
Many people call button-only joysticks or gamepads digital. This is kind of
|
|
right, because a button is either pressed or not. You can't have an analog
|
|
values in between. However by digital, in this case, we mean something different.
|
|
A gameport contains 15 pins, 8 of which are used for joystick communication. 4
|
|
pins are for buttons and carry digital values in sense of on/off and 4 pins are
|
|
for analog axes, which deliver voltage somewhere between 0V and 5V. Joysticks
|
|
which were made in the early days used this pinout. They could have a
|
|
maximum of 4 buttons and 4 axes and were DOS compatible. Later, in the time of
|
|
Windows 95/98 many joysticks were made to be plugged into a gameport as well,
|
|
but they were not limited to 4 buttons and 4 axes. They had a lot more exciting
|
|
features, like hat switches and throttle controls. But how did this work? Well
|
|
the manufacturers implemented their drivers to communicate with the joystick via
|
|
gameport using a proprietary communication protocol. For example, by using one
|
|
pin of the gameport as clock and another one as data, the possibilities were
|
|
almost limitless. Such joysticks are called digital as well, because they used
|
|
digital protocols to communicate with the PC. And suddenly, many features were
|
|
possible, but the price of these features was the lost compatibility to DOS. You
|
|
couldn't just plug such a joystick into the gameport and expect it to work in
|
|
old DOS games. The plug was the same, but the signaling was completely different.
|
|
|
|
## Which joysticks does this adapter support?
|
|
|
|
Currently, the following drivers are implemented. To select the right driver, you
|
|
have to use four switches, as shown in the table. The switches may be changed or
|
|
extended in the future, so please pay attention to the updates.
|
|
|
|
Joystick Model | Buttons | Axes | Hat | SW1-4 | Protocol | Comments
|
|
-----------------------------|---------|-------|------|-------|------------|------------------------------------
|
|
Generic Analog | 2 | 2 | 0 | 0000 | Analogue |
|
|
Generic Analog | 4 | 2 | 0 | 1000 | Analogue |
|
|
Generic Analog | 4 | 3 | 0 | 0100 | Analogue | 3rd Axis is throttle
|
|
Generic Analog | 4 | 4 | 0 | 1100 | Analogue |
|
|
CH FlightStick | 4 | 4 | 1 | 0010 | Analogue |
|
|
CH F16 Combat Stick | 10 | 3 | 1 | 0110 | Analogue |
|
|
ThrustMaster | 4 | 3 | 1 | 1010 | Analogue | FCS MARK I/II & PFCS
|
|
Sidewinder GamePad | 10 | 2 | 0 | 1110 | Sidewinder |
|
|
Sidewinder 3D Pro | 8 | 4 | 1 | 1110 | Sidewinder |
|
|
Sidewinder 3D Pro Plus | 9 | 4 | 1 | 1110 | Sidewinder | First version of Precision Pro
|
|
Sidewinder Precision Pro | 9 | 4 | 1 | 1110 | Sidewinder |
|
|
Sidewinder FFB Pro | 9 | 4 | 1 | 1110 | Sidewinder | FFB not yet implemented
|
|
Sidewinder FFB Wheel | 8 | 3 | 0 | 1110 | Sidewinder | FFB not yet implemented
|
|
Gravis GamePad Pro | 10 | 2 | 0 | 0001 | GrIP |
|
|
Logitech WingMan Extreme | 6 | 3 | 1 | 1001 | ADI |
|
|
Logitech CyberMan 2 | 8 | 6 | 0 | 1001 | ADI |
|
|
Logitech WingMan Interceptor | 9 | 3 | 3 | 1001 | ADI | 2 hats are mapped as 4 axes
|
|
Logitech ThunderPad Digital | 8 | 2 | 0 | 1001 | ADI | Directional buttons mapped as 2 axes
|
|
Logitech WingMan Gamepad | 11 | 2 | 0 | 1001 | ADI | Directional buttons mapped as 2 axes
|
|
Logitech WingMan Light | 2 | 2 | 0 | 0000 | Analogue |
|
|
|
|
*Remarks:*
|
|
|
|
- Please pay attention to how the same switches are used for different families
|
|
of digital devices. This is possible due to fully digital communication. Using
|
|
this method, the adapter implements autodetection as soon as it knows, that it
|
|
is connected to a digital joystick.
|
|
- Currently, only the drivers for the listed Sidewinder devices are implemented,
|
|
since I have no other models at hand. The Precision Pro works natively on USB
|
|
as well, but was still implemented, because we can.
|
|
- Gravis used their GrIP protocol, which is currently implemented only for the
|
|
Gravis GamePad Pro, but without daisy chaining possibility so far.
|
|
- The implementation of the ADI protocol used by Logitech should work with all
|
|
the devices which support that protocol. However only the listed Logitech devices
|
|
were tested so far.
|
|
|
|
## Which joysticks were tested?
|
|
|
|
Many joysticks in the wild are using the same digital protocol or are backwards
|
|
compatible to the analog joysticks as they were used back in the days in DOS.
|
|
Following list contains all the devices which were reported by others as working
|
|
so far:
|
|
|
|
* CH Mach I+ (analog, 2-axes, 2-buttons)
|
|
* Gravis Analog Pro (analog)
|
|
* Gravis GamePad Pro
|
|
* Gravis PC GamePad (analog)
|
|
* InterAct UltraRacer PC (analog)
|
|
* Logitech CyberMan 2
|
|
* Logitech WingMan Extreme Digital
|
|
* Logitech WingMan Interceptor
|
|
* Logitech WingMan Light
|
|
* Logitech ThunderPad Digital
|
|
* Logitech WingMan Gamepad
|
|
* Medion Joypad MD9823 (analog, 4-axes, 4-buttons)
|
|
* QuickShot QS-123E "Warrior 5" (analog)
|
|
* Quickshot QS-146 "Intruder 5" (analog)
|
|
* Quickshot QS-151 "Aviator" (analog)
|
|
* QuickShot QS-201 "Super Warrior" (analog)
|
|
* QuickShot QS-203 "Avenger" (analog)
|
|
* Sidewinder 3D Pro
|
|
* Sidewinder 3D Pro Plus
|
|
* Sidewinder ForceFeedBack Pro
|
|
* Sidewinder ForceFeedBack Wheel
|
|
* Sidewinder GamePad
|
|
* Sidewinder Precision Pro
|
|
|
|
Sidewinder 3D Pro can be switched between analog and digital mode and in analog
|
|
mode it can emulate the ThrustMaster and CH FlightStick. That's why you see them in
|
|
the table above. Unfortunately I don't possess those joysticks in reality, so it may
|
|
be that the implementation is not quite correct.
|
|
|
|
## What is auto calibration?
|
|
|
|
Old analog joysticks have resistors inside, which are specified to be 100 kOhm.
|
|
Unfortunately, these resistors are either worn out, bad quality or were wrong from
|
|
the beginning. Therefore most of the generic analog joysticks had adjustment
|
|
screws to correct the center point of the joystick. Also many games had
|
|
calibration options in their settings to readjust the joystick. With USB and new
|
|
digital solutions the calibration was not required anymore and was completely
|
|
implemented in the joysticks and/or drivers. Many modern games have no option
|
|
to re-calibrate the joystick anymore. If we try to play such newer games with
|
|
an old analog joystick through this adapter, the joystick center point would be
|
|
totally offset. That's why the adapter implements auto calibration internally and
|
|
presents already corrected values to the operation system.
|
|
|
|
__ATTENTION__: a hard requirement for using the analog joysticks is that during
|
|
plugging into the USB port all axes must be in their middle state, because all
|
|
the subsequent calibration happens based on the initial state.
|
|
|
|
## Technical insights into implementation
|
|
|
|
The code is well documented, so if you are interested in the details, feel free
|
|
to take a look into the driver implementation. All the analog joysticks were
|
|
actually a straight forward task, but the Sidewinder digital protocol was kind
|
|
of tough. There are already some implementations of Sidewinder protocol made for
|
|
Arduino. However, they are mostly only for the Sidewinder GamePad and not really
|
|
universally made. In the end I was heavily inspired by the Linux Sidewinder
|
|
driver implementation. The code you can see in this project is a complete rewrite,
|
|
I just took the Linux driver implementation as a reference to understand how it
|
|
works. Also the Sidewinder patent US#5628686A helped a lot, especially with
|
|
switching between digital and analog mode for Sidewinder 3D Pro.
|
|
|
|
In opposition to the already mentioned Sidewinder for Arduino implementations,
|
|
this one doesn't rely on interrupts. This implementation is from a similar idea
|
|
to what the Linux driver does. It polls the port and makes a lot of things
|
|
simpler due to synchronous process. The biggest problem was that the Sidwinder
|
|
devices send the data incredibly fast, with a clock pulse of only 5us. It was
|
|
not possible to use Arduino's digitalRead(...) function for that. It was too
|
|
slow with about 2.7us per call on an Arduino Pro Micro of 16MHz. It simply
|
|
made it impossible to poll 5us pulses, with such a slow function, not even
|
|
considering doing something with the data in between. So out of that need, my
|
|
own implementation came about, which is up to 50% faster and needs only about
|
|
1.6us per call, on the same hardware. The custom I/O functions made it possible
|
|
to read the data with the speed which a Sidewinder joystick requires. The best
|
|
part is that the code is written in pure C++. It is very simple to read and to
|
|
use. There are no macros, no assembler or any dirty hacks, just a lot of
|
|
optimization.
|
|
|
|
## Bill of materials (BOM)
|
|
|
|
The hardware is super simple. To build an adapter you'll need the PCB from this
|
|
project and following parts:
|
|
|
|
Part | Qty | [LCSC](https://lcsc.com/) # | [Digikey](https://www.digikey.com/) # | [Mouser Electronics](https://www.mouser.com/) # | Comment
|
|
--------|-------|---------|--------------------------|----------------------|------------------------------------------
|
|
CONN1 | 1 | C77835 | 609-5371-ND | 523-L77SDA15SA4CH4F | DB15 female connector
|
|
R1..R4 | 4 | C172965 | 13-MFR-25FTE52-100KCT-ND | 603-MFR-25FTE52-100K | 100 kOhm resistors
|
|
SW1 | 1 | C15781 | 2449-KG04ET-ND | 642-DS04T | DIP-4 switch
|
|
U1 | 1 | C72120 | ED3051-5-ND | 649-DILB24P-223TLF | DIP24 Socket (optional)
|
|
U1 | 1 | N/A | 1568-1060-ND | 474-DEV-12640 | Arduino Pro Micro (ATmega32U4 16MHz, 5V), including two 12 pin header connectors, MicroUSB version (see "Known issues")
|
|
|
|
## Known issues
|
|
|
|
* *Some axes on an analog joystick are offset*
|
|
|
|
Auto calibration requires all the axes to be in the center position during
|
|
initialization. Please see the paragraph about auto calibration.
|
|
|
|
* *Joystick doesn't work*
|
|
|
|
Make sure that you are using one of supported joysticks or a joystick which can
|
|
work in legacy analog mode
|
|
|
|
* *MicroUSB port on the Arduino is not stable enough*
|
|
|
|
Use the USB-C version of the Arduino instead.
|
|
Or always keep the MicroUSB cable attached to the Arduino MicroUSB version to avoid further wear and apply plug/unplug operations only on the remote side of the cable.
|
|
|
|
## How to help the project?
|
|
|
|
The best way is to implement more drivers. Since I have only the joysticks
|
|
mentioned above, I can't contribute more than what is currently included.
|
|
|
|
## Special thanks
|
|
|
|
I would like to give some special thanks to *Creopard* from the German
|
|
dosreloaded.de community for providing me the mentioned joysticks. Without that
|
|
donation this project wouldn't be possible. Especially dealing with Sidewinder
|
|
3D Pro was a very exciting task.
|
|
|
|
## Links
|
|
* [Linux Sidewinder Driver](https://github.com/torvalds/linux/blob/master/drivers/input/joystick/sidewinder.c)
|
|
* [Sidewinder patent](https://patents.google.com/patent/US5628686A/en)
|
|
* [Creopard Retro Site](https://www.creopard.de/)
|
|
|