MCPcopy Create free account
hub / github.com/JRickey/BattleShip

github.com/JRickey/BattleShip @v1.5

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.5 ↗ · + Follow
1,780 symbols 4,027 edges 197 files 366 documented · 21% updated 7d agov1.5 · 2026-07-06★ 33910 open issues

Browse by type

Functions 1,583 Types & classes 197
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

BattleShip

BattleShip

BattleShip is a PC port of Super Smash Bros. (N64) — both the US (NTSC-U v1.0) and Japanese (Nintendo All-Star! Dairantou Smash Brothers) releases — built on top of the VetriTheRetri/ssb-decomp-re decompilation, using libultraship for PC-native rendering / audio / input and Torch for extracting assets out of the ROM at build time.

Runs natively on macOS (Apple Silicon), Linux, Windows, and Android.

Download the high resolution texture pack from GhostlyDark here!

No copyrighted assets are included in this repository

None of Nintendo's assets (code, textures, audio, models, text, ROM data) are checked into this repo or distributed with builds. The port is a pure C/C++ source tree; every byte of Nintendo-owned data is extracted at build time from a ROM that you supply. If you do not own a legal copy of Super Smash Bros. for the Nintendo 64, you cannot build or run this project.

You supply your own ROM. The decomp game code is region-compiled, so US and JP are separate builds — build the one matching your ROM (-DSSB64_VERSION=us|jp, see BUILDING.md). The canonical, supported dumps (internal name SMASH BROTHERS):

Version Game code SHA‑1 MD5
US — NTSC-U v1.0 NALE e2929e10fccc0aa84e5776227e798abc07cedabf f7c52568a31aadf26e14dc2b6416b2ed
JP — Nintendo All-Star! Dairantou Smash Brothers v1.0 NALJ 4b71f0e01878696733eefa9c80d11c147ecb4984 66db457b130d31a286a23d6e4dd9726e

If your dump does not match the hashes for its version, it will not work.

Project stats

<img src="https://github.com/JRickey/BattleShip/raw/v1.5/assets/readme-stats/star-growth-light.svg" alt="GitHub star growth chart" width="840">



















<img src="https://github.com/JRickey/BattleShip/raw/v1.5/assets/readme-stats/release-downloads-light.svg" alt="Downloads by Platform chart" width="840">

Charts are generated by GitHub Actions. Downloads are split by platform and ROM region; GitHub exposes current per-asset totals, not per-download timestamps.

Features

Everything below is toggleable in-game from the ESC menu.

Input enhancements (per-player)

  • Disable Tap Jump
  • C-Stick Smash
  • D-Pad to Jump
  • NRage analog-stick remap with customizable per-axis ranges

Gameplay & match options

  • Classic Co-op — play the originally single-player Classic mode with 2-player local co-op, with an optional friendly-fire toggle
  • Z-Cancel assists — Auto Z-Cancel and Flash on Failed Z-Cancel (L-cancel practice aids)
  • Competitive ruleset — one-click tournament rules, plus neutral spawns on Dream Land
  • Disable Stage Hazards
  • Hitbox view — visualize hitboxes / hurtboxes / collision
  • Boot straight to the VS character-select screen, Skip Results Screen, Force CPU Level 9
  • Unlocks — unlock everything, or individual characters (Captain Falcon, Jigglypuff, Luigi, Ness) and features (Mushroom Kingdom, Item Switch menu, Sound Test)

Audio

  • Music shuffler — randomize stage BGM
  • Music selection screen — pick the track per stage
  • Independent Master / Music / Sound / Voice volume sliders

Rendering (powered by libultraship / Fast3D)

  • Internal resolution scaling, MSAA anti-aliasing, three-point texture filtering
  • Full widescreen support, including ultrawide resolutions.
  • Renderer backend selection (OpenGL / Metal / Direct3D), VSync, windowed-fullscreen, multi-window
  • Post-process shader support with an in-app shader-pack downloader

Textures & mods

  • Hi-res texture packs on desktop and Android (opt-in, read in place straight out of a .zip). Download GhostlyDark's pack from evilgames.eu.
  • Native C mod support — write mods in C, compiled at runtime (TinyCC), with hot-reload, function detours, and a documented engine/fighter event catalog. See docs/modding.md. (Desktop only; scripting is disabled on Android.)

Controls

  • Controller and rumble support powered by SDL2, with plug-and-play routing for up to 4 pads
  • Native Raphnet adapter support up to 4 channels through hidapi
  • Per-controller configuration UI and a bundled gamecontrollerdb.txt mapping database

Platform & quality-of-life

  • Runs natively on macOS (Apple Silicon), Linux, Windows, and Android
  • First-run ROM-extraction wizard, built-in update checker/downloader, and Discord Rich Presence

Rollback netcode & online play

Work in progress.

Author's notes

About the project

This is a project that I started and developed alone with Claude until the v0.3-beta release. It took a little over a month of night and day work to get to the first beta release, and a massive 4 day long sprint working all day resolving bugs from v0.3-beta to v0.7-beta. As of now, this is no longer a pure AI project. Many people have offered their time playtesting, their knowledge of the game, or their experience with modding or competitive play; to bring improvements, bug fixes, new feature suggestions, and additions. Without them, the project would not be what it is today.

If you find anything that you would like to see improved, create an issue on Github. I'll fix it.

This port was started when the original decomp was 96% complete code only. The remaining 4% was the internal debug menu and Libultra functions that aren't necessary to port the game. The relocatable data was also not decompiled at the time. The port was designed with this in mind, and it is why certain design decisions had to have been made. I like to move fast, obviously.

This project uses a heavily modified LibUltraShip and Torch, those two modules obviously don't work with every n64 game out of the box and a lot of game specific things needed to be implemented. The original game is quite unique and uses rendering techniques and n64 hardware tricks in ways other LUS projects did not need to account for.

This is a passion project for me. Not out of nostalgia, but to actually make something. I don't have too much nostalgia for the original game, considering I didn't own a copy as a kid, but I remember playing it at a friend's house a handful of times. What motivates me to work on this is because I can. Because it's hard, because it hasn't been done before (at least not open source). It's required a ton of my personal time, even using AI. It's forced me to get creative, to design custom tools, to force the agents into certain boxes.

People may not like it because I used AI, and that's okay. I'm not going to argue with your opinion or try to say that my way is the correct way of doing things. It works for me and that's what matters to me. My code is open source, it's free, it's MIT Licensed, and everyone can learn from it. That's what should matter to you.

I hope you enjoy the project.


Building

If you want to manually compile BattleShip, please consult the building instructions.

Architecture

The port has three layers and they are kept deliberately separate:

┌──────────────────────────────────────────────────────────────┐
│  decompiled game code  (decomp/src/)                         │
│  Unmodified C produced by the decomp project. Talks to the   │
│  N64 the same way the original ROM did: GBI display lists,   │
│  ALSeqPlayer audio, OS threads, OSContPad input.             │
├──────────────────────────────────────────────────────────────┤
│  port layer            (port/)                               │
│  Modern C++ glue. Translates N64-shaped APIs into LUS calls, │
│  fixes endianness on freshly-loaded data, owns Ship::Context │
│  and the resource factories, and quarantines every change    │
│  the decomp doesn't need to know about.                      │
├──────────────────────────────────────────────────────────────┤
│  libultraship         (libultraship/)                        │
│  PC-native runtime: Fast3D renderer (OpenGL / Metal / D3D),  │
│  SDL2 input, miniaudio output, OTR/O2R resource manager,     │
│  ImGui overlay.                                              │
└──────────────────────────────────────────────────────────────┘

Asset pipeline

baserom.us.z64 is never read at runtime. At build time, Torch walks the ROM with the YAMLs under yamls/us/ and emits BattleShip.o2r — a zip-format archive of typed resources (textures, sequences, sample banks, animations, reloc files). At launch, libultraship's resource manager mounts BattleShip.o2r + f3d.o2r and the port code requests resources by path. This is the same pipeline used by Ship of Harkinian, Starship, SpaghettiKart, etc.

The relocatable-data files (fighter tables, item tables, effects, sprites) are SSB64-specific and required custom factories on the Torch side and a custom loader (port/resource/RelocFileFactory.cpp) on the runtime side.

Build-time codegen

A small amount of generated code lives outside the source tree (gitignored) and is regenerated on every build from tools/reloc_data_symbols.us.txt:

  • include/reloc_data.h — extern declarations for every relocatable symbol
  • yamls/us/reloc_*.yml — Torch extraction configs
  • port/resource/RelocFileTable.cpp — the runtime symbol table

If you ever see "undefined reference to dFooBarReloc" you regenerated the table without rebuilding, or vice versa.


Code conventions

#ifdef PORT — what it is and what it isn't

Every meaningful change to a decomp source file is wrapped in #ifdef PORT / #else / #endif. The discipline this enforces:

  • The original decomp code path stays intact and compilable under the IDO toolchain on a real N64 build. This is non-negotiable — if it ever stops being true, upstreaming improvements back to the decomp project becomes impossible.
  • The PORT branch is allowed to be ugly — an explicit endian conversion, a struct rewrite, a function shim — as long as the contract it presents to the rest of the file is the same as the N64 branch.
  • Reloc tokens vs. raw pointers: a field declared u32 under #ifdef PORT where the N64 branch declared T* is a reloc token, not a raw pointer. Resolving it requires PORT_RESOLVE(token). Assigning a real pointer with (uintptr_t)ptr will silently truncate on LP64 — wrap post-load writes in PORT_REGISTER.

Decomp preservation: behavior, not bytes

The repo follows a single principle for changes to decomp/src/:

Accuracy to game behavior > accuracy to ROM bytes.

That means IDO idioms that encode original N64 semantics — odd casts, goto flow, deliberate temporaries — are load-bearing and stay. But compiler-compat shims (warning suppressions, permissive flags, header shortcuts) that mask real bugs on modern LP64 toolchains do not survive. The most expensive lesson of the project was that -Wno-implicit-function-declaration was silently truncating 64-bit pointer returns to 32-bit int in dozens of places — see docs/bugs/item_arrow_gobj_implicit_int_2026-04-20.md. The shim is gone; the real declarations are in.

Naming prefixes

The decomp uses two-letter module prefixes throughout. Knowing them makes the source tree navigable:

Prefix Meaning
ft Fighter (ftMario, ftKirby, ftFox, …)
it Item (itAttribute, itManager)
wp Weapon
ef Effect / particle
gm Game mode
gr Stage (ground)
mp Map / collision
mn Menu
sc Scene
sy System (engine internals)
sf Saved-state / save file
db Debug
cm Camera
lb Library (low-level utilities)
obj GObj / DObj / OMObj — game-object wrappers

Full reference: docs/c_conventions.md.

Endianness handling

The N64 is big-endian; PC targets are little-endian. The port handles this in three layers:

  1. Gross byteswap at loadlbRelocLoadAndRelocFile byteswaps relocatable files word-by-word during load.
  2. Per-struct fixups — small portFixupStructU16 / portFixupStructU8 helpers fix sub-word fields that the gross swap got wrong (e.g., {u16, u8, u8} patterns where the two u8s end up swapped).
  3. Per-stream walkers — animation events, spline interpolators, and other variable-length streams are halfswapped at file-bake time and need a per-stream un-halfswap on first access. These live in port/port_aobj_fixup.{h,cpp} and friends.

If you find a new struct that reads garbage, the playbook in docs/n64_reference.md will tell you which layer it belongs in.

Bitfield layout

The IDO compiler packs small bitfields into preceding u16 pad gaps, MSB-first. Modern compilers (Clang, GCC) on LE targets pack LSB-first into the next storage unit. Bitfield structs that travel through file data must be rewritten under #ifdef PORT to match the IDO physical layout — see docs/debug_ido_bitfield_layout.md for the workflow (compile + rabbitizer disasm to verify bit positions before porting).

Patching the reads in game code instead of the layout is forbidden by team policy; the bug always comes back. See `feedbac

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Function 1,046
Method 537
Class 176
Enum 20
Interface 1

Languages

C++47%
Java26%
Python20%
C7%
Kotlin1%

Modules by API surface

android/app/src/main/java/org/libsdl/app/SDLActivity.java134 symbols
android/app/src/main/java/org/libsdl/app/SDLControllerManager.java70 symbols
port/bridge/lbreloc_byteswap.cpp59 symbols
port/gui/UIWidgets.cpp55 symbols
port/fighter_registry.cpp53 symbols
android/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java52 symbols
port/stubs/n64_stubs.c42 symbols
android/app/src/main/java/org/libsdl/app/HIDDeviceManager.java41 symbols
port/bridge/lbreloc_bridge.cpp39 symbols
port/hires/HiResPack.cpp33 symbols
tools/save_editor.py30 symbols
debug_tools/sprite_deswizzle/sprite_deswizzle.py29 symbols

For agents

$ claude mcp add BattleShip \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page