CTR Decrypted

CTR-AP Setup

This is a quickstart for playing CTR-AP, the Archipelago integration for the native PC port of Crash Team Racing. Follow the steps in order.

What you need first

CTR-AP ships no game data. You supply the game files from your own copy of the disc. You will need:

  1. A disc image of your own NTSC-U (North American) Crash Team Racing PlayStation disc. A .cue plus .bin, a single .bin, or a .chd all work. Only the North American release is supported right now. PAL (European) and Japanese discs are detected and refused.
  2. The release archive for your platform from the releases page: the Windows .zip, or the Linux and Steam Deck .tar.gz.

That is everything you need on the game side when you are joining an existing room. With a raw .bin image you do not need Python and you do not need to extract the disc. A .chd image uses the extractor in the appendix. If you are generating the multiworld yourself, you also need the matching ctr.apworld and a CTR YAML file; see Generating or hosting a multiworld.

For a guided first setup, use the CTR setup guide on AP-Pie. To create a player file, open the YAML builder.

Choose your next step: if your room is already generated, install the client and connect using the host's details. If the host is still collecting players, make a YAML (your settings file) and send it to them. If you are generating the room, install the matching APWorld (the package that adds CTR to Archipelago) and follow the hosting guide.

Step 1: get the game executable

Download and extract the archive for your platform from the releases page: ctr-decrypted-vX.Y.Z-windows-x86.zip on Windows, or ctr-decrypted-vX.Y.Z-linux-x86.tar.gz on Linux and Steam Deck. Keep the extracted files together in their own folder. The rest of these steps add the game data and your server settings there.

Step 2: your disc image

The game reads the raw disc image directly. On the first launch without one, it looks in the game folder, the folder above it, and Downloads, Desktop, Documents and Games in your home folder (three folders deep). If it finds your disc it asks whether to use it; otherwise a file picker opens. Either way it then offers to copy the image into the game folder, or to remember where it is.

You can also put it there yourself: copy your NTSC-U .bin into an assets folder next to ctr_native_ap.exe (launching the game once creates that folder):

CTR-AP/
  ctr_native_ap.exe
  assets/
    ctr-u.bin

The filename does not matter: the game scans the .bin files in assets and uses the one whose boot id matches the NTSC-U disc (SCUS_944.26). ctr-u.bin is just the conventional name. That's it: no Python, no extraction step. The image must be the common single-track raw PlayStation BIN layout (MODE2/2352 sectors). A cooked 2048-byte .iso does not carry the audio and video sector data the game needs, so it will not work. PAL (European) and Japanese images are detected and refused with a message naming their boot id.

Go straight to Step 3. If your image is a .chd, or you specifically want to save disk space, see the appendix at the end of this guide.

Step 3: connect to your room

Launch ctr_native_ap.exe. On the first start a setup screen opens on the title screen: it asks for your room details, then a few options (fullscreen, aspect ratio, render scale, 60 FPS, skipping the intros, Discord status). Skip it, or come back later, in OPTIONS → Connection. The room details are:

Select Connect (in the setup, Next connects too). The status line on the same screen shows the connection state (Connecting… / Connected / an error message). Your settings are saved to config.ini next to the executable, and the game dials automatically on later launches. A startup dial that cannot reach the room stops after a few automatic attempts instead of retrying forever: the status line then says that automatic attempts stopped, and selecting Connect retries with the same settings.

Your first five minutes

Once the status says Connected, return to the main menu and start Adventure mode. Use the normal save station in the hub to save your local Adventure progress. The Archipelago server remains authoritative for received items and completed locations, and rebuilds your received-item counts when you reconnect.

The locations in your seed depend on its YAML options. They can include Trophy Races, CTR Token Challenges, relic Time Trials, boss races, Gem Cups, Crystal Bonus Rounds, Oxide races, and additional finishing-position checks. Complete an event and continue past its results or award screen to send its check. Items you receive, and the ones your checks send to other players, appear in the feed during the race as well as in the Adventure hub. Progression items update your available gates; traps arm silently and fire during a later race.

If the connection drops, checks completed offline are retained and sent after you reconnect to the same seed and slot. The Connection screen shows the current state and any error message. A drop after you have connected once keeps the client recovering in the background, so a player mid-seed is not stranded away from the main-menu Connection screen; a startup or manual dial that never reached a room stops after a few automatic attempts and waits for you to select Connect.

The client verifies the seed after connecting. If the hub shows a red SEED NOT COMPLETABLE warning, stop and report it with your YAML and spoiler log. For a crash or a seed that appears stuck, follow Reporting a crash or a stuck seed. Setup questions and reproducible bugs can go to the GitHub issue tracker; if you are unsure which repository is responsible, file it there anyway.

Alternative: config file

If you prefer a text file, copy ap-config.example.txt to ap-config.txt in the same folder as ctr_native_ap.exe and set uri, slot, and password there; the game reads it at startup. Values saved from the in-game Connection screen (config.ini) take precedence when both exist. The example file also documents a few optional quality of life toggles (skip_hints, map_flash), which can equally be changed in the in-game options menu.

Item boxes

If your YAML turned on box_locations, the tracks carry AP item boxes: crates placed around the course that send a location check when you break them. This is separate from itemsanity, which controls received weapon items and weapon- use checks. A broken AP box stays broken for the rest of the seed, across reconnects and relaunches, because the client asks the server what has already been checked rather than keeping its own tally.

You do not have to install anything for this. The placement set, meaning where every box stands on every track, is compiled into the client, so the boxes are simply there once your seed includes them.

Two things decide whether a box appears:

If a track looks empty and you expected boxes, open ctr-ap.log. Every level load writes one line saying how many boxes are standing out of how many placements the track holds and which placement set is live, plus, when nothing stands, which reason applies.

By default an AP box shows the Archipelago colour of the item inside it: purple for progression, blue for useful, cyan for filler and salmon for a trap. A box is pink until the client has looked up what is inside, a moment after connecting. To see every box pink instead, turn off OPTIONS → Archipelago → Item Box Colours; the setting is saved in config.ini. The seed can also turn colours off for everyone with the YAML option color_boxes_by_item, for example for a race. Then the row shows OFF (SEED) and cannot be turned on.

AP boxes break when your kart touches their collection area, when your moving bomb, missile or thrown shield hits them, or when your weapon explodes close enough. Direct projectile hits check the movement between frames. Opponent karts and weapons cannot collect your AP boxes. Kart and direct-projectile contact have extra tolerance; weapon explosion ranges are unchanged.

Experimental recorded AI laps

Recording your laps and using recorded lines are separate options under OPTIONS → Authoring. Both default to off. You can collect laps without changing how the opponents drive.

Save your laps

  1. Enable Save AI Lap Recordings before starting a race. To set the name saved in your recordings, close the game and edit nav_driver_name under [Authoring] in config.ini. If empty, it uses your configured AP slot name. The Driver Name row displays the value but cannot edit it.
  2. Complete a multi-lap race and continue to its results. Only eligible clean, complete laps are saved, up to three per recording. The standing-start lap is excluded because it starts on the grid rather than at the finish line; a one-lap race therefore does not provide a usable recording.
  3. Look in ap-navpaths, beside the config.ini used by your game. This is relative to the game's working directory, which may differ from the executable's folder. ctr-ap.log records each saved file and explains when no eligible lap was saved.

Files are named navpath-<track-number>-<recording-number>.navlap. New recordings use an unused number and preserve earlier files. Nothing is uploaded. Turning recording off during a race discards its unsaved laps.

Use recordings

Close the game before adding .navlap files to ap-navpaths. Keep the track number in the filename. If a filename already exists, give the incoming file an unused three-digit recording number from 001 to 999; do not overwrite the existing file. Custom-track recordings must match the package's navigation identity and revision as well as the expected filename. Changing a filename does not make a recording compatible with another track.

Enable Use Recorded AI Laps, then start a race on the matching track. You can leave Save AI Lap Recordings off. To return to the track's normal AI lines, turn Use Recorded AI Laps off and start a new race. Your recordings remain on disk.

Current playback is experimental. The loader searches newest files first, opens at most eight candidates and chooses up to three usable recordings, preferring different contributor names. Those recordings fill three shared AI lines. Names can repeat across opponents; fewer recordings can also produce offset copies of a line. The field is not randomly selected, and each racer does not yet own a distinct recording with vanilla AI filling the remaining places. If no usable recording loads, the track's own navigation remains in use.

Recorded lines do not guarantee the original lap time. Finish-line movement and ordinary-crate interactions still need improvement and gameplay testing. Independent racer assignment and vanilla fallback are planned corrections. For troubleshooting, search ctr-ap.log for [AP NAVREC]: it lists selected files, lane assignments and reasons recordings were skipped. Include that log, your client version, track and relevant recording when reporting a problem through Reporting a crash or a stuck seed.

Generating or hosting a multiworld

Create your player file with the YAML builder. Its options come from the ctr.apworld of the latest release. Download the resulting YAML and give it to the person generating the room. The builder only writes your player file; it does not generate the seed or host the server.

Only the person generating the room needs the ctr.apworld. Download it from the same release as the client and install it by double-clicking it or placing it in Archipelago's custom_worlds folder. Add every player's YAML to the generator's Players folder, then generate and host the resulting multiworld through Archipelago as usual.

As an offline alternative to AP-Pie, use Generate Template Options in the Archipelago Launcher after installing the matching ctr.apworld, then edit the generated Crash Team Racing YAML locally.

The released client and apworld are a pair. Update both together, even when a release appears to change only one side.

If an in-game update is interrupted

The in-game updater (a prompt on the main menu appears when a newer stable release exists) installs ctr.apworld, the Cortex Vortex files (in the assets folder the game reads), the bundled solo runtime (solo-runtime/, replaced as a whole folder) and the client in one step. It keeps your previous files next to the new ones with a .old ending (solo-runtime.old for the runtime). If the game is closed, killed or loses power during that step, the next start restores the .old files by itself. Your solo seeds and saves in solo/ are never touched. While Play Solo runs a session or makes a seed, the update waits: stop Play Solo first, then choose RESTART.

On Linux and Steam Deck the client file is never missing during the update: the new one replaces it in a single step, and the previous one is kept as ctr_native_ap.old.

On Windows one moment cannot be covered: the client is renamed to ctr_native_ap.exe.old just before the new one takes its place. If that is the moment the install was cut off, the game does not start because no ctr_native_ap.exe exists. Rename ctr_native_ap.exe.old back to ctr_native_ap.exe and start the game; it then restores the other files. The same step by hand works for any file whose .old copy is still there (for example ctr.apworld.old back to ctr.apworld, or the solo-runtime.old folder back to solo-runtime after removing the new one). Your config.ini, saves, solo seeds and the disc image are never touched by an update.

Playing solo, without a server

From 0.3.0 the client can make and host a single-player seed itself. Choose PLAY SOLO on the title screen, or open Options > Connection > Play Solo:

The client starts a private Archipelago server on your own computer (127.0.0.1, ports 38301 to 38320) and connects to it; nothing goes over the internet. Everything solo is stored in the solo folder next to the game; the game keeps backups of its saves with your memory card (see Backups). Multiplayer still uses Connect as before.

Backups: going back to an earlier save

The game keeps copies of your progress in the backups folder next to it: your memory card save and the save of every Play Solo seed. A copy is made each time the game starts and, while you play, before a save when the last copy is more than 15 minutes old. Nothing is copied when nothing changed. The 10 newest copies are kept.

To go back, open OPTIONS → Backups. Each copy shows when it was made and why (game start, while playing, before a restore); the line under the list says what it holds. Cross on one asks to restore it, and the game restarts and loads it. What you had before is backed up first, so a restore can be undone the same way. Started from Steam, the game cannot restart itself: quit and start it again from Steam, and the copy is restored then. Until then the row reads AT NEXT START, and Cross on it cancels.

A multiworld's progress (checked locations, received items) lives on its server, not here: a restore brings back your save and Play Solo seeds only.

Custom tracks and racers: the Mods screen

Choose MODS on the title screen (or OPTIONS → Mods from anywhere). L1 and R1 switch tabs:

Installed tracks appear on extra pages after the normal tracks in a one-player Arcade race and in Time Trial: at the track list, press Right past the last page. They race outside Archipelago, so disconnect from a room first. A room that needs a track you installed from Tracks finds it without downloading it again.

60 FPS

The game runs at 60 FPS by default. To go back to the original 30 FPS, turn off OPTIONS → Video → 60 FPS (Next Load) (saved as fps60 in config.ini). The change applies the next time a track or menu loads. Every mode runs at 60, Time Trial included; ghosts recorded at either rate play at both.

Importing custom tracks from an xdelta patch

Some custom tracks come as an xdelta patch for the game disc (for example a custom adventure pack). The client can take the race tracks out of such a patch using your own disc; nothing from the patch is downloaded or shared.

  1. Open MODS on the title screen and press Select (Import track files).
  2. Choose the patch with the file dialog, drop the .xdelta file on the game window, or put it in assets/tracks/import/ (useful on Steam Deck in Game Mode) and pick it from the list.
  3. Check the list of found tracks and press Cross to install.

The tracks are saved in assets/tracks/<track>/original/, where rooms and solo seeds look for custom tracks, and appear on the Mods screen's Installed tab and in Arcade and Time Trial. If a pack descriptor (<patch name>.ctrpack.json) sits next to the patch, it supplies the track names, laps and relic times. Only race tracks are imported; arenas, game code and other changed files are listed but skipped.

Optional: controllers and Steam Input

Controllers work out of the box: the game uses SDL, so common gamepads (Xbox controllers, DualShock 4 / DualSense, and most others) are picked up automatically with a PlayStation-style layout, whether connected before or after launch.

To change which device each player uses, rebind buttons, set a stick deadzone for a drifting stick, or switch Steering to Modern if the stick feels weaker than the D-pad, open Options → Controls and pick a player. Your choices are saved in controls.ini next to config.ini. The full guide is docs/CONTROLS.md.

If you would rather run your controller through Steam Input (a Steam Controller, custom button remapping, or per-game controller configurations), add the game to Steam as a non-Steam game: in Steam, choose Games → Add a Non-Steam Game to My Library…, browse to ctr_native_ap.exe, and from then on launch it from your Steam library. Steam Input then treats it like any other Steam game.

On a Steam Deck, use the Linux .tar.gz. In Desktop Mode, extract it into a folder of its own (for example ~/Games/CTR), put your disc image in its assets folder, then right-click ctr_native_ap and choose Add to Steam. From then on start it from your library in Gaming Mode. The first launch on a Deck is fullscreen at 16:10, the Deck's screen, and the built-in controls work as a controller. You do not need a keyboard: focusing any field on the Connection screen brings up the Steam on-screen keyboard, and the whole edit works from the pad: X or START saves the field, TRIANGLE cancels it.

Reporting a crash or a stuck seed

If the game crashes, or a seed seems impossible to progress, run support-bundle.bat (Windows) or ./support-bundle.sh (Linux/Steam Deck) from the game folder. It creates one small archive (ctr-ap-support-<date>.zip / .tar.gz) containing the game log, the AP log, the crash report if there was one, and your connection settings with the password removed. No game data is included. Attach that archive to a GitHub issue, or bring it to the Crash Team Racing channel on the Archipelago Discord, together with a line about what you were doing; if the seed itself seems broken, include your YAML and the spoiler log too.

The client also checks every seed on connect: if a solo seed cannot be completed, a red "SEED NOT COMPLETABLE" warning appears on the hub and the AP log records which locations are unreachable. Mention that verdict in your report if you see it.

Troubleshooting

Appendix: extracting the assets (most people should skip this)

You almost certainly do not need this. Step 2 is the normal way to set the game up, and it needs no extra tools. Extract only if one of these applies:

It needs Python 3.8 or newer, and .chd images additionally need the chdman tool on your PATH. From the folder that holds ctr_native_ap.exe, run:

python extract_assets.py "path/to/your/CTR.cue"

You can also point it at a .bin or a .chd. By default it writes an assets folder in the current directory. To send it somewhere else, add --out:

python extract_assets.py "path/to/your/CTR.bin" --out "path/to/CTR-AP/assets"

When it finishes you should have this layout:

CTR-AP/
  ctr_native_ap.exe
  assets/
    BIGFILE.BIG
    SOUNDS/KART.HWL
    TEST.STR
    XA/ENG.XNF
    XA/ENG/EXTRA/S00.XA ... S05.XA
    XA/ENG/GAME/S00.XA ... S20.XA
    XA/MUSIC/S00.XA ... S01.XA

If you extracted with a version older than v0.1.2, run the extractor again with the current one. Earlier versions truncated part of the audio data, which makes music and the race announcer sound wrong or go missing.