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 /nixos.qcow2
/emulationstation-source result
result-*

View file

@ -1,25 +1,13 @@
{ {pkgs, ...}: {
retronix.emulationstation = { retronix = {
systems = { systems = {
"Arcade" = { "Arcade" = {
command = "bash -c 'echo $XINIT'"; extension = ".sh";
games = [ games = with pkgs.roms; [
{ atetris
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";
}
];
}; };
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 #!/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 $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); attrToXml = attrs: lib.concatLines (lib.mapAttrsToList (k: v: "<${k}>${builtins.toString v}</${k}>") attrs);
gameTemplate = args: let gameTemplate = game: let
attr = [ attr = [
"path" "path"
"name" "name"
"sortname"
"desc" "desc"
"image" "image"
"thumbnail"
"video" "video"
"marquee"
"thumbnail"
"rating" "rating"
"releasedate" "releasedate"
"developer" "developer"
"publisher" "publisher"
"genre" "genre"
"players" "players"
"sortname" "favorite"
"hidden"
"kidgame"
"playcount"
"lastplayed"
]; ];
args = game.meta // { path = "@out@/${game.name}.sh"; };
in '' in ''
<game> <game>
${attrToXml (filterAttrs' attr args)} ${attrToXml (filterAttrs' attr args)}
@ -52,7 +59,7 @@ let
</gameList> </gameList>
''; '';
symlinkCommands = builtins.map ( symlinkCommands = builtins.map (
v: "ln -s ${v.src} $out/${v.filename}" v: "ln -s ${v}/${v.launchPath} $out/${v.name}.sh"
) games; ) games;
in pkgs.runCommand "${name}-roms" { in pkgs.runCommand "${name}-roms" {
@ -63,7 +70,7 @@ let
} '' } ''
mkdir -p $out mkdir -p $out
cp $gamelistPath $out/gamelist.xml cp $gamelistPath $out/gamelist.xml
substituteInPlace $out/gamelist.xml --subst-var out substituteAllInPlace $out/gamelist.xml
${lib.concatLines symlinkCommands} ${lib.concatLines symlinkCommands}
''; '';
@ -79,19 +86,18 @@ let
type = lib.types.str; type = lib.types.str;
default = name; default = name;
}; };
path = lib.mkOption { # TODO: check it works path = lib.mkOption {
type = lib.types.path; type = lib.types.path;
}; };
command = lib.mkOption { command = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "echo \"Hello world !\""; default = "%ROM%";
}; };
extension = lib.mkOption { extension = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = ".zip";
}; };
games = lib.mkOption { games = lib.mkOption {
type = lib.types.listOf gameOptions; type = lib.types.listOf lib.types.package;
description = "Takes attributes of `games` tag in gamelist.xml"; description = "Takes attributes of `games` tag in gamelist.xml";
}; };
}; };
@ -99,90 +105,64 @@ let
path = mkSystemPath config.name config.games; 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 { in {
options = { 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 { systems = lib.mkOption {
type = lib.types.attrsOf (sectionOptions); type = lib.types.attrsOf (sectionOptions);
default = {}; 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 = { config = {
retronix.emulationstation = { retronix.emulationstation = {
systemCfgFile = writeESDir "es_systems.cfg" '' systemCfgFile = pkgs.writeTextDir "es_systems.cfg" ''
<?xml version="1.0"?> <?xml version="1.0"?>
<systemList> <systemList>
${lib.concatLines (lib.mapAttrsToList (_: systemTemplate) cfg.systems)} ${lib.concatLines (lib.mapAttrsToList (_: systemTemplate) config.retronix.systems)}
</systemList> </systemList>
''; '';
inputCfgFile = lib.mkDefault (writeTextDir "es_input.cfg" cfg.inputCfg); inputCfgFile = lib.mkDefault (pkgs.writeTextDir "es_input.cfg" cfg.inputCfg);
homeDir = pkgs.symlinkJoinSubDir { homeDir = pkgs.symlinkJoinSubdir {
name = "es-config-dir"; name = "es-config-dir";
subdir = ".emulationstation";
paths = [ paths = [
cfg.systemCfgFile cfg.systemCfgFile
cfg.inputCfgFile cfg.inputCfgFile
] ++ cfg.extraConfigFiles; ] ++ 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: { final: prev: {
joy2keyd = final.python3.pkgs.callPackage ./joy2keyd {};
retropieSetup = final.callPackage ./retropie-setup.nix {}; retropieSetup = final.callPackage ./retropie-setup.nix {};
joy2keyd = final.python3.pkgs.callPackage ./joy2keyd {};
joy2key = final.callPackage ./joy2key.nix {}; joy2key = final.callPackage ./joy2key.nix {};
runcommand = final.callPackage ./runcommand.nix {}; runcommand = final.callPackage ./runcommand.nix {};
emulationstationPatched = final.emulationstation.overrideAttrs (_: previous: { emulationstationPatched = final.emulationstation.overrideAttrs (_: previous: {
patches = [ ./emulationstation.patch ]; patches = [ ./emulationstation.patch ];
}); });
symlinkJoinSubdir = symlinkJoinSubdir =
args_@{ name args_@{ name
, paths , paths
@ -29,4 +33,6 @@ final: prev: {
done done
${postBuild} ${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