An AutoBleem scanner processor that turns PE app packages (.mod files) into AutoBleem Apps. A user drops a
.mod in the Mods/ folder; before the next scan this processor unpacks it, and each program inside shows up
as an App (Apps/pe-<name>/, category "PE"). It is modelled on proc_unzip:
one C++ file, src/main.cpp, nothing but the standard library and the vendored decoders
(libarchive with liblzma for the tar.xz data, miniz
for a gzip'd control file). Once a package is converted the .mod moves to Mods/done/ (see "The rules it keeps");
the package is never executed by this program.
System/Processors/pe/
processor.ini
bin/psc/pe <- the PlayStation Classic (the packages are for it)
bin/linux-armhf/pe bin/linux-arm64/pe bin/linux-i386/pe bin/windows-x86_64/pe.exe <- builds for tests
It is Kinds=mods: the launcher's scan starts it for the Mods/ folder (--start --mods, with AB_APPS_DIR for
the Apps folder). It is Default=on: the launcher switches it on the first time it meets it (a player who switches
it off in Scanner processors keeps it off). The compatibility list is rc/pe_compat.ini of the launcher's package; without it the copy
built into the program is used.
A package is a Debian archive (ar: debian-binary, control.tar.gz|xz, data.tar.xz). For every launcher
folder media/project_eris/etc/project_eris/SUP/launchers/<dir>/ that has a launcher.cfg and a launch.sh and
that the compatibility list allows, Apps/pe-<launcher_filename>/ holds:
- the folder, byte for byte as the package has it (modes kept; a link inside it becomes a copy - the stick is FAT);
app.ini:Title=<launcher_title> Author=<launcher_publisher, else the maintainer's name (no address), else empty> Version=<control Version> Image=<launcher_filename>.png (only if the file exists) Readme=readme.txt Startup=run.sh Exec.psc=run.sh (so only the console lists it; Exec.rpi=run.sh for a package whose control file says "Platform: RPI armhf" - only the Raspberry Pi 32-bit lists that one. The first word of the Platform line decides, without case; no line or a word we do not know = psc) Category=PE (or the package type, see below) PeSource=<the .mod file name> PadMode=<pad= of the launcher's section in pe_compat.ini: psc, x360, psc-kernel or x360-kernel; psc-kernel without it> (an unknown pad value is a #WARN and psc-kernel; an unchanged package keeps its App, a changed one gets the current value) Dpad2Analog=<dpad2analog= of that section, 1 or 0; no line without it> Analog2Dpad=<analog2dpad= of that section, 1 or 0; no line without it>- A package type: a control file that names one of the launcher's App categories - a metadata line of the
Description (
Category: games, aspe_portswrites it) or a field of its own (Category: games); games, emulators, tools, media or other, any case - files the App there:Category=<type>and the title gets the suffix(mod)(Title=OpenLara (mod)). A package with no type (a user's own.mod), or a word that is no category, stays in the launcher's "PE apps" category (Category=PE) with its title as it is. The App is typed when it is made: a package already converted at the same version is not touched, so a newly typed package needs a new version. readme.txt: the control Description (its free-text lines, not its metadata), "Put the files this program needs (game data) in this folder.", and a one-line compatibility note - never the package's own README;run.sh(executable):exec sh "${AB_RC_DIR:-/media/Autobleem/rc}/pe_run.sh" "$APP_DIR".
launcher.cfg is read as data (name="value" lines, CRLF, quotes of both kinds, comments) and never run. The
product's old name in any shown text is written as "PE".
The compatibility list ([section], block=1 or skip=1, reason=; a section is a launcher_filename, or the
folder's name) refuses a launcher with a #WARN and the reason; the rest of the package is still converted.
- A launcher folder whose
launcher.cfgsayslauncher_package="1"is game data: it needs nolaunch.shand makes no App. It is unpacked intoPackages/pe-<launcher_filename>/(--packages, else$AB_PACKAGES_DIR, elsePackages/next to Apps/; made only when there is a package to put in it) with the game's files unchanged, minuslauncher.cfgandlaunch.sh. The folder carries the descriptorpackage.ini(spec 2.2:Title,Kind,Game<N>.Title/.File, ...); proc_pe checks it (a Title, a content kind for every game, at least one game whose file is in the folder, no path outside it -#WARN - ... not added (<why>)and nothing added otherwise) and stampsVersion=<control Version>,Source=modandPeSource=<the .mod>(the mod's own values of these are replaced), plusImage=<launcher_filename>.pngwhen the descriptor names none. - The same rules as for an App: a folder without
PeSourcestays, the same or an older Version changes nothing, a newer Version replaces the package whole (a package keeps nothing of the old one), a marker inApps/.pe_state/(Packages=) makes a second run a no-op. - An App an older proc_pe made from the same mod is removed once the package is in place:
Apps/pe-<launcher_filename>whose app.iniPeSource=names a.modof the same package (freedoomdata-0.13.0-1.modfor-2.mod: the name up to the first-and a digit), together with that old.mod's marker. Any other App stays. - An engine's
launcher_uses="doom-iwad;heretic-iwad"becomesUses=doom-iwad; heretic-iwadandlauncher_package_dir="WAD;MODS"becomesPackageDir=WAD; MODSin app.ini. A value that does not fit (a kind is[a-z0-9]with single-; a folder is relative, inside the App) is dropped with a#WARN; the App is still made.
- atomic: everything is unpacked into
Apps/.pe_tmp/(same filesystem) and a folder is renamed intoApps/only when complete. A killed run is cleared at the next start; a folder a killed replacement had moved aside is put back. - idempotent: a package already converted (its marker in
Apps/.pe_state/, same size and Version, its Apps there with the samePeSourceandVersion) is not even unpacked. - the
.modmoves toMods/done/after a successful conversion (--start --modsonly; a single--modfile stays where it is), so the files are not on the stick twice in plain sight - and it is not deleted, the user can take the original back. Success means the package was read to the end and its marker inApps/.pe_state/is written (a launcher the list refuses is a#WARN, not a failure). A package that fails stays inMods/and is tried again at every scan.Mods/done/is never scanned. A.moddropped intoMods/again - the same name or a newer version - is converted again and replaces the copy indone/; a newer version under another file name also removes the old version's.modfromdone/. The move never removes an App: this program never removes an App for a missing.mod(the marker, not the file, says what is converted). A move that fails (Mods/doneis a file, the stick is read-only) is a#WARN; the App is complete and the.modstays inMods/. - never overwrites what is not its own: an
Apps/pe-*folder withoutPeSourcestays; the same or an older Version than the installed one changes nothing (an older one warns); a newer Version replaces the folder and keeps every file of the old folder that the new package does not ship, at any depth (saves, game data - and also a file the old version shipped and the new one dropped). - safe: only the launcher folders are unpacked. A name with
.., an absolute name, a backslash or a drive colon anywhere in the package refuses the whole package; a link must stay inside its own launcher folder; a file is at most 2 GB, a package 3 GB, 50 000 entries. - a package that is damaged, unsafe, not of type
USB_MODor not an archive is a#WARNand at the end#ERROR - n of m packages could not be converted(exit 1); a refused launcher is only a#WARN.
pe --version #PE app packages V<Version> - Turns PE app packages (.mod) into Apps
pe --ismine --mod <file> exit 0 = a .mod that is an ar archive, 1 = not mine
pe --start --mods <Mods dir> [--apps <dir>] [--packages <dir>] [--compat <file>]
pe --start --mod <file> [--apps <dir>] [--packages <dir>] [--compat <file>]
The Apps folder is --apps, else $AB_APPS_DIR, else Apps/ next to the Mods folder. The list is --compat,
else $AB_PE_COMPAT, else rc/pe_compat.ini under $AB_ROOT (or $AB_ROOT/Autobleem), else the built-in copy.
It prints, flushed line by line: #Starting - <title>, #Converting <file>, n/m, 0..100, #Adding <title>,
#WARN - <text>, then #DONE (exit 0) or #ERROR - <text> (exit 1).
- Every target as CI does:
ci/build.sh allin theghcr.io/autobleem2/autobleem-build:developimage (dist/pe-<version>.zip). Windows by hand:./make_win.sh(MSYS2 UCRT64). - Anything else:
cmake -S . -B build && cmake --build build && (cd build && ctest). - The self-test (
tests/selftest.cpp) runs the real program on the packages intests/data/, made bytests/make_fixtures.py(Python standard library, so unsafe ones can be made too) andtests/make_dpkg_fixture.sh(the realdpkg-deb).
GPL-3.0-or-later (LICENSE); miniz is MIT, libarchive BSD-2-Clause, liblzma 0BSD (third_party/*).