161 lines
6.2 KiB
Markdown
161 lines
6.2 KiB
Markdown
# 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
|
||
|
||
```sh
|
||
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
|
||
|
||
```sh
|
||
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:
|
||
|
||
```sh
|
||
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`
|
||
|
||
```sh
|
||
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:
|
||
|
||
```sh
|
||
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_t`s.
|
||
- `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.
|