Note
This post is a work in progress, and is being published now to give an idea of the complexity of this setup for anyone interested in recreating it for their own purposes. Any part or all of this page is subject to change. Contact the e-mail address at the bottom of this page to send feedback.
One of my favorite things is showing off unfamiliar video games to people, and one of the most efficient ways to do that is a mystery games tournament. I've played in, observed, and organized a fair number of mystery tournaments over the last decade and gathered a lot of intel on what to do and not to do when running one, and my highest priority is fast and efficient game changing to keep the participants engaged. This entails doing everything possible to minimize the burden on players, including configuring games in advance, providing controllers, and making sure the players know what the controls are so they don't accidentally do something like exit the game.
This post describes the current hardware setup I use to run events. It is a somewhat complex tutorial and makes many assumptions of the reader's level of technical know-how, as many common processes like setting up a Raspberry Pi are omitted or greatly simplified for readabiilty. I created this setup to run mystery games, but I wrote this guide as generally as I could reasonbly make it for anyone interested in building a PC for use in a public location with multiple games that can be changed at any time. Games are played on a dedicated Windows PC—my previous gaming PC that was sitting in storage complete with old graphics card—and a Raspberry Pi 3 configured to run as digital signage. NFC is used for launching games, specifically a deck of NFC cards and a common USB NFC reader[a]. The open-source solution Zaparoo is used to manage cards and launching games. This setup is completely self-contained and designed to be portable, with no internet access. The PC will communicate to the Raspberry Pi digital signage with a direct ethernet cable connection.
Aside
Since the games are kept a mystery from the players until they play, I use unmarked NFC cards and a card reader and have the players choose. You are free to present the cards any way you choose. See the Zaparoo documentation for advice on this.
The PC is a kiosk optimized for visual presentation. It has only game controllers and an NFC card reader accessible to the players, with no keyboard or mouse or any other inputs available, and the desktop has no icons or taskbar visible. When a card is inserted into the reader, the PC will launch a batch file. The batch file will, in order, send a request to the Raspberry Pi to change the image it displays to one that corresponds to the game, change the wallpaper on the PC to show a loading message, and then launch the game.
Requirements
- PC with games installed and pre-configured, with an ethernet port
- NFC reader and tags compatible with Zaparoo
- I use NTAG215 cards and this PN532-based USB reader.
- (Recommended) An enclosure for the NFC reader to secure the tags and prevent accidental removal
- I use a 3D printed enclosure but the files for it have since been deleted by the author.
- Raspberry Pi (any model, preferably one with integrated HDMI and ethernet ports)
- Secondary monitor and requisite cables
- Files in this GitHub repository
PC Setup, Part 1
The PC that will run the games in the public location will be referred to as the "kiosk PC" for the rest of this post. Ideally, it should run a version of Windows with access to the Group Policy Editor, to minimize or eliminate disruptions from Windows Update.
This section assumes you have set up and configured the games you plan on running.
Create a folder named "bat" on the desktop. Download update.py and wallpaper.py from the above repository and place them in the bat folder.
Required Software
Install these programs before continuing:
- Zaparoo Core, Windows version 2.4.0 or later. The mobile app is not required, as this setup will use mappings based on the NFC tags' UIDs and not do any other reading or writing to the tags themselves. Ensure Zaparoo Core is set to launch on startup.
- NirCmd - Go to the bottom of the page and download the appropriate version (almost certainly the 64-bit build). Unzip the download, open nircmd.exe and click on the button to Copy to Windows Directory.
- The latest version of Python 3
- An SFTP or SCP client - I prefer WinSCP
- The Raspberry Pi Imager or some other means to flash Raspberry Pi OS to microSD (can be done on another networked PC)
The documentation for Zaparoo Core notes that support for Windows is limited, and therefore has instructions for configuring it to launch executables. For security reasons, Zaparoo Core enforces a whitelist for programs. Rather than whitelist every individual game you plan on running, it is recommended to write batch files in an easily accessible location and whitelist those.
Furthermore, when a batch file is launched, it opens a Command Prompt window, which I find unsightly. Presentation is a priority for this project, so I want there to be as little visual disruption as possible too. As a workaround, I use NirCmd to launch the batch file without showing a window. Keeping the display unobstructed also allows for a custom image to be shown immediately before the game starts, which will be covered later.
This setup will use an NFC card reader that will read a tag and launch a game that corresponds to the mapping of that tag's UID, and then close the game when the tag is removed from the reader. To do this, two settings need to be changed in the Zaparoo Core configuration. In version 2.4.0, the config file can be opened quickly from Zaparoo Core by right-clicking its tray icon and choosing Edit Config.
For simplicity, I create a folder on the Desktop for batch files, named "bat", and add all .bat files to the whitelist. The batch files will create another batch file named "exit.bat" that will close the game when the tag is removed.
In config.toml, change the [readers.scan]
section to set the reader to "hold" mode and specify an on_remove
action, and set the allow_file
option in [launchers]
to allow NirCmd:
[readers.scan]
mode = 'hold'
on_remove = 'C:\Windows\nircmd.exe exec hide %USERPROFILE%\Desktop\bat\exit.bat'
[launchers]
allow_file = [
'C:\\Windows\\nircmd.exe'
]
allow_file
expects regular expressions, so the double-backslashes are required.
Warning
Whitelisting a single program capable of launching other programs effectively whitelists every executable. With that said, this is for an isolated kiosk setup that should present limited risk if it is compromised this way. If this security hazard is unacceptable, change allow_file
to 'C:\\Users\\user\Desktop\\bat\\.+.bat'
, changing the directory as needed for the username. This will result in Command Prompts being opened when a tag is inserted or removed, so any custom loading backgrounds will be obscured and the user experience will be slightly worse because of it.
Creating the Batch Files
I place all batch files in a folder named "bat" on the desktop. A sample batch file is included in the GitHub repository for this post. Edit it to suit the game's requirements and save it to the bat folder. At minimum, you'll need to edit line 6 with the game's name, line 15 with the name of the executable of the game, and the end of the batch file with the commands to launch the game.
For some programs, such as certain emulators, you may need to change the working directory to the program's own directory with a cd
command before launching the game.
The sample batch file will use NirCmd to move the mouse cursor to the corner, hiding it, and prevent the taskbar from appearing at all. If you need to show the taskbar, open the Run dialog with Win + R and run nircmd win show class Shell_TrayWnd
.
Advice for Configuring Games
MAME
Most of the games in my own setup are emulated games with command line arugments to load a save state. For example, MAME would be launched with the following at the bottom of the batch file:
cd C:\Games\MAME\
mame.exe sf2ce -state 1
and line 15 the sample batch file would be changed to:
echo taskkill /f /im mame.exe
Even after launching a game in MAME with a save state in the command line, any warnings about imperfect emulation will display and must be dismissed with a button input. If the save state is on a character select screen, pressing a button to close the message may pass that input to the game and accidentally select a character. To avoid this, if the game has such a warning, create the save state on the title screen instead and have the players press their Start buttons to begin.
Emulators With Configuration File Overrides in Command Line
Some emulators, such as BizHawk and Dolphin, allow for different configurations to be used from the command line. I use this to override controller mappings for games that don't support in-game controller remapping. For console games, I recommend remapping controls such that the button to confirm selections is in a consistent place wherever possible, or indicate which button is used to confirm selections in your instructions pages for the digital sign.
Other
Some of my games are old PC games that either lack or have poor joystick support. For these, I use AntiMicroX to simulate keyboard input with controllers. AntiMicroX needs to be launched alongside the game with an autoloaded profile and closed along with the game. To launch AntiMicroX, add this line before the game:
start /min antimicrox.exe
and add to the taskkill
command:
echo taskkill /f /im game.exe
echo taskkill /f /im antimicrox.exe
Programming the NFC Tags
The traditional Zaparoo setup writes a line of ZapScript in the tags containing a path to a game. For this setup, each card would be given the path to a batch file, and reading the tag would launch that batch file. An alternative to this setup, and my preference, is to instead use mapping files on the PC that contain the UID of the tag and the ZapScript that it would launch. I prefer using mapping files as in my experience, Zaparoo Core on Windows is not able to write to cards with the NFC reader I use, but it can retrieve IDs with the web UI that can be copied to mapping files, so no external devices are needed.
- Open the web UI by right-clicking on the Zaparoo Core tray icon and selecting Open.
- In the Scan tab, scan a tag, and note the updated timestamp and the ID that appears.
- Open the mappings directory by right-clicking on the Zaparoo Core tray icon and selecting Mappings.
- Create a new .toml file in this directory with the following:
[[mappings.entry]]
token_key = 'id'
match_pattern = 'ID reported in the web UI'
zapscript = 'C:\Windows\nircmd.exe exec hide C:\path\to\batch\file.bat'
If you are not using NirCmd to launch the batch files due to the aforementioned security concern, set the zapscript
to just the path to the batch file.
[[mappings.entry]]
token_key = 'id'
match_pattern = 'ID reported in the web UI'
zapscript = 'C:\path\to\batch\file.bat'
- Repeat with each tag, then reload the config by right-clicking on the Zaparoo Core tray icon and selecting Reload.
Creating Loading Backgrounds (Optional)
On the desktop, create a folder named "wallpapers". In this folder, put a default background named "000" in an appropriate format (JPG or PNG). You can place any number of other wallpapers that will be randomly selected and replace the default background, acting as loading messages. Ensure they have names that will be sorted after "000" alphabetically.
As an example, my own setup contains an static image named 000.png, and the loading images are sequentially numbered and consist of text written over the same imge, with messages such as "GET READY" and "GOOD LUCK" and "ONLY ONE WILL WIN".
This step is handled by wallpaper.py. Open it and edit line 20 to the path of the wallpapers folder, with double backslashes, if necessary.
Raspberry Pi Setup, Part 1
This setup will use the standard Raspberry Pi OS with desktop environment. Install it with the Raspberry Pi Imager or your alternative imager of choice. The rest of this section assumes the default username pi
, and Bookworm is the installed version of Raspberry Pi OS.
The Raspberry Pi will be connected to its own dedicated display. For setup, it will need an internet connection to download updates and other software, but once deployed, it will be connected by ethernet to the PC and have no internet access. The media player mpv will be used to show the media in the directory /home/pi/Pictures/idle
while no game is loaded. When a game is loaded, a matching image file in the directory /home/pi/Pictures/games
will replace it, until the game is unloaded. Updating the images will require remote access, either in a local network or on the kiosk PC using SCP or SFTP via SSH. Samba network shares is another option, but it is outside the scope of this guide.
Set the Raspberry Pi OS installation up to your preferences, and for convenience later, set the hostname to sign
if you're using the Raspberry Pi Imager. (If not, change the hostname later in raspi-config
.) Additionally set up networking on your local network, enable SSH access, update the OS with apt update && apt upgrade
, and enable autologin to the desktop of the default user. The steps to do this are outside the scope of this guide, as the exact process is subject to change over time as Raspberry Pi OS evolves.
Next, install mpv and create directories:
sudo apt install mpv lua-socket
mkdir /home/pi/.config/mpv
mkdir /home/pi/.config/mpv/scripts
mkdir /home/pi/Pictures/idle
mkdir /home/pi/Pictures/games
Download the latest version of simple-mpv-webui (version 3.0.0 as of July 2025) and extract its contents to /home/pi/.config/mpv/scripts
.
Create the file /home/pi/.config/mpv/mpv.conf
with the following contents:
fs=yes
idle=yes
image-display-duration=60
loop-playlist=inf
osc=no
osd-level=0
shuffle
script-opts=webui-collections=/home/pi/Pictures/idle;/home/pi/Pictures/games,webui-osd_logging=no
Change the image-display-duration
value if desired, and remove the shuffle
line if you don't want the idle assets to be played in random order.
Create the file /home/pi/.config/autostart/mpv.desktop
with the following contents:
[Desktop Entry]
Name=mpv
Exec=mpv /home/pi/Pictures/idle/
Type=Application
This changes the Raspberry Pi into a rudimentary digital signage display, starting mpv on login with a playlist of media files in /home/pi/Pictures/idle/
. Upload media (images and/or videos) to be cycled in an infinite loop to /home/pi/Pictures/idle/
and images to show upon game loading in /home/pi/Pictures/games/
, ensuring that the file names for the game images exactly match what you wrote in the batch files on the PC. Once done, launch mpv with mpv /home/pi/Pictures/idle/
for the purpose of testing in the next step.
PC Setup, Part 2
With both the kiosk PC and the Raspberry Pi connected to the same local network, test the setup by scanning an NFC tag that has been configured to launch a game. Close all open windows, hide the desktop icons by right-clicking on the desktop and unchecking View > Show desktop icons, and scan an NFC tag with its mapping configured. The wallpaper should change, the game launch, and the Raspberry Pi now show the corresponding image for the game. After 10 seconds, remove the tag and all of the above should be undone. Communication with the Raspberry Pi consists of issuing HTTP requests to change the mpv playlist to a single item, the image file named for the game name in the batch file. This is done by update.py, which sends the requests to the networked device with the hostname sign
by default.
This setup is intended to be deployed standalone with no external network access once setup is complete. The PC will connect directly to the Raspberry Pi by their ethernet ports. To do this, a static IP will need to be assigned to both the PC and the Raspberry Pi.
Open the adapter settings for the ethernet device in Control Panel > Network and Sharing Center > Change adapter settings. Open the properties for Internet Protocol Version 4 (TCP/IPv4), and open the Alternate Configuration tab. Set a static IP here such as 192.168.0.1
, as seen below. Using the Alternate Configuration allows for the PC to still connect to a typical local network with DHCP.
If possible on your version of Windows, disable notifications and automatic reboots.
Raspberry Pi Setup, Part 2
Exit mpv if it is open. Edit the wired connection's IPv4 properties to the manual address 192.168.0.2
and a gateway of 192.168.0.1
, as seen below, using either Raspberry Pi OS's network configuration utility in the top-right network tray icon or sudo nmtui
.
Plug an ethernet cable between the kiosk PC and the Raspberry Pi, restart both, and test the NFC tags.
Further Considerations
This section contains suggestions for further customization, including some ideas that may be more appealing for your own setup that I don't necessarily use myself.
The Python scripts that manage the Windows wallpaper and the mpv display are deliberately simplistic. It would be possible to, for example, change the wallpaper to a slideshow by editing the Registry or use mpv for Windows to show a video loop and show that instead of a static background, which would be necessary in a location like a game room where a long time may pass without anyone playing. Modifying the scripts to do this is left as an exercise to the reader.
To further expedite the process of installing and starting games, I also defeat many of Windows' security features and prevent it from accessing Windows Update with TinyWall. Security is not a concern for me with this PC, as it acts as an embedded device with no personal information included, and the greatest risk is that the OS somehow becomes corrupted. The last thing I want is for any games to be interrupted with notifications or Windows Update notices, so the tradeoff in security is accepted to me.
As a mystery tournament organizer, one of my highest priorities is to reduce player friction wherever possible. The controller I provide for both players is a custom-built arcade-style control panel, with a pair of GP2040-CE boards in XInput mode. This naturally limits me to games that can be played with 8 or fewer buttons and no analog control, but I still have a very large array of arcade games and retro console games to choose from in addition to any number of arcade-styled games available on PC.
My own setup uses unmarked cards numbered 001-050, numbered such to allow for more cards to be added. My mapping files point to batch files numbered the same way (001.bat, 002.bat, etc.). I create batch files named for the games they actually launch in a separate folder and then copy them to the bat folder and rename them to the numbers matching the cards. This allows me to quickly change the games assigned to the cards without editing any configuration files, so the mystery tournament roster is never the same twice.
One of my eventual long-term projects is to reconstruct this setup in a Versus City-style double cabinet arrangement, with digital signs mounted below the game monitors for the players' convenience. Both will use HDMI splitters.
I bought a set of 50 NTAG 215 cards to use with this project and they all work as expected. I was then gifted a set of NTAG coins roughly 1 inch in diameter, and it gave me the idea to 3D print custom cards with leftover PLA with the coins embedded in them. I've had to modify my NFC reader enclosure to accommodate the cards due to their thickness, as I've had to print the cards to roughly three times the thickness of a typical card to contain the coins. These custom cards are printed in black and metallic colors, so I have designated them "boss cards" for the latter end of the bracket, containing the most choice selections (more recently released games that take more setup than usual). It would be possible to print much thinner cards using NFC stickers instead.