* spawn_players: cast player flag combinations to s16 explicitly The PLAYER_* flag defines OR into values with bit 15 set; assigning them to s16 fields wraps to the intended negative value. The casts make that explicit (82 warnings, no behavior change). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * render_objects: mechanical warning cleanup uintptr_t casts for display list macro args, u8* casts for asset name pointers, UNUSED on decomp-preserved dead locals and params, one loop index sign fix. 75 warnings, no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * update_objects: mechanical warning cleanup (42 warnings, casts and UNUSED) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * menu_items: mechanical warning cleanup (50 warnings, casts and UNUSED) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * stubs, kart_dma: mechanical warning cleanup (43 warnings) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * code_80057C60, audio/external: mechanical warning cleanup (113 warnings) Includes two decomp artifacts worth noting: a comma operator inside an array index ([0, soundIndex] indexed only soundIndex) and a no-op for init clause, both formerly needed for byte-matching. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * some_data, actors, code_8006E9C0, code_80005FD0, main, render_player, mixer, skybox, load: mechanical warning cleanup (111 warnings) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Remaining game C files: mechanical warning cleanup to zero Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Format the changed lines per .clang-format Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ending: fix the bcopy shim reversing its arguments The port shimmed bcopy to memcpy, but bcopy takes (src, dst) and memcpy takes (dst, src), so every call through the shim copied backwards. The one call site is the debug character switch in the ceremony cutscene, which is meant to reset gCharacterIdByGPOverallRank to defaultCharacterIds. Instead it overwrote the default table with the current standings, so the reset never happened and the defaults were clobbered for later use. Reachable only with gEnableDebugMode on and all D-pad plus C buttons held. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Address review: delete dead port helper, widen D_8015F718, comment out size lookup get_texture2 was port-added and has no callers, so it goes away rather than wearing the decomp UNUSED tag. D_8015F718 holds pointers, so it is uintptr_t now. The kart_dma size lookup is commented out instead of annotated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * menu_items: replace func_80097274 with the matched decomp version Straight copy of the matched function; the NON_MATCHING guard and GLOBAL_ASM fallback go away with it. The matched body also uses the (u32) comparison forms, which keeps it warning-clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Update menu_items.c * Address review round 2: audio loop form, cast collapse, dead code removal func_800C3478 takes the while form; the (s8*)(u8*) stacks collapse to one cast (40 sites); func_800BA8B0 and clamp32 go away (no callers); gCourseOutlineTextures is const char* so its casts vanish; the podium test line and render_screens matrix line are gone; set_screen keeps its refactoring breadcrumbs commented out; the display-list walker is reverted to the vanilla form as requested, which brings its one shift-negative warning back; gCurrentlyLoadedTrackAddr defaults to 0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Address review round 3: endianness.h byteswap, size_t indices, stub pragma BSWAP16 now comes from libultraship's endianness.h on little-endian targets, whose builtin returns u16 and needs no casts at the data.c initializers. The intrinsic pragmas leave the repo. Actor and save loops index with size_t instead of casting their bounds. stubs.c silences unused parameters once for the file instead of tagging every signature. spawn_player takes s32 and casts once inside, dropping 82 call-site casts. The item window arrays are const char* end to end, race_begin_viewport loses its unused mode argument, mio0encode takes uintptr_t, and the neon TLUT math is written in bytes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * data.c: use BOMSWAP16_CONST in the static envelope initializer MSVC's _byteswap_ushort is a function call, not a constant expression, so the plain BSWAP16 broke every Windows build at this initializer. The _CONST variant is the manual shift form on MSVC and the same builtin everywhere else. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Address review round 4: single BSWAP16 home, mixer arg refactor, stragglers effects.h includes macros.h instead of carrying its own BSWAP16 copy. mixer.c drops its unused arguments and locals outright, with the ABI macros absorbing the removed parameters the same way they already absorb pkt. func_8028EC98 takes no argument, the fourth intrinsic pragma leaves math_util_2.c, the backup checksum loop joins its siblings on size_t, and two leftover casts and an UNUSED go away. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ending: back out the debug-print cast for #745 The int-to-pointer warning it silenced returns until #745 reworks this code. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * effects.h: drop the include annotation Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Retrigger CI after runner disconnect * mixer: restore the Impl signatures and suppress the unused-parameter warning instead * Clean up unused variables in code_80005FD0.c Removed unused variables and assignments in CPU behaviour code. * Remove unused camera variable from function Remove unused camera variable in look_behind_toggle function. * Update comment for bcopy and memcpy clarification Clarified comment about bcopy and memcpy usage. --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: MegaMech <MegaMech@users.noreply.github.com>
Discord
Official Discord: https://discord.com/invite/shipofharkinian
If you're having any trouble after reading through this README, feel free ask for help in the SpaghettiKart Support text channels. Please keep in mind that we do not condone piracy.
Quick Start
SpaghettiKart does not include any copyrighted assets. You are required to provide a supported copy of the game.
1. Verify your ROM dump
The US ROM is the only supported version. You can verify you have dumped a supported copy of the game by using the SHA-1 File Checksum Online at https://www.romhacking.net/hash/. The hash for a US ROM is SHA-1: 579C48E211AE952530FFC8738709F078D5DD215E.
2. Verify your ROM is in .z64 format
Your ROM needs to be in .z64 format. If it's in .n64 format, use the following to convert it to a .z64: https://hack64.net/tools/swapper.php
2. Download SpaghettiKart from Releases
3. Generating the O2R from the ROM
Windows
- Extract every file from the zip into a folder of your choosing.
- Run "Spaghettify.exe" and select your US ROM.
Linux
- Extract every file from the zip into a folder of your choosing.
- Ensure
zenityorkdialogpackage is installed. - Run "spaghetti.appimage" and select your US ROM. You may have to chmod +x the appimage via terminal.
Nintendo Switch
- Run one of the PC releases to generate an
mk64.o2rfile. After launching the game on PC, you will be able to find these files in the same directory asSpaghettify.exeorspaghetti.appimage. - Copy the files to your sd card
4. Play
- Launch
Spaghettify.exeCongratulations, you are now sailing with SpaghettiKart! Have fun!
Configuration
Default controls configuration
| N64 | A | B | L | R | Z | Start | Analogue stick | C buttons | D-Pad |
|---|---|---|---|---|---|---|---|---|---|
| Keyboard | Shift | Ctrl | Q | Space | Z | Enter | Arrow keys | TGFH (↑ ↓ ← →) | Num 8 2 4 6 |
| SDL Gamepad | A | X | LB | RB | LT | Start | L-Stick | R-Stick Up, B, Y, R-Stick Right (↑ ↓ ← →) | D-Pad |
Other shortcuts
| Keys | Action |
|---|---|
| F11 | Fullscreen |
| Tab | Toggle Alternate assets |
| Ctrl+R | Reset |
| Esc | Settings |
Graphics Backends
Currently, there are three rendering APIs supported: DirectX11 (Windows), OpenGL (all platforms), and Metal (macOS). You can change which API to use in the Settings menu of the menubar, which requires a restart. If you're having an issue with crashing, you can change the API in the spaghettify.cfg.json file by finding the line "Backend":{... and changing the id value to 3 and set the Name to OpenGL. DirectX 11 with id 2 is the default on Windows. Metal with id 4 is the default on macOS.
Modding
Custom assets are packed in .o2r or stored .zip files. To use custom assets, place them in the mods folder.
There is an official gamebanana page.
If you're interested in creating and/or packing your own custom asset .o2r files, check out the documentation page.
Note that .otr archives are not supported in SpaghettiKart!
Development
Building
If you want to manually compile SpaghettiKart, please consult the building instructions.
Playtesting (nightly)
If you want to playtest a continuous integration build, you can find them at the links below. Keep in mind that these are for playtesting only, and you will likely encounter bugs and possibly crashes.
Maintainers: MegaMech, Coco, Kirito

