lo-tech Blog

CannonBall-SE: A CannonBall Fork focused on Experience

The first in a series of four posts covers a 12‑year journey to build a home-brew OutRun cab which feels, to me, like the arcade. Find this project, including a ready-to-run Windows build, on GitHub.

Some things from childhood just stick. The smell of an electronics shop. The lights and noise of an arcade on a wet winter afternoon. That feeling when you realise you’ve deleted your Dad’s work trying to install Doom on the family computer.

For me, playing OutRun (randomly, on the QE2) was such a thing. The colours, that sound track, and of course, the sense of speed; it was like nothing else at the time. I spent maybe an hour on it. But that shimmering start line, the haloed edges of palm trees in their shadows, and the difficulty seeing over the hill crests hold clear in my mind.

But memories aren’t always accurate. The way I think the game looked isn’t quite the way it really did. We didn’t have 4k graphics as a reference point. Our imagination did the HD upscaling through the haze.

When Chris White released his brilliant open-source re-implementation, CannonBall, the game was no longer locked inside the dusty arcade board in my “in-need-of-repair drawer”, the eternally enthusiastic start line crowd presumably awaiting another pound coin that would never come. It provided a way to test my memory against reality — and maybe to rebuild the version that lived in my head.


A Slow-Burn Side Project

It would need a cabinet and a wheel. A home-made bartop. I didn’t know it would take me 12 years, but I did know I’d never be happy looking at it on an LCD screen. So I set about modifying it and eventually ended up with this:

The goal was simple — make OutRun feel right, and have it running on a (new at the time) Raspberry Pi. The original arcade hardware used a high-quality RGB system, but even so the CRT screens blurred, blended and desaturated the image in a way that encouraged our minds to fill in the gaps. LCDs take that away, and we’re left with the stark reality of a 320×224 image. The challenge was capturing the feel of the arcade screen, without needing massive processing power.

A true back-burner project, picked up and put down over twelve years. Which gave time to stumble on bugs in the arcade code along the way. Did anyone ever notice that the game count-down and stage timers didn’t count seconds on the same basis I wonder.

What started as trying to modify the game to use the Blargg NTSC filter library, something I’d read about some years previous, soon became a deep dive into areas new to me: SDL, GLSL shaders, multi-threading, the intricacies of 1980s video signal handling, and latterly, 3D printing (of the cabinet dashboard).


Re-Capturing the Analogue Soul

Actually adding the NTSC filter produced immediately satisfying results. It also ran a 7fps. But the concept seemed like it should work, scenery suddenly looking more believable:

Viewed at close range, CRTs are full of dots caused by the shadow mask. It was obvious some kind of emulation was needed, but simulating the mask or adding scan lines just decimated brightness. At least the arrival of the Pi2 whilst I pondered had lifted the frame rate a bit.

Performance continued to trouble me. The Raspberry Pi could easily play full-screen video, but took ages to do basic tasks like compile anything. It’s because it’s mostly GPU, a small CPU strapped on the side almost as an afterthought. Video plays well because the tiny ARM core isn’t really involved.

So I needed to learn how to use the GPU – the subject of the next post. But I’d settled on my approach and felt it should be possible to get it all to run at 60fps. Oh, and acquired some wood.

Behind the cabinet plexiglass, the end result is surprisingly effective at creating the impression a real CRT is within, producing an image that feels closer to memory than to mathematics. In motion it’s even better, with the soft shimmer in the trees.

Zoomed in 5x, we can see what the processing is doing. The combination of filter to soften the image and non-linear mask overlay that preserves highlight brightness just kind-of works. Visuals sorted.


More than Video

OutRun wasn’t just about visuals — the music and sound are instantly recognisable to a anyone born in the 70s. My heavy video processing, though, left the music stuttering and laggy. So I’ve rewritten the audio engine to run smoothly even on the most basic Raspberry Pi boards, using threading to stay consistent under load. And added MP3 playback; who hasn’t wanted to race away from the line to A-ha’s Take On Me? The audio system will be the subject of a future post.

But the foundation remains Chris White’s truly outstanding work — a meticulous de-compilation of the original. CannonBall-SE builds on it, making what I wanted for my bartop. After twelve years, it finally feels right. Not exactly how it was, but how I remember it; perhaps the only version that really matters.

Coming Soon: CannonBall-SE: The Shaders.


If you’d like to try CannonBall-SE, you can grab the Windows executable and source from GitHub. Installing on RaspberryPi boards is super easy too — clone the repo and run ./install.sh, which automatically installs dependencies and compiles the game in about 5 minutes on a Pi3.

👉 https://github.com/J1mbo/CannonBall-SE

CannonBall-SE is a personal project that I hope will be of interest to vintage computing enthusiasts.

Important: CannonBall-SE is an open-source engine that requires original OutRun ROMs from a legally sourced PCB to function. This project is not affiliated with or endorsed by SEGA. OutRun is a registered trademark of SEGA. This software is provided for educational and preservation purposes only.

XMS Support Now Available for the Lo‑tech 2MB EMS Board

(Powered by the EXMS86 driver by Mateusz Viste)

I’m very pleased to share an update on the 2MB EMS board! I recently received an email from Mateusz Viste, explaining that he’d just finished a driver that provides XMS using an EMS card, and on XT-class machines – something I never imagined could be done since, as far as I know, no commercial product ever offered this, and the EMS/XMS years were full of frustration for many.

With EXMS86, software that depends on XMS memory can now run on classic systems like the IBM PC and XT,” writes Viste. And it just keeps getting better – “In addition to providing XMS support, EXMS86 can also repurpose your EMS page frame to create up to 64 KB of UMB, offering extra space to load TSRs and such”. Had this existed in 1989, it would have been a game‑changer!

Head over to EXMS86 (EMS-backed XMS) for details on how it works and to download the binaries an executable. I’ve also included a mirror of the downloads in the Lo-tech Wiki.

Yamaha C1 IDE Adapter

It’s been a while since a new Lo-tech product was released, but “we’re back” with a new PCB, this time for the Yamaha C1 Music Computer, which is a kind of laptop (powered by 110V mains only) that has 8 MIDI ports on the back. It’s a pretty rare machine but there are certain musicians out there that love this little box.

So here is the Lo-tech C1 Music Computer IDE Adapter:

This board differs from the other Lo-tech storage products because it’s a conventional 16-bit IDE interface – the C1 is an 80286 equipped machine. It replaces the MFM controller (if fitted) just under the keyboard and is coupled with a patched system ROM, which must be written out to a pair of 27C256 EPROMs to replace the stock system ROM. Once done and the board fitted, the machine will be able to boot right up from an attached ATA hard drive, CompactFlash card, or SD card via a suitable adapter.

Performance

This board is a full 16-bit IDE controller and as such the 12MHz 80286-based C1 will achieve 2MB/s from a CompactFlash card and up to about 100 IOPs.

Product Documentation

The Lo-tech Wiki has full product documentation and downloads, including the ROM images:

Lo-tech Yamaha C1 Music Computer IDE Adapter – Lo-tech Wiki

The ROM image is provided in two files, since the machine used two 8-bit ROM chips to create a 16-bit system ROM. Each ROM chip (IC39 and IC40) is a 32K 27C256. The patched version includes the XTIDE Universal BIOS (XUB) pre-configured for the card.

Please note that there are DIP switches within the C1 that need to be appropriately set and some jumpers on the card that must also be set correctly for this adapter to work. These are documented in the wiki.

Special Thanks

Special thanks are due to a number of people that have made this product possible.

VCFED user eeguru purchased and sent me the service manual.

Kevin @ TexElec managed to acquire and then ship me a working (and re-capped) C1 earlier this year to help get this board tested. Since the machine is 110V only, it’s never been available here in the UK as far as I know.

XUB developer Krille figured out the weird checksum algorithms Yamaha used in the BIOS. I have no idea how he managed to reverse engineer this, but his work completely cleared two years of deadlock in getting this board working.

And, as always, the many VCFED users that have helped with information about the machine and testing of early releases etc.

Availability

This board will be available to order as a fully assembled, finished product from TexElec here soon. These will be made to order due to the very small remaining userbase of these machines so the shipping times may vary.

Announcing Official Lo-tech Outlet: TexElec

TexElec – the Official Lo-tech Distributor

Lo-tech has now moved to a licensed distributor model, and it is with great pleasure that I can announce Kevin Williams, aka TexElec, as the official distribution partner!

TexElec’s online store can be found at texelec.com, and their eBay outlet here.

I’ve been working with Kevin for the last 18 months and this is a big step forward for Lo-tech. This distribution model gets the products closer to the end-user, since well over 50% of Lo-tech sales have been to the USA, and also means lower cost, more reliable supply than has been possible running Lo-tech as a hobby.

Please support Kevin – his work is of excellent quality and he has already fulfilled orders for hundreds of boards.

Raspberry Pi VGA HAT, 24-bit 1080p

lo-tech-vga-r01-banner

The Raspberry Pi uses HDMI for it’s built-in display interface, and it’s well documented that a second screen can be connected to the GPIO header when switched to ‘display parallel interface’ (DPI) mode. The DPI is powered from the Raspberry Pi’s GPU and so has the same performance and capabilities as the HDMI port – 1080p, 24-bit colour, 60Hz.

Project boards exist already to connect a VGA screen to the GPIO, but these are very simple designs and have some limitations such as 6-bit colour and sensitivity to interference from the wireless peripherals in the RPi 3. The RPi GPIO is also stressed by the TTL control signals in the VGA interface and the project boards lack the certifications needed to be offered as finished products.

The Lo-tech Raspberry Pi VGA Board aims to address these problems, providing a true-colour VGA Adapter in a ‘HAT’ PCB format that will provide a reliable VGA output for primary or secondary display purposes whilst protecting the RPi, both from ESD when the screen is connected hot and from over-stressing the GPIO outputs via buffering of the key control signals.

I’m excited to report that this board has just cleared EMC testing, meeting EN 55032:2015 Class B limits, and ESD testing, passing BS EN 61000-4-2:2009 level 4, and so can be pre-ordered today (first deliveries expected approx. February 2017).

vga-r01-slider

Graceful Shutdown with APC BackUPS HS 500

APC’s BackUPS HS 500 UPS has been around forever, as has it’s firmware. Still, a wall-mountable network connected UPS with three switchable outputs for less than £100 from one of the most reputable brands seems like a good deal to me.

backups-hs-500-banner

There are issues with this product though. The web interface doesn’t work on any recent browser and it’s also impossible to configure it without Windows 2000 (XP if you’re lucky). So graceful shutdown is a non-starter then.

Having suffered a few prolonged power-outages recently I thought perhaps it’s time this problem was solved. Fortunately, Anton Bagayev has posted on Github a script to control the outlets from Linux, using Curl to interact with it’s primitive web interface, and this can easily be adapted into a shutdown script – I’ve called this check-power and have it running via cron every minute. When the UPS is on battery and run-time goes to 13 minutes or less, it calls some other shutdown script as needed:

#!/bin/bash
# This script uses the web interface of the APC BackUPS HS-500 to check it's status, and
# calls some other script to effect a host shutdown, should the UPS be on battery and the
# runtime be less than 13 minutes.
# temp file for operational status - battery level etc
STATUS="/tmp/apc-500-status.tmp"
UPS="[ip-address-goes-here]"

# get output values from web-control
curl -sl "http://$UPS/status.cgi" | tr -dc '[:print:]\n' > $STATUS
# Extract the unit operating status fields - battery level etc
LOAD="$(cat $STATUS | grep -o '[0-9]* Watts' | grep -o '[0-9]*')"
BATTERYLEVEL="$(cat $STATUS | grep -o '[0-9]* %' | grep -o '[0-9]*')"
RUNTIME="$(cat $STATUS | grep -o '[0-9]* minutes' | grep -o '[0-9]*')"
BATTERYSTATUS="$(cat $STATUS | egrep -o 'Charged|Charging|Discharged|Discharging')"
UPSSTATUS="$(cat $STATUS | egrep -o 'On Line|On Battery' | sed 's/ / /g')"
LASTTEST="$(cat $STATUS | egrep -o 'Result of last self-test is:.*(Passed|Failed)</font>' | egrep -o '(Passed|Failed)')"
LASTTRANSFER="$(cat $STATUS | egrep -o 'No&nbsp;Transfer|Blackout' | sed 's/&nbsp;/ /g')"
# show active configuration
logger "UPS Status $UPSSTATUS, $RUNTIME minutes remaining (load: $LOAD Watts)"
if [ "$UPSSTATUS" == "On Battery" ]; then
 if [ $RUNTIME -le 13 ]; then
 logger "UPS Critical: $RUNTIME minutes remaining. Starting shutdown procedure."
 [call-shutdown-script-goes-here]
 fi
fi
# garbage collector
rm -f $STATUS

OK so now we can control it with Anton’s script – the three outputs are individually switchable – and monitor it with this script, but what about configuration? Firing up a Windows 2000 VM and grabbing some Wireshark captures from the supplied configuration utility (really APC?), this is pretty straightforward too. The utility interacts with the UPS via UDP broadcast with some special command codes to make it do things like set the IP.

With a bit of fiddling, this too can be scripted Linux with a few dependencies (arping, xxd, socat). I’ve called this apc500.sh, and it can set the IP address and name of the device from the Linux command line, and uses Anton’s apc.sh to show device status (which can be modified per the above script to add battery levels etc if required):

#!/bin/bash
# UPS Management script for APC 500 HS
#
# -f - to Find and show detail of the device
# -s - to Set the IP address of the device (0.0.0.0 for DHCP)
# -n - to set the Name of the device
# Command line parameters - what are we doing?
for i in "$@"
do
case $i in
 -f*|--find*)
 FUNCTION="FIND"
 ;;
 -s=*|--setip=*)
 FUNCTION="SETIP"
 IPADDRESS="${i#*=}"
 shift # past argument=value
 ;;
 -n=*|--setname=*)
 FUNCTION="SETNAME"
 NAME="${i#*=}"
 shift # past argument=value
 ;;
 *)
 # unknown option
 ;;
esac
done
if [ "$FUNCTION" = "FIND" ]; then
 # Find UPS via broadcast
 DATA="$(echo '11 50 00 A0 10 50 43 43' | xxd -r -p | socat - UDP4-DATAGRAM:255.255.255.255:9950,so-broadcast,sourceport=9951 | tr -dc '[:print:]\n')"
 MODEL=${DATA:9:15}
 SERIAL=${DATA:24:12}
 MACADD=${DATA:37:12}
 TMP=${MACADD,,}
 MACADDR=${TMP:0:2}:${TMP:2:2}:${TMP:4:2}:${TMP:6:2}:${TMP:8:2}:${TMP:10:2}
 TMP=${DATA:52}
 NAME=${TMP::-1}
 # And lookup the MAC from ARP cache
 IPADD="$(arp -an | grep "$MACADDR" | egrep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*')"
 # Likely, there was nothing there. Check, and use arping (needs root) if we need to
 case "$IPADD" in
 "") IPADD="$(arping "$MACADDR" -c 2 -i eth0 | egrep -o -m 1 '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | head -1)" ;;
 esac
# Print out the information
 echo Model: $MODEL
 echo Serial: $SERIAL
 echo Name: $NAME
 echo MAC Address: $MACADDR
# Now check again to see if we have an IP address. If we do, we can get run-time information, eg battery level etc
 case "$IPADD" in
 "")
 echo "IP Address: Not known"
 ;;
 *)
 echo "IP Address: $IPADD"
 ./apc.sh ip=$IPADD status
 esac
fi;
if [ "$FUNCTION" = "SETIP" ]; then
 # Work out IP in Hex
 IPDEC="$(echo "$IPADDRESS" | sed 's/\./ /g')"
 TMP="$(printf '%02x ' $IPDEC ; echo)"
 IPHEX=${TMP::-1}
 RESULT="$(echo '12 50 00 a0 98 05 45 43 f5 f4 34 f6 '"$IPHEX" | xxd -r -p | socat - UDP4-DATAGRAM:255.255.255.255:9950,so-broadcast | tr -dc '[:print:]\n')"
 case "$RESULT" in
 "") echo "UPS did not respond.";;
 *) echo "UPS acknowledged command."
 esac
fi;
if [ "$FUNCTION" = "SETNAME" ]; then
 TMP="$(echo "$NAME" | xxd -p )"
 NAMEHEX=${TMP::-2}
 RESULT="$(echo '12 50 00 a0 10 08 45 43 f5 '"$NAMEHEX"' 00' | xxd -r -p | socat - UDP4-DATAGRAM:255.255.255.255:9950,so-broadcast | tr -dc '[:print:]\n')"
 case "$RESULT" in
 "") echo "UPS did not respond.";;
 *) echo "UPS acknowledged command."
 esac
fi;
# End of script.

8-bit IDE Adapter rev.3

The Lo-tech 8-bit IDE adapter has been designed around a 3D-printed ISA slot bracket, the primary reason being to keep the card itself within a 100mm width, which helps keep the price down. Until now!

Announcing then the rev.3 board, which is now compatible with the Keystone 9202 ISA slot bracket, as available from the usual online electronics retailers such as Mouser.

8-bit-IDE-Adapter-rev-3-front

As well as the slightly larger PCB form factor, this version also includes another jumper (JP3) providing a choice of IO ports, either the default 300h or 320h.

The board keeps everything else the same – XTIDE Universal BIOS powered, 32KB Flash ROM, excellent IDE and SATA device compatibility, high-speed read and write performance, key-pin power for Disk On Module devices, and PC/XT Slot-8 compatibility (with option SMT components fitted).

The Lo-tech 8-bit IDE adapter is available in the store as a bare PCB now.

MIF-IPC-B rev.2

Back in Jul-15 I introduced the Lo-tech MIF-IPC-B, a clone of Roland’s MIF-IPC board that connects the legendary MPU-401 to the IBM PC. Unfortunately an error in the schematic in the address decoder meant the prototypes were effectively useless – but when does anything work first time?

So here at last is the Lo-tech MIF-IPC-B, rev.2 – hopefully with everything as it should be:

MIF-IPC-B-rev2

Full details on this board are available in the wiki now.

The first assembled units are with beta testers now and all being well, PCBs will be available within the next 4-6 weeks.

Best Ever ISA CompactFlash PCB

ISA-CompactFlash-Adapter-Banner

The Lo-tech ISA CompactFlash Board has been a consistent best seller since it’s launch back in 2013. Having been through a number of relatively minor revisions, I’m today pleased to announce availability of the best version yet!

Now formally rev.3 and made in the UK, the PCB features a thicker, 2.5µm gold card-edge connector for long-term durability as well as ENIG finish for easy soldering and bevelled edge.

ISA-CF-rev3

The design also includes ROM address selection, PC/XT slot-8 functionality with disable jumper, and more durable power supply for key-pin powered DoM and CompactFlash adapters with an optional 2.2uF tantalum capacitor at the header.

The SMT components on the back of the board remain optional, meaning this design is still the cheapest, easiest to assemble, fastest, and most compatible storage adapter for PC and PC/XT class hardware.

The ISA CompactFlash PCB is available in the site store now.

MIF-IPC-B

Finally a prototype of the new Lo-tech MIF-IPC-B board, a Roland MIF-IPC compatible adapter that combines the functionality of the original (multiple MPU-401 support) with the compatibility of the revised MIF-IPC-A board (for PC/AT systems). This board also has fully populated resource selector headers, for easier system integration.

MIF-IPC-B-Prototype

Unfortunately the DB-25 is 2mm to far away from the ISA bracket but apart from that it looks good. Next step is to get this to someone that will know what to do with it and what it should be doing – so it’s being sent to a top-secret lab in Maryland testing. Watch this space!