Perfect Dark Dab's Mod

Perfect Dark Dab's Mod is a Windows, Linux, and macOS port of Perfect Dark that adds new movement options, raises the simulant cap, and includes a spectator camera.

README

Dab's Mod

Download — Windows, Linux and macOS. You supply the ROM; see You need a ROM. There is also a rolling dev build of the newest commit, if you want fixes before they reach a release.

A fork of the Perfect Dark PC port, which is itself a port of the Perfect Dark decompilation.

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.

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 <path> 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
SettingWhat it does
JumpOff, or a height from 1 to 5. Bound to the use button, behind whatever that button opens — doors and objects still take priority
Jump ForWhether simulants jump too, or only players
Combat RollA dodge roll. C on the keyboard, right stick click on a pad
Melee CombosThe punch and kick combos solo play has always had, in multiplayer
Flinch When ShotBodies react to where the shot landed instead of ignoring it
Start ArmedSpawn 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 ForWhether simulants spawn armed too, or only players
Mission RespawnA 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
LivesHow 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.

SettingWhat it does
Thin Text OutlinesOutlined 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 TextThe 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 UpscaleThe 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
SupersamplingThe 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
TAATemporal 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 ColoursSaturation 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 LevelA 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.

SliderWhat it scales
SpeedTop running speed
AccuracyHow far its aim strays from the target; 500% is a fifth of the error
ReactionHow soon it fires once it sees someone, and how fast its aim settles
DamageDamage it deals
ToughnessDamage 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.

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:

PackBy
PD Plus HD TexturesParabolee 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/<pack>/pd-n64/<model name>.obj    replaces one of the game's own models
model-packs/<pack>/pd-xbla/<model name>.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 .v64GoldenEye: 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 unpackedThe 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 unpackedGoldenEye 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. Go to Options > Extended Options > Load Mods and pick the mod from the list. One mod at a time.
  5. If the game offers Restart Now, take it: a mod that replaces ROM audio, textures or its data tables can only be read at start-up. The choice is remembered, so the next start comes up with the mod loaded.

To go back to the stock game, choose None on the same page.

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 on the Load Mods page.

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,