Inspiration

We owe this idea to David from NotBinary. The concept was quite simple - to control a running arcade machine from the comfort of one's couch via laptop or mobile device. The spice came with the wealth of different aspects David wanted to see like Serverless Functions, Mobile Friendly website control or TLS security. This made us come up with many different crazy control mechanisms until we settled on a flexible, modern approach.

What it does

The rundown

WeCameForFreebies (aka RoyalArcade, aka ComfyArcade) uses automated processes to find, register and launch ROM games that are installed on the local MAME emulator. There exists convenient access via a web interface that adapts to mobile as well as desktop and laptop screens.

The techy insides

The core of the project is the NodeJS server running on our hardware. The entire OS is wired to boot into single-user mode upon which it starts the preconfigured Node runtime. When it launches it first checks the local install directory for MAME ROM files. From that the server compiles a list of all playable (and hence callable) games.These are reported to our GCP Functions via a POST request. GCP registers this device as active and available then.

To receive commands the device needs to double reverse shell out of the current internet connection (CampusNet) and into our "reverse shell" VM, also hosted on GCP. This is because to start a game we pass it POST requests to the port that Node listens on - 8000. The user can now load our website via www.wecameforfreebies.com on any device and is presented with a responsive design website that will adapt to the screen size used. On said site are buttons that are loaded dynamically via more GCP Functions based on which games were reported as available on the DragonBoard.

Pressing any such button will then send a launch request directly to the device (via the tunnel VM due to router restrictions) and it will proceed to open a MAME instance with the specified game. This is a fantastic solution when sitting away from the device it to avoid having to get up and manually type in commands / select a new ROM when they can be available the tip of a finger via a smartphone.

Running games can also be 'overridden' via subsequent launch requests that prompt the server to close all currently running MAME instances to close and open the new session. This was a point of contention and with more time we'd have made this behaviour user-defined (e.g. via a config file).

How we built it

We screamed. A lot. Mostly at Debian network configurations and automatic change rollbacks.

The emulator is based on the Qualcomm DragonBoard 410C as an abstraction to any other hardware layer running our NodeJS server. The local server controls the game library, emulator and handles information exchange with the Cloud platform. We chose to have an IoT/Embedded/Low-Power device act as our server to emulate actually having a Retro Box (something akin to a RetroPi perhaps) that we could model and design our system against. It also has further advantages: With proper peripherals connected, the system could be used as a standalone media emulator as it is right now. With some more work (e.g. casing, etc) it could even be made to resemble a true arcade machine.

GCP is used to provide Cloud Functions, Web Storage and a Reverse Shell VM. The lambda functions act as information exchange points between the website and the IoT device which can communicate asynchronously to automatically adapt to new games being added or old ones being removed. GCP was chosen as a backend due to the ability to create new functionality with the click of a button (and a few lines of code). It acts as our central exchange between the device, "mobile" users and the website. Every piece of information sent and received runs over GCP.

Challenges we ran into

Hey, have you ever tried running Debian on an Arm64-based CPU? Half your packages don't work or are outdated.

sudo apt install node
node --version

^ This for example results in beautiful versions like 6.5.0.

sudo apt install npm
npm --version

And thiiiiis thinks it should be v1.6. Natively. Not fun.

One of the biggest issues we had to tackle early on was the absolutely abhorrent management of anything JS/Node/NPM related under Debian. This eventually lead to us writing a nuking script that would manually eradicate every last trace of Node or npm on the system and allow for a clean install from the beginning. We even had to manually pull in and install the latest version of Node as it wasn't represented in the apt repositories (yet).

  • Everything to do with internet
  • Everything to do with reserve ssh tunnelling
  • Everything that carries the name "Debian"

Our biggest challenge arguably was to get POST requests back to the device once it's online. But we couldn't do that in any standard fashion as this is blocked by the local CampusNet. So we had to get creative. With some external help, some 100 forum posts and 8 hours of nerve-wrecking custom systemd service-writing later and we had a reserve ssh tunnel between our Dragon and the VM running on GCP. From there we had to get the endpoints right - Yikes.

Accomplishments that we're proud of

  • The damn double reverse SSH tunnel we custom built using a VM instance in the cloud to provide a public facing IP and POST request ingest point.
  • Serverless solution
  • Fully powered by restful API
  • POSTs designed so would be easy to extend to other iot devices such as voice control
  • Dynamically built website from games reported as available by the arcade device

What we learned

  • Do NOT ever use Debian in your life.
  • If a problem MIGHT have a simple solution, it most likely HAS a simple solution.

What's next for WeCameForFreebies

Win big prizes. Go home. Sleep.

Built With

Share this project:

Updates