Play classic N64 HD texture packs — like Djipi's gorgeous Wind Waker–style "Celda" pack for Majora's Mask — inside 2 Ship 2 Harkinian, the PC port of The Legend of Zelda: Majora's Mask.
Those old texture packs were made for emulators (Mupen64 / Project64) and don't work in 2 Ship 2 Harkinian out of the box — the two use completely different texture systems. This little Python script bridges the gap automatically.
🚢 Playing Ocarina of Time instead? Use the sister tool: Rice → Ship of Harkinian Converter — same idea, for SoH.
The single easiest path: use an AI coding harness. Tools like Claude Code and Antigravity don't just give advice — they actually do the work on your computer. They'll even install 2 Ship 2 Harkinian itself for you (straight from its official GitHub releases), set up Python and Pillow, download the script, run it, and drop the finished pack right into the game. You don't have to worry about any of the setup. Point one at this repo and say:
"Read this repo and get Djipi's Celda / Wind Waker pack for Majora's Mask running in 2 Ship 2 Harkinian for me, from scratch. Install 2 Ship 2 Harkinian itself if I don't already have it, install whatever else is needed, run the converter, and put the finished pack in my 2Ship
mods/folder. I'm a complete beginner — handle everything."It sets up the dependencies and runs the whole thing for you, fixing any snag as it goes. That's as hands-off as it gets. 🪄
No coding harness? A regular chat AI still makes it easy. Open a free assistant — ChatGPT, Claude, or Gemini — give it the link to this page, and say:
"I want to convert a Rice texture pack (like Djipi's Celda pack for Majora's Mask) into a 2 Ship 2 Harkinian mod. Read this repo and walk me through every step on my computer — assume I'm a complete beginner with GitHub, Python, and the command line."
It can't run commands itself, but it'll translate every step to your exact setup and fix any error you hit — start to finish, for free.
Djipi's "Celda" pack repaints Majora's Mask in a hand-drawn, cel-shaded Wind Waker style — Clock Town, Termina Field, the masks, the works. These are actual in-game shots of the converted pack running in 2 Ship 2 Harkinian (made with this tool):
➡️ See more of Djipi's Celda 2016 for Majora's Mask — screenshots & download »
| What it's for | Get it | |
|---|---|---|
| 🎨 | Djipi's "Celda" 2016 MM pack — the textures themselves | Download here — choose the "Rice Format" download |
| 🎭 | 2 Ship 2 Harkinian — the game you'll play it in | Official releases |
| 🐍 | Python 3.8+ — runs this script | python.org/downloads (on Windows, tick "Add Python to PATH" while installing) |
| 🖼️ | Pillow — the image library it uses | After Python: run pip install Pillow |
🎨 More of Djipi's Majora's Mask work: 2016 "Celda" (recommended) · 2011 Cel Shade · 2016 3DS Style
⚠️ Important: Always pick the Rice Format version of a pack. The Glide64 / GlideN64 "cache" downloads use a different format this tool can't read. And 2 Ship 2 Harkinian needs you to supply your own legally-owned Majora's Mask ROM (it ships no game data) — you can check your ROM at 2ship.equipment.
Four steps. That's the whole thing.
Download Djipi's MM pack (Rice Format) and unzip it. You'll end up with a folder full of .png files named like ...#003334A1#3#0_all.png.
Download rice_to_2ship.py and place it in the same area as your texture folder. By default it looks for the PNGs in a ./celda_rice folder next to the script (any nesting inside is fine — it scans recursively) — or you can point it anywhere with --rice (next step).
Open a terminal/command prompt in the script's folder and run — just point it at your 2 Ship 2 Harkinian folder (the one with mm.o2r in it — launch 2Ship once first so it generates mm.o2r from your ROM):
python rice_to_2ship.py "C:\path\to\your\2 Ship 2 Harkinian"If your texture folder is somewhere else, add --rice:
python rice_to_2ship.py "C:\path\to\2 Ship 2 Harkinian" --rice "C:\path\to\your\texture\pngs"It finds every matching texture and writes celda-mm.o2r straight into 2Ship's mods/ folder. 🎉
💡 Want a preview first? Add
--dry-run— it finishes in a few seconds and writes the report files without building the big pack. Great for checking how much will match before committing.
Restart 2 Ship 2 Harkinian — anything in the mods/ folder loads automatically. Welcome to Wind Waker Termina. 🌊🎭
Honestly, this is the perfect thing to hand to a free AI assistant (ChatGPT, Claude, Gemini — whatever you like). If a step is confusing, a command errors, or you're not sure where a folder is:
Copy this entire README, paste it into the AI along with whatever you're stuck on, and ask: "Walk me through this step by step for my computer — I'm a beginner."
It'll adapt every command to your exact setup, fix classic snags like 'python' is not recognized, and hold your hand the whole way. There's zero shame in it — that's just how a lot of this stuff gets done now. 😊
Because Rice packs and 2 Ship 2 Harkinian identify textures in totally different ways, not every texture transfers — and that's expected, not a failure. Verified in-game with Djipi's Celda 2016 MM pack against 2Ship 4.0.2 (NTSC-U 1.0 ROM):
- ✅ 85% of the pack's textures converted (5,614 of 6,528) and 7,656 base-game textures got replaced — the title screen, Clock Town, Romani Ranch, NPCs, UI, the works. (Even better than the sister OoT tool's ~62%.)
- ❌ Roughly 15% can't be matched — they have no counterpart in 2Ship's game data, so those spots simply stay vanilla.
- 📄 The script writes
unmatched_rice.csv(everything that didn't make it) andmatched.csv(everything that did) — so there's no mystery about what landed where.
| Command | What it does |
|---|---|
python rice_to_2ship.py "<2Ship folder>" |
The normal way — auto-detects the base game and output location |
--rice "<folder>" |
Point to your Rice PNG folder if it's not the default |
--out "<file.o2r>" |
Choose exactly where to write the converted pack |
--dry-run |
Match + write the CSV reports only; skip building the big file (fast) |
Prefer not to use the command line at all? Open rice_to_2ship.py in any text editor and set SHIP_DIR near the top, then just run python rice_to_2ship.py.
🔧 How it works (technical details — click to expand)
The Rice video plugin identifies textures using CalculateRDRAMCRC from FrameBuffer.cpp. It's a custom hash (not standard CRC32) that operates on raw N64 RDRAM data using ROL4 + XOR + ADD accumulation.
Key technical details:
- N64 RDRAM stores data in big-endian byte order
- The CRC reads
uint32values as big-endian (struct.unpack('>I', ...)) - N64 texture pitch =
max(8, (width * bpp + 63) // 64 * 8)
2Ship's .o2r files are ZIP archives containing binary texture resources (the same libultraship format Ship of Harkinian uses):
- Header: 64 bytes (endianness, isCustom,
OTEXmagic, version, ID) - Body (V1): Type(u32), Width(u32), Height(u32), Flags(u32), HByteScale(f32), VPixelScale(f32), ImageDataSize(u32), ImageData(bytes)
- Flags:
TEX_FLAG_LOAD_AS_IMG = 0x02tells the engine the data is raw RGBA32 pixels
- Read each texture from the base
mm.o2rarchive - Compute the Rice CRC on the raw texture data (big-endian reads)
- Match the CRC against the Rice pack's filenames
- For matches, load the replacement PNG and convert to RGBA32
- Pack everything into a new
.o2rwith V1-format headers
| Type | Name | BPP | N64 Format | N64 Size |
|---|---|---|---|---|
| 1 | RGBA32bpp | 32 | RGBA | 32b |
| 2 | RGBA16bpp | 16 | RGBA | 16b |
| 3 | Palette4bpp | 4 | CI | 4b |
| 4 | Palette8bpp | 8 | CI | 8b |
| 5 | Grayscale4bpp | 4 | I | 4b |
| 6 | Grayscale8bpp | 8 | I | 8b |
| 7 | GrayscaleAlpha4bpp | 4 | IA | 4b |
| 8 | GrayscaleAlpha8bpp | 8 | IA | 8b |
| 9 | GrayscaleAlpha16bpp | 16 | IA | 16b |
- Djipi — the beautiful cel-shaded "Celda" texture artwork
- Rice / Mupen64Plus — the texture CRC algorithm (
CalculateRDRAMCRC) - 2 Ship 2 Harkinian (HarbourMasters) — the OTR/O2R resource format and the PC port that makes all this possible
- Sister project: Rice → Ship of Harkinian Converter for Ocarina of Time
This tool only converts texture packs — it contains no game assets or copyrighted artwork. You provide your own pack and your own legally-owned game.


