The standard PC joystick was an analog design that uses potentiometers to vary the rate of a capacitor's charge. Most console systems of the time used joysticks with pure digital switches. Before console emulators became popular with PCs, there were some historical hardware that could implement a digital, Atari-style joystick. This post will describe the methods used to implement them.
1. Amstrad PC-1512 & 1640
The Amstrad PC-1512 and PC-1640 supported a digital joystick, with a port built into the keyboard. The joystick directionals and fire buttons function just like keyboard keys, and send the following untranslated scancodes :
77 Fire 2
78 Fire 1
A program can read the raw scancode, but most typically use Int 16H to read a translated scancode. The Amstrad translates the joystick directions into the XT compatible numberpad cursor scancodes. Thus the joystick functions identically to the 2, 4, 6 & 8 keys on the numberpad, assuming the program is not trying to distinguish between the number pad cursor keys and the dedicated cursor keys with their raw scancodes. The buttons are not defined by the BIOS and are ignored until an assignment is given to them by writing to the systems' non-volatile RAM. As its name implies, this RAM will retain its contents even after the system is powered down. This provides for maximum configurability, because games commonly use the Spacebar, Enter/Return or even F1 as a fire key.
Amstrad connects pins 1-4 and 6-8. Pin 7 is normally unconnected on an Atari joystick, but Amstrad uses it as a second button. Amstrad CPC JY2 and JY3 joysticks function properly with this pin arrangement.
2. Covox Sound Master
The original Covox Sound Master has two DE-9 ports. Having viewed closeups of the PCBs of the board, I can give a fair analysis of how the joysticks work. The joystick lines for each joystick are connected to pullup resistors and then a 74HC365 line buffer, non-inverting. From the solder side of the board, there are lines connecting pins 1-5 and 8 & 9 to these buffers. Pin 9 is used on a Sega Master System controller as button 2, but it is unconnected on an Atari one-button controller. However, pin 6, which is the only button on an Atari controller, is unconnected on the Covox's PCB. Pin 5, which is unconnected on an Atari controller, is connected. This leads me to believe that Covox either sold its own joysticks or, more likely, connected pins 5 & 6 on the component side of the board. We cannot see underneath the plastic.
From the line buffers, the joystick inputs appear to be connected to the I/O pins of the AY8930. The AY8930 contains a pair of 8-bit I/O ports that can be set to input or output. The original SimCity has explicit support for Covox Sound Master Joysticks. It sets the I/O ports to input and reads the values of the pins. More information will have to wait until the project to clone the board has been completed.
3. The FTL Sound Adapter
This device was a parallel port dongle that output sound in the manner of a Covox Speech Thing and had a DE-9 port on the end of it. It was included in some releases of Dungeon Master for the IBM PC. PCB and schematic for the device can be found here :
As you can see, each joystick input is connected to one of the five status port lines. Four of those five inputs are also connected to a separate control port line. Here are the connections :
1 Up 15 1 (Strobe - Error)
2 Down 13 14 (Select - Line Feed)
3 Left 12 17 (Paper Out - Select Printer)
4 Right 10 (Acknowledge)
6 Fire 11 16 (Busy - Reset)
8 Ground 18
When a directional or button is pressed, a bit in the status port will flip to indicate that the direction has been pressed. As you can see, you cannot use more than a one button joystick by this method.
The control port lines, which are not intended to function as input lines, are connected to allow Dungeon Master to detect the presence of the FTL Sound Adapter. First, the game writes 0C to the control port and checks to see if bit 5 is a 0 on the status port. Then it writes 04 to the control port and checks to see if bit 5 is a 1 on the status port. If either check fails, the game will not allow the user to select the FTL Sound Adapter. Now recall how the DB-25 parallel port connector is wired :
Bit 7 6 5 4 3 2 1 0
Data Port Pin 9 8 7 6 5 4 3 2
Status Port Pin 11 10 12 13 15 NC NC NC
Control Port Pin NC NC NC NC 17 16 14 1
underlined = inverted input or output from value written
0C = 0000 0011
04 = 0000 0100
Now, bit 5 of the status port is connected to bit 1 of the control port, which inverts. If a 1 is written to bit 1 of the control port, then a 0 will appear at bit 5 of the status port. Conversely, if a 0 is written to bit 1 of the control port, then a 1 will appear at bit 5 of the status port.
Dungeon Master will attempt this check for every parallel port address reported by the BIOS. Once it has passed, then it will allow the user to select the FTL Sound Adapter and should allow the user to use the joystick plugged into the Sound Adapter. The adapter cannot actually verify if a joystick is connected, however, unless it asks the user to move the joystick around and press the button.
The PC version of Dungeon Master that came with the FTL Sound Adapter shows an Atari joystick plugged into the back of the Adapter. It says that the joystick port is the next best thing and the user can plug in any switch style joystick for easy game play. (The computer in the photo looks like a Tandy 1000 TL, SL or SL/2). However, the quick start guide only talks about analog joysticks and identifies the DE-9 port on the Sound Adapter as "Future expansion port". The sound functionality is adequately described in the quick start guide, but because the joystick isn't specifically mentioned, I wonder whether the game actually supports a digital joystick.
If it does, then it would read the joystick in parallel, with a 0 value on each bit of the status port, except for bit 7, which would be a 1, indicating that a directional or button was pressed.
4. The Dyna Blaster Adapter
The Dyna Blaster Adapter, on the other hand, is a truly working Atari parallel port joystick adapter. Dyna Blaster, a.k.a. Bomberman in the U.S. and Japan, was released for DOS only in Europe. Apparently it was a somewhat obscure release; it is not easy to find.
This adapter has two DE-9 ports and supports two Atari joysticks. Uniquely for a PC game, the dongle functions as the copy protection. The system requirements label on the box states that an Atari joystick is required, and without the joystick and the dongle you cannot make any selections on the main menu screen. Fortunately the dongle's function has been more or less reverse engineered. (There is also a crack available for the game to use the keyboard at the menu).
When the game starts up, it calls a subroutine that writes FF to the data port and then checks to see if bit 6 of the status port is 0. Then it writes 7F to the data port and then checks to see if bit 6 of the status port is 1. This sequence then loops 20 times for each parallel port the BIOS reports. In terms of bits, the patterns are
FF = 1111 1111
7F = 0111 1111
Therefore, data port bit 7 is connected to status port bit 6 because that is the only bit that is changing.
The second subroutine is called at the menu and when playing the game. It writes the following values to the data port twice :
3E = 0011 1110
3D = 0011 1101
3B = 0011 1011
37 = 0011 0111
2F = 0010 1111
The first time this data is written, bit 5 of the status port is checked after each write, and if 0, then a directional bit is set in the program's memory. The second time this data is written, bit 7 of the status port is checked after each write, and if 1, then a directional bit is set in the program's memory. Obviously, this corresponds to the first and second joysticks.
The bit pattern for the five values above gives us the key as to how each joystick is wired. The joystick is being read in a serial fashion. Instead of the status lines being connected to each switch, instead the common line of each joystick is connected to a single status bit. The low five bits of the data port are connected to the five switch lines of both joysticks. The data lines send logical 1s to everything but the joystick switch being queried. If the first joystick switch is pressed, a logical 0 will appear on status bit 5. If a second joystick switch is pressed, a logical 1 will appear on status bit 7 (which is inverted at the parallel port adapter)..
One last necessary observation is that data bit 6 is always a logical 1. I believe that this is to allow a pull-up resistor on status bit lines 5 & 7. According to this page, 4.7K resistors should be sufficient as a pull up resistor : http://arcadecontrols.com/arcade_tormod.html Otherwise, the program would have no way to determine whether a joystick switch has stopped being pressed. As a consequence of the pull-up resistor, when the joystick switch is no longer pressed, then the line will settle back to a logical one 1. Thus the FTL problem is solved.
While Bomberman does not use diagonals, what happens if a user pushes the stick in a way that closes two switches or pushes the button as he holds the joystick down? As the adapter can only test one joystick switch at a time, there will be a 0 and 1 (or two 1s if the diagnonal is pressed) coming down the status line. Fortunately, it is almost impossible to press two directionals and or the fire button exactly at the same time. The game, however, only cares about 0s on the first joystick port. Each time it reads the port, it is only reading for one direction. Presumably it will read the stick several times to make sure it finds the 0, if there is one.