All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
README.mdfor theboytacean-reactpackage, documenting the components, props, hooks and keys, with a quick start, a complete emulation page example and copy and paste instructions to build one from scratch
- Faster and more resilient release builds through caching of native dependencies
- Resolution of the default WASM binary path in
boytacean-core, which pointed at alibdirectory that only exists in the repository and therefore failed whenever the package was installed from npm - Build of the web front-end, which was broken by the resolution of the WASM binary through a bare specifier, as Parcel resolves those at build time and the
boytaceanpackage is aliased to a local file
- Publish of the core and React packages, which failed as the deploy job did not install the dependencies required by their build
- Keyboard navigation in the game playlist (arrow keys to browse results, Enter to load)
- Performance profiling support with per-frame timings, render timings and memory access counters - #34
- Performance audit document with benchmark comparisons against other emulators - #34
- Headless
boytacean-corepackage with aGameBoyCorethat carries the emulation logic without any React, EmuKit UI or bundler-specific dependency - #2 StorageAdapterabstraction for the persistence of battery-backed RAM and settings, allowing embedders to replace the Web Storage API - #2boytacean-reactpackage with a drop-inBoytaceancomponent, rendering the display, binding the physical keyboard and showing an on screen game pad out of the box - #2Boytacean.Provider,Boytacean.Screen,Boytacean.GamepadandBoytacean.Keyboardcomponents, allowing the complete presentation to be replaced by the embedder - #2useBoytacean(),useBoytaceanStatus()anduseBoytaceanStats()hooks, keeping the context identity stable so that consumers are never re-rendered by the emulation - #2- Embedding example covering the out of the box usage, a custom layout with a remapped keyboard and a fully custom game pad - #2
- Unit test suites for both the core and the React packages, run as part of the WASM continuous integration jobs - #2
loadedRomName,loadedRomSizeandloadedaccessors inGameBoyCore, exposing the currently loaded ROM to embedders - #2
- Faster background rendering and main loop clocking with identical emulation output - #34
GameboyEmulatorreduced to an EmuKit adapter over the headless core, keeping only the UI-bound surface - #2- WASM path and extra settings are provided as core options instead of being resolved through bundler-specific
requirecalls - #2 - Both web packages are now built into plain JavaScript with type declarations, so that they are resolvable outside of a TypeScript aware bundler - #2
- The
deploy-npmjob publishes the core and React packages alongside the WASM one - #2
- Physical keys stayed pressed whenever the page lost focus, as the key up event is not delivered in that situation - #2
- Build of the web packages, which failed while EmuKit could not be compiled by TypeScript 5.7 or newer - #2
- Type error in
buildRomData()when unpacking a zipped ROM, which prevented the type check of the web front-end - Freeze with a blank screen (music still playing) in demos that wait for the first V-Blank line
- Garbled graphics in demos that change video registers in the middle of a scanline (raster effects)
- Raised the minimum supported Rust version to 1.86
- JSON-based game playlist support with search and remote ROM loading via
playlist_urlparameter - Documentation describing the playlist file format and how to build one
- High-pass audio filter options (Preserve, Accurate, Disable) with save-state support
- SDL frontend shader loading support via
--shader-path - PyBoy 2.x compatible Python interface (
PyBoyV2) withtick(count, render),button/button_press/button_release,screen.ndarray/screen.image,memory[addr]bracket accessor,mb.cpu.registersregister file,set_color_paletteand a genericGameWrapper Tile,SpriteandTileMapAPI objects with bracket access, slice/2D indexing anduse_tile_objects(True)toggle;tilemap_background/tilemap_windowattributes plusget_tile/get_sprite/get_sprite_by_tile_identifierhelpers onPyBoyV2- Standalone game wrappers (
GameWrapperTetris,GameWrapperSuperMarioLand,GameWrapperKirbyDreamLand) auto-selected by cartridge title, plusgame_area/game_area_collision/game_area_mapping/game_area_dimensionshelpers .symsymbol-file loader andsymbol_lookup(name)returning(bank, addr)onPyBoyV2- Lightweight pure-Python
hook_register/hook_deregisterover per-frame PC checks (no opcode patching, zero cost when no hooks are registered) MemoryScannerwith EXACT/LESS_THAN/GREATER_THAN scans plus CHANGED/UNCHANGED/INCREASED/DECREASED/MATCH rescansGameSharkcheat manager applying 8-bit RAM-write codes (ttvvaaaaformat) every frame, withadd/remove/clear_allPyBoyV1.botsupport_manager()returning aBotSupportManagerproxy withscreen(),sprite(),sprite_by_tile_identifier(),tile(),tilemap_background()andtilemap_window()methodsLegacyScreenexposing the 1.x 3-channel RGBscreen_image,screen_ndarray,raw_screen_buffer*andtilemap_position*shapes used by older AI scriptsPyBoyV1.override_memory_value(rom_bank, addr, value)for legacy memory-patching scripts (RAM addresses only — ROM patching surfaces a clearRuntimeErroruntil the core exposes cartridge writes)GameBoy.next_frames(count)andframe_buffer_rgba()Rust bridges;PyBoyV2.tick(count, ...)now batches the loop entirely inside Rust when no hooks/cheats/recorders are active, andscreen.ndarray/screen.image/screen.raw_bufferconsume the native 4-channel buffer directly- HBlank HDMA transfer support
- Python 3.14 support via pyo3 0.25
boytacean.testpackage shipped with installs, with automatic skip guards whennumpy/Pilloware missing or required test ROMs are absentGameBoy.cpu_f/set_cpu_faccessors and a matchingPyBoyV2.register_file.Fproperty that reads and writes the real flag byteTile(..., bank=)kwarg and CGB-awareSpriteinitialisation that routes bank-1 OAM sprites to the right VRAM bank instead of silently reading bank 0- Coverage for the PyBoy compatibility layer: 8 new Python unit tests (V1/V2
set_emulation_speed, banked memory rejection, appliedgame_area_mapping, per-tickpost_tick, banked hook rejection, multi-byterescan_memory, overlapping GameShark codes) and a Rust unit test forCartridge::title()on an unloaded cartridge
- Python extension defaults to release builds (
debug=Falseinsetup.py), makingpip installandpip install -e .produce optimised binaries out of the box - Inlined the per-cycle dispatch chain (
GameBoy::clock,*_clockwrappers andMmu/GameBoyaccessors for ppu/apu/dma/pad/timer/serial); native baseline frame rate on Tetris improved from ~7900 fps to ~8700 fps (+10%) and the cost of clocking idle serial hardware dropped from ~12% of frame time to ~1% - Promoted hot dispatch-chain hints from
#[inline]to#[inline(always)]acrossgb.rs,mmu.rsandppu_fast.rsso the inlining is no longer left to the optimiser - PyBoy compatibility surface reorganised into a
boytacean.pyboysubpackage (api,core,debug,wrappers); import paths fromboytacean.pyboy(e.g.from boytacean.pyboy import PyBoy) remain stable - Standalone PyBoy 1.x compatible class (
PyBoyV1) withWindowEvent,send_input,screen_image,get_memory_value/set_memory_valueandcartridge_title()method PyBoyalias resolving toPyBoyV2so the modern surface is the default forfrom boytacean.pyboy import PyBoy- Python bindings for VRAM, OAM, HRAM, ROM/RAM data, ROM/RAM banks, CPU register file, mode predicates and clock frequency
PyBoyV1.set_emulation_speed/PyBoyV2.set_emulation_speednow compute against a captured base clock rather than the currentclock_freq, so repeated calls no longer compound;speed=0follows the PyBoy 2.x convention and means "unbounded",speed<0raisesValueErrorPyBoyV2.game_area_mapping(mapping, sprite_offset)actually applies the mapping insideGameWrapper.game_area()instead of silently storing it; agents that pass a tile-id remap table now receive the remapped observationMemoryScanner.rescan_memoryreuses the original scan'sbyte_width/value_type/byteorderso dynamic comparisons on 2-byte/4-byte/BCD scans no longer fall back to a single-byte readGameShark.add/removereference-count the pre-cheat snapshot per address, so overlapping codes on the same byte share one snapshot and removing one cheat no longer prematurely restores the original valueHookRegistry.registerrejects bank-aware registrations (bank != 0) withNotImplementedErrorrather than silently colliding with bank-0 entries at the same addressMemory._read/_writeraiseNotImplementedErrorwhen called with a non-Nonebank instead of silently returning the flat-bus valueDisplay.set_hud(frame_index=...)accepts a baseline so the first FPS sample doesn't include frames that ran before HUD activation
boytacean.pyboysubpackage was missing from shipped wheels/sdistsCartridge::title()now returns"UNKNOWN"and guards against out-of-rangetitle_offsetinstead of returning an empty string (or panicking onrom_data.len() < 0x0134) for unloaded cartridgesPyBoyV1.screen_image()was calling a non-existentself.image()and raisingAttributeError; it now produces the 3-channel RGB image PyBoy 1.x callers expectPyBoyV1.tick()/PyBoyV2.tick()invokeself.game_wrapper.post_tick()after advancing frames, so wrapper-cached fields (score,level,world, ...) no longer stay stale during normal emulation- Fixed
audio_ch1_enabledreturning the wrong channel status - Shader program was not applied to SDL output
- SDL shader rendering failed due to lifetime issues
- SDL shader context version mismatch caused blank output
- Major issue with the VBlank STAT, should fix many visual glitches in games
- Issues with the LCD STAT interrupt not triggering correctly due to incorrect handling of the internal STAT line state and edge detection
- WX and WY constants address in the code
- Dependency issues with the Web frontend
- BOSC decompressor utility documentation and usage
- Bumped some packages
- Process package reference in GitHub Action workflow
- BOSC decompressor utility documentation and usage
- Add new dependency to fix GitHub Action workflow
- State management support for:
pad,ppuandcpu
- Structure of the BOS save file format, breaking change!
- Major bug related to OAM masking
- Greatly improved state management in BOS
- Support for MBC2
- Bumped EmuKit to improve Web runtime performance
- Extra react reference
- Major PPU related issue in state loading, which used to create PPU mode related issues
- Warning message in wasm-bindgen loading
- Unit test issue
- Memoised some of the class generation process
- Updated Emukit version, for faster performance
- Issue related with DMA transfer being triggered while loading state
- Sound glitch in loading save state, by setting proper sound raw values
- Unit test that was failing
- Improved Zippy format to include opaque feature support, for future proof
Licenseeenumeration with the description of the publisher of the ROM- Support for Zippy encoding format for fast compression
- New hashing crate that includes CRC-32 and CRC-32C implementations
- Issue with the web frontend and
hardReset()implementation
- Support for cartridge region detection
- Bumped web packages
- Support for SIMD based color space conversion - #45
- Support for
window.requestAnimationFrame()and game loop inversion of control - #26 - Custom Boot ROM support for CGB - #34
- Removed binary distribution from PyPi
- Bumped base rust version to fix issue with GitHub Action Deploy workflow
- Initial support for the
PyBoycompatibility layer - #36 - Support for PyPi registry for the PyO3 package - #43
- Python interface file for base boytacean (
boytacean.pyi) - Interface to custom boot ROM loading in Python
- Better
boot_dump.pyscript with support for other string output formats - Improved error handling using the
Errorenum
- Issue related to interrupt timing, reduce interrupt to 20 cycles instead of 24
- Libretro issue with the loading of the base emulator info
retro_get_system_info()
- Support for Python 3 API - #36
next_frame()method for frame by frame navigation- Support for palette switching option in Libretro - #37
- Made part of the frontend code conditional on
NODE_ENV = "development" - Re-release of version
0.9.17
- Support for Python 3 API - #36
next_frame()method for frame by frame navigation- Support for palette switching option in Libretro - #37
- Made part of the frontend code conditional on
NODE_ENV = "development"
- Bumped emukit version to fix a bug with zip file handling
- Support for ROM in zip files (Web frontend)
- Support for raw frame buffer
- Lazy evaluation of frame_buffer (on-demand) for DMG
- XRGB8888 support for Libretro frontend, for better color fidelity and faster render
- Support for save state - #7
- LibRetro save state support - #7
- Support for fast mode in SDL frontend
- Support for GameShark cheat codes - #33
- Made audio flush for libretro and sdl frontends flush by the end of the frame
- Improved MBC5 to support 9 bit ROM bank addresses
- Breaking issue with Libretro frontend and Linux
- Fix
window_counterissue in PPU - Issue with BESS header testing
- Improved command line parsing with positional ROM path value
- Better CI/CD for releases
- Hidden test panel in Web UI
- Small issue with command line arguments
- New WASM build
- Build of a new release
- Issue with release life-cycle
- Issue with release life-cycle
- Better release life-cycle
- Support for image based testing
- Support for rumble, works for both mobile devices and Gamepads (web APIs)
- Bumped emukit to 0.8.8
- CGB-ACID2 test passing - #30
- Support for the
clock_m()function - Benchmark CLI option in SDL
- Major performance improvements for the DMG specific code
- Support for displaying speed at which the CPU is running in Web mode, for debug purposes
- Headless execution mode in Boytacean SDL
- Many more parameters added for Boytacean SDL
- Small panic recovering issue
- Support for auto emulation mode selection
- Support for enabling and disabling audio channels
- Issue with CH2 envelope initialization
- Support for Game Boy Color (CGB) emulation! 🥳 - #8
- Support for CLI params in Boytacean SDL
- Support for
GameBoyConfigstructure that is passed to some comments - New
DMAcomponent
- Support for serial data transfer - #19
- Support for printing of images using Printer emulation - #19
- Support for display of logger and printer in Web panels
- Converted serial-sections strategy to event driven
ButtonSwitchissues by updating the value strategy nad bumpingemukitAudioGBwith display of canvas with no visibility
- Support for variable clock speed for APU, means variable audio speed
- Moved debug into the base emulator (from emukit)
- Support for audio channel 4 (noise) 🔈
- Better trigger support for audio channels 🔈
- Added CH4 public API method for WASM
- Envelope support for both channel 2 and 4 🔈
- Issue related to the wave length stop flag 🔈
- Support for CGB flag parsing
- Waveform plotting support
- Major JoyPad issue with Action/Select read in register
- Small issue with channel 3 audio and DAC disable
- Support for stereo sound 🔊
- APU
clock()method withcyclesparameter, improving performance by an order of magnitude 💪
- Added reset of APU, which fixes annoying "garbage" data in buffer when restarting the state of the emulator
- Bumped emukit, fixing a lot of bugs
- Support for Audio 🔈!!! - #12
- Support for WASM engine version printing
- Build process for the docs.rs website
- Unused code issue
- Old compilation problem with
NUM_CPUSgeneration
- Bumped emukit dependency
- Support for the
build.rsgeneration file that creates thegen.rsfile - Support for benchmark in the SDL frontend
- Palette switching for the SDL frontend
- Bug with ROM title that included 0x0 characters in it
- V-Sync issue with SDL
- Bumped base emukit version
- Support for theme and palette selection
- Theme stored in
localStorage
- Canonical URL support for boytacean.joao.me
- Small help changes regarding Gamepad
- Emukit version bump
- Emukit version bump
- Made UI generic by extracting components into EmuKit 🎉
- More generic help panels
- Exclusion of files from
Cargo.toml
- Support for Ctrl+D (Speedup) and Ctrl+K (Keyboard toggle) shortcuts
- Initial help panel
- Palette debugging panel
- Android highlight color in buttons
- Android issue with arrow pointers
- More issues related with bad PPU handling
- Issue with background color and change of palette colors
- Issue related with STAT interrupt not being triggered for all conditions
- PPU issue related to the maximum number of objects/sprite per line being 10, issue detected by ACID test
- Object pixel drawing priority issue, issue detected by ACID test
- Issue associated with the wrongful flipping of 8x16 sprites, issue detected by ACID test
- Issue associated with drawing of window tiles, due to extra
update_stat()operations, issue detected by ACID test
- Critical issue with loading of Boot ROM
- New default demo ROM
- Start and Select buttons order
- Small cosmetic changes
- Support for true fullscreen at a browser level
- Support for more flexible palette colors
- Support for setting palette colors using WASM
- Local storage usage for saving battery backed RAM
- Critical error that prevented physical keyboard from working ⌨️
- Support for responsive physical keyboard
- Better debug panel support
- Support for some
GETparameters - Support for fullscreen on screen keyboard mode
- Arrow keys usage for on-screen Gamepad
- Wrong UX for keyboard focus and fullscreen
- Logic frequency control using on click UI and keyboard
- Support for on screen keyboard for Game Boy
- Support for remote ROM loading using URL - #3
- A whole new layout implemented using React.JS 🔥
- Instant boot support using the
GameBoy.boot()method - Support for pending cycles in web version
- Improved drawing speed at the SDL example
- Better handling of
panic!()in web version
- Issue related to STAT interrupt and H-Blank
- Issue related to overflow in sprite drawing
- Issue related to the RAM bank selection in some of the MBCs
- Support for 8x16 sprites
- Support for MBC5, think Pokemon Yellow
- Issue with MBC1 and Advanced ROM Banking Mode
- Issue related to LDC power of and return mode
- Support for drag and drop loading in SDL
- SDL fixes related to timing
- Support for drawing windows
- Initial experimental support for MBC3 (for Pokemon Red/Blue)
- Timer related issue, made test on inst timing pass
- Clear first frame issue, with
first_frameflag
- License name in the
Cargo.tomlfile
- Support for sprite drawing, works with Tetris
- Support for timers
- Initial working version 🥳
- Problem in the switching of the LCD mode