Runtime for traditional ports or recompilations of N64 games.
Find a file
Matthew Stanley 948df06a75 librecomp: auto-increment RSP DMA addresses after each transfer
Real RSP DMA hardware advances SP_MEM_ADDR and SP_DRAM_ADDR by
(length + 1) after each transfer (verified against Ares' n64/rsp/dma.cpp:
pbusAddress += 8 / dramAddress += 8 per 8-byte chunk). The runtime's
DO_DMA_READ / DO_DMA_WRITE macros didn't replicate this, so any ucode
that fires DMAs in a loop without re-writing SP_MEM_ADDR/SP_DRAM_ADDR
each iteration would reload the same DMEM region forever.

Observed as Pokemon Stadium's aspMain hanging in its dispatch loop:
the L_10EC <-> L_11B4 DMA pump (which walks through the audio command
stream chunk by chunk on real hardware) collapsed into a tight
no-progress cycle. With the auto-increment in place the dispatch
makes forward progress and aspMain advances past the hang point. (A
downstream UnhandledJumpTarget then surfaces — a separate issue with
the recompiler's static indirect-branch-target list, not this layer.)

Diff verified via diff_aspmain.py against the standalone Ares oracle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 22:16:23 -07:00
.github/workflows Update mac CI runners after deprecation of macos 13 (#129) 2025-12-12 02:04:42 -05:00
librecomp librecomp: auto-increment RSP DMA addresses after each transfer 2026-05-05 22:16:23 -07:00
N64Recomp@81213c1831 Update N64Recomp submodule to fix build issue with clang 21 (#136) 2026-01-17 02:02:23 -05:00
thirdparty Update nlohmann json to 3.12.0 (#135) 2026-01-17 01:54:24 -05:00
ultramodern Fix __osContGetInitData mask to detect multiple controllers (#134) 2026-01-16 20:57:47 -05:00
.gitignore Namespace librecomp headers under recomp 2024-06-01 19:48:53 +02:00
.gitmodules Add modified o1Heap library and set up recomp heap (#66) 2024-10-21 22:23:33 -04:00
CMakeLists.txt CMake fixes to allow building this repo as a submodule (#25) 2024-05-30 09:16:07 +02:00
COPYING Initial commit 2024-05-19 14:14:54 -04:00
README.md Remove WIP section in README (#52) 2024-06-20 17:16:43 +02:00

N64 Modern Runtime

A modern runtime for traditional ports and recompilations of N64 games.
The runtime is consists of two libraries: ultramodern and librecomp.

ultramodern

ultramodern is a reimplementation of much of the core functionality of libultra. It can be used with either statically recompiled projects that use N64Recomp or direct source ports. It implements the following libultra functionality:

  • Threads
  • Controllers
  • Audio
  • Message Queues
  • Timers
  • RSP Task Handling
  • VI timing

Platform-specific I/O is handled via callbacks that are provided by the project using ultramodern. This includes reading from controllers and playing back audio samples.

ultramodern expects the user to provide and register a graphics renderer. The recommended one is RT64.

librecomp

librecomp is a library meant to be used to bridge the gap between code generated by N64Recomp and ultramodern. It provides wrappers to allow recompiled code to call ultramodern. Librecomp also provides some of the remaining libultra functionality that ultramodern doesn't provide, which includes:

  • Overlay handling
  • PI DMA (ROM reads)
  • EEPROM, SRAM and Flashram saving (these may be partially moved to ultramodern in the future)

Building

The recommended usage of these libraries is to include them in your project's CMakeLists.txt file via add_subdirectory. This project requires C++20 support and was developed using Clang 15, older versions of clang may not work. Recent enough versions of MSVC and GCC should work as well, but are not regularly tested.

These libraries can be built in a standalone environment (ie, developing new features for the libraries of this project) via the following:

cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug
cmake --build build