1{ pkgs, lib, ... }:
2{
3 name = "shadps4-openorbis-example";
4 meta = {
5 inherit (pkgs.shadps4.meta) maintainers;
6 };
7
8 nodes.machine =
9 { config, pkgs, ... }:
10 {
11 imports = [ ./common/x11.nix ];
12
13 environment = {
14 # Samples from the OpenOrbis PS4 homebrew toolchain, gpl3Only
15 etc."openorbis-sample-packages".source =
16 let
17 sample-packages = pkgs.fetchurl {
18 url = "https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/releases/download/v0.5.2/sample-packages.zip";
19 hash = "sha256-aWocIVpyMivA1vsUe9w97J3eMFANyXxyVLBxHGXIcEA=";
20 };
21 in
22 pkgs.runCommand "OpenOrbis-PNG-Sample"
23 {
24 nativeBuildInputs = with pkgs; [
25 unzip
26 liborbispkg-pkgtool
27 ];
28 meta.license = lib.licenses.gpl3Only;
29 }
30 ''
31 unzip ${sample-packages} samples/IV0000-BREW00086_00-IPNGDRAWEX000000.pkg
32 mkdir -p $out/OpenOrbis-PNG-Sample
33 pkgtool pkg_extract samples/IV0000-BREW00086_00-IPNGDRAWEX000000.pkg $out/OpenOrbis-PNG-Sample
34 '';
35
36 systemPackages = with pkgs; [
37 imagemagick # looking for colour on screen
38 shadps4
39 xdotool # move mouse
40 ];
41
42 variables = {
43 # Emulated CPU doesn't support invariant TSC
44 TRACY_NO_INVARIANT_CHECK = "1";
45 };
46 };
47
48 virtualisation.memorySize = 2048;
49 };
50
51 enableOCR = true;
52
53 testScript = ''
54 from collections.abc import Callable
55 import tempfile
56 import subprocess
57
58 selectionColor: str = "#354953"
59 openorbisColor: str = "#306082"
60
61 # Based on terminal-emulators.nix' check_for_pink
62 def check_for_color(color: str) -> Callable[[bool], bool]:
63 def check_for_color_retry(final=False) -> bool:
64 with tempfile.NamedTemporaryFile() as tmpin:
65 machine.send_monitor_command("screendump {}".format(tmpin.name))
66
67 cmd = 'convert {} -define histogram:unique-colors=true -format "%c" histogram:info:'.format(
68 tmpin.name
69 )
70 ret = subprocess.run(cmd, shell=True, capture_output=True)
71 if ret.returncode != 0:
72 raise Exception(
73 "image analysis failed with exit code {}".format(ret.returncode)
74 )
75
76 text = ret.stdout.decode("utf-8")
77 return color in text
78
79 return check_for_color_retry
80
81 machine.wait_for_x()
82
83 with subtest("starting shadps4 works"):
84 machine.succeed("shadps4 >&2 &")
85 machine.wait_for_text("Directory to install games")
86 machine.screenshot("0001-shadps4-dir-setup-prompt")
87
88 machine.send_chars("/root\n")
89 machine.wait_for_text("Game List")
90 # Make it fullscreen, so mouse coords are simpler & content isn't cut off
91 machine.send_key("alt-f10")
92 # Should now see the rest too
93 machine.wait_for_text("Play Time")
94 machine.screenshot("0002-shadps4-started")
95
96 with subtest("running example works"):
97 # Ensure that chosen openorbis logo colour isn't present already
98 assert (
99 check_for_color(openorbisColor)(True) == False
100 ), "openorbisColor {} was present on the screen before we launched anything!".format(openorbisColor)
101
102 machine.succeed("xdotool mousemove 20 30 click 1") # click on "File"
103 machine.wait_for_text("Boot Game")
104 machine.send_key("down")
105 machine.send_key("ret")
106
107 # Pick the PNG sample (hello world runs too, but text-only output is currently broken)
108 machine.wait_for_text("Look in")
109 machine.send_chars("/etc/openorbis-sample-packages/OpenOrbis-PNG-Sample/uroot/eboot.bin\n")
110
111 # Look for logo
112 with machine.nested("Waiting for the screen to have openorbisColor {} on it:".format(openorbisColor)):
113 retry(check_for_color(openorbisColor))
114 machine.screenshot("0003-shadps4-sample-running")
115 '';
116}