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