# Dab's Mod **[Download](https://github.com/DabDavis/perfect-dark-dabs-mod/releases/latest)** — Windows, Linux and macOS. You supply the ROM; see [You need a ROM](#you-need-a-rom). There is also a [rolling dev build](https://github.com/DabDavis/perfect-dark-dabs-mod/releases/tag/dabs-mod-dev) of the newest commit, if you want fixes before they reach a release. A fork of the [Perfect Dark PC port](https://github.com/perfect-dark-pc-port/perfect_dark), which is itself a port of the [Perfect Dark decompilation](https://github.com/n64decomp/perfect_dark). It adds movement the N64 game never had — jump, a combat roll, melee combos, a third person camera — raises the Combat Simulator simulant cap from 8 to 80, keeps bodies lying where they fell, and gives you a free-flying spectator camera, a screenshot key and a video recorder for watching the results. Everything here is engine-side and lives in the executable. No custom levels or assets are bundled, and none are needed - but mods drop in, see [Mods](#mods). ## You need a ROM This is an executable, not a game. It reads every texture, model, level and line of dialogue out of a Perfect Dark ROM at startup, and ships with none of that. You need `Perfect Dark (USA) (Rev 1)`, also called `ntsc-final` or `US V1.1` — md5 `e03b088b6ac9e0080440efed07c1e40f`, and the one the boot screen calls `NTSC version 8.7 final`. Dumping it from your own cartridge is on you; don't ask here. PAL and JPN ROMs are not supported by this fork. The stock port supports them if you need one. ## Running it 1. Unpack the download somewhere. 2. Put your ROM in the `data` folder next to the executable, named exactly **`pd.ntsc-final.z64`**. (The folder is already there, with a `put_your_rom_here.txt` in it.) 3. Run it: - **Windows** — `pd.x86_64.exe` - **Linux** — `./pd.x86_64` - **macOS** — `./pd.x86_64` or `./pd.arm64`, whichever matches your machine If the ROM is missing or is the wrong one, the game says so in a dialog box and names the exact directory it looked in. On Linux and macOS you can put the `data` folder in `~/.local/share/perfectdark` or `~/Library/Application Support/perfectdark` instead, and `--basedir ` overrides both. macOS will refuse to run an unsigned binary downloaded from the internet. Either right-click → Open, or run `xattr -dr com.apple.quarantine .` in the unpacked folder. A GPU with OpenGL 3.0 / ES 3.0 or better is required. ## What it adds All of the fork's settings are under **Options → Extended Options → Dab's Mod Options**, on five pages that swipe left and right the way the Perfect Menu swipes to Options: **Player**, **Camera**, **Display**, **Missions** and **Recording**. A key bind sits on the page of the feature it drives. Each setting persists to `pd.ini` under a `Mod.` key. ### Movement | Setting | What it does | | - | - | | Jump | Off, or a height from 1 to 5. Bound to the **use** button, behind whatever that button opens — doors and objects still take priority | | Jump For | Whether simulants jump too, or only players | | Combat Roll | A dodge roll. **C** on the keyboard, right stick click on a pad | | Melee Combos | The punch and kick combos solo play has always had, in multiplayer | | Flinch When Shot | Bodies react to where the shot landed instead of ignoring it | | Start Armed | Spawn holding a weapon — the arena's, or a random one. Off by default, because stock is off. In a solo mission, Random adds a random gun to the mission's kit; First Weapon changes nothing there, the mission having armed you already | | Start Armed For | Whether simulants spawn armed too, or only players | | Mission Respawn | A death in a solo mission is a new life where you fell, with full health and everything you were carrying, instead of Mission Failed. Off by default | | Lives | How many lives a mission has in all: Unlimited, or 5 to 50 in fives. With 5, the fifth death ends the mission | ### Third person **V** on the keyboard, Back on a pad, in solo and multiplayer both. You drop back to first person while aiming. Camera Distance and Camera Wall Clearance tune the framing. A wall behind you brings the camera in, as far as the eye if it must, and your character fades out as it comes close (Camera Body Fade is how close) rather than the view cutting to first person. **Camera Tether** makes the camera a pole attached to you instead of one bolted to the back of your head. The right stick orbits the camera all the way round you, the left stick moves you in screen space and you turn to face the way you go, and holding the trigger turns you to face the camera, which is where the shot goes. The pole is elastic: strafing swings it round and it settles back behind the camera. Loose lets it swing further and takes its time, Tight holds it close and is nearly a rigid pole. Off is the rigid camera, with you always facing the aim, and is the default. Body Turn Speed is how fast you come round to face the way you are going, in degrees per frame: 30 by default, 90 is as good as instant. ### Picture Built in, no pack needed. Texture Upscale, Supersampling and TAA are under Extended Video Options; the rest share a page of their own. | Setting | What it does | | - | - | | Thin Text Outlines | Outlined text gets a thin halo drawn by the renderer instead of the black cell the font bakes in, which at monitor resolutions is a slab behind every letter. Off is the bold border the cell stands for, drawn the same way | | Smooth Text | The font's glyphs are scaled up four times over with their edges sharpened, so letters have a clean edge instead of a staircase of blurred squares. Off by default | | Texture Upscale | The game's own textures scaled up two, four or eight times over as they load, resampled through a curve rather than the GPU's straight blend. Nothing is invented, but a 32-texel wall stops being a grid of soft blobs. Textures that are themselves a dot pattern, like a halftone portrait or a screen of tiny text, are left alone. 2x by default; 4x costs four times the video memory and 8x sixteen | | Supersampling | The game drawn at 1.5 or 2 times the window and averaged down to it, which smooths every edge, including the alpha cut-outs and texture detail MSAA leaves alone. Stacks with MSAA and SMAA. 2x draws four times the pixels, so it is for a strong GPU; the drawn frame stops at 8192 pixels on its longer side. Off by default, and choosing it turns FSR Upscaling off, since both set the size the game draws at | | TAA | Temporal anti-aliasing, the last choice under Anti-aliasing: the world is drawn a fraction of a pixel off each frame and blended with the frames before it, following the camera through the depth buffer, so edges, thin rails and texture shimmer settle. The gun and the HUD are drawn after it and stay sharp. It takes MSAA's place rather than stacking with it; SMAA and Supersampling still add. Things that move on their own, like guards, can soften slightly while they move | | Vivid Colours | Saturation and contrast turned up on the finished frame, which was drawn for a CRT and looks flat on a panel. Light by default; Normal and Heavy go further. Screenshots and recordings get it too | | Black Level | A floor taken off the frame's blacks, so black is black rather than dark grey, without crushing the shadows above it the way contrast would. Light takes 2% off and is the default; Normal 4%, Heavy 7% | Texture packs, where installed, are left alone by Texture Upscale and Smooth Text: their images are already whatever size their author chose. ### Simulants Up to **80** in a Combat Simulator match, set the usual way in the simulant menu. Stock hides any count above four until ten Combat Simulator challenges are done; this fork does not gate its own cap, so all 80 are there on a fresh profile. The four Bond heads that share that unlock are still earned normally. The save file only grows past the stock 8-simulant format when a setup actually needs it, so ordinary setups stay readable by an unmodified port. Each simulant has its own **Stats...** page under its entry in the simulant menu, with five sliders from 10% to 500% of what its type and difficulty give it. All start at 100%, a stock simulant. | Slider | What it scales | |---|---| | Speed | Top running speed | | Accuracy | How far its aim strays from the target; 500% is a fifth of the error | | Reaction | How soon it fires once it sees someone, and how fast its aim settles | | Damage | Damage it deals | | Toughness | Damage it takes, to shield and health alike; 500% takes a fifth | **Reset to Stock** puts all five back, **Copy Simulant** carries them to the copy, and they save with the setup. A challenge or a preset always plays stock simulants. A setup file that holds a moved slider is in a newer format that older builds of this fork cannot read; one with every slider at 100% is not. ### Bodies Bodies stay where they fell instead of vanishing. **Bodies** caps how many are kept (up to 500), **Body Time** how long each lies there, and **Bodies Drawn** how many may be drawn in one frame — lower that one first if the frame rate suffers, since the bodies still exist, they just aren't all rendered. ### Spectator A camera that comes off the player and flies through the level, including outside it. **F** on the keyboard. **Start Spectating** enters it automatically on every stage; **Spectator Start Game** in the Combat Simulator menu arms it for one match only. Spectator Speed sets how fast it flies. Combined with a match with no time or score limit, it's the tool for watching 80 simulants fight. ### Playing online Combat Simulator matches can be played over the internet with up to twelve players, their simulants and two spectators. One player's game hosts the match (a listen server); everyone else's connects to it. A full room of twelve needs about 2 Mbit/s of upload from the host. **Rooms.** **Online Game** is on the main menu. The GoldenEye and ROM hack modes have the row in their Combat Simulator instead, where a room is made on their own arenas. Online play uses your Ghost Trials account. The page's **Sign In** row opens the account page (the same one as Ghost Trials > Account): type a name and a PIN and press **Sign In**. There is no separate Create Account - a name nobody has yet becomes your account, after you pick three security questions (they are only used to reset a forgotten PIN). The Online Game page signs in as it opens and its first line says whether the lobby knows you; a refused sign-in says why. On a PC keyboard, just type: Enter is OK and Escape is Cancel on every on-screen keyboard. Then: - **Browse Rooms** opens the Briefing Room: every open room with its host, players in/max, arena, mode, ping and whether it has a password. A room marked **!** cannot be joined from your game - select it to see why (another version of the game, or different ROM, mods or added content). The ping there is an estimate (you to the lobby plus the lobby to the host); a **~** in front means your network blocks the lobby's UDP port and your half was estimated from the web request instead. Once you are in the room the Game Lobby shows the real one. - **Create Room** makes a room from your current Combat Simulator setup: name, password, how many players, then the usual scenario, arena, weapons, limits and simulants. - **Game Lobby** is the room itself: the players by team with how each one reaches the host and their ping (LAN, DIR direct, NAT punched through, RLY relayed through the lobby), chat, Change Team (team 1, team 2 or spectator) and Ready. The host has Launch, Kick and Settings. After the match everyone comes back to the room for the next one. To chat there, press **Space** (or **T**) and type; **Enter** sends, **Escape** cancels. On a controller, **Chat...** opens the on-screen keyboard. **Co-op missions.** A room can be a co-op mission instead of a match: in Create Room (or the host's Settings) set **Game** to Co-op Mission, pick whose missions under **Missions** (Perfect Dark's, GoldenEye's, Goldfinger 64's or Tomorrow Never Dies 64's, as converted on the host's machine), then the mission, difficulty, radar and friendly fire. Up to twelve of you play the mission together as Perfect Dark's own co-operative mode does: one player is Joanna (or Bond), everyone else a coop agent in their Combat Simulator character. Deaths follow the host's **Mission Respawn**: with it on, a dead player gets up again where they fell once the screen has gone black, with full health and everything they were carrying, and **Mission Lives** is the whole team's (with five, the team's fifth death does not come back). A player whose death does not come back - Mission Respawn off, or the lives spent - drops their guns for the others and watches the rest of the mission (Z the next player, A a free camera, START or ESC the pause menu), with no gun and nothing to do but watch. The mission fails when everyone is dead; on GoldenEye's missions (and the two ROM hacks') the last death is first replayed three times from GoldenEye's own cameras, as it is alone. Everyone starts on the mission's own start spot, and anyone joining mid-mission appears on a living player's spot: co-op players walk through each other, so nobody is ever put behind a wall to make room. Every mission and difficulty is open online, and nothing played online counts towards your own solo progress. Without the lobby, a `--host` session starts one from the Carrington Institute's mission briefing with Co-Operative and a human buddy. **Counter-op missions.** Set **Game** to Counter-Op Mission and the room's players pick a side: in the Game Lobby, **Change Side** moves you between the **Agents** and the **Counter-Ops** (a newcomer joins the smaller side), and the host can launch once each side has a player. The agents play the mission together as in a co-op mission, Mission Respawn and its lives included. Every counter-op is Perfect Dark's own counter-operative: they take over one of the mission's living guards - its body, its gun and its health - and when that guard dies, **A**, **Z** or **START** puts them in the next one, for as long as the mission has guards to give (Guards Alerted!'s count too, so its waves keep the counter-ops in bodies). The guards never go after a counter-op, the agents see no name over one, and on GoldenEye's, Goldfinger 64's and Tomorrow Never Dies 64's missions a counter-op only ever takes an ordinary armed guard, never Ourumov, Natalya or anyone the mission needs. The agents win by completing the mission, the counter-ops by killing every agent with no lives left. **Campaigns.** Set **Game** to a campaign instead (Perfect Dark, GoldenEye, Goldfinger 64 or Tomorrow Never Dies 64) and the room's launch puts the host in that game's own menus rather than a match: GoldenEye's folder, or the Perfect Menu's missions. Every mission the host starts there is the room's next co-op mission, and the others are pulled into it from the Game Lobby without a new launch; when it ends the host is back in the folder and everyone else back in the room, ready for the next one. A campaign's room stays open to newcomers for as long as the host plays it: anyone who joins between missions waits in the Game Lobby for the host's next one, and anyone who joins during one drops into it. The host plays through the game as offline, with its own difficulty (GoldenEye's 007 sliders included), and the room follows. A GoldenEye, Goldfinger 64 or Tomorrow Never Dies 64 mission ends as it does offline: everyone watches its ending through the host's camera, anyone's button skips it, and each player gets the folder's report and statistics pages for their own game before the next mission. A room that is already playing can still be joined: you drop into the match in progress. If your game crashes or your connection drops, rejoin the room within 30 seconds (`Net.ReconnectHold`) to get your seat and score back. **If the host leaves.** The room carries on without them. The lobby hands it to the player best placed to host it: one whose game has the room's arena or conversion (a conversion the host sent you counts), preferring an open connection and a low ping. Mid-match, the match starts again on the same arena under the new host and carries on where it was: the clock, everyone's score, and each player back where they stood with their health, shield, guns and ammo. The arena's pickups and a scenario's briefcase, hill or terminal start over, and a player who was dead when the host left starts a fresh life. A co-op mission starts again from its beginning. It takes a second or two when the host quits, and up to about ten seconds when the host's game crashes or its connection drops. Between matches the room simply has a new host, who keeps its settings, and anyone the old host had to send a conversion to can still be sent it by the new one. If the old host comes back within 30 seconds, it gets its seat and score back as a player. **In the match.** A line at the top left of the screen says when someone joins the match in progress, leaves, loses the connection, comes back to their kept seat or starts watching, with how many seats are being played ("3/8"). Press **T** to chat (and **Space** too, if none of your binds use it - by default it is a second fire button): type straight away, **Enter** sends, **Escape** cancels. Hold **P** to see the players: each one's score, deaths and ping, the open seats and who is watching. On a controller, pause and pick **Players** (on the Combat Simulator's Control page, or the mission's pause page) for the same list, the on-screen keyboard and a list of quick messages. The keys are `Net.ChatKey`, `Net.PlayersKey` and `Net.ChatSpace` in `pd.ini`. Put your crosshair on another player, in a Combat Simulator match or a co-op mission, and their name shows over their head (in their team's colour in a team game); it fades a moment after the crosshair leaves them, and never shows through a wall or a cloak. `Net.PlayerNames=0` turns it off. **Ports.** Nobody needs to open a port for a room to work: the game finds its own way to the host - over your LAN, straight to the host, punched through both routers, or through the lobby's relay as the last resort. Hosting is smoother if the host forwards **UDP 27100** (`Net.Port` in `pd.ini`) to its machine, because joiners can then connect directly. The lobby itself only needs outgoing HTTPS and UDP, which every home router allows. **Without the lobby.** On a LAN, or with a forwarded port, start the host with `--host` (or `--host PORT`) and have the others run `--connect ADDRESS` (or `ADDRESS:PORT`); the host then starts the match from its Combat Simulator as usual. A direct host seats four players unless `Net.MaxPlayers` in `pd.ini` says more (up to 12). `--dedicated` runs a host with no window and no player of its own. Everyone needs the same game version and Perfect Dark ROM; the game names what differs when it refuses. **Only the host needs the rest.** A room on a GoldenEye, Goldfinger 64 or Tomorrow Never Dies 64 arena or mission, or on another mod's map, says so in the Briefing Room, and a joining game that has not got that conversion or mod is sent its files by the host when the match starts (a GoldenEye conversion is about 13 MB, a second or two on a LAN). They are held in memory for the session only: nothing is written to your disk, nothing is offered to anyone outside the room, and they are gone when the game exits. A joiner that has its own copy plays from that instead. A Perfect Dark mod (GoldenEye X, the Mario characters) is the host's choice too: the host enters it from the Perfect Menu's **Perfect Dark Mods** before making the room, and a joining game switches to its own copy (or is sent the host's when it has none) and back to the stock game when it leaves, with no restart. Your own `Mod.MapMods` is never changed. Online Game is on Perfect Dark's main menu and in the Combat Simulator of GoldenEye and the ROM hacks; counter-operative is offline only for now. **Your look is your own.** Everyone picks the N64 look or the XBLA/HD look for themselves, and F6 switches it during a match too. The few things a look changes in the game itself (GoldenEye's Community Edition fixes, the XBLA release's corrected collision on Area 51 and Ruins) are the host's for everyone. The simulants' AI (Simulant AI) is the host's setting as well. **So are your settings.** You play by your own controls, aim and camera settings: the third person camera and Camera Tilt, COD Style Aiming and Aim Lock, Akimbo Triggers, Quick Weapon Swap and Skip Death Screen. The same goes for what you see: Disable Fog, Glass See-Through and the Tranquilizer Effect's drugged screen. The match's rules come from the host: jumping, rolling, melee combos, Flinch When Shot, Start Armed, Akimbo, bodies, and a mission's guards, respawns and lives. ### Screenshots and video - **F12** writes a PNG to `screenshots/` beside your `pd.ini`. - **F11** starts and stops recording an MP4 in `recordings/`, picture and sound. Recording shells out to **ffmpeg**, which is not bundled — install it and make sure it's on your `PATH`, or point `Mod.RecordEncoder` in `pd.ini` at the binary. Frame rate, quality and the on-screen red dot are in the options page. Screenshots need nothing extra. ### Texture packs A pack goes in **`texture-packs/`** beside the executable - a folder, or the `.zip` or `.7z` it came in - and is chosen in Extended Options under **Texture Packs**, where **Use Texture Packs** turns the whole thing on. F8 toggles packs in play, F9 re-reads the one you are using (and the model pack with it), F10 steps to the next. **Community Packs**, on that page, does the whole of that for you for the packs it knows about: it asks the pack's own release page which version is current, downloads it, checks it against the hash the release publishes, unpacks it and selects it. It also writes the row-order marker a pack needs when its images are stored the way an emulator wants them, which is the one thing that is invisible when a pack is installed by hand and turns every texture in the game upside down when it is missing. The list is short and everything on it is somebody else's work, credited on the page with a link to where it came from: | Pack | By | | - | - | | PD Plus HD Textures | Parabolee of Retro Foundry | A pack made from the dump below keeps the dump's folder names: `pd-n64/` (or images at the top of the pack) repaints Perfect Dark's own textures, `pd-xbla/` (or `xbla/`) the XBLA release's, and `ge-n64/`, `gf64-n64/` and `tnd64-n64/` repaint GoldenEye's, Goldfinger 64's and Tomorrow Never Dies 64's levels and nothing else. File names are the dump's, unchanged (`gf64-n64/0f12_rgba16.png`). ### Model packs A model pack replaces the game's geometry the way a texture pack replaces its pictures. It goes in **`model-packs/`** beside the executable, a folder per pack, and is chosen on the same page, where **Use Model Packs** turns it on: ``` model-packs//pd-n64/.obj replaces one of the game's own models model-packs//pd-xbla/.obj replaces the XBLA release's mesh for it ``` (`n64/` and `xbla/`, the names before the dump took GoldenEye's layout, still work.) The names are the ROM's own (`Pcrate`, `CcarringtonZ`, ...), which is what the dump below writes, so a pack is made by dumping, editing in Blender or anything else that reads OBJ, and dropping the file back in. A material named `n64_0a9a` draws with that texture of the game's and `xbla_1156` with that record of the XBLA release's - both of which a texture pack can then repaint, live, the same as it repaints anything else. A material whose `map_Kd` is a picture shipped inside the pack draws that picture instead (the dump's own `map_Kd` points out of the pack at `texture-dumps/`, which is what makes the OBJ open with its art in a modeller and is not a picture of the pack's). Everything about a pack is live: choosing one, turning them off, and **Reload Pack** (`F9`) for a file you have just edited all take effect where you stand, without leaving the level. Where a model has both a pack's `n64/` file and a mesh of the XBLA release's, **A Model With Both Draws** says which of the two wins - the pack's model by default. ### Dumping everything **Dump All Assets To Disk**, on the Texture & Model Packs page (or `--dump-assets` from the command line), writes every texture and every model the game has, somewhere you can edit them: ``` texture-dumps/pd-n64/ every texture in the ROM and an index.csv, the layout a texture pack reads back texture-dumps/pd-n64/raw/ their raw N64 data, for the converters in tools/texpack/ texture-dumps/pd-xbla/ every texture of the XBLA release, the layout a pack's pd-xbla/ folder is model-dumps/pd-n64/ every model in the ROM as OBJ, a group per part, textures in the MTL model-dumps/pd-xbla/ every mesh of the XBLA release the same way ``` and GoldenEye's and its ROM hacks', each in folders of their own: ``` texture-dumps/ge-n64/ the textures of GoldenEye converted from your ROM (index.csv: GoldenEye's own numbers) texture-dumps/gf64-n64/, tnd64-n64/ the same for Goldfinger 64 and Tomorrow Never Dies 64, when they are converted model-dumps/ge-n64/props, chars, hand/ its props, characters and first person guns/gadgets, by GoldenEye's own file names model-dumps/ge-xbla/new/..., original/... the GoldenEye XBLA release's char, head, gun, prop, background (levels) and skydome, by its own names texture-dumps/ge-xbla/... those models' pictures, a folder each, and the release's own picture files ``` The two XBLA folders are written when a copy of the release is in `added-content/`; the GoldenEye ones when the GoldenEye ROM (or its conversion) and the GoldenEye XBLA release are there, and each hack's when it is converted. A dump from before October 2026 (`texture-dumps/ntsc-final/`, `model-dumps/n64/`) is left where it is. It takes a few minutes and the game stays usable while it runs; the line under the row says where it is up to. F7 still writes out the textures the game draws as it draws them, which is the way to learn which file a particular wall or jacket is. Each file is named for the model it belongs to, which is also the name a model pack puts it back under. Thirty-nine of the release's meshes belong to models this game has not - 4J's build had a few more - and those are named for where they sit in the release's own order, `Ghand_a51guardZ+1` being the first mesh after `Ghand_a51guardZ`'s. Nothing in the game draws them, so a pack cannot put anything in their place; they are there to be looked at, and each one says so at the top of the OBJ. ### Added content: the GoldenEye ROM and the XBLA releases Everything you add to the game that is not a mod goes in one folder, **`added-content/`** beside the executable. The game makes it the first time it runs, with a `WHAT GOES HERE.txt` inside saying the same as this: | Put this in `added-content/` | What it gives you | | --- | --- | | A **GoldenEye 007 (US)** N64 ROM - any file name, `.z64`, `.n64` or `.v64` | **GoldenEye**: GoldenEye's arenas, missions, menus and music, converted once at the next start into `mods/GoldenEye Arenas/` | | **`Perfect Dark XBLA.7z`** - the archive as it is, or its package unpacked | The Xbox 360 (XBLA) page: the release's textures, models, rooms, font and skies. Unpacked once into `cache/xbla/` | | **`GoldenEye_007_XBLA.7z`** - the archive as it is, or its folder unpacked | GoldenEye XBLA's HD characters, guns and levels on GoldenEye and GoldenEye X | Each is found by its contents, so a file keeps whatever name it came with. Restart the game after adding one. Nothing else goes there: the Perfect Dark ROM stays in `data/`, a mod goes in `mods/`, and texture and model packs in their own folders above. An install from before this folder existed is moved over the first time it starts: the GoldenEye ROM comes out of `data/` and the releases out of `xbla/` into `added-content/`, and the log says what moved. Anything that could not be moved is still found where it was. Everything found there is used - there is nothing to switch on. ## Mods The port can mount mod directories, and this fork extends that to stages, Combat Simulator arenas, weapons and characters a mod supplies - including console mods, the ROM patches made for the N64 game. Nothing is bundled here: mods are other people's work, and you get them from their authors. ### Dropping a mod in 1. Make a folder called `mods` next to `pd.x86_64` (or `pd.x86_64.exe`). 2. Put the mod in it, exactly as you downloaded it. Any of these work: - a mod folder (one holding `files/`, `segs/` or `textures/`); - the `.zip`, `.rar` or `.7z` that folder came in; - a console mod's download: an archive with its `.xdelta`, `.bps` or `.ips` patch inside, or the bare patch file; - a whole collection of the above in one archive. Nested archives are fine. 3. Start the game. Archives are unpacked and patches are converted on that first start - a few seconds for one mod, up to a minute for a big collection, with nothing on screen yet while it happens. 4. On the Perfect Menu, choose **Perfect Dark Mods** and pick the mod from the list. One mod at a time. It goes in where you stand, with no restart, and the Perfect Menu comes back with the mod's missions, arenas, guns and text. To go back to the stock game, choose **Back to Perfect Dark** on the Perfect Menu. Every start begins with the stock game. ### What ends up in `mods/` Each zip is unpacked into a folder of the same name, and each console patch becomes a folder named after the patch, with an `IMPORT.txt` inside that says what came across and what the port could not use. Everything happens once; delete a folder to have it done again, for instance after replacing the zip with a newer version. A patch that was made against a different ROM is refused, and `IMPORT.txt` says so - the Japanese-region patches need the Japanese ROM. A patch made on top of another mod's patch is tried on top of each patch found beside it, so a download that ships both works as it comes. A mod that changed only the game's code has nothing the port can carry over, and its folder says that too. Neither shows up in the Perfect Dark Mods list. A console mod's download may include the hi-res texture pack made for it, as an emulator cache file (`..._HIRESTEXTURES.htc` or `.dat`). That is picked up too and loads with the mod - once **Use Texture Packs** is switched on, in Extended Options under Texture Packs (it is off by default; F8 toggles it in play). GE-X's is a text pack: its fonts. What a console mod built for its own patched code cannot be used as is - a setup or character model in a format the port does not read - is set aside in `files.incompatible/` inside its folder rather than crashing the game. The stock file stands in for it. ### Every mod's maps at once **Options > Extended Options > Stage Loader** puts the maps of installed mods into the Combat Simulator's arena list, beside the game's own, named after the map and the mod. Tick a mod there, or "every installed mod", and its maps appear at once. Nothing in the game's own maps is replaced: a mod chosen here is read for its maps alone, whatever mod you have entered from Perfect Dark Mods. The game has room for 27 extra maps at a time, so with a big collection choose the mods you want rather than all. ### From the command line Pass one or more directories with `--moddir`, which wins over the menu choice: ``` pd.x86_64 --moddir mod_allinone ``` The directory is looked for next to the executable and in your home data directory. Folders whose name starts with `mod` sitting next to the executable are listed too, which is how mods have shipped for the stock port. The command line flags the All in One Mod's own launcher uses (`--gexmoddir` and friends) are accepted as aliases so its scripts work unchanged. `tools/importmod` in the source tree does the same conversion of a console patch outside the game. ## Sharing a machine with the stock port The config file is called `pd.ini` regardless of which build wrote it, so a Dab's Mod build unpacked into the same folder as a stock port will share its settings and saves. The `Mod.` keys are ignored by builds that don't know them, and MP setups stay in the base format unless they need more than 8 simulants, so nothing breaks — but if you want them kept apart, unpack into separate folders, or pass `--savedir `. ## Building from source Same as the stock port: ```sh git clone --recursive https://github.com/DabDavis/perfect-dark-dabs-mod.git cd perfect-dark-dabs-mod cmake -G"Unix Makefiles" -Bbuild . cmake --build build -j8 ``` You need gcc/g++ 10+, cmake, python3, SDL2 2.0.12+, libGL and zlib. Windows builds go through MSYS2's MINGW64 prompt; see the [upstream README](https://github.com/perfect-dark-pc-port/perfect_dark#building) for the package list. Non-debug builds compile at `-Og`, not `-O2` — that's upstream's setting, not an oversight, and the official port binaries are built the same way. `-O2` breaks decompiled code that relies on undefined behaviour. ## Anything not listed here Controls and rebinding, PAL/JPN and Nintendo Switch builds, video and audio settings, and the rest of the port's behaviour are unchanged from upstream and documented in its [README](https://github.com/perfect-dark-pc-port/perfect_dark#readme) and [wiki](https://github.com/perfect-dark-pc-port/perfect_dark/wiki). ## Credits and licence **[CREDITS.md](CREDITS.md)** is the full account: whose work this is built on, ranked by how much of what you run depends on it, what is original to this fork, what is shipped and what is not, and how the claims in it can be checked. MIT, same as the port and the decompilation it came from — see `LICENSE`. - The decompilation: [n64decomp/perfect_dark](https://github.com/n64decomp/perfect_dark), Ryan Dwyer and contributors - The PC port: [perfect-dark-pc-port/perfect_dark](https://github.com/perfect-dark-pc-port/perfect_dark) and contributors - Perfect Dark is © Rare / Microsoft. This project ships no game assets and is not affiliated with either. - RAR archives are read with RARLAB's UnRAR source (`port/src/external/unrar`), © Alexander Roshal, under its own licence: UnRAR source code may be used in any software to handle RAR archives without limitations free of charge, but cannot be used to develop RAR (WinRAR) compatible archiver and to re-create RAR compression algorithm, which is proprietary. Distribution of modified UnRAR source code in separate form or as a part of other software is permitted, provided that full text of this paragraph, starting from "UnRAR source code" words, is included in license, or in documentation if license is not available, and in source code comments of resulting package. The full text is in `license.txt` beside the source. - 7z archives are read with the LZMA SDK (`port/src/external/lzma`), public domain, Igor Pavlov.