NAME
Chandra::Same::Boy - play Game Boy / Game Boy Color games in a Chandra window
VERSION
Version 0.01
SYNOPSIS
use Chandra::App;
use Chandra::Same::Boy;
my $app = Chandra::App->new(title => 'Game Boy');
my $gb = Chandra::Same::Boy->new(
app => $app,
rom => 'game.gbc',
scale => 3,
);
$gb->mount; # canvas + input + game loop (phase 3+)
$app->run;
DESCRIPTION
Chandra::Same::Boy is a Chandra widget that renders a Same::Boy emulator to a canvas in a native webview window, with real keyboard input, save states and battery-backed saves.
mount injects the canvas, the JavaScript blit helper, keyboard input listeners and the on_tick game loop; audio and toolbar chrome arrive in later phases. See plan/chandra-same-boy/.
CONSTRUCTOR
new(%args)
Requires app (a Chandra::App). Optional: rom (path or scalar ref), model (dmg|mgb|sgb|sgb2|cgb, default cgb), id, scale (default 3), sample_rate (default 44100; 0 disables audio), volume (0..1, default 1), autosave (battery autosave interval in seconds, default 10; 0 disables), sav and state paths.
METHODS
mount
Set the app's page content to a scaled, pixelated canvas, register the keyboard input bridge, and start the on_tick game loop that runs the emulator at ~60fps and blits each frame. Returns $self. Call before $app->run.
load_rom($path_or_ref)
Load (or hot-swap) a cartridge ROM, flushing the previous cartridge's battery first and loading any <rom>.sav.
pause / resume / toggle_pause / is_paused
reset / set_speed($multiplier) / press($btn) / release($btn)
set_volume($v) / mute([$bool]) / is_muted
Audio output level. set_volume takes 0..1. mute with no argument toggles; audio is captured only when sample_rate is non-zero, and is automatically silenced while fast-forwarding.
save_state([$path]) / load_state([$path])
Snapshot to / restore from <rom>.state (or an explicit path).
save_battery([$path])
Write cartridge save RAM to <rom>.sav (or an explicit path). The battery is also autosaved periodically during play and flushed by shutdown.
shutdown
Flush the cartridge battery. Registered as the app's on_close handler and called by Chandra::Same::Boy::App after the window closes, so in-game saves survive every exit path.
press_for_player($btn, $player) / release_for_player($btn, $player)
Input for SGB multiplayer ($player from 0).
app / boy / id / scale / frame / rom_title / rom_crc32 / dimensions
Accessors. boy is the underlying Same::Boy instance.
EVENTS
Register embedder callbacks with on($event, $coderef) (or pass on => { $event => $cb, ... } to new). Each callback is invoked as $cb->($widget, @args). Multiple callbacks per event are allowed.
- rom => ($title, $crc32)
-
Emitted after a ROM is loaded or hot-swapped.
- save => ($kind, $path)
-
Emitted after a save is written;
$kindis'state'or'battery'. - frame => ($frame_number)
-
Emitted per rendered frame from the game loop (from phase 3).
- fps => ($measured_fps)
-
Emitted periodically with the measured frame rate (from phase 3).
- action => ($result)
-
Emitted when a UI action key fires.
$resultis one ofsave_state,load_state,load_state_missing,save_state_no_path,paused,resumed,reset,fast_forward_on,fast_forward_off.
CONTROLS
After mount, the window handles these keys:
Arrows / WASD D-pad Z / X (or Space) B / A
Enter Start \ Select
F2 / F4 save / load state
P pause / resume
R reset
Tab (hold) fast-forward (4x while held)
D-pad and buttons are true press/hold/release (webview key-up events); action keys fire on press (Tab also on release).
A toolbar (Pause, Reset, Save, Load, Mute, Open) sits above the screen, with a HUD showing the ROM title, current speed and measured FPS. The Open button uses the native file dialog (Chandra::Dialog) to hot-swap ROMs. Actions also raise a toast (Chandra::Toast) for feedback.
SEE ALSO
Same::Boy, Chandra::App, Chandra::Same::Boy::App.
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION.
This is free software, licensed under the Artistic License 2.0.