1{
2 apple-sdk_13,
3 stdenv,
4 cmake,
5 lsb-release,
6 ninja,
7 lib,
8 fetchFromGitHub,
9 fetchurl,
10 copyDesktopItems,
11 makeDesktopItem,
12 python3,
13 glew,
14 boost,
15 SDL2,
16 SDL2_net,
17 pkg-config,
18 libpulseaudio,
19 libpng,
20 imagemagick,
21 zenity,
22 makeWrapper,
23 darwin,
24 libicns,
25 libzip,
26 nlohmann_json,
27 tinyxml-2,
28 spdlog,
29 writeTextFile,
30 fixDarwinDylibNames,
31 applyPatches,
32 shipwright,
33}:
34
35let
36
37 # The following would normally get fetched at build time, or a specific version is required
38
39 gamecontrollerdb = fetchFromGitHub {
40 owner = "mdqinc";
41 repo = "SDL_GameControllerDB";
42 rev = "a74711e1e87733ccdf02d7020d8fa9e4fa67176e";
43 hash = "sha256-rXC4akz9BaKzr/C2CryZC6RGk6+fGVG7RsQryUFUUk0=";
44 };
45
46 imgui' = applyPatches {
47 src = fetchFromGitHub {
48 owner = "ocornut";
49 repo = "imgui";
50 tag = "v1.91.6-docking";
51 hash = "sha256-28wyzzwXE02W5vbEdRCw2iOF8ONkb3M3Al8XlYBvz1A=";
52 };
53 patches = [
54 "${shipwright.src}/libultraship/cmake/dependencies/patches/imgui-fixes-and-config.patch"
55 ];
56 };
57
58 libgfxd = fetchFromGitHub {
59 owner = "glankk";
60 repo = "libgfxd";
61 rev = "008f73dca8ebc9151b205959b17773a19c5bd0da";
62 hash = "sha256-AmHAa3/cQdh7KAMFOtz5TQpcM6FqO9SppmDpKPTjTt8=";
63 };
64
65 prism = fetchFromGitHub {
66 owner = "KiritoDv";
67 repo = "prism-processor";
68 rev = "fb3f8b4a2d14dfcbae654d0f0e59a73b6f6ca850";
69 hash = "sha256-gGdQSpX/TgCNZ0uyIDdnazgVHpAQhl30e+V0aVvTFMM=";
70 };
71
72 stb_impl = writeTextFile {
73 name = "stb_impl.c";
74 text = ''
75 #define STB_IMAGE_IMPLEMENTATION
76 #include "stb_image.h"
77 '';
78 };
79
80 stb' = fetchurl {
81 name = "stb_image.h";
82 url = "https://raw.githubusercontent.com/nothings/stb/0bc88af4de5fb022db643c2d8e549a0927749354/stb_image.h";
83 hash = "sha256-xUsVponmofMsdeLsI6+kQuPg436JS3PBl00IZ5sg3Vw=";
84 };
85
86 stormlib' = applyPatches {
87 src = fetchFromGitHub {
88 owner = "ladislav-zezula";
89 repo = "StormLib";
90 tag = "v9.25";
91 hash = "sha256-HTi2FKzKCbRaP13XERUmHkJgw8IfKaRJvsK3+YxFFdc=";
92 };
93 patches = [
94 "${shipwright.src}/libultraship/cmake/dependencies/patches/stormlib-optimizations.patch"
95 ];
96 };
97
98 thread_pool = fetchFromGitHub {
99 owner = "bshoshany";
100 repo = "thread-pool";
101 tag = "v4.1.0";
102 hash = "sha256-zhRFEmPYNFLqQCfvdAaG5VBNle9Qm8FepIIIrT9sh88=";
103 };
104
105 metalcpp = fetchFromGitHub {
106 owner = "briaguya-ai";
107 repo = "single-header-metal-cpp";
108 tag = "macOS13_iOS16";
109 hash = "sha256-CSYIpmq478bla2xoPL/cGYKIWAeiORxyFFZr0+ixd7I";
110 };
111in
112stdenv.mkDerivation (finalAttrs: {
113 pname = "shipwright";
114 version = "9.0.2";
115
116 src = fetchFromGitHub {
117 owner = "harbourmasters";
118 repo = "shipwright";
119 tag = finalAttrs.version;
120 hash = "sha256-xmRUUMjQt3CFJ0GxlUsUqmp//XTRWik3jSD4auql7Nk=";
121 fetchSubmodules = true;
122 deepClone = true;
123 postFetch = ''
124 cd $out
125 git branch --show-current > GIT_BRANCH
126 git rev-parse --short=7 HEAD > GIT_COMMIT_HASH
127 (git describe --tags --abbrev=0 --exact-match HEAD 2>/dev/null || echo "") > GIT_COMMIT_TAG
128 rm -rf .git
129 '';
130 };
131
132 patches = [
133 ./darwin-fixes.patch
134 ./disable-downloading-stb_image.patch
135 ];
136
137 nativeBuildInputs = [
138 cmake
139 ninja
140 pkg-config
141 python3
142 imagemagick
143 makeWrapper
144 ]
145 ++ lib.optionals stdenv.hostPlatform.isLinux [
146 lsb-release
147 copyDesktopItems
148 ]
149 ++ lib.optionals stdenv.hostPlatform.isDarwin [
150 libicns
151 darwin.sigtool
152 fixDarwinDylibNames
153 ];
154
155 buildInputs = [
156 boost
157 glew
158 SDL2
159 SDL2_net
160 libpng
161 libzip
162 nlohmann_json
163 tinyxml-2
164 spdlog
165 ]
166 ++ lib.optionals stdenv.hostPlatform.isLinux [
167 libpulseaudio
168 zenity
169 ]
170 ++ lib.optionals stdenv.hostPlatform.isDarwin [
171 # Metal.hpp requires macOS 13.x min.
172 apple-sdk_13
173 ];
174
175 cmakeFlags = [
176 (lib.cmakeBool "BUILD_REMOTE_CONTROL" true)
177 (lib.cmakeBool "NON_PORTABLE" true)
178 (lib.cmakeFeature "CMAKE_INSTALL_PREFIX" "${placeholder "out"}/lib")
179 (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_IMGUI" "${imgui'}")
180 (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_LIBGFXD" "${libgfxd}")
181 (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_PRISM" "${prism}")
182 (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_STORMLIB" "${stormlib'}")
183 (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_THREADPOOL" "${thread_pool}")
184 ]
185 ++ lib.optionals stdenv.hostPlatform.isDarwin [
186 (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_METALCPP" "${metalcpp}")
187 (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_SPDLOG" "${spdlog}")
188 ];
189
190 env.NIX_CFLAGS_COMPILE = lib.optionalString stdenv.hostPlatform.isDarwin "-Wno-int-conversion -Wno-implicit-int -Wno-elaborated-enum-base";
191
192 dontAddPrefix = true;
193
194 # Linking fails without this
195 hardeningDisable = [ "format" ];
196
197 preConfigure = ''
198 mkdir stb
199 cp ${stb'} ./stb/${stb'.name}
200 cp ${stb_impl} ./stb/${stb_impl.name}
201 substituteInPlace libultraship/cmake/dependencies/common.cmake \
202 --replace-fail "\''${STB_DIR}" "$(readlink -f ./stb)"
203 '';
204
205 postPatch = ''
206 substituteInPlace soh/src/boot/build.c.in \
207 --replace-fail "@CMAKE_PROJECT_GIT_BRANCH@" "$(cat GIT_BRANCH)" \
208 --replace-fail "@CMAKE_PROJECT_GIT_COMMIT_HASH@" "$(cat GIT_COMMIT_HASH)" \
209 --replace-fail "@CMAKE_PROJECT_GIT_COMMIT_TAG@" "$(cat GIT_COMMIT_TAG)"
210 '';
211
212 postBuild = ''
213 port_ver=$(grep CMAKE_PROJECT_VERSION: "$PWD/CMakeCache.txt" | cut -d= -f2)
214 cp ${gamecontrollerdb}/gamecontrollerdb.txt gamecontrollerdb.txt
215 mv ../libultraship/src/graphic/Fast3D/shaders ../soh/assets/custom
216 pushd ../OTRExporter
217 python3 ./extract_assets.py -z ../build/ZAPD/ZAPD.out --norom --xml-root ../soh/assets/xml --custom-assets-path ../soh/assets/custom --custom-otr-file soh.otr --port-ver $port_ver
218 popd
219 '';
220
221 preInstall = ''
222 # Cmake likes it here for its install paths
223 cp ../OTRExporter/soh.otr soh/soh.otr
224 '';
225
226 postInstall =
227 lib.optionalString stdenv.hostPlatform.isLinux ''
228 mkdir -p $out/bin
229 ln -s $out/lib/soh.elf $out/bin/soh
230 install -Dm644 ../soh/macosx/sohIcon.png $out/share/pixmaps/soh.png
231 ''
232 + lib.optionalString stdenv.hostPlatform.isDarwin ''
233 # Recreate the macOS bundle (without using cpack)
234 # We mirror the structure of the bundle distributed by the project
235
236 mkdir -p $out/Applications/soh.app/Contents
237 cp $src/soh/macosx/Info.plist.in $out/Applications/soh.app/Contents/Info.plist
238 substituteInPlace $out/Applications/soh.app/Contents/Info.plist \
239 --replace-fail "@CMAKE_PROJECT_VERSION@" "${finalAttrs.version}"
240
241 mv $out/MacOS $out/Applications/soh.app/Contents/MacOS
242
243 # "lib" contains all resources that are in "Resources" in the official bundle.
244 # We move them to the right place and symlink them back to $out/lib,
245 # as that's where the game expects them.
246 mv $out/Resources $out/Applications/soh.app/Contents/Resources
247 mv $out/lib/** $out/Applications/soh.app/Contents/Resources
248 rm -rf $out/lib
249 ln -s $out/Applications/soh.app/Contents/Resources $out/lib
250
251 # Copy icons
252 cp -r ../build/macosx/soh.icns $out/Applications/soh.app/Contents/Resources/soh.icns
253
254 # Codesign (ad-hoc)
255 codesign -f -s - $out/Applications/soh.app/Contents/MacOS/soh
256 '';
257
258 fixupPhase = lib.optionalString stdenv.hostPlatform.isLinux ''
259 wrapProgram $out/lib/soh.elf --prefix PATH ":" ${lib.makeBinPath [ zenity ]}
260 '';
261
262 desktopItems = [
263 (makeDesktopItem {
264 name = "soh";
265 icon = "soh";
266 exec = "soh";
267 comment = finalAttrs.meta.description;
268 genericName = "Ship of Harkinian";
269 desktopName = "soh";
270 categories = [ "Game" ];
271 })
272 ];
273
274 meta = {
275 homepage = "https://github.com/HarbourMasters/Shipwright";
276 description = "PC port of Ocarina of Time with modern controls, widescreen, high-resolution, and more";
277 mainProgram = "soh";
278 platforms = lib.platforms.linux ++ lib.platforms.darwin;
279 maintainers = with lib.maintainers; [
280 j0lol
281 matteopacini
282 ];
283 license = with lib.licenses; [
284 # OTRExporter, OTRGui, ZAPDTR, libultraship
285 mit
286 # Ship of Harkinian itself
287 unfree
288 ];
289 };
290})