Wednesday, July 4, 2018

Apple II 4serjoy - Gaming through the serial port




The 4Serjoy is a device that allows you to connect four digital joysticks to an Apple II computer using a serial port.

With the release of the 4Play card, the Apple II models now have a great option for multiplayer gaming using digital joysticks. But what about the poor ole Apple IIc, the slotless Apple II? Having a slotless Apple II is like having your arms and legs chopped off. It really limits the expandability of the machine. Any interaction with external devices is reduced to what you can put through the serial ports. Some IIc motherboard revisions allow special expansion cards but I'm talking about compatibility on all IIc systems. Not only did the IIc have to contend with not having any of the standard Apple II expansion slots but existing functionality, that a hacker would come to expect, was removed in the name of compactness. This includes the 16pin game port (which was more than just a dual analog joystick port) and the second joystick port which made way for the mouse interface.

So what options could there be for multiplayer joystick control on the IIc? Well, like I said, the interface is limited to the serial ports. I wondered how well games would perform if having the joystick control flow through this interface. Would it even be feasible to begin with? I did some rough calculations. The maximum time for the Apple II's analog paddle read to reach stability is just under three milliseconds and all the paddle/joystick reads are in parallel so that's still three milliseconds. Now for the serial port solution. At 9600 baud in a typical N81 setup, 8 data bits, 1 start bit and 1 stop bit results in a transfer rate of about 960 bytes per second or one byte every millisecond. Four joystick bytes should work out to four milliseconds. A baud rate of 19200 should yield a time of about two milliseconds for four joysticks bytes. The serial times seem like they are on par with the analog circuits. Therefore if the overheads are small I figured that this was certainly possible. That was enough for me to proceeded with the challenge. 



The hardware comprises of an ATmega1284P microcontroller, a breakout board and a "Serial TTL to Serial RS232" converter. For the software I started off by using an existing 4Play modified multiplayer game. Using an already converted 4Play game saved me time because the analog joystick/ keyboard handler to digital control was already done. I didn't have any four player games so the closest I could find was Mario Bros which is a two player game. The microcontroller can handle reading four joysticks but only two are currently hooked up. I threw together a simple assembly program to test the serial stream.



The way this device works is that it uses the microcontroller to read the digital signals from four joysticks (four direction positions and two fire buttons per joystick). This information is encoded into four bytes that is similar to the 4Play protocol. The four least significant bits are kept the same (direction signals), the two most significant bits are kept the same (two fire buttons) and the remaining two bits now encode the joystick number instead of the 4Play card identifier (bits 00: joystick 1, 01: joystick 2, 10: joystick 3 and 11:joystick 4). These four joystick status bytes are continually streamed to the Apple II via the serial port. Software running on the Apple II reads these values and replaces the existing direction commands that came from the game port / keyboard with the new digital signals.

The biggest issue with this setup is the need to modify the original software. The software needs to be modified to read the serial port instead of the game port or keyboard. This is a lot more work than modifying software to handle the 4Play card. Unlike the 4Play card which uses up less code then the original software (when hard coding the card's slot location ie not using the 4Play identification bits) the 4Serjoy needs to find space for 1. Serial port initiation (roughly 15 bytes), 2. Routine to read the serial port and store the joystick status bytes (roughly 25 bytes), 3. Storage of the joystick status bytes (4 bytes), 4. Call to the serial processing routine (roughly 20 bytes because there are multiple calls per loop) and then 5. As per the 4Play card you need to change the existing joystick/keyboard handler to use digital signals.



Apart form the usual great tools that I use to put together a project like this, having Hex Ray (a part of Nick's Virtu Apple II emulator) was a life saver. It allowed me to work out which parts of the Apple II memory were free to add in all the extra code that I needed for this game. Mario Bros is a resource hungry game so it wasn't easy to find available space.

Within the Mario Bros game there is a loop in which the joystick/keyboard handler gets called. When adding in the new call for the "check serial port" routine I found that every now and again the trigger button would not register. This seemed reasonable because there are four joystick status bytes to transport and checking one byte each loop means that a single joystick will only be read once every four loops. I added a second call to the loop however this did nothing to fix the trigger button issue. The problem was that the calls were too close to each other. By placing multiple calls within the loop and placing them further apart made all the difference. This means that joysticks 1 and 2 are being read every odd time through the loop and joysticks 3 and 4 every even time. This produced the game play that I was expecting.

My first lot of testing was using the default baud rate of 9600 but I wanted to know how the buad rate affected signal lag so I setup the system with baud rates 19200, 9600, 4800, 2400, 1200, 600 and 300. I had a preconceived idea that the game would not work below 9600 but I found that having baud rates between 19200 and 1200 did not change the game play enough for me to notice a difference. Maybe on a different game the lag would be more noticeable at the lower rates. Mario Bros is more of your "get the timing right" then a "test your reflexes" type of game. However the lag was obvious once 600 baud was used and 300 baud was even worse. What surprised me the most was that the lag was pretty bad at 300 baud but the game was still relatively playable. Using this baud rate I still managed to complete the first five levels without a problem. I could have continued playing the game further but the lag was annoying the crap out of me. This shows that the positioning of the code to read the serial port within the game loop is far more critical then the baud rate.

I built this device to full-fill the problem for the IIc but it will work just as well on an Apple II/II+/IIe (with a serial card) and the IIgs.

There are a few small changes I would need to make if I was to get this product up and running. These includes adding in the resistors to make it compatible with the Sega Genesis (Maga Drive) / Amiga CD32 type controllers and turning off the JTAG fuse on the microcontroller to free up port C which would then allow the connection with four joysticks instead of two.

Even though I don't see much of a demand for this device it answered a few of my questions and with surprising results. However on the rare chance that a landslide of multiplayer games becomes available for the Apple II then I know I'll be ready to go.

All the project files are contained here. https://docs.google.com/open?id=1m-IbGrzWqj3kRNCGpvAYJO-W6phvg0IZ

4 comments:

Dagen said...

I love your work. It is not falling on deaf ears. I've planned to add 4-play emulator support to GSplus for over a year, and I recently started on updating that section of code. It will happen. I think if we push for a few emus to support, and maybe do some more demos at places like KFest, there will be a few more titles with support. I doubt a "landslide" :) but one never knows.

This was a great idea for sure, using the serial port. Perhaps there could be a "universal" driver, even if it was bigger to accommodate both devices types. It may not easily work for all titles, but could be quickly patched into a lot of them.

Anyway, really cool stuff. Thanks!

sicklittlemonkey said...

Very cool!

In fact, this is perhaps the best solution because on machines with slots, no slot is "wasted"/dedicated to 4play - assuming everyone has a serial card. (Perhaps you should also develop a parallel version just in case! ; - )

I'm glad Virtu came in handy. I wish other emulators were as easy to add features like this to!

Cheers,
Nick.

Lukazi said...

Hi Guys,

Thanks for the support. I've followed both your work and it's great to see people pulling together and building stuff on top of each other's work to support the community. It's a great time to be in this hobby.

Cheers,
Alex.

Lukazi said...

I'm looking at ways in which I can change this solution to make it run through the game port. That could make it faster, more universal (be able to run on machines that don't have a serial card) and allow it to be powered directly off the Apple II.

Cheers,
Alex.