This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
PixelVoice adds AI-generated character voice dialogue to classic SNES games in the browser. It runs SNES ROMs via EmulatorJS, captures video frames and reads game WRAM to detect dialogue events, then uses Gemini Flash Live for dialogue extraction and Gradium TTS for voice synthesis.
pnpm dev # Next.js dev server
pnpm build # Build Next.js app
pnpm lint # ESLint
pnpm deploy # Build with OpenNext + deploy to Cloudflare
pnpm preview # Build with OpenNext + local Cloudflare preview
pnpm cf-typegen # Regenerate Cloudflare env typesNo test framework is configured yet.
Stack: Next.js 16 (App Router) + React 19 + TypeScript, Tailwind CSS 4, EmulatorJS (SNES9x core via CDN), deployed to Cloudflare Workers via OpenNext.
Key paths:
src/app/play/page.tsx— Main app page: ROM upload, emulator UI, debug panel (?debug=1)src/components/snes-player.tsx— EmulatorJS lifecycle wrapper (client component). SetsEJS_*globals, injects loader script, manages cleanup. Uses blob URLs for ROM files.src/lib/snes-hooks.ts— WRAM reader with fallback (libretro API → Emscripten heap), canvas snapshot utility, Chrono Trigger text table decodersrc/types/emulatorjs.d.ts— Ambient type declarations for EmulatorJS globals
EmulatorJS integration: The emulator is loaded by injecting a <script> tag for the CDN loader after setting window.EJS_* config globals. WRAM access probes gameManager.functions.getSystemRam() first, falling back to Module._retro_get_memory_data().
Voice pipeline (planned): Frame capture → WebSocket → backend → Gemini Live API (video→dialogue) → Gradium TTS (dialogue→audio) → WebSocket → browser playback.
- Path alias:
@/*maps to./src/* - Client components use
"use client"directive (required for EmulatorJS/browser APIs) - Game-specific logic (e.g., Chrono Trigger text table at WRAM 0x7E0290) lives in
snes-hooks.ts