big refactor on how games are built
This commit is contained in:
parent
7c41b132ec
commit
6f9cefa75f
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
/nixos.qcow2
|
/nixos.qcow2
|
||||||
/emulationstation-source
|
result
|
||||||
|
result-*
|
||||||
|
|
24
games.nix
24
games.nix
|
@ -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";
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
inputCfg = builtins.readFile ./es_input.cfg;
|
emulationstation.inputCfg = builtins.readFile ./es_input.cfg;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
5
launch_es.sh
Executable file
5
launch_es.sh
Executable 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
|
|
@ -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
|
|
@ -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,47 +105,16 @@ 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 = {
|
||||||
systems = lib.mkOption {
|
emulationstation = {
|
||||||
type = lib.types.attrsOf (sectionOptions);
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
systemCfgFile = lib.mkOption {
|
systemCfgFile = lib.mkOption {
|
||||||
type = lib.types.path;
|
type = lib.types.path;
|
||||||
};
|
};
|
||||||
inputCfgFile = lib.mkOption {
|
inputCfgFile = lib.mkOption {
|
||||||
type = lib.types.path;
|
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 {
|
themesDir = lib.mkOption {
|
||||||
type = lib.types.path;
|
type = lib.types.path;
|
||||||
};
|
};
|
||||||
|
@ -157,32 +132,37 @@ in {
|
||||||
description = ''
|
description = ''
|
||||||
Must be store paths.
|
Must be store paths.
|
||||||
Directory structure will be merged.
|
Directory structure will be merged.
|
||||||
Must contain .emulationstation folder
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
cli = lib.mkOption {
|
cli = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.package;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
systems = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (sectionOptions);
|
||||||
|
default = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
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";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
18
pkgs/roms/atetris.nix
Normal 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";
|
||||||
|
};
|
||||||
|
}
|
19
pkgs/roms/build/mkRetroarchRom.nix
Normal file
19
pkgs/roms/build/mkRetroarchRom.nix
Normal 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
54
pkgs/roms/build/mkRom.nix
Normal 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
12
pkgs/roms/default.nix
Normal 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
|
Loading…
Reference in a new issue