1{
2 lib,
3 stdenv,
4 fetchFromGitHub,
5 alsa-lib,
6 SDL2,
7 SDL2_ttf,
8 copyDesktopItems,
9 expat,
10 fetchpatch,
11 fetchurl,
12 flac,
13 fontconfig,
14 glm,
15 installShellFiles,
16 libXi,
17 libXinerama,
18 libjpeg,
19 libpcap,
20 libpulseaudio,
21 makeDesktopItem,
22 makeWrapper,
23 pkg-config,
24 portaudio,
25 portmidi,
26 pugixml,
27 python3,
28 qtbase,
29 rapidjson,
30 sqlite,
31 utf8proc,
32 versionCheckHook,
33 which,
34 wrapQtAppsHook,
35 writeScript,
36 zlib,
37}:
38
39stdenv.mkDerivation rec {
40 pname = "mame";
41 version = "0.278";
42 srcVersion = builtins.replaceStrings [ "." ] [ "" ] version;
43
44 src = fetchFromGitHub {
45 owner = "mamedev";
46 repo = "mame";
47 rev = "mame${srcVersion}";
48 hash = "sha256-YJt+in9QV7a0tQZnfqFP3Iu6XQD0sryjud4FcgokYFg=";
49 };
50
51 outputs = [
52 "out"
53 "tools"
54 ];
55
56 makeFlags = [
57 "CC=${stdenv.cc.targetPrefix}cc"
58 "CXX=${stdenv.cc.targetPrefix}c++"
59 "TOOLS=1"
60 "USE_LIBSDL=1"
61 # "USE_SYSTEM_LIB_ASIO=1"
62 "USE_SYSTEM_LIB_EXPAT=1"
63 "USE_SYSTEM_LIB_FLAC=1"
64 "USE_SYSTEM_LIB_GLM=1"
65 "USE_SYSTEM_LIB_JPEG=1"
66 # https://www.mamedev.org/?p=523
67 # "USE_SYSTEM_LIB_LUA=1"
68 "USE_SYSTEM_LIB_PORTAUDIO=1"
69 "USE_SYSTEM_LIB_PORTMIDI=1"
70 "USE_SYSTEM_LIB_PUGIXML=1"
71 "USE_SYSTEM_LIB_RAPIDJSON=1"
72 "USE_SYSTEM_LIB_UTF8PROC=1"
73 "USE_SYSTEM_LIB_SQLITE3=1"
74 "USE_SYSTEM_LIB_ZLIB=1"
75 ];
76
77 # https://docs.mamedev.org/initialsetup/compilingmame.html
78 buildInputs = [
79 expat
80 zlib
81 flac
82 portmidi
83 portaudio
84 utf8proc
85 libjpeg
86 rapidjson
87 pugixml
88 glm
89 SDL2
90 SDL2_ttf
91 sqlite
92 qtbase
93 ]
94 ++ lib.optionals stdenv.hostPlatform.isLinux [
95 alsa-lib
96 libpulseaudio
97 libXinerama
98 libXi
99 fontconfig
100 ]
101 ++ lib.optionals stdenv.hostPlatform.isDarwin [
102 libpcap
103 ];
104
105 nativeBuildInputs = [
106 copyDesktopItems
107 installShellFiles
108 makeWrapper
109 pkg-config
110 python3
111 which
112 wrapQtAppsHook
113 ];
114
115 patches = [
116 # by default MAME assumes that paths with stock resources are relative and
117 # that you run MAME changing to install directory, so we add absolute paths
118 # here
119 ./001-use-absolute-paths.diff
120 ]
121 ++ lib.optionals stdenv.hostPlatform.isDarwin [
122 # coreaudio_sound.cpp compares __MAC_OS_X_VERSION_MIN_REQUIRED to 1200
123 # instead of 120000, causing it to try to use a constant that isn't
124 # actually defined yet when targeting macOS 11 like Nixpkgs does.
125 # Backport mamedev/mame#13890 until the next time we update MAME.
126 (fetchpatch {
127 url = "https://patch-diff.githubusercontent.com/raw/mamedev/mame/pull/13890.patch";
128 hash = "sha256-Fqpw4fHEMns4tSSIjc1p36ss+J9Tc/O0cnN3HI/ratM=";
129 })
130 ];
131
132 # Since the bug described in https://github.com/NixOS/nixpkgs/issues/135438,
133 # it is not possible to use substituteAll
134 postPatch = ''
135 for file in src/emu/emuopts.cpp src/osd/modules/lib/osdobj_common.cpp; do
136 substituteInPlace "$file" \
137 --subst-var-by mamePath "$out/opt/mame"
138 done
139 ''
140 # MAME's build system uses `sw_vers` to test whether it needs to link with
141 # the Metal framework or not. However:
142 # a) that would return the build system's version, not the target's, and
143 # b) it can't actually find `sw_vers` in $PATH, so it thinks it's on macOS
144 # version 0, and doesn't link with Metal - causing missing symbol errors
145 # when it gets to the link step, because other parts of the build system
146 # _do_ use the correct target version number.
147 # This replaces the `sw_vers` call with the macOS version actually being
148 # targeted, so everything gets linked correctly.
149 + lib.optionalString stdenv.hostPlatform.isDarwin ''
150 for file in scripts/src/osd/{mac,sdl}.lua; do
151 substituteInPlace "$file" --replace-fail \
152 'backtick("sw_vers -productVersion")' \
153 "os.getenv('MACOSX_DEPLOYMENT_TARGET') or '$darwinMinVersion'"
154 done
155 '';
156
157 desktopItems = [
158 (makeDesktopItem {
159 name = "MAME";
160 desktopName = "MAME";
161 exec = "mame";
162 icon = "mame";
163 type = "Application";
164 genericName = "MAME is a multi-purpose emulation framework";
165 comment = "Play vintage games using the MAME emulator";
166 categories = [
167 "Game"
168 "Emulator"
169 ];
170 keywords = [
171 "Game"
172 "Emulator"
173 "Arcade"
174 ];
175 })
176 ];
177
178 # TODO: copy shaders from src/osd/modules/opengl/shader/glsl*.*h
179 # to the final package after we figure out how they work
180 installPhase =
181 let
182 icon = fetchurl {
183 url = "https://raw.githubusercontent.com/PapirusDevelopmentTeam/papirus-icon-theme/refs/heads/master/Papirus/32x32/apps/mame.svg";
184 hash = "sha256-s44Xl9UGizmddd/ugwABovM8w35P0lW9ByB69MIpG+E=";
185 };
186 in
187 ''
188 runHook preInstall
189
190 # mame
191 mkdir -p $out/opt/mame
192
193 install -Dm755 mame -t $out/bin
194 install -Dm644 ${icon} $out/share/icons/hicolor/scalable/apps/mame.svg
195 installManPage docs/man/*.1 docs/man/*.6
196 cp -ar {artwork,bgfx,plugins,language,ctrlr,keymaps,hash} $out/opt/mame
197
198 # mame-tools
199 for _tool in castool chdman floptool imgtool jedutil ldresample ldverify \
200 nltool nlwav pngcmp regrep romcmp split srcclean testkeys \
201 unidasm; do
202 install -Dm755 $_tool -t $tools/bin
203 done
204 mv $tools/bin/{,mame-}split
205
206 runHook postInstall
207 '';
208
209 # man1 is the tools documentation, man6 is the emulator documentation
210 # Need to be done in postFixup otherwise multi-output hook will move it back to $out
211 postFixup = ''
212 moveToOutput share/man/man1 $tools
213 '';
214
215 enableParallelBuilding = true;
216
217 doInstallCheck = true;
218 nativeInstallCheckInputs = [ versionCheckHook ];
219 versionCheckProgramArg = "-h";
220
221 passthru.updateScript = writeScript "mame-update-script" ''
222 #!/usr/bin/env nix-shell
223 #!nix-shell -i bash -p curl common-updater-scripts jq
224
225 set -eu -o pipefail
226
227 latest_version=$(curl -s https://api.github.com/repos/mamedev/mame/releases/latest | jq --raw-output .tag_name)
228 update-source-version mame "''${latest_version/mame0/0.}"
229 '';
230
231 meta = {
232 homepage = "https://www.mamedev.org/";
233 description = "Multi-purpose emulation framework";
234 longDescription = ''
235 MAME's purpose is to preserve decades of software history. As electronic
236 technology continues to rush forward, MAME prevents this important
237 "vintage" software from being lost and forgotten. This is achieved by
238 documenting the hardware and how it functions. The source code to MAME
239 serves as this documentation. The fact that the software is usable serves
240 primarily to validate the accuracy of the documentation (how else can you
241 prove that you have recreated the hardware faithfully?). Over time, MAME
242 (originally stood for Multiple Arcade Machine Emulator) absorbed the
243 sister-project MESS (Multi Emulator Super System), so MAME now documents a
244 wide variety of (mostly vintage) computers, video game consoles and
245 calculators, in addition to the arcade video games that were its initial
246 focus.
247 '';
248 changelog = "https://github.com/mamedev/mame/releases/download/mame${srcVersion}/whatsnew_${srcVersion}.txt";
249 license = with lib.licenses; [
250 bsd3
251 gpl2Plus
252 ];
253 maintainers = with lib.maintainers; [
254 thiagokokada
255 DimitarNestorov
256 ];
257 platforms = lib.platforms.unix;
258 mainProgram = "mame";
259 };
260}