Files
DOOM/linuxdoom-1.10/README.macos.md
gronod 6aaf73d70c
Build macOS app / Build DOOM.app (push) Canceled after 0s
macOS port: add app build workflow
2026-09-18 20:01:16 +01:00

6.2 KiB
Raw Permalink Blame History

linuxdoom 1.10 — macOS port

This tree is the original linuxdoom 1.10 source, ported to build and run natively on macOS (12.0+, x86_64). X11/MIT-SHM video and Linux OSS audio were replaced with SDL2 and Apple AudioToolbox while keeping the original software renderer and sound mixer.

There are two ways to build:

Output SDL2 IWAD
App bundle (recommended) DOOM.app vendored SDL2.framework, embedded bundled FreeDoom, runs standalone
CLI binary linuxdoom-1.10/macos/doom Homebrew sdl2 bring your own via DOOMWADDIR

App bundle: DOOM.app

The committed DOOM.xcodeproj (at the repo root) builds a self-contained DOOM.app: it embeds a real SDL2 2.30.x SDL2.framework (not sdl2-compat, so no SDL3 dependency) and an IWAD, so the result runs on any macOS 12+ x86_64 machine with no Homebrew install.

One-time dependency fetch

macos-app/Scripts/fetch-deps.sh

This downloads SDL2.framework into macos-app/Frameworks/ (pinned to 2.30.12) and makes sure at least one IWAD is in macos-app/Resources/: any *.wad in the repo's wads/ dir is copied first, otherwise freedoom2.wad is downloaded (pinned to FreeDoom 0.13.0). The script is idempotent and also runs as the first Xcode build phase, so it's safe to skip this step and let the build do it — it only needs the network once.

Build

open DOOM.xcodeproj        # then ⌘R
# or
xcodebuild -scheme DOOM -configuration Release

The product lands in the usual DerivedData location (.../Build/Products/Release/DOOM.app).

Where things live at runtime

When launched as a bundle (Finder or open DOOM.app), the working directory is /, so the app chdir()s to its data directory:

  • Savegames / screenshots: ~/Library/Application Support/DOOM/
  • Config: $HOME/.doomrc (absolute path, unchanged upstream)

IWAD search order

The engine checks each IWAD filename across all search dirs before moving to the next name, so a higher-priority IWAD anywhere wins:

  • Filenames (high → low): doom2f (French), doom2, plutonia, tnt, doomu, doom, doom1, freedoom2, freedoom1
  • Directories (high → low): $DOOMWADDIR, bundle Contents/Resources, ~/Library/Application Support/DOOM, .

Consequences:

  • doom.wad in macos-app/Resources/ beats the bundled freedoom2.wad.
  • A doom2.wad dropped in ~/Library/Application Support/DOOM beats a bundled freedoom2.wad (filenames are compared before directories).
  • To bundle your own IWAD, drop it in macos-app/Resources/ (or wads/ before running fetch-deps.sh) and rebuild.

Command-line arguments

The scheme ships with no arguments. To add some (-3, -warp 1 1, -file foo.wad), edit the scheme in Xcode (Product ▸ Scheme ▸ Edit Scheme ▸ Run ▸ Arguments). Equivalent from a terminal:

DOOM.app/Contents/MacOS/DOOM -warp 1 1

Signing

The target signs ad-hoc (CODE_SIGN_IDENTITY = "-"). That's fine on the machine that built it; on other Macs Gatekeeper will complain — either right-click ▸ Open, or re-sign with a Developer ID for real distribution.

CLI binary: make

brew install sdl2    # sdl2-compat (SDL3-backed) also works
cd linuxdoom-1.10 && make

Produces linuxdoom-1.10/macos/doom. Needs an IWAD via DOOMWADDIR or cwd:

DOOMWADDIR=/path/to/wads ./macos/doom

The same IWAD search order above applies (App Support dir included), so IWADs are shared between the app and the CLI binary.

Useful options

Option Effect
-2 / -3 / -4 Start at 640×480, 960×720, or 1280×960
-fullscreen Fullscreen (scaled desktop mode)
-grabmouse Grab the mouse (relative mouse mode)
-warp E M Warp to episode/map, e.g. -warp 1 1
-nomouse / -nojoy Disable input devices

The window is freely resizable down to 640×480. DOOM keeps its original 320×200 internal framebuffer and scales it with nearest-neighbour filtering into the largest centered 4:3 area, adding black bars for wider or taller windows. SDL's renderer output size is used so the presentation also stays correct on Retina displays.

A new configuration starts at 960×720. Normal window resizing updates the window_width and window_height settings in .doomrc, and that windowed size is restored on the next launch. Fullscreen size changes and the -2, -3, and -4 startup presets do not overwrite the remembered size unless the window is subsequently resized by the user.

Porting notes

  • i_video.c — resizable, high-DPI SDL2 window/renderer/streaming ARGB8888 texture; the 320x200 indexed framebuffer is palette-expanded each frame and aspect-corrected to 4:3 for presentation. Keyboard/mouse SDL events are translated to DOOM event_ts.
  • i_sound.c — original software mixer retained; output is queued to an SDL2 audio device (11025 Hz s16 stereo) instead of /dev/dsp. Music lumps are converted by mus2mid.c (MUS→MIDI; already-MIDI lumps pass through) and played with AudioToolbox MusicSequence/MusicPlayer through the system DLS synth — no SDL_mixer or soundfont needed. Track looping uses kSequenceTrackProperty_LoopInfo.
  • i_mac.c — bundle detection (CFBundleGetIdentifier), resource-dir and ~/Library/Application Support/DOOM lookup, and the bundled-app chdir() that redirects all relative-path writes (savegames, screenshots) somewhere writable.
  • 64-bit fixes: pointer-size casts in the renderer, savegame code, zone allocator and m_misc defaults; WAD maptexture_t layout corrected (columndirectory is a 4-byte offset, not a pointer); *4-sized allocations for pointer arrays fixed; unsequenced eventhead/eventtail updates made well-defined.
  • Networking (i_net.c) still uses UDP/BSD sockets and should work for -net play; it is unchanged apart from byte-order/socket fixes.

Known limitations

  • Embedded demo lumps recorded for other engine versions print "Demo is from a different game version" — use -warp to skip the title-screen demo loop if the IWAD's demos mismatch (e.g. FreeDoom).
  • Music volume slider is tracked but not applied to the MusicPlayer (AudioToolbox has no per-sequence gain at this API level).
  • x86_64 only; no arm64 slice. sndserv/, ipx/, sersrc/ are unused by this port.