# pc-victorious Toward a native PC port of **Victorious: Taking the Lead** (Wii, D3 Publisher / High Voltage Software, 2012), the point-and-click adventure tie-in to the Nickelodeon series. It was a Wii exclusive and never re-released. The goal is the game running natively on PC, with the Wii Remote pointer replaced by the mouse. This repository documents the disc, its formats and its code, and grows the tooling for the port. Alongside it grew **[wiikit](https://github.com/vs-sr-dev/wiikit)**, a game-agnostic toolkit for Wii reverse engineering: everything the port needs that is not specific to Victorious. wiikit now has its own repository, taken here as a submodule: clone with `--recursive`, or run `git submodule update --init`. ## BYOA — Bring Your Own Assets This repository contains **documentation and tools only**. No game data, no executables, no assets. You need your own original disc. The work is done on the North American release, S2VEG9. ## Layout docs/ disc, format and code analysis, and the plan tools/ Victorious-specific tools, the port's own layer over the runtime, the native self-test wiikit/ game-agnostic Wii toolkit (submodule: github.com/vs-sr-dev/wiikit) wiikit/recomp/ the static recompiler (Gekko -> C++) wiikit/runtime/ the C++ side: CPU model, guest memory, OS, hardware, IOS, the renderer, the audio; wiiboot ## Tools The Python tools need only Python 3.8+ and no dependencies (pycryptodome, if installed, speeds up disc decryption). Building the recompiled code needs CMake, Ninja, a C++20 compiler (clang 22 from MSYS2 is what is used here) and SDL3; running it needs OpenGL 4.5. Run from the repository root. ```sh # the disc: header, partitions; extract the DATA partition (.iso or .wbfs): # sys/, files/, and the ticket and TMD python -m wiikit.disc GAME.wbfs --info python -m wiikit.disc GAME.wbfs --extract build/extract # the executable: sections, symbols, the ELF against the retail DOL, libraries python -m wiikit.dol build/extract/sys/main.dol --info python -m wiikit.dol build/extract/files/Oscar_wii_final_versioned.elf \ --same-as build/extract/sys/main.dol python -m wiikit.dol build/extract/files/Oscar_wii_final_versioned.elf --libs python -m wiikit.dol build/extract/files/Oscar_wii_final_versioned.elf \ --symbols build/symbols.tsv # code: a function, its callers, who builds an address, the instruction census ELF=build/extract/files/Oscar_wii_final_versioned.elf python -m wiikit.ppc $ELF --func readController python -m wiikit.ppc $ELF --callers bGetShake__5CGameFi python -m wiikit.ppc $ELF --xref 0x8079ADA0 python -m wiikit.ppc $ELF --mix python -m wiikit.cw 'process__19CSongMoveBlockActorFf' # the game's archives, UI movies, rhythm charts and sounds python tools/pod.py list build/extract/files/WIICOMMON.POD python tools/pod.py extract build/extract/files/WIICOMMON.POD build/pod/WIICOMMON python tools/gfx.py build/pod/WIIART/flash --census python tools/gfx.py build/pod/WIIART/flash/rhythmgamecontrol.gfx --strings python tools/songs.py build/pod/WIICOMMON/data/songs python tools/wwise.py events build/pod python tools/wwise.py wav build/pod build/sounds Play_JadeStingerCine2 # recompile the executable to C++, build it, run the game's code natively python -m wiikit.recomp $ELF --out build/recomp cmake -S build/recomp -B build/recomp-build -G Ninja -DCMAKE_CXX_COMPILER=clang++ \ -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS_RELEASE=-O1 \ -DWIIKIT_EXTRA=$PWD/tools/selftest.cmake ninja -C build/recomp-build build/recomp-build/selftest build/extract/sys/main.dol build/symbols.tsv # boot the game: the NAND in build/nand; the boot ROM's fonts and the DSP # ROM's resampling table in build/fonts (font_western.bin, font_japanese.bin, # dsp_coef.bin: Dolphin's Sys/GC has free ones) # a window opens; the mouse is the Wii Remote's pointer: left button or # Enter = A, right button or Backspace = B, W A S D or the arrows = d-pad, # Tab = +, Q = -, 1 and 2, Space or the middle button = shake; Esc pauses # 16:9, a 1280 x 720 window, the internal resolution from the window's size; # F11 or Alt+Enter for fullscreen (borderless); the keys are in build/keys.txt build/recomp-build/wiiboot build/extract --symbols build/symbols.tsv build/recomp-build/wiiboot build/extract --window 1920x1080 # x3 inside build/recomp-build/wiiboot build/extract --aspect 4:3 --language fr # the console's settings, kept build/recomp-build/wiiboot build/extract --scale 2 --dump build/shots --dump-every 300 build/recomp-build/wiiboot build/extract --no-video --watch 10 # no window build/recomp-build/wiiboot build/extract --no-audio # no sound # where the time goes: per-frame figures, and a sampling profiler (Windows) WIIKIT_PERF=1 WIIKIT_PROFILE=1 build/recomp-build/wiiboot build/extract 2> run.err python -m wiikit.profile build/recomp-build/wiiboot.exe run.err build/symbols.tsv # standard Wii formats python -m wiikit.u8 build/extract/files/HomeButton2/homeBtn.arc python -m wiikit.tpl build/extract/files/HomeButton2/homeBtnIcon.tpl build/icon ``` ## Status Session 8: **the game is played through.** All four episodes, the Romeo and Juliet finale and the credits ran on the port, played by hand with an Xbox pad, the mouse and the keyboard, the longest sitting 2 h 21 min at 30 fps, saves kept across restarts. The renderer met nothing it lacks on the way: the game uses no fog, no Z textures and no TMEM preloads. What is left is polish: rare hitches when a dialogue loads, likely the disc reads waiting on the host's disk, and a release a player can run. The Wwise banks are read too (`tools/wwise.py`), and the disc's stories grew (`docs/04-curiosities.md`). Session 7: **the game is a PC game.** The port writes the console's settings (SYSCONF) in the NAND, and at 16:9 the game stops letterboxing: every frame is drawn anamorphic at full height, 448 lines instead of 360. The window takes any size and shape with the picture and the mouse in step, fullscreen is borderless (F11), the internal resolution follows the window (three times the Wii's at 1080 lines, still 30 fps), and the keys come from a file. The two-player rhythm game turned out to be turns on one Remote. Next was playing on through the episodes. Session 6: **the game has sound.** Wwise plays on the DSP's hardware voices, so the DSP's mixer is now C++: the AX command list, DSP-ADPCM, the polyphase resampler, envelopes, filters, the aux effects' round trip through the CPU. Music, voices (the series' cast), effects and the Bink movies' sound are heard, through SDL3 with 20 ms of latency, and the rhythm game is played by ear. The heaviest scene so far, a nightclub, went from 17 to a steady 30 fps once a sampling profiler showed where the time went: a libm call in every quantised paired-single load, and fresh memory for the GX record. Next was the PC finish. Session 5: **the game is played with the mouse.** The pointer follows the mouse one to one (the game's own cursor smoothing is lifted by the port's layer, the first code only Victorious needs), A and B are the mouse's buttons, the rhythm game's shake is Space, and Esc opens the port's own pause box in place of the Wii's Home Button menu. The first act, E1A1, was played by hand from the classroom tutorial through the school to its rhythm game, which keeps time even without sound. Next is the sound. Session 4: **the game is drawn.** The GX command stream is decoded on the game's side and drawn with OpenGL 4.5 on the host's main thread: the TEV becomes generated GLSL in integer arithmetic, indirect textures included, EFB copies stay on the GPU, and VI presents each frame at the height it scans out. The Wii Strap screen, the Bink logos, the Scaleform title and menus, and, past "Press A" with a debugging Remote, Sikowitz's classroom at Hollywood Arts in 3D all render, at the game's own 30 frames a second on about one host core. Next is the mouse as the Remote. Session 3: **the game boots to its main loop.** The runtime replaces the Wii under the recompiled code: guest threads on host threads with only the SDK's context switch replaced, interrupts delivered through the game's own handlers, IOS emulated at the IPC registers, the DSP's micro-codes, the GX FIFO parsed. From `__start` the SDK reports itself, passes its anti-modchip check, and the game runs `CGame::init` (the strap screens, Wwise, the Bink logos) and settles in `CGame::run`, sending whole frames of GX commands. Nothing is drawn yet: next is the renderer. Session 2: **the whole executable recompiles to C++, compiles, links and runs.** All 20 653 functions (1.66 million instructions) become 124 MB of C++ that clang builds in under two minutes, and the game's own code, run natively on the retail `main.dol` image, matches the host in 15 of 15 tests: its `sprintf`, 64-bit division, libm, `qsort` through its comparators, the SDK's paired-single matrix library, its FPR-based `memcpy`. Session 1: the disc is read and mapped, and the developers' symbolised ELF turns out to be on it, byte-identical to the retail executable, with 20 619 named functions. The engine (Infernal Engine), the middleware (Scaleform, Wwise, Bink) and the archive format are identified. The input question is answered: the mouse covers the adventure, and the only motion input is a shake in the rhythm game. The route is static recompilation with the Wii SDK replaced. wiikit has a disc reader, an executable loader, a demangler and a Gekko decoder checked over all 1.66 million instructions. See [docs/00-sessions.md](docs/00-sessions.md) for the log, [docs/06-attack-plan.md](docs/06-attack-plan.md) for the route, [docs/07-next-session.md](docs/07-next-session.md) for what is next and [docs/04-curiosities.md](docs/04-curiosities.md) for the interesting bits. ## Documentation 00-sessions.md progress log 01-disc-layout.md what is on the disc 02-container-formats.md every format, with verified layouts 03-executable.md the symbolised ELF, what is linked, engine landmarks 04-curiosities.md what the disc reveals about its making 05-open-questions.md what is still unknown 06-attack-plan.md the porting route 07-next-session.md the plan for the next session 08-input-and-rhythm.md the input path, the controls, the mouse as the Remote, the rhythm game 09-recompiler.md the recompiler, the CPU model, the native tests 10-wiikit.md the game-agnostic toolkit: now its own repository 11-runtime.md the runtime: OS, interrupts, IOS, DSP, GX; the boot step by step 12-renderer.md the renderer: GX on OpenGL, TEV to GLSL, EFB copies, VI 13-audio.md the audio: the AX mixer in C++, the way to the speakers, latency ## Licence MIT — see [LICENSE](LICENSE). This covers the documentation and tools in this repository only. It says nothing about Victorious: Taking the Lead or the Victorious series, which remain the property of their rights holders.