The Nintendo 64 Renaissance

The N64 Renaissance

The Nintendo 64 marked its 30th birthday this past June, and yet despite its age, work on the platform has seen a resurgence over the last decade. The N64’s passionate fan community of software developers, hardware hackers, and reverse engineers have made improvements to many aspects of the system. They’ve added digital video output, flash-based cartridges, new and improved emulators, modern development toolchains, complete console hardware reimplementations (plural!), and whole new games. Much of their work is also being done in an open-source fashion. I, along with contributions from others, have been attempting to catalog these advancements at n64.dev, but with the current state of things moving so quickly, it can be hard to keep up. So, as of this post, here is a big picture of where development on the N64 stands right now.

Digital Video

Video output on the N64 is analog composite (the yellow RCA connector), which produces a smeary and low-resolution picture by today’s high-def standards. CRT TVs also display input imperfectly, with interlaced scan-lines, phosphor persistence, and so on. Developers often took advantage of these limitations by making deliberate artistic choices that looked good on TVs of the time. However, modern TVs largely1 show the exact signal provided, and upscaling composite video to an HDTV exposes all the previously concealed flaws.

Various RGB mods mods have been available for some time which let you extract RGB video from the N64. While still analog, RGB video is clearer than composite by virtue of spreading picture information across three signal lines instead of one.

Better still, there have also been a series of mods that tap into the digital video lines on the N64 motherboard and then convert the signals to HDMI. UltraHDMI, 64HD, N64Digital, and most recently (and most-available), the PixelFX Retro GEM, all produce HDMI video output directly from the N64’s graphics chip, entirely bypassing the analog conversion step, while still offering scaling and interlacing modes to mimic the look of CRTs. Installation can be tricky because of the fine pitch of the solder points involved, but having a built-in HDMI port on a classic console is convenient for playing and capturing, and the video output looks as good as it possibly can because of the minimal amount of conversion steps involved.

Open Hardware

For years, running your own code on physical N64 hardware meant having to get your hands on a development kit or one of several rare-ish ROM backup devices like a Doctor V64 or Mr. Backup Z642, or making do with a parallel port equipped GameShark cartridge. None of the methods are particularly available (short of lucking out on eBay) or easy to set up, and some depend on legacy PC hardware like ISA cards, SCSI cables, and the like.

Later, the 64drive and EverDrive 64 (both closed-source flash cartridges) made it possible to load ROMs from an SD card. The 64drive and several of the EverDrive 64 models offer a USB port that supports uploading ROMs and booting them without having to physically move an SD card between machines, vastly shortening development and testing turnaround time. USB support enables a workflow where you can compile, upload, and boot a ROM on a console in seconds, and shortening that turnaround time makes homebrew development far less burdensome.

Various N64 flash cartridges

Both are fine options, but there is now a fully open competitor in the SummerCart64 flash cartridge. The SummerCart64 is open hardware and open firmware from top to bottom. It loads ROMs from microSD or USB-C, writes game saves to the card, and can even emulate the 64DD add-on that was only ever released in Japan. You can order a SummerCart64 board using the available manufacturing files or buy one pre-built for around $100. The SummerCart64 is currently the recommended way to run in-development ROMs on a console, and the community has focused software efforts on making this path a straightforward one.

Hardware Reimplementations

Besides cartridges, the console itself is being reimplemented too. An FPGA is a type of low-level programmable chip that lets you define its digital logic with a hardware description language. By painstakingly reverse engineering a console like the N64, sometimes involving chip decapping and a microscope, it’s possible to re-implement chips feature-for-feature (and sometimes critically, bug-for-bug) in an FPGA. This approach is still technically emulation, but in a wildly different sense (and far “closer to the metal”) than typical software emulation.

The MiSTer FPGA project shipped an official N64 “core” in 2024, and it plays most of the retail library. The MiSTer DE10-Nano board can be purchased for about $200 and can be loaded with FPGA cores that implement quite a number of consoles and arcade machines.

Analogue 3D console, games, and controller

Then, in November of last year, Analogue shipped the Analogue 3D, an independent FPGA reimplementation of the N64 that outputs 4K over HDMI, plays original cartridges of course, supports Bluetooth controllers, and ships in a slim N64-inspired enclosure.

There’s even a third N64 FPGA implementation, the ModRetro M64 that just recently started shipping. Though this implementation shares history with the MiSTer core, it targets a more recent FPGA platform and offers accuracy improvements and features not available with the MiSTer.

While it’s possible to do repair and maintenance on original N64 consoles to extend their lifespan, these FPGA projects go a long way towards ensuring that hardware continuing to age out isn’t the end of our ability to play games on and develop for N64 hardware.

Emulation

Early on, the N64 emulator story was pretty rough. Initial N64 emulators were built using high-level emulation, often requiring per-game workarounds and plugin mixing-and-matching to make them work well. As a result, they were only able to run a subset of commercial games. In the first few years of the 2000s when the N64 was still fairly new, people mostly just wanted to be able to play a handful of N64 games on PCs, and those initial emulators met the demand. High-level emulation allowed that to happen fairly quickly, even though there were plenty of rough edges and shortcomings.

cen64 took the opposite approach, using cycle-accurate CPU emulation, which came at the cost of speed. Achieving cycle-accurate emulation is perhaps surprisingly computationally intensive, even for 2D systems older than the N64. Ideally cen64 would achieve both goals, but accurate low-level emulation took priority over performance. For a while, cen64 held the ideals of the scene rather than being a practical tool for real-time testing.

ares running Super Mario 64 on macOS

The torch of accurate emulation has since passed to ares, a multi-system emulator descended from Near’s higan emulator. ares is accurate enough that the libdragon project recommends developing against it with the expectation that your ROM will then work on real hardware. It even has a homebrew development mode that adds extra correctness checks. More recently, gopher64, a newer emulator written in Rust, has joined it in libdragon’s recommended list, with gopher64 being more oriented towards performance in playing. cen64, ares, and gopher64 attempt to emulate the actual hardware rather than “just” passing drawing calls through to modern graphics libraries.

Toolchain Without Nintendo

Modern N64 development is generally centered around libdragon, an open source SDK that has become a complete replacement for Nintendo’s libultra (which shipped with their official SDK). The current version is built on a modern version of GCC, providing a full C11 environment with a 64-bit capable toolchain. Setup can be done via a Docker container, and builds are typically done with a plain Makefile. For deployment, you can use USB to connect to a flash cartrige, perhaps a SummerCart 64. Combined with a supporting USB loading tool like UNFLoader, a development ROM can stream logs back to the host machine as well, giving you an avenue for development feedback that, in the past, required an official or semi-official development kit and associated PC hardware.

The graphics options are similarly modern. libdragon includes a full OpenGL 1.1 port (well, “modern” for N64 standards, anyway) running on a custom RSP microcode, and the third-party Tiny3D library provides a faster native pipeline written from scratch. libdragon and Tiny3D both import models from Blender via the common glTF format and support skeletal animation (as opposed to the sausage-link style of animation seen in Super Mario 64). There’s also RSP microcode accelerated MPEG1 and H.264 video decode support, Opus audio playback, and a TrueType text engine.

In addition to the tools that ship with libdragon, lots of smaller, purpose-specific tools have been published to assist with development tasks like converting meshes and textures between authoring and run-time formats, audio sequencing, compression, and debugging.

More recently, Pyrite64, also from Tiny3D’s creator, wraps libdragon and Tiny3D in a Unity-style visual editor and runtime engine. It has scene management, an asset pipeline, and a node graph for scripting, and more, all on top of the same C toolchain underneath. It’s still early and requires accurate emulation (again, ares or gopher64) for testing in software, but it provides a lower barrier to entry than writing a game loop from scratch.

Running the ROM of a real cartridge on the N64 requires some initial setup code that’s verified by the console, with the participation by the CIC. The CIC is a security chip from Nintendo included inside commercial cartridges. A progressively-verified boot process brings up the environment before a game can start, with two stages, IPL1 and IPL2, built in the console itself and a final stage, IPL3, in every cartidge ROM. The stage built into ROMs was supplied by Nintendo as part of the offical N64 SDK. Homebrew ROMs historically re-used Nintendo’s IPL3 even if they used an open-source library like libdragon further down the pipeline. After much reverse engineering, an open source IPL3 reimplementation was made available, making the entire ROM boot chain able to be free of proprietary code3.

While programming in C is still the typical language for N64 games, it’s now possible to build in other languages as well. Under Rust, there’s support via nust64, which requires a Rust nightly build. On the Go side, Embedded Go supports the N64 as a target and is distributed as an installable Go toolchain. Neither ecosystem is near as complete or well-trod as the C path, but the fact that they exist and work at all is incredible, given that neither existed until many years after the N64’s release. The traditional MIPS assembly route remains available for those who enjoy artisanal suffering.

Game Reverse Engineering

Running alongside the homebrew scene is the reverse-engineering scene, and the two often feed each other. Matching decompilation projects, which aim to reproduce a byte-identical ROM from reconstructed C source, started with Super Mario 64 (of course) and have since worked through Ocarina of Time, Majora’s Mask, Perfect Dark, Mario Kart 64, Banjo-Kazooie, GoldenEye 007, and others in varying states of completion. Those codebases enabled native PC ports like Ship of Harkinian for Ocarina of Time and the Perfect Dark port with its improved framerates and mouse-and-keyboard controls.

Full, accurate decompilation takes years per game, though, which is what makes N64Recomp an interesting project. This tool mechanically translates a ROM’s N64 MIPS code into (difficult to understand) C, which is then compiled natively for modern platforms. This avoids the need to fully understand and decompile the game to readable C before targeting other platforms. Zelda 64: Recompiled shipped Majora’s Mask this way, with widescreen, high framerates, and gyroscopic aim, and it runs quite well. Since then, a modding framework has been developed that lets modders replace models, scenes, and code in recompiled games without traditional ROM-hacking constraints, and more recomp projects have been appearing, including Dr. Mario 64, Star Fox 64, and the never-released Dinosaur Planet. As with the decomps, you must supply your own ROM to start with, since no Nintendo IP can be distributed.

Reverse engineering existing games offers homebrew developers a better understanding of how commercial games used the hardware, and the tooling built for it sometimes even reused directly. For example, Fast64, a Blender plugin used to export N64 display lists and assets, started as an export utility for Super Mario 64 and now supports both decompilation work and homebrew output from the same codebase. Kaze Emanuar’s Super Mario 64 improvements build on top of the decompiled source rather than starting from a disassembly, since that source is now the shared starting point for anyone doing work on the game.

Pushing The Limits

The most fun corner of all this is watching people run the N64 far past what anyone managed in the ’90s. As mentioned earlier, Kaze Emanuar has spent years rewriting Super Mario 64 for performance, getting stable 60 fps on real hardware while pushing something like ten times the level geometry of the original game. Beyond updates to existing games, demoscene-style experiments have achieved a complete ROM in 4KB, very high texture detail, HDR and bloom effects, normal mapping, cel shading, and experimental VR support. A standout from a recent game jam, Junk Runner 64, is a cool open-world game with incredible draw distance.

Years of accumulated knowledge have been built up since the release of the N64, and there’s now a quite solid toolchain that lets you write games and even custom RSP microcode without having to deal with a period SGI Indy workstation or obscure development hardware. Though a few games did push the N64 pretty hard (looking at you, Perfect Dark), people are only just now seeing what the console is really capable of. At around only 97 MHz, it of course has hard limits, but it’s cool to see people wring ever more performance and capability out of a such a unique target.

The Community

Much of this activity converges on the N64brew community wiki and its very active Discord, which has run an annual game jam since 2020. The game jams have had various themes, one of which was a collaborative minigame collection in which all the submissions were built into a single ROM. The most recent jam drew dozens of submissions, more than any previous year. Game jam entries are where the toolchain (typically libdragon) gets battle-tested, and several have grown into full releases. A small physical publishing scene is even starting to form around them too, shipping newly created games on actual cartridges. I’m awaiting my copy of Junk Runner 64 as I write this.

It took a few decades, but the N64 finally has modern and reliable tools, good documentation, affordable and readily available development hardware, and a community that actively welcomes newcomers. The result is the healthiest development scene the console has ever had. If you want to poke at it yourself, the N64brew Getting Started guide, libdragon, and a copy of ares will have you rendering triangles in an afternoon, and with a SummerCart64, you can watch your own code boot on an original or FPGA N64. Off we go!


  1. Well, for the most part. Features like Motion Smoothing and other processing effects change the appearance of content bound for display on modern TVs. 

  2. Hence the commonly-encountered .v64 and .z64 ROM format filename extensions. The formats’ endianness differ, but the community has settled on using .z64, the N64’s native big-endian format, eschewing the other formats to encourage standardization after decades of dealing with mixups and byte-swapping code. 

  3. Flash cartridges typically circumvent this process and allow any ROM, official or otherwise, to execute by computing and then having its phony CIC implementation approve that very same ROM checksum at runtime. Modern console copy protection schemes are far more rigorous

Single File HTTP "Live" Streaming

Playing large video files on the web, short of uploading to YouTube or some other processing and hosting service, requires some preparation. For browsers to efficiently download just the portion surrounding what visitors are playing, you’ll generally want to rewrite the MP4 so its moov atom is at the beginning of the file (usually called “fast start”), allowing the browser to grab the metadata needed for playback and seeking without first having to download all the way to the end of the file.

One alternative is to provide the media in the HTTP Live Streaming format developed by Apple, which as the name suggests, was originally designed for live streaming. The format also supports post-live (oftentimes referred to as Video on Demand or VOD) playback of media. However, HTTP Live Streaming defaults to playing back pieces of the original media by chopping it up into segment files, since during a truly live recording, the end is not yet known, so segments are fetched moments after being captured and made available. It’s a convenient format for the modern web because the recording’s manifest and segments are delivered over the ubiquitous and typically network-allowed HTTP protocol instead of one of the more temperamental media streaming protocols like RTSP.

But for HTTP Live Streaming playback of post-live or pre-existing media, having to maintain a manifest and a whole pile of media segments can be kind of a pain. It’s way simpler to track and manage as few as two files instead of potentially a bunch. When producing an HTTP Live Stream with ffmpeg, you can set a couple of flags to cause it to produce just one .ts segment file:

ffmpeg \
-i input.mp4 \
-c:v libx264 \
-c:a aac \
-hls_time 6 \
-hls_segment_type mpegts \
-hls_flags single_file \
-hls_playlist_type vod \
index.m3u8

Setting -hls_flags single_file will cause ffmpeg to output index.m3u8 and index.ts, where index.ts contains the entire duration of the media rather than splitting it into several-second chunks and listing those in the index.m3u8 manifest. -hls_playlist_type vod adds #EXT-X-PLAYLIST-TYPE:VOD and #EXT-X-ENDLIST to the manifest, which tells the player the whole timeline is known up front so it can scrub freely. It also implies -hls_list_size 0, so you don’t need both. Everything else is ordinary encoding using whatever bitrate, preset, and profile settings you prefer, since none of that interacts with the single-file part.

The .m3u8 manifest text file is where the single-file mapping happens:

#EXTM3U
#EXT-X-VERSION:4
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:6.000000,
#EXT-X-BYTERANGE:1128144@0
index.ts
#EXTINF:6.000000,
#EXT-X-BYTERANGE:1093472@1128144
index.ts
#EXTINF:6.000000,
#EXT-X-BYTERANGE:1121368@2221616
index.ts
#EXT-X-ENDLIST

Unlike a live broadcast where each segment is added moments after it’s captured and encoded, the VOD playlist uses the same media file name on every line. The media is still logically divided into segments, but each segment is now a length@offset byte range into a single file rather than pointing to one of potentially many files on disk.

Single-file HTTP Live Streaming has been supported by playback clients, particularly iOS, since iOS 5. All that’s required to support this on the server side is accepting and respecting the HTTP Range header, which lets the client ask for a given range of bytes and the server respond with those bytes. The Range header has been part of HTTP/1.1 for decades and is supported by basically all HTTP servers, making serving single file HTTP Live Streaming quite convenient. This only works for media that’s already finished (i.e. isn’t live), though, since you can’t append to a file you’re actively serving byte ranges out of.

If you’re serving this with a CDN, individual segment files may still be the way to go. CDNs can have different caching and range-request behaviors, and a large single object can be less convenient to cache (or invalidate) than many smaller immutable segment objects. Depending on the CDN, a Range request may also result in more data being fetched from the origin than the client actually requested.

There’s also a variant of this that works with an MP4 container instead of an MPEG-2 transport stream, and you do get some nominal bandwidth savings. This requires iOS 10, which is long since available now, too.

ffmpeg \
-i input.mp4 \
-c:v libx264 \
-c:a aac \
-hls_time 6 \
-hls_segment_type fmp4 \
-hls_flags single_file \
-hls_playlist_type vod \
index.m3u8

Again, you get an index.m3u8 manifest, but now a index.m4s media file. The manifest gets an EXT-X-MAP tag pointing at index.m4s:

#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MAP:URI="index.m4s",BYTERANGE="900@0"
#EXTINF:6.000000,
#EXT-X-BYTERANGE:1119832@900
index.m4s
#EXTINF:6.000000,
#EXT-X-BYTERANGE:1086104@1120732
index.m4s
#EXT-X-ENDLIST

H.264/AVC can be carried in either MPEG-2 TS .ts files or fMP4’s .m4s, but H.265/HEVC, AV1, and Dolby Vision require fMP4. If you want to use one of those newer codecs, you’ll have to use the fMP4 segment type. As well, players like hls.js transmux transport streams into fMP4 before handing it to the browser’s media API, so giving it fMP4 in the first place lets them skip a step.

HTTP Live Streaming (segmented or single-file) is one of my favorite formats because it puts a complicated thing like video playback on top of a solid, well-supported protocol like HTTP. In addition to being pretty well-adopted by clients, there’s no special streaming server to run, no unusual ports to open, and nothing that breaks when someone tries to watch a video over a restrictive corporate or hotel type of network.

Importing Certificates into Xcode 27's Device Hub

Xcode 27 introduced, among other new features, a new Device Hub app for developers that takes the place of the Simulator app. Where Simulator relied on separate windows for each device, Device Hub brings them all together into a single window where each simulated device is the detail view from a source list of devices on the left. It’s a more organized approach, made necessary by the wide variety of platforms Apple and Apple platform app developers have to build and test against.

Xcode 27's Device Hub

For enterprise users or developers building apps that communicate with web services over HTTPS, those services need to be using a certificate pair signed by a globally-trusted authority like DigiCert or Let’s Encrypt for them to work “out of the box” in the simulated OS. If they are using a certificate pair signed by a self-signed or in-house/enterprise CA (Certificate Authority), the OS will refuse to connect, displaying a “This connection is not private” interstitial in Safari or failing with a TLS trust error like NSURLErrorServerCertificateUntrusted. Even if the host Mac has the CA root certificate installed and trusted, the simulated devices rely on their own per-virtual-device trust store.1

In releases prior to Xcode 27, you could resolve this by importing the root public certificate into the simulated OS. On iOS, this could be done by dragging and dropping the .cer file onto the Simulator device window. Nothing would appear to happen, but you could then navigate to Settings, General, About, Certificate Trust Settings and mark the certificate as trusted. On tvOS, the process was even more complex, requiring you to open Settings, General, Privacy & Security, hold down the virtual remote’s Play button on the Share AppleTV Analytics option to bring up a hidden dialog, then enter an HTTP URL to a .cer file. Similar to iOS, you’d have to mark it as trusted by navigating tvOS to Settings, General, About, Certificate Trust Settings and enabling the switch for that certificate. This process was slow and, especially on tvOS, quite obscure.

In Xcode 27 with Device Hub, this process is much more uniform.

Signed mobileconfig profile in Apple Configurator

  1. Open Apple Configurator and create a new profile.
  2. Under General, give the profile a name, a unique identifier, and perhaps an organization name.
  3. Under Certificates on the left, click the Configure button and choose the .cer file you wish to install into the simulated OS.
  4. From the File menu, choose “Sign Profile…” and select a developer identity to sign with. Alternatively, you can sign profiles from the command line with security cms -S -N "My Signing Identity" -i unsigned.mobileconfig -o signed.mobileconfig.
  5. In Device Hub, select the target device, then open the Profiles tab in the right-side device inspector.
  6. Click the plus button below the list and choose the .mobileconfig file you just signed.
  7. The profile and its contained certificate should be immediately installed into the simulated OS. In iOS, you can verify by navigating to Settings, General, VPN & Device Management, and on tvOS the list of installed profiles is at Settings, General, Profile.

While this new process does require you to wrap certificates in an Apple Configurator profile, this is much more consistent with how Apple’s device management system works, as it relies on signed profiles with policies, not loose .cer files. And now, just by adding the .mobileconfig to the Profiles section of the device inspector, the embedded certificate is automatically marked as trusted, greatly speeding up installation on new virtual devices.


  1. Much like Simulator devices, Xcode’s built-in SwiftUI Previews rely on their own dedicated trust store separate from both the host Mac and Simulator/Device Hub devices, but there’s seemingly no way to configure certificates in that SwiftUI Preview environment. Apple folks, please see FB10667327

Macrochips

I was so inspired by Jason Coon’s macrochips project – 4” slate drink coasters laser-engraved to look like notable chips from computing history – that I had to design and make some of my own. I don’t own a laser cutter, but the local hardware store had one available, and I was able to convince them to let me engrave similar slate coasters despite them not being among their pre-defined set of available engraving targets (keychains, mugs, and the like). But what to pick? I decided to go with some chips that were meaningful to me:

  • Apple A17 CPU
  • Nintendo 64 CPU
  • Sony PlayStation CPU
  • Broadcom Raspberry Pi 5 CPU
  • NVIDIA Media and Communications Processor (from the original Xbox)
  • IBM PowerPC 603 CPU (from early PowerPC Macs)
  • Motorola PowerPC G4 CPU (from later PowerPC Macs)
  • AMD K6 CPU
  • Intel i386 EX CPU

The hardest part of designing these was tracking down vector versions of some of these companies’ now-obsolete logos, extracting them from PDF files and datasheets, but I think the designs turned out pretty good:

My macrochip designs

Once designed, it was time to hand them off to the laser cutter:

Laser cutter mid process

It was fun to watch the designs get laid down by the laser cutter:

The results turned out alright:

My macrochip designs as slate coasters

Though, there were a number of text layers I forgot to convert to outlines, so the engraving prep software replaced them with Myriad instead of the specific fonts I had chosen. As well, a few early attempts were also a little mis-aligned. I could certainly do better if I had time to sit and make adjustments with my own laser cutter…

Indiana Jones and the Great Circle

Indiana Jones and the Great Circle title screen

I finally caught up to 2024 and finished playing Indiana Jones and the Great Circle to 100%. I had been putting off starting the game for some time because I’m really not much of a gamer, and I find it oddly difficult to internalize new game control schemes and menu systems. But once I finally picked up the controller, it didn’t take long to get acquainted with the intuitive grip and whip system, and I’m so glad I did, because this game is really something special.

Look and Feel

MachineGames did a fantastic job at matching the feel of the source material. The levels are dense with detail, the typography looks just right, and there are both first person in-game and third person cutscene references to the films’ cinematic choices at every turn. Most notably, the use of hard contrasting light and shadow appears fairly often while exploring. Following along with the game’s story feels like enjoying a lost installment from the original trilogy, which is a bar I didn’t expect it to clear going in.

A spotlight casts Indy's shadow on the wall Carefully placed spotlights and torches regularly cast Indy’s recognizable shadow.

Light shines across Indy's eyes as he thinks Light reveals Indy’s eyes when he’s making a connection or solving a puzzle.

Welcome to Sukhothai screen Open Kapitalen and Eurostile Extended welcome you to new regions and lend film authenticity.

Choosing a mostly first-person adventure also seemed like a big development risk. For an iconic character like Indiana Jones, it’s definitely a choice to not show him for large swaths of the game. To make it convincing, they had to lean hard into what it would be like to be Indiana Jones. So much would revolve around what you can do with your hands and whip and items. Therefore, that in-game system had to feel very comfortable to use and be pretty extensive. I had played a few previous Indiana Jones (and of course, Tomb Raider) games which were all third person, so going in, I thought first person would be weird or off-putting, but this game does it so well that I now prefer it over third person or over-the-shoulder views.

The developers clearly spent a lot of time studying the films. They picked up so many of Indy’s smirks, quirks, and mannerisms, and when combined with Troy Baker’s shockingly accurate voiceover work, you’d be surprised to learn it wasn’t voiced by and motion captured from Harrison Ford himself. The humor from the films is also ever present and used to great effect. Even beyond the dialogue, the yells, grunts, and exclamations all sound so perfect, capturing Indy’s intonation well.

What really put it over the top for me, though, is the music and sound. The game features a lovely and familiar score, threading John Williams’ original themes through new material in a way that sounds completely organic and unforced, rather than just quoting the Raiders March and calling it a day. As well, the sound effects are also very much on point, with whip, punch, and gunfire having the signature cracks, thuds, and pops that seem right out of the films.

There are a few behind-the-scenes videos that go deep into all of this, and I watched them with a big stupid grin on my face. Hearing the development team talk about watching the films together, cataloging the core details that had to be right, and obsessing over everything clearly paid off.

It’s also just a gorgeous game. The id Tech 7 engine looks incredible on modern devices, rendering lighting and geometry in more detail than I’m used to in games (again, I don’t play a ton of games). The amount of just stuff to see in the levels is impressive. I can’t even imagine how long it took to set-dress all these areas. Notably, many of these items can be used as weapons or distractions, including wrenches, frying pans, mops, and bottles.

Indiana Jones turns to think, revealing his adventure companion Gina behind him Just marvel at the level of detail achieved here: The fine individual hair, the wear on the seams of the leather jacket, the distressed fur felt on the fedora, and the specular highlights on the sclera of the eyes.

Looking through a town and down the main river in Sukhothai Every region has loads to explore, little sub-plots to follow, and NPCs going about their business. Some casually relay details or hints towards as-yet-unsolved puzzles.

Gameplay

The game heavily encourages you to lean on Indy’s punch and whip maneuvers rather than using his revolver. Ammo isn’t something to be spent carelessly. Rather, you save it for the moments when you get into a jam that’s larger than you can otherwise take on. But the cost of using a loud weapon is that nearby enemies will overhear it, blow the whistle on you, and rally reinforcements, so you need to pick and choose your battles carefully rather than playing it like a run-and-gun first person shooter. While not a stealth game, climbing, disguise, distraction, and a healthy dose of hand-to-hand combat will get you further than running headlong into battle. Certain classes of enemies will also see through your various disguises and similarly call attention to you, so you need to be aware of who’s nearby.

Looking down from atop a scaffold, reloading Attention to detail is everywhere in this game. Here, the number of remaining shots in the heads-up display corresponds to the number of visibly unfired rounds in the revolver. The reload animation has Indy individually pluck out spent rounds and replace them, rotating the cylinder for each.

The game balances exploration, discovery, collection, puzzle solving, and storytelling well. I rarely found myself spending too much time doing any one of those activities. The puzzles aren’t particularly difficult, with key items often just in adjacent crawlspaces, but they’re also not too simple. They feel calibrated to make you think, but aren’t so onerous that they impede advancing the story.

Along the way, you pick up money, bandages, food, local maps, and Adventure Books that expand your capabilities. The books are the game’s skill system, where you can improve your abilities like reducing reloading time, increasing damage dealt against enemies, or boosting climb and run stamina, and finding them is a nice reward for exploration. Once learned, they make future encounters progressively more achievable and boost your confidence to take swings at more aggressive confrontations. Indy is a scholar and a problem-solver first, so getting better at the job through research feels like the right approach.

A view of the menu system listing Adventure Books that boost combat skills Acquiring and reading Adventure Books boosts combat, survival, brawling, etc.

Indiana Jones' Pause menu Even the Pause menu looks like it belongs. Also, hey, it’s me: I’m mac_minded on PlayStation and Mac Minded on Xbox.

That Belongs in a Museum

The Order of Giants DLC is a worthwhile addition, though it left me wanting even more time in this world. What MachineGames accomplished here is astounding. Licensed games based on beloved properties like Indiana Jones have a history of often getting surface details right but missing what actually made the source material work. This one didn’t miss at all. It understood what Indiana Jones is about well enough to make a game that genuinely belongs on the same shelf as the films. I don’t know if it will happen, but I would very much love a sequel.

Mastodon