big refactor on how games are built

This commit is contained in:
sinavir 2024-01-06 22:42:36 +01:00
parent 7c41b132ec
commit 6f9cefa75f
10 changed files with 181 additions and 96 deletions

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
/nixos.qcow2
/emulationstation-source
result
result-*

View file

@ -1,25 +1,13 @@
{
retronix.emulationstation = {
{pkgs, ...}: {
retronix = {
systems = {
"Arcade" = {
command = "bash -c 'echo $XINIT'";
games = [
{
src = ./emulationstation/roms/Arcade/atetris.zip;
filename = "atetris.zip";
name = "Tetris";
desc = "Tetris, le classique des jeux de puzzle que tout le monde connait (et auquel tout le monde joue quand on met les affaires dans le coffre en partant en vacances). Tetris est devenu un phénomène mondial lorsqu'il a été vendu en pack avec l'achat de la Gameboy originale, en 1989. L'OST est célèbre, avec ses origines classiques russes qui sont maintenant célèbres. ";
rating = "0.9";
releasedate = "19880101T000000";
developer = "bootleg";
publisher = "Atari";
genre = "Puzzle-Game";
players = "1-2";
}
];
"Arcade" = {
extension = ".sh";
games = with pkgs.roms; [
atetris
];
};
};
emulationstation.inputCfg = builtins.readFile ./es_input.cfg;
};
inputCfg = builtins.readFile ./es_input.cfg;
};
}

5
launch_es.sh Executable file
View file

@ -0,0 +1,5 @@
export NIXPKGS_ALLOW_UNFREE=1
RESULT=$(nix-build -E 'import ((import ./npins).nixpkgs + "/nixos")' -A config.retronix.emulationstation.cli -I nixos-config=configuration.nix --no-out-link $@)
$RESULT

View file

@ -1,5 +1,7 @@
#!/usr/bin/env bash
RESULT=$(nix-build -E 'import ((import ./npins).nixpkgs + "/nixos")' -A config.system.build.vm -I nixos-config=configuration.nix --no-out-link --option substituters "" $@)
export NIXPKGS_ALLOW_UNFREE=1
RESULT=$(nix-build -E 'import ((import ./npins).nixpkgs + "/nixos")' -A config.system.build.vm -I nixos-config=configuration.nix --no-out-link $@)
$RESULT/bin/run-nixos-vm

View file

@ -6,22 +6,29 @@ let
attrToXml = attrs: lib.concatLines (lib.mapAttrsToList (k: v: "<${k}>${builtins.toString v}</${k}>") attrs);
gameTemplate = args: let
gameTemplate = game: let
attr = [
"path"
"name"
"sortname"
"desc"
"image"
"thumbnail"
"video"
"marquee"
"thumbnail"
"rating"
"releasedate"
"developer"
"publisher"
"genre"
"players"
"sortname"
"favorite"
"hidden"
"kidgame"
"playcount"
"lastplayed"
];
args = game.meta // { path = "@out@/${game.name}.sh"; };
in ''
<game>
${attrToXml (filterAttrs' attr args)}
@ -52,7 +59,7 @@ let
</gameList>
'';
symlinkCommands = builtins.map (
v: "ln -s ${v.src} $out/${v.filename}"
v: "ln -s ${v}/${v.launchPath} $out/${v.name}.sh"
) games;
in pkgs.runCommand "${name}-roms" {
@ -63,7 +70,7 @@ let
} ''
mkdir -p $out
cp $gamelistPath $out/gamelist.xml
substituteInPlace $out/gamelist.xml --subst-var out
substituteAllInPlace $out/gamelist.xml
${lib.concatLines symlinkCommands}
'';
@ -79,19 +86,18 @@ let
type = lib.types.str;
default = name;
};
path = lib.mkOption { # TODO: check it works
path = lib.mkOption {
type = lib.types.path;
};
command = lib.mkOption {
type = lib.types.str;
default = "echo \"Hello world !\"";
default = "%ROM%";
};
extension = lib.mkOption {
type = lib.types.str;
default = ".zip";
};
games = lib.mkOption {
type = lib.types.listOf gameOptions;
type = lib.types.listOf lib.types.package;
description = "Takes attributes of `games` tag in gamelist.xml";
};
};
@ -99,90 +105,64 @@ let
path = mkSystemPath config.name config.games;
};
});
gameOptions = lib.types.submodule ({config, name, ... }: {
freeformType = with lib.types; attrsOf str;
options = {
src = lib.mkOption {
type = lib.types.path;
};
name = lib.mkOption {
type = lib.types.str;
};
desc = lib.mkOption {
type = lib.types.str;
default = "";
};
path = lib.mkOption {
type = lib.types.str;
default = "@out@/${config.filename}";
};
filename = lib.mkOption {
type = lib.types.str;
};
};
});
in {
options = {
retronix.emulationstation = {
retronix = {
emulationstation = {
systemCfgFile = lib.mkOption {
type = lib.types.path;
};
inputCfgFile = lib.mkOption {
type = lib.types.path;
};
themesDir = lib.mkOption {
type = lib.types.path;
};
inputCfg = lib.mkOption {
type = lib.types.str;
default = "";
};
homeDir = lib.mkOption {
internal = true;
type = lib.types.path;
};
extraConfigFiles = lib.mkOption {
type = with lib.types; listOf path;
default = [];
description = ''
Must be store paths.
Directory structure will be merged.
'';
};
cli = lib.mkOption {
type = lib.types.package;
};
};
systems = lib.mkOption {
type = lib.types.attrsOf (sectionOptions);
default = {};
};
systemCfgFile = lib.mkOption {
type = lib.types.path;
};
inputCfgFile = lib.mkOption {
type = lib.types.path;
};
systemsDir = lib.mkOption {
internal = true;
type = lib.types.path;
description = "Directory containing the symlinks to roms and gamelists.xml files";
};
themesDir = lib.mkOption {
type = lib.types.path;
};
inputCfg = lib.mkOption {
type = lib.types.str;
default = "";
};
homeDir = lib.mkOption {
internal = true;
type = lib.types.path;
};
extraConfigFiles = lib.mkOption {
type = with lib.types; listOf path;
default = [];
description = ''
Must be store paths.
Directory structure will be merged.
Must contain .emulationstation folder
'';
};
cli = lib.mkOption {
type = lib.types.str;
};
};
};
config = {
retronix.emulationstation = {
systemCfgFile = writeESDir "es_systems.cfg" ''
systemCfgFile = pkgs.writeTextDir "es_systems.cfg" ''
<?xml version="1.0"?>
<systemList>
${lib.concatLines (lib.mapAttrsToList (_: systemTemplate) cfg.systems)}
${lib.concatLines (lib.mapAttrsToList (_: systemTemplate) config.retronix.systems)}
</systemList>
'';
inputCfgFile = lib.mkDefault (writeTextDir "es_input.cfg" cfg.inputCfg);
homeDir = pkgs.symlinkJoinSubDir {
inputCfgFile = lib.mkDefault (pkgs.writeTextDir "es_input.cfg" cfg.inputCfg);
homeDir = pkgs.symlinkJoinSubdir {
name = "es-config-dir";
subdir = ".emulationstation";
paths = [
cfg.systemCfgFile
cfg.inputCfgFile
] ++ cfg.extraConfigFiles;
};
cli = t "${pkgs.emulationstation}/bin/emulationstation --home ${cfg.homeDir}";
cli = pkgs.writeScript "emulationstation" "${pkgs.emulationstationPatched}/bin/emulationstation --home ${cfg.homeDir} --gamelist-only";
};
};

View file

@ -1,11 +1,15 @@
final: prev: {
joy2keyd = final.python3.pkgs.callPackage ./joy2keyd {};
retropieSetup = final.callPackage ./retropie-setup.nix {};
joy2keyd = final.python3.pkgs.callPackage ./joy2keyd {};
joy2key = final.callPackage ./joy2key.nix {};
runcommand = final.callPackage ./runcommand.nix {};
emulationstationPatched = final.emulationstation.overrideAttrs (_: previous: {
patches = [ ./emulationstation.patch ];
});
symlinkJoinSubdir =
args_@{ name
, paths
@ -29,4 +33,6 @@ final: prev: {
done
${postBuild}
'';
roms = final.callPackage ./roms {};
}

18
pkgs/roms/atetris.nix Normal file
View file

@ -0,0 +1,18 @@
{mkRetroarchRom}:
mkRetroarchRom {
name = "Tetris";
src = ./bin/atetris;
emulator = "mame";
filename = "atetris.zip";
meta = {
desc = "Tetris, le classique des jeux de puzzle que tout le monde connait (et auquel tout le monde joue quand on met les affaires dans le coffre en partant en vacances). Tetris est devenu un phénomène mondial lorsqu'il a été vendu en pack avec l'achat de la Gameboy originale, en 1989. L'OST est célèbre, avec ses origines classiques russes qui sont maintenant célèbres. ";
rating = "0.9";
releasedate = "19880101T000000";
developer = "bootleg";
publisher = "Atari";
genre = "Puzzle-Game";
players = "1-2";
};
}

View file

@ -0,0 +1,19 @@
{ mkRom , retroarchFull }:
{ name
, src
, emulator
, filename
, settings ? {}
, meta
}:
let
retroarch = retroarchFull.override (prev: {
settings = prev.settings // settings;
});
in
mkRom ({
runtimeInputs = [ retroarch ];
# To do add a check for the emulator
command = "retroarch -L ${emulator} ${builtins.placeholder "out"}/usr/share/${filename}";
inherit meta src name;
})

54
pkgs/roms/build/mkRom.nix Normal file
View file

@ -0,0 +1,54 @@
{ runCommand, runtimeShell, stdenv, shellcheck-minimal, lib, lndir }:
{ name
, src
, runtimeInputs ? [ ]
, command
, meta ? {}
}:
runCommand name {
inherit meta src;
allowSubstitutes = true;
preferLocalBuild = false;
launchPath = "launch.sh";
script = ''
#!${runtimeShell}
set -o errexit
set -o nounset
set -o pipefail
'' + lib.optionalString (runtimeInputs != [ ]) ''
export PATH="${lib.makeBinPath runtimeInputs}:$PATH"
'' + ''
${command}
'';
passAsFile = [ "script" ];
checkPhase = ''
runHook preCheck
${stdenv.shellDryRun} "$target"
${lib.getExe shellcheck-minimal} "$target"
runHook postCheck
'';
} ''
target=$out/bin/${lib.escapeShellArg name}
rom_dir=$out/usr/share
mkdir -p "$(dirname "$target")"
mkdir -p "$rom_dir"
# symlink rom_dir
${lndir}/bin/lndir $src $rom_dir
mv "$scriptPath" "$target"
chmod +x "$target"
# symlink the executable to help emulation station calls
ln -s $target $out/$launchPath
eval "$checkPhase"
''

12
pkgs/roms/default.nix Normal file
View file

@ -0,0 +1,12 @@
{ lib, newScope }:
let
romsFun = self: let
inherit (self) callPackage;
in {
atetris = callPackage ./atetris.nix {};
mkRom = callPackage ./build/mkRom.nix {};
mkRetroarchRom = callPackage ./build/mkRetroarchRom.nix {};
};
in lib.makeScope newScope romsFun