https://github.com/chameleonTwistRet/ct1-JP-SpeedrunMod

Intro

Working with the @Rainchus from the Decompilation Project, we developed a modification for the game Chameleon Twist to help speedrunners practice.

Github: We are currently moving old assembly based hooks into the decomp hooks and as such have moved the repo: The old repository for the mod can be found here. The new repository for the mod can be found here.

Mods for chameleon twist use a mod hook we have built into the Decompilation Project so that they are built as N64 ROMs that are even playable on real hardware.

This specific mod PracTWIST is written in C, however some of the code is written in MIPS assembly depending on how low level we need to be. As an example here is the code I wrote to remove enemies from the game:

.org 0x8002D660
J _tobj // hook
NOP

toggleSpawnsOff:
.byte 0x00
.align 4

// Toggle Object Spawns ON ^ OFF
_tobj:
    LI t0, toggleSpawnsOff
    LB t1, 0x00 (t0)
    BNEZL t1, _tobj_return
    ADDIU a1, r0, 0x0 // No enemies or objects appear
    NOP
_tobj_return:
    ADDIU t7, t7, 0xAC68
    J 0x8002D668// +0x08 from hook
    NOP

Features

Custom Input Handler:

We created a custom input handler that allows us to read the controller inputs and button presses so that our mod menu can be controlled irrespective of the game’s own input handler.

Custom Menu System:

We decompiled the game’s print functions and the colour data structs used to make gradiented text; we then were able to create our ownm wrapper function that prints text to the screen in a similar way to the game’s own print function with our own palettes. We then created the back end menu system in C using function pointers and structs that is displayed using our print wrapper function.

Savestates System:

Savestates are a commonplace tool on emulators and are used very often by speedrunners to repeatedly practice the same situation; however, this is not something that could have been done on console.

Rain implemented a system to DMA copy RAM data to 3 sections of memory so they may be loaded back in at any time. LZ4 compression is used to compress the data to save space. The data is then copied back into RAM when the user loads the savestate.

Specific Practice Tools:

I developed a few systems throughout the game that allows a player to practice specific speedrun tricks.

As an example the screenshot above shows the JungleLand Cave Skip practice tool. This tool is tuned with the angle and z position needed when starting the backwards jump to clip through the door. It has a range of values that work and the text display colour changes depending on whether the player is within the range of values or not.

Fully functional in game timer:

The game has a timer on the pause menu that is used to time the player’s progress through the level. I reverse engineered the timer and made it so that it is always running. This is useful for speedrunners to time their level runs without having to use an external timer.

Enable Developer/Debug Mode

Through reverse engineering to make the decomp we found a system that switched off the devloper menu for the release of the game, we remove this restriction and allow the user to enable the developer menu.

Luckily this means we didnt have to develop code for collision viewing or noclipping.

Toggleable Enemy/Object Spawns

I wrote an assembly hook to toggle enemy spawns on and off, this is useful for practicing sections of the game that require precise movement. The code jumps away to set every object in the heap to 0 before returning to generating the objects in the heap.

Everything Unlocked

We reverse engineered key global variables for unlocking characters; stages and secrets and set their defaults such that everything is unlocked. This means that speedrunners can practice anything in the game without having to 100% it every time they reset the game to do new runs.