Repository navigation
Building from Source
You need Rust (the version is pinned in rust-toolchain.toml), Task and,
to build for the device on a machine that is not Linux on arm64, Docker.
task run # build the cores and run omega-zero on the desktop
OMEGA_CANVAS=640x480 task run # see what a 640x480 device draws
task check # format, lint, tests on every canvas, timing tests, card scripts
task dist:device # the aarch64 card tree, in dist-device/
task deploy:device # push to a device over adb and restart it
task deploy:wifi # copy a build onto a console on your Wi-Fi and reboot itThe device build compiles the cores in an arm64 Linux container, which keeps the pinned toolchain
and the crates it downloads in the docker volumes omega-zero-rustup and omega-zero-cargo.
gpSP's compiler needs more memory than a 2 GB Docker VM has, and more cores build faster; with
colima, colima start --cpu 6 --memory 6.
omega-zero hosts five libretro cores: mGBA and gpSP for the GBA and the Game Boys, Snes9x and
Supafaust for the SNES, and PCSX ReARMed for the PlayStation. They live in vendor/, which git
ignores.
-
task coregets all five for the desktop: it builds mGBA and Supafaust (the libretro buildbot has no Supafaust for macOS) and fetches gpSP, Snes9x and pcsx_rearmed from the buildbot. One at a time:task core:mgba:host,core:gpsp:host,core:snes9x:host,core:supafaust:host,core:pcsx:host. A core that is missing runs the mock instead, a test pattern and a tone. -
task cores:devicebuilds the five for the device in the container, from commits pinned in the taskfile. gpSP, Snes9x, Supafaust and pcsx_rearmed are built from a source archive kept beside them invendor/, which ships inSystem/licenses/. One at a time:task core:device(mGBA),core:gpsp,core:snes9x,core:supafaust,core:pcsx; those four also have an:updatetask that fetches the source again. pcsx_rearmed is built with its ARM64 dynarec and NEON GPU. -
task deploy:wifi CORES=1builds the five device cores too and copies them intoSystem/.
task deploy:wifi builds omega-zero, copies it to the console over SSH, checks it arrived whole,
reboots the console and waits until the new build starts. Any game still running loses whatever
it has not saved. It builds with the device-dev profile, which skips the release build's
whole-program optimisation, so a rebuild after an edit takes seconds; PROFILE=device copies the
shipping build instead. SCRIPTS=1 copies the scripts in card/System too, and CORES=1 the
five cores (see The cores).
It finds the console as rg35xxsp.local and the card at /mnt/sdcard. CONSOLE (a name or
address, HOST:PORT for another port) and SD change those. For root's password it takes
CONSOLE_PASSWORD, else the first line of .console-password at the root of the repository
(git ignores it), else root, BaseOS's own. omega-zero gives root six random digits the first
time it runs on a card, so from then on the password is the one Settings > Network shows with Y
on the SSH row (see Wi-Fi, SSH and SFTP): put it in .console-password once. A
console that turns the password away says so, also when a deploy reboots it into the first
omega-zero to run on a card. task log:wifi prints omega-zero.log off the console the same
way. Both need sshpass (brew install sshpass).
task build:device PROFILE=device-dev builds the same thing without copying it.
The boot screen, the still image the bootloader shows while Linux starts, is
card/System/bootlogo-<width>x<height>.bmp, one per panel. task bootlogos renders all of them
with crates/omega-zero/examples/bootscreens.rs: a BIOS screen after Award's, in the opening's
letters and where its terminal prints, with the OmegaZero logo in 16 colours from
assets/logo/omega-zero-logo-bios.png. assets/logo/bioslogo.sh makes that logo again
(ImageMagick). task bootlogos:logo renders the logo over the shelf's grid that was the boot
screen before (Chrome and ImageMagick).
The opening is crates/omega-zero/src/opening.rs: what it tells, its script, fades and skip. Its
letters are crates/omega-ui/src/opening.rs and its sounds crates/omega-zero/src/audio/chime.rs.
Cart labels need ScreenScraper's key for the program, which is not in the source. Set
OMEGA_SS_DEVID and OMEGA_SS_DEVPASSWORD when building to put it in; releases get it from the
repository's secrets. A build without it says so on Settings > Labels.
The menus are drawn from the pixel-art kit in assets/ui/; its
README has the rules.
Open assets/ui/storybook.html from disk to see every component. assets/ui/flow.html walks
every menu screen with the slides the device draws, and is the reference the Rust screens are
built to: the arrow keys, X, Z, Enter and Space stand in for the D-pad, A, B, START and
SELECT, a toggle runs the slides five times slower, and the URL's hash picks the screen, colour,
panel size and any moment of a slide:
flow.html#screen=network&from=settings&t=0.5&colour=amber&shot=1
The kit is in Rust too, in crates/omega-ui/src/kit/. Its tests in
crates/omega-ui/tests/suite/kit/ hold each face to a screenshot Chrome takes of the HTML kit,
pixel for pixel; after changing a component, make-refs.sh there takes the screenshots again
(CHROME points it at another Chrome). Each menu screen's input and drawing is a file of its
own in crates/omega-zero/src/screens/, its faces are made in frontend/sync_*.rs, and
nav.rs slides between them.
task screens draws omega-zero's main screens headless to PNGs, and task screens:compare fails
on any pixel that differs from a baseline: the way to prove a change leaves a layout alone.
SCREENS_SCRIPT=file runs another script in its place, for one-off previews.
Each crate's tests live in tests/suite/ and build as one binary, so a run spends its time on
the tests rather than on linking and starting a binary per file. A new test file goes in that
folder and gets a mod line in its main.rs; a suite test fails on a file the list leaves out.
A test that needs a process to itself, because it changes the environment or a setting a process
makes only once, stays a file of its own in tests/.
The emulator's worker tests run against real time, so a plain cargo test leaves them out and
task test:timing runs them; task check includes it. The render tests need macOS. There, add
your terminal app under System Settings > Privacy & Security > Developer Tools, or macOS scans
every test binary the first time it runs.
Start here
Using it
Helping