A Link to the Past Randomizer¶
Synopsis¶
Zelda: A Link to the Past is a Super Nintendo game.
A Link to the Past Randomizer is a new way to replay this classic game by shuffling the location of the items (and many other things).
Its then possible to track the progress of the game using a tracker. Ex: Dunka Track that you can use manually or automatically by connecting the game to the site (using the emulator or your flash cart connected on your computer using sd2snes).
Play a game¶
Normally you would:
Go the the website
Upload the rom (you have to find the ROM yourself first)
Select the game options
Download the rom
With the ROM you can play the game on a SNES emulator OR use a flash cart (Ex: FXPAK Pro) to play on a real SNES.
To play on a flash cart you need to:
remove the SD Card from the flash cart
insert it into your computer
copy the rom to the SD Card
remove the SD Card from your computer
insert it into the flash cart
insert the flash cart into the SNES
turn on the SNES
use the controller to find the rom and Boot the game
You need to do this every single time you want to play a new seed.
However for advanced user tools can let you upload directly the rom on the flash cart when it’s connected on your computer.
My problems¶
I don’t want to use my computer at all in the process
I want to play on the real SNES
I am too lazy to do so many steps
My Overkill Solution¶
I had to spend countless hours to continue to be lazy.
create a mobile website on my local network I use to generate the rom
create an API used by my website to generate the rom from https://alttpr.com/
upload the generated rom to my flash cart from the website
start the game on the flash cart
Oh and also auto track the progress of my game on the wall mounted monitor (This video is a bit old, the monitor is now wall mounted):
The Pieces of the Puzzle¶
This part is not fully detailed but all the pieces of the puzzle are there.
Reverse Proxy¶
I use Caddy as a reverse proxy to expose the website and the API on my local network from the raspberry pi.
{
auto_https disable_redirects
}
http://retro-controller.local, http://192.168.18.3 {
# expose sni
handle_path /sni/* {
reverse_proxy :8190
}
# website of the tracker
handle_path /zt/* {
root * /home/retro/alttptracker/
file_server {
hide .git
}
}
# redirection of the tracker's second page
redir /tracker.html /zt{uri}
# mobile website
handle_path /* {
root * /home/retro/sni-web/public
file_server {
hide .git
}
}
# wetbsocket for the tracker
handle_path /ws:80 {
reverse_proxy :23074
}
# api used by the front-end
handle_path /pyz3r/* {
reverse_proxy :8000
}
}
Mobile website (sni-web)¶
This is the source code of my website. sni-web
The build of the static site is uploaded to the raspberry pi using scp:
scp ./public/* retro@retro:/home/retro/sni-web/public/
API used by the website (pyz3r-api)¶
pyz3r-api is the API I made that communicates with https://alttpr.com/ (through pyz3r) to generate the rom.
Its configured this way:
git clone on the device
setup a virtual environment
install the roms on the machine
configure a service
[Unit]
Description=pyz3r
After=network.target
[Service]
User=retro
WorkingDirectory=/home/retro/pyz3r-api
ExecStart=/home/retro/pyz3r-api/venv/bin/uvicorn --host 127.0.0.1 --port 8000 pyz3r_api.asgi:app
Restart=always
Environment=FLASK_ROM_PATH="./Zelda no Densetsu - Kamigami no Triforce (Japan).sfc"
Environment=FLASK_SM_ROM_PATH="./Super Metroid (JU) [!].smc"
MemorySwapMax=0
[Install]
WantedBy=multi-user.target
SNI¶
SNI stands for Super Nintendo Interface. It’s a tool to control a flash cart from a computer.
I made this SNI pi compiler to make a headless version for raspberry pi. Then I upload it on my raspberry pi using scp.
Sni is exposed on my local network using the reverse proxy.
[Unit]
Description=sni
Documentation=
After=network.target
[Service]
Type=simple
User=retro
ExecStart=/home/retro/sni
Restart=always
#RuntimeMaxSec=1d
MemorySwapMax=0
MemoryMax=120M
#MemoryHigh=90M
[Install]
WantedBy=multi-user.target
Tracker¶
This is a custom version of Dunka Track I tweaked to be able to run over my local network.
It’s a static website exposed by caddy on my local network but it communicates with the websocket of my raspberry pi.
Casting on my wall mounted monitor¶
I use the Home Assistant integration ha-catt-service I created to start the tracker on the Chromecast of my wall mounted monitor.
I trigger it using a button my Home Assistant’s dashboard.
service: catt_service.cast_site
data:
device_id: 74e61b172c2aafaaa1f753ffed2d8335
# the chromecast does not work with my hostname, I have to use the IP
url: >-
http://192.168.18.3/zt/tracker.html?f=ONNNNNNN0000NNNNGC7C7R&d=CNNYY0080000000N0&s=00000000000000000000000000&p=princess_peach&h=192.168.18.3/ws&r=1699666453697#!
It has the following caveats:
I cannot interact with the tracker (ex: changing the number of chests opened in the dungeon);
I hardcoded the tracker’s URL parameters for the gameplay settings I play normally.