Turok Dinosaur Hunter from cartridge to code
Nintendo 64 / 1997 / Iguana Entertainment
The game. Turok: Dinosaur Hunter is a first-person shooter developed by Iguana and published by Acclaim. It released for Nintendo 64 in North America on 4 March 1997 1 2. The comic-book hero crosses the Lost Land, fighting dinosaurs and other enemies while recovering pieces of the Chronoscepter 3.
The makers. Producer David Dienstbier recalled a final game team of about 17 or 18 people 4. The N64 credits name Rob Cohen as lead programmer, Nigel Cook as Iguana’s creative director, and Alan D. Johnson as lead artist. Another account gives nine programmers, 22 artists, and more than 61 contributors, but does not explain how it counted the team 5. GameFAQs lists 62 numbered credit entries across specialties, including Acclaim roles and repeated names; those entries are not a headcount of Iguana’s core team 6.
The leak. In 2017, a preservationist found Turok source code on former Acclaim SGI Indy workstations 7. He said their previous owner had acquired them at Acclaim’s 2004 bankruptcy auction 7. A leaked copy surfaced in public discussion in 2018 8. The files do not establish their exact route from those machines into circulation.
Why it matters. Turok has been identified as the first commercial Nintendo 64 game whose original source code became public 5. The ROM layout, bootstrap loader, asset index, cheats, and Controller Pak code show how cartridge data becomes a running world.
What survives. The top level of PR/tengine in this copy contains 78 .c files, four .s files, and one .cpp file. The source is predominantly C, with assembly for selected low-level routines.
The cartridge and what is inside
The North American cartridge presents the same game art seen on the box. Inside is the game’s ROM: the read-only program and data the console loads. A surviving development file called spec shows how its pieces were meant to be arranged.
An opened Nintendo 64 cartridge helps locate the ROM chip and edge connector physically. The board below is a representative NUS-01A-01 board, not an identified Turok board; it should not be used to infer the components or capacity of this particular copy.
The retail game was distributed on a 64 Mbit (8 MiB) cartridge 10. The surviving files include PR/tengine/rom.rnc, a ROM image just shy of that size. Despite the .rnc name, the file begins with a Nintendo 64 ROM header: it is a cartridge image, not one compressed archive.
The rom.rnc image is a surviving result; PR/tengine/spec is the build plan. The plain-text spec lists the pieces to put into a ROM, from boot and game code to sound and other data, and gives key memory locations. Some pieces were compressed to make the most of the cartridge’s limited space. These files show how Iguana planned the ROM, though they do not establish whether this particular image matches a retail release byte for byte.
Development environment
The archive mixes Iguana’s game files with Nintendo’s PR SDK tree. The game files show how Turok worked; the neighboring SDK samples and libraries show the tools available to its programmers.
The PR/README_DEMOS names 35 sample projects. A separate guide to the N64 SDK demos explains their techniques and compares their files with the Oman APPS tree.
Nintendo 64 SDK and ROM layout
PR/tengine/Makefile includes $(ROOT)/usr/include/make/PRdefs from Nintendo’s official N64 SDK. The adjacent spec file defines boot code, audio and display-list memory, frame buffers, a cartridge cache, a Z-buffer, raw data segments, and the main code segment. It also names Nintendo microcode objects such as gspF3DEX.NoN.fifo.o.
flowchart LR
A["<b>Game C and assembly</b><br>PR/tengine"] --> B["<b>Object files</b><br>codesegment.o and others"]
C["<b>Assets</b><br>cartdata.dat, sound banks"] --> D["<b>ROM spec</b><br>segments and addresses"]
B --> D
E["<b>Nintendo SDK</b><br>PRdefs, libraries, microcode"] --> D
D --> F["<b>ROM image</b><br>boot, code, raw data"]
The diagram traces the roles of these files. The Makefile contains commented final-build commands, so the archive does not establish that the retail game can be rebuilt without changes.
The SDK overview places these build files beside the operating-system libraries and tools they depend on:
Workstations and authoring tools
Iguana combined SGI test hardware, an in-house world editor, 3D modeling and motion capture, and a separate music workflow. The hardware photo and software screens below are representative; only the documentary frame shows Acclaim’s own workspace.
SGI stations and the changing development kit
Two shared stations. David Dienstbier described one SGI workstation in a common room where artists could test assets in the engine, and another in the lead programmer’s office 11 5. The source discovery also involved former Acclaim SGI Indy machines 7.
A console on a board. The SGI-based Nintendo 64 development kit used a GIO expansion card inside the Indy, as Nintendo’s hardware documentation describes 12. It allowed testing on N64 hardware without writing a cartridge for every change. Creative director Nigel Cook recalled receiving final development kits about halfway through production, with little rework despite earlier hardware uncertainty 13.
The SDK release notes in PR/relnotes discuss IRIX 5.3 and 6.2. An src/X11 folder exists, but does not identify the desktop the team used. The PR/man/F3DEX/README date of 15 October 1996 belongs to F3DEX microcode release 1.00, not the entire SDK. The game files use Nintendo headers, libraries, and microcode; no separate third-party SDK has been identified in those files.
The development-hardware guide shows the SGI board and later devices such as the Doctor V64 mentioned below:
World building and character animation
Iguana’s own editor. Dienstbier said the team built its world editor and animation handling internally 14. Cook recalled building the editor while Nintendo 64 hardware was still being finalized 13. The editor’s project and executable have not been identified in this supplied archive.
Two kinds of movement. Animator Greg Omelchuck said the human animation was motion captured, while the dinosaurs were animated by hand in 3D Studio, with their legs adjusted frame by frame 13. Acclaim’s motion-capture team described filming stunt performer Brad Martin as he was pulled and thrown to simulate attacks 4.
A source-code clue. PR/tengine/tengine.h declares CMtxF mf_3dstudio_to_u64, a coordinate-conversion matrix. cartdir.h indexes geometry and animation data. Together they show the path into game-ready assets, though the editable 3D scene projects are not present here.
Omelchuck recalled the software as “3D Studio Max v4” 13. Autodesk’s records put 3D Studio Release 4 in 1994, 3D Studio MAX on sale by January 1997, and 3ds max 4 in use by January 2001 15 16 17. That last version postdates Turok’s launch, so the exact version behind the recollection remains uncertain. The wider range of N64 3D modeling software gives this tool choice context.
Music, samples, and compression
Composer’s tools. Darren Mitchell said he used sounds from Ensoniq ASR-10 and TS-12 instruments for the first two Turok games. He sequenced in Performer, then used proprietary tools to get the music running on Nintendo 64 18.
Mitchell said the producer described each level’s creatures and atmosphere before he composed, followed by revisions together 18.
Cartridge packing. PR/tengine/cart.c calls PackRNC; boot.c checks for an RNC code-segment header and dispatches to method 1 or 2 decompression. The archive includes unpack.c and rnc2.s. Sega Retro’s RNC overview explains the format.
Two audio banks. The ROM build plan places music and sound effects in separate N64 sound-bank pairs. A .ctl file describes instruments and sounds; its matching .tbl holds the sample bytes that the audio engine plays. In audio.c, alBnkfNew connects each control bank to its sample table.
The N64 sound guide explains the control-bank and sample-table format in more detail:
The loose audio files contain these banks:
| Use | Control file | Sample table |
|---|---|---|
| Music | testbank.ctl - 5,504 bytes, 24 instrument entries |
testbank.tbl - 257,752 bytes |
| Sound effects | sfx.ctl - 127,688 bytes, one instrument with 624 sound entries |
sfx.tbl - 7,298,152 bytes |
The 624 entries are mappings inside the sound-effects bank, not a verified count of distinct recorded samples. The surviving ROM image contains the testbank pair byte for byte, but its sound-effects control bank has 228 sound entries and differs from the loose sfx.ctl. The loose sfx.tbl does not appear byte for byte in that ROM image either.
The working directory also holds 5,034 individual sound files under PR/tengine/sounds: 4,406 .aif sources and 628 .n64 files whose headers identify Nintendo 64 VADPCM audio. The chart counts files, not unique sounds or the contents of a retail bank. Most run for one to two seconds - a glimpse of the many short effects behind the Lost Land.
The header of PR/tengine/rnc.s calls itself “PROPACK Unpack Source Code - Sony PSX, Method 2” and records a conversion to SGI assembler on 13 September 1996. It documents the unpacker’s code lineage, not a PlayStation build of Turok. In boot.c, the RNC signature check applies to the loaded code segment; cart.c handles individual asset blocks separately.
What later Acclaim footage shows
A documentary about Turok 3 shows a Bung Doctor V64 and Windows development tools 19 20. A 1997 report priced the V64 at US$450 21. The footage establishes later Acclaim use, but not whether Iguana had one for the first Turok.
The same documentary shows an Acclaim ArtSend debugging cartridge around the seven-minute mark 22. That shot features the ArtSend, a different device from the V64. PR/tengine/cart.c also has a WIN32 branch for host-side code, but that does not identify the IDE used for the original N64 game. A Windows edition, ported by Sculptured Software, has a 26 November 1997 US release in GameFAQs and MobyGames 23 24.
Find the game in the archive
The src/PR directory contains many SDK examples, including simple, gtdemo, and spgame. The game-specific material is under src/PR/tengine. Its dosvers directory contains a separate host-side source variant; compiled objects and generated files also appear beside the C and assembly sources.
The game-specific trail begins in tengine. Its spec file maps the ROM layout, while cartdir.h names the asset blocks. The neighboring SDK demo directories are separate from the Turok engine.
Browse the archive as a desktop
This SGI desktop-inspired simulation lets you explore the names and folders in this copy of the Turok archive. Start in PR/tengine, where the game code sits, or jump to the Nintendo SDK samples and the neighboring workstation software. Select a file to see its size and a short account of its purpose. The index covers 10,478 files in 160 folders, but contains no file contents.
Loading archive index...
The source copy gives every file an October 2026 filesystem date, matching when this copy was made. Those dates do not identify when Iguana wrote the files, so the explorer omits them.
Four versions of the asset directory
The three loose cartdata files and the ROM image each contain an eleven-block directory. cartdir.h names those blocks: graphic objects, textures, levels, sound-effect definitions, and other game data. Their matching structure hides different contents. These are counts of indexed entries, not counts of playable maps or original art projects:
| Asset directory | Stored bytes | Graphic entries | Texture-set entries | Level entries | Binary entries |
|---|---|---|---|---|---|
PR/tengine/cartdata.dat |
7,576 | 1 | 0 | 1 | 5 |
PR/cartdata.dat |
6,489,336 | 674 | 1,035 | 50 | 14 |
PR/tengine/oldcartdata.dat |
6,451,432 | 674 | 1,033 | 51 | 30 |
Inside PR/tengine/rom.rnc |
6,502,520 | 674 | 1,033 | 50 | 30 |
The tiny file named by spec has only one graphic entry, no texture sets, and one level entry. The large PR/cartdata.dat has hundreds of graphic and texture entries; it is the file explored in the next section. oldcartdata.dat is another substantial version, but its name alone does not date it. The ROM image contains a fourth version, beginning at byte 7,936 (0x1F00), which matches none of the loose files byte for byte.
The large PR/cartdata.dat and loose sfx.tbl together occupy about 13.1 MiB, before code or music. Both could not simply be copied in full into an 8 MiB cartridge. The surviving files represent different asset and audio versions rather than one complete, matching set for a retail build.
The game Makefile includes Nintendo’s PRdefs, and the archive contains SDK demos beside tengine. No matching demo or copied-file history has been identified, so these clues show SDK integration rather than which template, if any, Iguana started from.
How the game data is packed
PR/tengine/cartdir.h names eleven root blocks in the asset container. cart.h defines a CIndexedSet: a big-endian block count followed by offsets. cart.c uses adjacent offsets to calculate each stored block’s byte length. The first block begins after the aligned index header.
The root blocks in the 6,489,336-byte PR/cartdata.dat file are summarized here. These are stored sizes; compressed content may expand at runtime.
| Block | Content named in cartdir.h | Stored bytes |
|---|---|---|
| 0 | Graphic objects | 2,380,400 |
| 1 | Object attributes | 9,504 |
| 2 | Object types | 1,360 |
| 3 | Texture sets | 1,900,192 |
| 4 | Particle effects | 11,720 |
| 5 | Sound effects | 9,824 |
| 6 | Levels | 2,110,736 |
| 7 | Persistent counts | 448 |
| 8 | Warp destinations | 5,024 |
| 9 | Binaries | 60,008 |
| 10 | Binary types | 64 |
Graphic objects, texture sets, and levels account for most stored bytes in this copy. The names tell us how the root directory is organized; they do not imply that every original authoring file or editable 3D Studio scene is present.
The sound effects block in this file is a compact set of game-side sound definitions, not the complete waveform library. scene.c looks up a sound type there and reads its sound elements before asking the audio system to play them. The much larger .tbl files hold sample data separately.
Packed game assets are present; editable art projects are not evident. cartdir.h names geometry and animations under graphic objects, bitmaps and palettes under texture sets, and collision, instances, and grid sections under levels. The surviving src tree contains no .3ds or .max scene files. Its binary data can drive the game, but these runtime formats are not the original 3D Studio authoring projects. Audio and other media files also survive.
An early Windows 95 demo was reportedly supplied with issue 28 of the Italian PC Gamer (1998). Its asset file, demodata.dat, was reported to contain RNC-compressed sections in a layout resembling the N64 cartdata.dat 5. The reported similarity remains unverified because that demo file is absent from the surviving source tree.
Explore the index yourself
The viewer starts with the real root offsets from PR/cartdata.dat and shows the sizes of its eleven blocks. Readers with their own copy of that file can select it below. The viewer reads only its header in the browser; it does not upload the file or decompress assets.
The sample shows eleven root blocks from PR/cartdata.dat.
The first four bytes of PR/cartdata.dat, 00 00 00 0B, give the block count of eleven in big-endian order. The next word, 00 00 00 38, places the first block at offset 56. cartdir.h identifies that block as graphic objects. Those few bytes show how the game finds an asset group without storing file names in the index.
From ROM to running code
PR/tengine/spec names the nearby 7,576-byte cartdata.dat in a raw static segment, yet the surviving rom.rnc contains a different, 6,502,520-byte indexed asset bundle. The loose build plan and ROM image therefore do not explain one reproducible build on their own. boot.c separately loads the main code segment from ROM. It first reads twelve bytes and checks for the ASCII RNC signature. If present, it reads the compressed length, transfers the compressed block, then calls the method 1 or method 2 unpacker. Otherwise it copies the code segment directly. It then clears caches and BSS before calling boot().
// PR/tengine/boot.c: the decision at the start of BootEntry
DecompFlag = ((_codeSegmentStart[0] == 'R') &&
(_codeSegmentStart[1] == 'N') &&
(_codeSegmentStart[2] == 'C'));
This distinction matters: the bootstrap’s RNC check is for the code segment, while cart.c also supports compression of individual asset blocks. An RNC header in one place does not mean the entire cartdata.dat file is a single RNC stream.
Game systems visible in the source
The archive is more than a ROM packaging exercise. Its game modules expose systems that can be followed from input through state changes to rendering and saving.
Cheats and menu drawing
PR/tengine/cheats.c contains the menu state, selection logic, cheat flag toggles, and draw calls. In CCheat__Draw, the game draws a translucent box, places a highlight bar using m_RealSelection, and renders the enabled option text. CCheat__Update handles moving the selection and toggling flags such as invincibility and unlimited ammo.
cheats.c.The three draw steps from CCheat__Draw show how this screenshot is assembled. First, the menu background is a black box with alpha scaled by m_Alpha:
// PR/tengine/cheats.c: menu background
COnScreen__InitBoxDraw(ppDLP);
COnScreen__DrawHilightBox(ppDLP,
CHEAT_X, CHEAT_Y,
CHEAT_X + CHEAT_WIDTH, CHEAT_Y + CHEAT_HEIGHT,
1, FALSE, 0, 0, 0, 200 * pThis->m_Alpha);
Next, the selected row gets a bar inset by eight pixels horizontally. Its vertical position depends on m_RealSelection and the current menu spacing:
// PR/tengine/cheats.c: selected row
CPause__InitPolygon(ppDLP);
CPause__DrawBar(ppDLP,
CHEAT_X + 8,
CHEAT_Y + CHEATMENU_Y + (pThis->m_RealSelection * CHEATMENU_SPACING),
CHEAT_WIDTH - 16, CHEATMENU_SPACING, pThis->m_Alpha);
Finally, the draw loop skips unavailable items and advances the text baseline for each visible cheat:
// PR/tengine/cheats.c: option labels
COnScreen__InitFontDraw(ppDLP);
COnScreen__SetFontScale(0.7, CHEAT_SCALE);
COnScreen__SetFontColor(ppDLP, 200, 200, 200, 200, 200, 200);
yStart = CHEAT_Y + CHEATMENU_Y;
for (i = 0; i < CHEAT_END_SELECTION; i++) {
if (cheat_menu_items[i]) {
COnScreen__DrawText(ppDLP, cheat_text[i], 320/2, yStart,
(int)(255 * pThis->m_Alpha), TRUE, FALSE);
yStart += CHEATMENU_SPACING;
}
}
These are whitespace-normalized excerpts from cheats.c; the calculations and calls match the source.
The path of a cheat flag runs from CCheat__Update into CCheat__Draw and the game system that consumes it. The source distinguishes flags that are enabled for display from flags that are active in play.
How enemies notice Turok
An enemy does more than wait for Turok to step into a fixed circle. In ai.c, seeing a target requires three checks: the target must be close enough, inside the enemy’s viewing angle, and reachable by an unobstructed ray. When all three pass, the code raises a sight event and increases the enemy’s agitation.
An enemy emerges through the mist in this original Nintendo 64 screenshot from Nintendo64Ever.
Sound follows another route. Quiet and loud noise events each compare Turok’s distance with a hearing distance configured for that enemy. A heard event adds agitation; AI_Increase_Agitation can wake an enemy that was waiting between update cycles. Choose a route below to follow its checks from left to right. The cards show decisions in the code, not measured detection ranges for the enemy in the screenshot.
m_SightRadiusm_SightAngleCAnimInstanceHdr__CastYeThyRayAI_MEvent_QuietNoisem_QuietRadiusAI_EV_QUIETNOISEAI_MEvent_LoudNoisem_LoudRadiusAI_EV_LOUDNOISEA boss fight written as states
The Tyrannosaurus is not one long animation. trex.c has a table that pairs each boss mode with an animation, update callback, speed, and flags. A mode can track Turok’s head position, protect the boss during an entrance, enable a laser, or mark a flame attack. boss.c supplies the shared boss-mode machinery. Select a mode below to see one actual row of the table, from the animation it plays to the flags that shape its behavior.
The idle pose on the elevator stays invincible while the boss enters the arena.
- Animation
AI_ANIM_BOSS_TREX_IDLE- Update callback
TRex_Code_OnElevator- Animation speed
- 1
- Flags
BF_INVINCIBLE | BF_ENTER_MODE
This run row combines movement code, faster playback, head tracking, and the laser flag.
- Animation
AI_ANIM_BOSS_TREX_RUN- Update callback
TRex_Code_Movement- Animation speed
- 1.5
- Flags
BF_RUNNING_MODE | BF_HEAD_TRACK_TUROK | BF_LASER_ON
The setup callback prepares the breath attack; the update callback keeps its firing loop running.
- Animation
AI_ANIM_BOSS_TREX_BREATH_FIRE- Setup callback
TRex_Setup_BREATH_FIRE- Update callback
TRex_Code_FireLoop- Animation speed
- 1
- Flags
BF_FLAME_MODE
The cave attack routine runs this look animation. This row sets no special mode flags.
- Animation
AI_ANIM_BOSS_TREX_CAVE_LOOK- Update callback
TRex_Code_CaveAttack- Animation speed
- 1
- Flags
0
The camera has its own script
The opening’s bow shot is a small piece of camera choreography. In introcam.c, IntroTrack specifies a starting and final rotation, radius, eye height, and focus height. The camera interpolates along that track for 12.8 seconds as it circles toward Turok. During the shot, the code also changes the field of view before the game moves to its logo shot.
Nintendo 64 intro screenshot contributed to MobyGames. The camera track controls how this shot moves.
The same idea extends beyond the introduction. cinecam.c has distinct modes for deaths, resurrection, a Longhunter arrival, Humvee shots, boss conclusions, and key pickups. Letterboxing and camera focus are controlled by the game, rather than being pre-rendered video. Step through the opening’s source-defined beats below.
Separate camera modes handle Acclaim's logo and the Iguana intro before the character shot.
INTRO_ACCLAIM_LOGO_WARP_ID / INTRO_IGGY_WARP_ID
A camera track changes rotation, radius, eye height, and focus height across a 12.8-second bow-drawing shot.
CCameraView__TweenTrackAroundTurok
The bow shot also advances its field of view and eye position as its stage timer runs.
CCamera__SetFieldOfView
The next intro mode zooms toward the title, and the transition can be accelerated after the first run.
CAMERA_INTRO_ZOOM_TO_LOGO_MODE
The map remembers where Turok has been
The map in map.c is a discovery system, not a static poster. RevealMap runs every fifth update. It marks the player’s current region and recursively visits nearby neighbors when their corners fall within a reveal distance. A closed door blocks that traversal until its region carries the open-door flag. The small model below shows that relationship; its rooms and distances are illustrative.
The closed door keeps the next connected region hidden.
Keys open the route; pieces complete the weapon
Turok’s pickups serve two different long journeys. Level keys unlock later destinations: pickup.c keeps separate bit fields for keys belonging to levels 2 through 8, and its remaining-key display counts what can still be found in the current level. The source also triggers a short cinema when a key is collected.
Original Nintendo 64 key-pickup screenshot from Nintendo64Ever.
The Chronoscepter is a separate collection. Its eight pieces set eight different bits in ChronoSceptorPieces. When the mask reaches 0xff, the pickup code grants the completed weapon and ammunition. Try collecting the eight pieces below; the board represents the bitmask, not their locations in the levels.
0x00Each piece sets one bit in the collection mask.
Why the air meter appears near the end
Swimming has a hidden clock. tmove.c allows 70 seconds underwater without an oxygen tank, but the on-screen air bar begins to fade in only when fewer than 15 seconds remain. Its fill then falls across that final interval. Once Turok runs out of air, the drowning routine damages health and temporarily bypasses armor.
An oxygen tank has its own reserve: while that reserve lasts, the breath counter is held at zero. The slider isolates the no-tank case so the late warning is easy to see.
Turok is using his breath, but the air bar has not appeared yet.
How an unattended game plays itself
attract.c stores a demonstration as a starting warp and a stream of controller changes. Its header records frame count and separate bit offsets for buttons and stick axes. The button reader rebuilds A, B, R, Z, C-button and right D-pad states; a compact time packet says how many frames to hold them. Recording code is present behind a disabled compile-time switch, while playback remains in the source. Select a beat below to see the idea. The sequence is illustrative, not extracted from a recorded demo.
The header selects a warp and records how many frames the demo spans.
warp ID + total frames
The X and Y axes have their own bit streams. A change is followed by a frame duration.
stick X / stick Y + time
Button bits reproduce a controller state; the duration says how long it persists.
R button + frame count
Playback reads the next packed button state, then advances by its stored duration.
Z trigger + frame count
The level is full of little machines
aidoor.c gives doors, pressure actions, collapsing platforms, portals, locks, and drains their own advance routines. They use state flags and timers alongside animations. A collapsing platform, for example, waits, moves away, pauses, and moves back; a pressure action checks whether it has received a message before entering its active animation. The cutaway translates those routines into stages.
A collapsing platform changes its region, waits, moves to its destination, then returns after another timer.
The pressure-action routine tests its interactive message timer before it enters the active animation.
The portal routine makes its region a warp and ramps an effect value upward while active.
From trigger pull to screen effect
The weapon code in aiweap.c dispatches updates for the Tek Bow, rocket launcher, and Chronoscepter. particle.c handles projectile behavior and collision effects; it starts named swoosh trails for explosive arrows and Chronoscepter shots. fx.c maintains and draws those trails. Pick a shot to see how the work crosses modules. The paths show code responsibilities rather than a frame-accurate simulation.
aiweap.cparticle.cfx.caiweap.cparticle.cfx.caiweap.cparticle.cfx.cA sunbeam meets the depth buffer
Sun glare looks atmospheric, but sun.c gives it a precise visibility test. The renderer copies eight depth samples from a short strip around the sun’s screen position. Each clear neighboring sample contributes one part; the sample at the sun itself contributes three. The result ranges from zero to one. When scenery covers the sun, fewer samples count as clear.
tengine.c uses that visibility when drawing a screen tint, strongest when the sun is near the center of view. The model below lets a canopy edge cross the samples. It shows the weighting in the code, not a captured frame or an exact reconstruction of the game’s artwork.
Weighted visibility 1.0 / 1.0
Seven neighboring samples plus the three-weight sun sample yield full visibility.
The sun sample and three neighbors remain clear, so the weighted result is six tenths.
Three versions of the training room
The instructions in train.c are part of the game code. Conditional sections supply English, German, and KANJI text for lessons such as jumping, swimming, and climbing. English and German are readable strings in the archive, although the German text uses characters such as / in place of accented letters for the game’s font. The Japanese branch stores font-encoded byte values, so those bytes cannot be presented as ordinary Japanese text without the game’s character mapping. Compare how one jumping prompt is represented below.
press the r
button to jump.
zum springen
knopf r dr/cken.
2C 3D 27 36 64
E9 13 22 28 41 33 0F 27
Controller Pak saves
PR/tengine/control.c holds OSPfs ControllerPak, directory state, and the game’s Controller Pak identifiers. Its GameCode is NTUE and its CompanyCode is 51. The GameName array in this copy uses encoded byte values, rather than the plain ASCII turok array left in a comment. The save payload is modeled by CPersistantData in tengine.h, including inventory, level keys, settings, health, and cheat flags.
control.h declares the SDK’s OSPfs handle and OSPfsState, plus file counts, free pages, and a directory of t_File records. Each record carries an index, a 20-character string, and a page count:
Nintendo’s manual calls each Controller Pak save a game note. Its PFS file system uses OSPfs as the file handle and manages data in 32-byte units 25. This explains the Pfs names in the code without needing to infer a longer expansion of the acronym.
// PR/tengine/control.h: Controller Pak directory state
extern OSPfs ControllerPak;
extern OSPfsState FileState;
extern s32 FilesUsed, MaxFiles;
extern s32 TurokFiles;
extern s32 FreePages;
typedef struct s_File {
int index;
char string[20];
int pages;
} t_File;
extern t_File FileDirectory[];
The bundled SDK header PR/tengine/u64inc/os.h defines the file state returned by its Pak APIs. The record includes a byte size, game and company identifiers, and the names stored with the note:
typedef struct {
u32 file_size;
u32 game_code;
u16 company_code;
char ext_name[4];
char game_name[16];
} OSPfsState;
The identifier declarations in control.c show a difference between the readable name left in a comment and the encoded bytes used by the game:
u16 CompanyCode = '51';
u32 GameCode = 'NTUE';
// char GameName[16] = {'t', 'u', 'r', 'o', 'k', 0,0,0,0,0,0,0,0,0,0,0};
char GameName[16] = {0x2d, 0x2e, 0x2b, 0x28, 0x24, 0,0,0,0,0,0,0,0,0,0,0};
char ExtName[4] = {0,0,0,0};
The complete CPersistantData declaration is preserved below. Its fields include weapon ownership and ammunition, level keys, player options, cheat flags, health, checkpoints, and boss state. The field names are as written in the source, including Persistant.
Show the full save-data structure from tengine.h
typedef struct CPersistantData_t
{
BOOL SemiAutomaticPistolFlag, // weapons owned flags
RiotShotgunFlag,
AutomaticShotgunFlag,
AssaultRifleFlag,
MachineGunFlag,
MiniGunFlag,
GrenadeLauncherFlag,
TechWeapon1Flag,
RocketFlag,
ShockwaveFlag,
TechWeapon2Flag,
ChronoSceptorFlag ;
BOOL ArmorFlag, // miscellaneous inventory flags
BackPackFlag ;
int BulletPool, // weapons ammo
ShotgunPool,
EnergyPool,
ExpTekBowAmmo,
ExpShotgunPool,
TekBowAmmo,
MiniGunAmmo,
GrenadeLauncherAmmo,
RocketAmmo,
TechWeapon2Ammo,
ChronoSceptorAmmo;
int ArmorAmount ;
int WeaponUsing ;
int Level2Keys,
Level3Keys,
Level4Keys,
Level5Keys,
Level6Keys,
Level7Keys,
Level8Keys ;
int Level2Access,
Level3Access,
Level4Access,
Level5Access,
Level6Access,
Level7Access,
Level8Access ;
int ChronoSceptorPieces ;
int Difficulty ;
BOOL RunWalk ; // TRUE for RUN
BOOL ControlSide ; // TRUE for right handed
BOOL Blood ; // TRUE for blood is on
BOOL Stereo ; // TRUE for stereo
u32 MusicVolume ;
u32 SFXVolume ;
u32 Opacity ;
u32 HAnalog ;
u32 VAnalog ;
u32 CheatFlags ;
u32 EnabledCheatFlags ;
int Health,
MaxHealth,
Tokens,
Lives ;
u16 Checkpoint ;
float BestTrainTime ;
INT32 BossFlags ;
u32 Crash ;
} CPersistantData;
A saved .mpk file from an emulator can be opened in a hex editor or a Controller Pak editor. Its directory entry and game code identify the note before the save payload is interpreted. The C structure alone is not a complete on-disk format specification.
Models, worlds, and related games
The 3D Studio conversion matrix in tengine.h connects the game runtime to its art pipeline. scene.c, romstruc.c, and cartdir.h provide better starting points for tracing geometry, collision, and level data than the generic SDK demo folders.
Iguana also built a world editor, according to a contemporary interview. David Dienstbier described the tools this way: “All of the tools for this game were created internally; the world editor, how the animation is handled, everything we have, we created here” 14. No obvious world-editor project or executable was found in the surviving src tree. Nightdive’s Stephen Kick said the remaster team could not find the original game’s source code when it began its work 26. The later remaster has an editor 27, but its connection to Iguana’s original tool is unknown. The available evidence also does not establish whether that original editor was ever released.
The first South Park Nintendo 64 game is reported to have been based on Turok technology 11. Shared engine code is therefore plausible, although this archive does not establish which exact source files were compiled for South Park.
Can this source rebuild Turok?
The archive includes game source, generated objects, and a ROM image. Its spec file describes the ROM segments, while boot.c shows how the game code loads. cart.h and cartdir.h explain the asset index: it stores big-endian offsets rather than file names.
A clean rebuild still depends on an appropriate historical toolchain and inputs. The build notes below record obstacles encountered with one setup; they do not establish a reproducible retail build.
Historical build attempt and compiler diagnostics
One build attempt copied stddef.h from Dragon SDK into c:/ultra/GCC/MIPSE/INCLUDE and changed a NULL definition at approximately line 400 of that header after seeing trex.c:229: invalid operands to binary | 5:
// #define NULL ((void *)0)
#define NULL 0
That records the historical environment and workaround; the line number depends on the exact header version, and the edit does not establish a correct fix for another toolchain.
as -o adpcm.o adpcm.s
adpcm.s: Assembler messages:
adpcm.s:96: Error: ERROR: Illegal operands `sub'
The build continued with the archive’s existing adpcm.o and produced these diagnostics:
Warning: type of symbol `osWritebackDCacheAll' changed from 2 to 1 in codesegment.o
Warning: type of symbol `osInvalICache' changed from 2 to 1 in codesegment.o
Reusing an object from the archive can change the resulting binary and does not demonstrate a clean source rebuild.
Video companions
The video carousel pairs Turok 64 Official Source Code Found with The Making of Turok Dinosaur Hunter for Nintendo 64, which includes footage of Acclaim’s later development equipment.
Digital Foundry examines how Turok developed the console first-person shooter on the Nintendo 64. The retrospective supplies visual context for the engine and hardware constraints discussed in this source-code analysis.
Other software in the archive
The source-code find preserves more than the game itself. Three folders near Turok’s code open windows onto the larger collection of software around it.
An SGI preprocessor from GNU
Among the Turok files is a small detour into the workstation’s software: src/gnu/acpp. It is the source code for an ANSI C preprocessor, the program that expands #include files and macros before the compiler tackles the C code. It is not a hidden Turok engine or an Iguana-made tool.
The folder’s README identifies it as GNU cpp with a few compatibility changes. Its version.c reports version 1.35.95x. Silicon Graphics’ acpp manual explains why it might be found beside game code from an SGI workstation: IRIX supplied this GNU-derived preprocessor as an option to the C compiler, selected with cc -acpp 28.
Neither Turok’s Makefile nor its ROM spec names acpp, so the folder’s presence alone cannot tell us whether this preprocessor was used for a Turok build. It shows the wider workstation software caught up in the source-code find.
SLATEC: a library of mathematics
Another unexpected neighbor is src/slatec. It contains SLATEC, a public library of more than 1,400 mathematical and statistical routines written in Fortran 77. Developed across US national laboratories, it offered ready-made calculations for problems such as numerical integration and special functions 29.
The copy here has an unusual shape. Its large sladaf file holds the Fortran routines in fixed-length records, while slatbl, slakwd, and slacat act as indexes to their names, keywords, and categories. The first routine introduces itself as the SLATEC Common Mathematical Library. The files resemble a searchable shelf of mathematical recipes, complete with a card catalog.
No reference to SLATEC appears in Turok’s game source or build files, so its presence does not establish that the game used these routines. Alongside acpp, it shows how a recovered source collection can preserve useful software that happened to sit near the game, as well as the code that made it.
A one-line clue to the SGI desktop
The entire src/X11/motif folder contains just one tiny file: mmkmf. Its 18 bytes spell out /usr/bin/X11/mmkmf, a path on an IRIX workstation. This looks like a saved link target, not a copy of the Motif toolkit.
Motif supplied the buttons, menus, and windows of many X11 desktop programs. On SGI’s IRIX, mmkmf generated Makefiles for Motif applications. This stray path offers a glimpse of the graphical workstation environment around the archive. Turok’s engine and build files do not refer to Motif or mmkmf, so it does not establish that the game or Iguana’s authoring tools used the toolkit.
References
-
Turok: Dinosaur Hunter Nintendo 64 release details at GameFAQs ↩
-
David Dienstbier’s recollection of Turok’s team size in an oral history ↩ ↩2
-
2017 report on Turok source code found on former Acclaim workstations ↩ ↩2 ↩3
-
Interview with Turok composer Darren Mitchell about his equipment and workflow ↩ ↩2
-
Behind the Code’s identification of Acclaim’s ArtSend cartridge in the Turok 3 footage ↩
-
Turok: Dinosaur Hunter Windows release details at MobyGames ↩
-
Nightdive’s Stephen Kick on the Turok remaster and missing original source ↩