fix: profile voxatron apart from pico-8

lexaloffle documented two programs, so every platform naming PICO-8
received Voxatron's files: ROCKNIX, RetroDECK and RetroBat run PICO-8
only. Voxatron is its own profile, named vox_official. A platform also
runs the emulators its standalone_cores list names: Batocera and KNULLI
list lexaloffle there and nowhere else.
This commit is contained in:
Abdessamad Derraz committed 2026-11-09 18:48:13 +01:00
1 parent 2fe15e99f9
commit f47c8b8e5a
5 files changed
+149 -92

No files matched your search

+9 -90
View File
@@ -12,30 +12,30 @@ version_basis:
version_source:
url: "https://www.lexaloffle.com/dl/docs/pico-8_changelog.txt"
pattern: '^\s*v(0\.\d+\.\d+[a-z]?)\s*$'
display_name: "Lexaloffle - PICO-8 / Voxatron"
display_name: "Lexaloffle - PICO-8"
cores:
- lexaloffle
- "pico-8"
- vox_official
- "pico8"
- "Pico-8"
- "pico_standalone"
- "float-scaled"
systems:
- pico8
- voxatron
standalone_directories:
- "executable directory"
notes: |
Commercial fantasy consoles by Lexaloffle Games LLP, sold as ZIP archives
per platform. Nothing in either program checks a hash of its own files:
the hashes below are those of the files in the official 0.2.7 archives.
Commercial fantasy console by Lexaloffle Games LLP, sold as ZIP archives
per platform. Nothing in the program checks a hash of its own files: the
hashes below are those of the files in the official 0.2.7 archives.
Voxatron, the same publisher's other program, is profiled apart
(voxatron.yml).
Each program finds its own folder through /proc/self/exe and reads its
The program finds its own folder through /proc/self/exe and reads its
.dat beside itself. The paths below are the layout of the archives, whose
top folders are pico-8/ and voxatron/: a launcher that runs one of these
files from a folder places the program folder there.
top folder is pico-8/: a launcher that runs one of these files from a
folder places the program folder there.
PICO-8 0.2.7 ships five archives. pico-8_0.2.7_amd64.zip holds pico8
(x86_64, SDL2 linked in) and pico8_dyn (x86_64, system libSDL2).
@@ -83,11 +83,6 @@ notes: |
and three other home folders on linuxarm, pico8 on linux and unix, and
pico8.exe on Windows.
Voxatron: Batocera's generator runs bios/voxatron/vox with
LD_LIBRARY_PATH set to bios/voxatron. x86_64 only. vox_dyn is the
variant linked against the system SDL2. libHoloPlayCore.so is the Looking
Glass SDK the binary links against.
files:
# -------------------------------------------------------
# PICO-8 0.2.7
@@ -234,79 +229,3 @@ files:
description: "SPLORE favourites list"
source_ref: "pico-8 0.2.7 amd64 pico8, string favourites.txt at 0x242346"
note: "Read from the -home folder. The bbs/<listing>.pip.png images beside it are downloaded from the BBS."
# -------------------------------------------------------
# Voxatron
# -------------------------------------------------------
- name: vox
path: voxatron/vox
system: voxatron
required: true
description: "Voxatron main executable"
source_ref: "batocera lexaloffleGenerator.py:20, 42, 48-52"
note: "The Voxatron program vox, an x86_64 ELF with SDL2 linked in. Batocera's generator runs bios/voxatron/vox and raises when it is missing or not executable."
- name: vox_dyn
path: voxatron/vox_dyn
system: voxatron
required: false
description: "Voxatron dynamically linked executable"
source_ref: "voxatron vox_dyn, NEEDED libSDL2-2.0.so.0, batocera lexaloffleGenerator.py:20, 42"
note: "The same program linked against the system SDL2 (its only extra NEEDED library). Batocera's generator never runs it."
- name: vox.dat
path: voxatron/vox.dat
system: voxatron
required: true
description: "Voxatron data file"
source_ref: "voxatron vox, string vox.dat at 0x2a58f, voxatron vox_dyn, string vox.dat at 0x1f1af"
note: "Opened from the folder of the binary that runs. Absent, vox stops with \"FATAL ERROR: could not load vox.dat\"."
- name: libHoloPlayCore.so
path: voxatron/libHoloPlayCore.so
system: voxatron
required: false
description: "Looking Glass holographic display support library"
source_ref: "voxatron vox, voxatron vox_dyn, batocera lexaloffleGenerator.py:41, 87-90"
note: "Neither binary links it or names it, and neither opens it in a run (strace, with and without the file). Batocera's generator sets LD_LIBRARY_PATH to bios/voxatron, where it keeps the library."
- name: config.txt
unsourceable: "written by the emulator on exit, no canonical file"
system: voxatron
required: false
description: "Voxatron settings"
source_ref: "voxatron vox, string config.txt at 0x27bea0"
note: "Read beside the binary, then from ~/.lexaloffle/Voxatron, and written there when absent."
- name: sdl_controllers.txt
unsourceable: "user supplied, no canonical file"
system: voxatron
required: false
description: "Custom SDL controller mappings"
source_ref: "voxatron vox, string sdl_controllers.txt at 0x2847f7"
note: "Read beside the binary, then from ~/.lexaloffle/Voxatron, where Voxatron writes it when absent."
- name: favourites.txt
unsourceable: "written by the emulator, no canonical file"
system: voxatron
required: false
description: "Cart browser favourites list"
source_ref: "voxatron vox, string favourites.txt at 0x27a39e"
note: "Read from ~/.lexaloffle/Voxatron."
- name: internal_carts.txt
unsourceable: "written by the emulator, no canonical file"
system: voxatron
required: false
description: "Voxatron internal cart list"
source_ref: "voxatron vox, string internal_carts.txt at 0x27a446"
note: "Read from ~/.lexaloffle/Voxatron and written there at startup."
- name: player_1.vpp
path: player/player_1.vpp
unsourceable: "written by the emulator, no canonical file"
system: voxatron
required: false
description: "Voxatron player profile"
source_ref: "voxatron vox, string player/player_%d.vpp at 0x273f90"
note: "Read from ~/.lexaloffle/Voxatron/player, and written there when absent."
+104
View File
@@ -0,0 +1,104 @@
emulator: Voxatron
type: standalone
core_classification: other
upstream: "https://www.lexaloffle.com/voxatron.php"
profiled_date: "2026-11-09"
core_version: "0.3.5b"
version_basis:
kind: unverified
why: no_artifact
display_name: "Lexaloffle - Voxatron"
cores:
- vox_official
systems:
- voxatron
standalone_directories:
- "executable directory"
notes: |
Commercial voxel fantasy console by Lexaloffle Games LLP, sold as ZIP
archives. The held binaries report voxatron 0.3.5b. Nothing in the
program checks a hash of its own files.
The program finds its own folder through /proc/self/exe and reads vox.dat
beside itself. The paths below put the program in voxatron/: a launcher
that runs vox from a folder places that folder there.
Batocera's generator runs bios/voxatron/vox with LD_LIBRARY_PATH set to
bios/voxatron. x86_64 only. vox_dyn is the variant linked against the
system SDL2. libHoloPlayCore.so is the Looking Glass SDK the binary links
against.
files:
- name: vox
path: voxatron/vox
system: voxatron
required: true
description: "Voxatron main executable"
source_ref: "batocera lexaloffleGenerator.py:20, 42, 48-52"
note: "The Voxatron program vox, an x86_64 ELF with SDL2 linked in. Batocera's generator runs bios/voxatron/vox and raises when it is missing or not executable."
- name: vox_dyn
path: voxatron/vox_dyn
system: voxatron
required: false
description: "Voxatron dynamically linked executable"
source_ref: "voxatron vox_dyn, NEEDED libSDL2-2.0.so.0, batocera lexaloffleGenerator.py:20, 42"
note: "The same program linked against the system SDL2 (its only extra NEEDED library). Batocera's generator never runs it."
- name: vox.dat
path: voxatron/vox.dat
system: voxatron
required: true
description: "Voxatron data file"
source_ref: "voxatron vox, string vox.dat at 0x2a58f, voxatron vox_dyn, string vox.dat at 0x1f1af"
note: "Opened from the folder of the binary that runs. Absent, vox stops with \"FATAL ERROR: could not load vox.dat\"."
- name: libHoloPlayCore.so
path: voxatron/libHoloPlayCore.so
system: voxatron
required: false
description: "Looking Glass holographic display support library"
source_ref: "voxatron vox, voxatron vox_dyn, batocera lexaloffleGenerator.py:41, 87-90"
note: "Neither binary links it or names it, and neither opens it in a run (strace, with and without the file). Batocera's generator sets LD_LIBRARY_PATH to bios/voxatron, where it keeps the library."
- name: config.txt
unsourceable: "written by the emulator on exit, no canonical file"
system: voxatron
required: false
description: "Voxatron settings"
source_ref: "voxatron vox, string config.txt at 0x27bea0"
note: "Read beside the binary, then from ~/.lexaloffle/Voxatron, and written there when absent."
- name: sdl_controllers.txt
unsourceable: "user supplied, no canonical file"
system: voxatron
required: false
description: "Custom SDL controller mappings"
source_ref: "voxatron vox, string sdl_controllers.txt at 0x2847f7"
note: "Read beside the binary, then from ~/.lexaloffle/Voxatron, where Voxatron writes it when absent."
- name: favourites.txt
unsourceable: "written by the emulator, no canonical file"
system: voxatron
required: false
description: "Cart browser favourites list"
source_ref: "voxatron vox, string favourites.txt at 0x27a39e"
note: "Read from ~/.lexaloffle/Voxatron."
- name: internal_carts.txt
unsourceable: "written by the emulator, no canonical file"
system: voxatron
required: false
description: "Voxatron internal cart list"
source_ref: "voxatron vox, string internal_carts.txt at 0x27a446"
note: "Read from ~/.lexaloffle/Voxatron and written there at startup."
- name: player_1.vpp
path: player/player_1.vpp
unsourceable: "written by the emulator, no canonical file"
system: voxatron
required: false
description: "Voxatron player profile"
source_ref: "voxatron vox, string player/player_%d.vpp at 0x273f90"
note: "Read from ~/.lexaloffle/Voxatron/player, and written there when absent."
+6 -1
View File
@@ -2997,7 +2997,12 @@ def resolve_platform_cores(
if cores_config == "all_libretro":
result = every_libretro()
elif isinstance(cores_config, list):
core_set = {str(c) for c in cores_config}
# An emulator the platform launches standalone runs there even when
# its own list names only the cores: Batocera's es_systems.yml files
# lexaloffle and gsplus as standalone emulators and nowhere else.
core_set = {str(c) for c in cores_config} | {
str(c) for c in config.get("standalone_cores") or []
}
index = upstream_profile_index(profiles)
platform = str(config.get("_key") or "")
+2 -1
View File
@@ -57,7 +57,8 @@ NAMED_FOR_A_LAUNCHER = {
# Profiles whose entries still rest on a launcher, with the fact that blocks
# reading the emulator itself.
LAUNCHER_SOURCED = {
"lexaloffle": "PICO-8 and Voxatron are sold binaries, and no copy of either is held to read",
"lexaloffle": "PICO-8 is a sold binary, and no copy is held to read",
"voxatron": "Voxatron is a sold binary, and no copy is held to read",
}
_SENTENCE = re.compile(r"(?<=[.!?])\s+(?=[A-Z0-9(\"'])")
+28
View File
@@ -364,5 +364,33 @@ class AProgramRunFromItsFolder(unittest.TestCase):
install._check_roms_directory({"files": files})
class EachProgramItsOwnProfile(unittest.TestCase):
"""PICO-8 and Voxatron are two programs: a platform running one gets its files only."""
def test_only_the_platforms_that_run_voxatron_get_it(self) -> None:
from common import list_registered_platforms, resolve_platform_cores
profiles = load_emulator_profiles(str(REPO_ROOT / "emulators"))
runs = {
name: {k for k in ("lexaloffle", "voxatron")
if k in resolve_platform_cores(
load_platform_config(name, str(REPO_ROOT / "platforms")), profiles)}
for name in list_registered_platforms(str(REPO_ROOT / "platforms"))
}
self.assertEqual(
{name for name, found in runs.items() if "voxatron" in found}, {"batocera", "knulli"}
)
self.assertTrue(all("lexaloffle" in runs[name] for name in (
"batocera", "knulli", "rocknix", "retrodeck", "retrobat", "recalbox")))
def test_a_standalone_emulator_is_run(self) -> None:
from common import resolve_platform_cores
profiles = {"emu": {"emulator": "Emu", "type": "standalone", "cores": ["emu"],
"systems": ["sys"], "files": []}}
config = {"cores": ["other"], "standalone_cores": ["emu"], "systems": {}}
self.assertEqual(resolve_platform_cores(config, profiles), {"emu"})
if __name__ == "__main__":
unittest.main()