Pureikyubu est un émulateur de Nintendo GameCube en cours d’élaboration basé sur Dolwin.
Le but de l’émulateur est de rechercher les caractéristiques matérielles de la GameCube et de faire de la rétro-ingénierie sur les technologies utilisées pour développer des jeux pour cette plateforme.

Les améliorations sont les suivantes:
Highlights
– Gekko recompiler: A new x86-64 basic-block compiler keeps guest GPRs in host registers and shares the interpreter’s decode cache.
– Paired-Single in SSE: Every arithmetic PS instruction and both quantised loads/stores (psq_l / psq_st) are translated to SSE/SSE2.
– No more busy-waiting: VI scan-out and serial poll run on the CPU thread, while CP, AI DMA, and DSP threads block on events instead of spinning.
– Aggregate interrupt lines: DSP and disk-interface PI lines follow the OR of latched unmasked causes, removing interrupt storms on SI polls.
– Games: Zelda: The Wind Waker and Metroid Prime boot to title screen; Animal Crossing passes audio ARQ handshake and displays Nintendo logo.
– RVZ disc images: Read-only support for Dolphin’s compressed RVZ container (Zstandard).
– SDL controller settings: Added pad backend and complete « Configure Controller N » dialog supporting keyboard and gamepad bindings simultaneously.
– New icon: Cube icon recoloured with blue logo palette and regenerated (pureikyubu.ico, 16–256 px).
Added
– Gekko: x86-64 recompiler for Gekko basic blocks with translation state generation counter for O(1) block drops on MMU/cache register writes.
– Gekko: 8192-entry decode cache keyed on PC/instruction word, and 2048-page direct-mapped TLB replacing unordered_map.
– Gekko: SSE Paired-Single translation for add, sub, mul, div, res, rsqrte, madd, msub, nmadd, nmsub, muls0/1, madds0/1, sum0/1, sel, mr, neg, abs, nabs, merge00/01/10/11, and _d recording forms.
– Gekko: Quantised paired loads and stores (psq_l / psq_st) for all indexed/non-indexed, update/non-update, and W = 0/1 forms.
– Gekko: Debugger command jit 0 / jit 1 for live engine switching.
– Disc images: Read-only support for Dolphin’s RVZ container (Zstandard compression, data-entry/group tables, pseudo-random disc junk regeneration).
– Disc images: .rvz extension accepted across command line, game selector, and file dialogs.
– Input and user interface: SDL pad backend driving keyboard and gamepad simultaneously per port, summing and clamping inputs instead of overflowing int8_t.
– Input and user interface: « Configure Controller N » dialog in SDL UI (Options → Controllers → Port 1..4) supporting bindings, axis deflections, and instant config application.
– Input and user interface: Recoloured pureikyubu_icon.svg embedded via pureikyubu_icon.h for SDL_SetWindowIcon.
– Command line and tooling: Instant boot via pureikyubu / –image , and console/log –help support.
– Command line and tooling: –bench [seconds] mode reporting throughput, Gekko::CpuStats, host cycle breakdown (BENCH_PROFILE=1), and instruction histogram (BENCH_STATS=1).
– Command line and tooling: Gekko differential harness expanded with BENCH_SPIN*, BENCH_PS_TEST, BENCH_FUZZ_PS, psq workload mix, and MSVC build_win.bat support.
– Testing: 17 new Serial Interface spec tests covering SIPOLL, buffers, COMCSR, TSTART, intervals, enables, and read-status interrupts.
– Testing: 19 Command Processor spec tests covering VCD/VAT field positions, component/colour byte counts, vertex attribute order, and gx_vtxsize.
– Testing: 5 DSP interrupt aggregation tests covering masked/unmasked cause lines, ARAM DMA completion, mailbox interrupts, and CPU→DSP request tests.
Changed
Performance and threading
– The VI scan-out and the serial poll are executed by the CPU thread from the tick it already advances (GekkoCore::Tick / TickN call Flipper::Update), so VI timing is exact instead of sampled by a thread.
– The Command Processor thread blocks on a new portable Event (utils.h) that the CPU thread signals when a batch of FIFO entries is due (CommandProcessor::TickSync); the drain stays at the emulated tickPerFifo rate.
– The AI DMA thread is woken by DSP::AITickSync (about every 6750 ticks at 48 kHz) and parks itself with Suspend() when no DMA is armed. The DSP thread is woken by DspCore::TickSync once per DspWakeTicks and drains a batch, so the emulated DSP no longer self-throttles by re-anchoring its deadline on every poll; the mailbox hold-off is now a tick deadline (DspCore::MailboxHoldTicks).
– mtmsr and rfi drop the compiled blocks only when MSR[IR]/[DR] actually change; the OS toggles MSR[EE] around every critical section and dropping the whole cache for it cost ~85,000 needless re-translations per second.
– Address translation, the tick and the branch-condition helpers are really inlined now (GEKKO_INLINE).
Behaviour and configuration
– The Windows and SDL builds keep separate settings: DefaultSettingsWin.json / SettingsWin.json and DefaultSettingsSdl.json / SettingsSdl.json. The two ports run from the same directory and used to overwrite each other’s configuration; each executable now embeds its own file names.
– The serial interface follows the documented register layout: SICnOUTBUF is the CPU-visible register with the shadow read by the transfer engine, SICOMCSR latches CHANNEL and INLNGTH on an ordinary write and TSTART reads back as a pending bit, and the poll register drives SIPoll(line) directly.
– The Flipper device threads and the emulator use the same Event abstraction, so the timing code is portable between Win32 and SDL.
Fixed
Interrupts and timers
– DSP/DI aggregate interrupt lines: Every cause in CDCR and DI_SR has its own mask bit, and the pairs are not adjacent; both re-evaluation helpers ANDed the group of causes with the group of masks, so the lines were never asserted at all. Animal Crossing hung in its ARQ wait because the ARAM DMA completion never reached the CPU. Both lines now follow the OR of (cause && its own mask) and are re-evaluated from DSPUpdateInt() / DIUpdateInt() whenever a cause or a mask changes.
– A cleared cause can drop the line: The lines were only ever dropped inside one write_cdcr / write_sr branch; clearing one cause while another was still latched left the line high with nothing left to clear it, so the CPU re-entered the external-interrupt handler on every rfi. Animal Crossing was executing ~11,500 exceptions a second.
– Serial-interface poll storm: The emulator polled on a fixed 0x10000-tick interval (about ten times the hardware frame rate) instead of the SIPOLL video-line schedule, so RDSTINT was re-raised continuously. On Animal Crossing the emulated time for a fixed wall clock went from 3.8 s to 74 s, exception entries from 165,000 to 2,213 and VI interrupts from 0 to 2,178; Zelda’s exception count dropped from 49,635 to 2,157.
– DSP microcode vectors: The interrupt vector base was taken from the live CDCR use-rom bit instead of the program that is running; Zelda’s microcode installs a CPU→DSP vector at 0x000E in IRAM and the loader’s vectors made it bounce the command. CDCR bit 1 is now latched as a request and re-tried until the core accepts it through the TE3/ET gate, so a request that arrives while te3 is closed is no longer lost.
– DSP/AI threads: DspAIOpen cleared its state with memset, which also wiped the Event the AI thread waits on (a wait on a zeroed handle returns immediately, so the thread silently went back to spinning); the clear is now an explicit DspAIControl::Reset.
Graphics
– Presentation (issue #361): pe.cpp switched the VI output off after the first GXDrawDone/PE token, which stopped scan-out for the rest of the run in titles that keep presenting; the gate had no hardware meaning and is gone. In the SDL build the VI picture was written into the same window that carries the OpenGL context, so the two presenters alternated; the GL backend owns the window while it runs and the VI still decodes the XFB and counts frames.
– Command Processor: CP_FIFO_COUNT was a stale software register and is now the live FIFO occupancy (« the distance between the write and the read pointer »). The break-point status bit was gated on CP_ENABLE[FIFOBRKINT] instead of [FIFOBRK], so a title that armed the break point without the interrupt never saw the flag. CommandProcessor::ResetFifoProcessor() drops the CP-side command buffer so a new stream starts clean.
– VI: VI_DTV_STATUS (0xCC00206E) is implemented instead of falling through to the default case, where it returned 0 and made the SDK’s VIGetTvFormat() always report NTSC.
– Texture decoder (issue #359): IA4 walked the tiles column first while the tiles of an image are stored row by row, so a map wider than one tile came out transposed (and the report encoder mirrored the same walk, which is why the gallery never showed it); the debugger’s gxtexdump read the colour fields after the decoder had serialised the texels into the R,G,B,A byte order GL wants, which rotated the channels of every non-grey format; C14X2 masked its palette index with 0x3ff instead of 0x3fff; and the transparent fourth colour of the CMPR three-colour mode lost the RGB of the endpoint average.
– Texture uploads: DecodeTexture compares the description and an FNV-1a hash of the raw texture bytes (plus a TLUT generation for the palette) and keeps the GL image when nothing changed; the upload reuses the image storage with glTexSubImage2D, the sampler parameters and the mip chain are only re-applied when TX_SETMODE0/1 really change, and TX_INVTAGS (GXInvalidateTexAll) marks every map for a decode again.
Interface and platform
– File → Reopen, a dead menu entry, is wired to the last loaded image (the LASTFILE setting the selector already maintains) with F3 as its accelerator.
– Writes to the SI input buffer registers no longer halt the emulation.
– The Gekko sources are valid UTF-8 (two CP1252 comment bytes in gekko.cpp / gekkoc.cpp were normalised).
– The DSP unit tests link a counter double (testing/dsp_test_support.cpp) now that the DSP sources are built without gekko.cpp, and the mailbox hold-off tolerates the null Core the tests use.
Télécharger Pureikyubu (32 bits) v1.4 (1.2 Mo)
Télécharger Pureikyubu (64 bits) v1.8 (2026/09/13) (1.2 Mo)
Site Officiel
En savoir plus…