Breaknes — change digest

PR #518 – #526 · August 30–31, 2026 · gate-level NES/Famicom/Dendy emulator

Six pull requests merged into main between August 30 and 31, 2026. The themes: a unified logging facility (#518), bringing the SDL2 port to parity with the managed app (#519), multi-screen infrastructure with PPU⇄TV binding (#520), aligning the board database with the real motherboard revisions (#522), the project icon (#524), and a rework of the cartridge PCB model (#526).

#518

Compile-time-controlled logging

author: ogamespec August 30, 2026 45 files · +1605 −17 issue #517

Ad-hoc printf tracing was replaced by a single macro-driven logging facility (Common/BaseLogicLib). The key decision is two levels of control: compile time (Release builds contain no logging code at all, with per-subsystem overrides) and run time (a source mask, a per-source category mask, file and stdout sinks). Categories are owned by the components themselves: every subsystem declares its own category enum and a public SetLogMask().

What changed

  • Traces added across all subsystems: 6502 (reset, NMI/IRQ, external bus writes), APU (OAM DMA, registers), PPU (CPU-interface registers, VBlank NMI), MMC1, CartPcb (memory accesses, latch captures), Board (board lifecycle — replacing the old printf tracing) and IO (controllers, device attach/detach).
  • BreaksCore registers the sources with their categories and exposes a logging API to the managed app.
  • The Settings dialog gained FormLogging: checkboxes per source and category, file/stdout output.

Links: PR #518 · issue #517

#519

IO subsystem ported to the SDL2 port

author: ogamespec August 30, 2026 14 files · +1720 −13 issue #516

The SDL2 port gained the controller input it was missing: SDL2 input events (keyboard keys, gamepad buttons/sticks/triggers) are turned into device events and dispatched through bindings to the devices attached to the motherboard — the same scheme as in the managed app. The configuration is stored separately (IOConfigSDL.json) so it never overlaps with the managed app’s config.

What changed

  • Interactive configurator (breaknes --ioconfig): device pool, actuator bindings (wait for an input event), attach/detach devices to the motherboard ports.
  • Device identifiers come from the shared IO::DeviceID enum instead of hardcoded values.
  • Builds fixed: CartPcbPort.cpp (missing from CMake since the #509 refactor) was added back; JsonLib was fixed for Linux (compilation, Int serialization via %llu).

Links: PR #519 · issue #516

#520

Up to two TVs: PPU⇄TV binding

author: ogamespec August 30, 2026 37 files · +1392 −248 issue #515

Infrastructure for boards with several PPUs. The board now owns a list of PPUs, each bound to a virtual TV Set, and the emulator window can display up to two TVs in a horizontal or vertical layout; for debugging, one PPU can be shown on both TVs at once. Multi-PPU board wiring (several PPUs simulated in one board) is the next step (NES-based arcade machines); the PPU list, binding, JSON schema and API are already in place.

What changed

  • BoardDescription.json: new ppus, tvs, tv_layout fields; debug boards “one PPU on two TVs” (horizontal / vertical).
  • Managed app: the screens are composited into a single window bitmap by TvWall (512×240 / 256×480); a single TV now scales to fill the window like the multi-TV canvas.
  • SDL2 port: reads BoardDescription.json instead of the hardcoded board, new --board option, the window renders once per frame.

Links: PR #520 · issue #515

#522

Board database aligned with real revisions

author: ogamespec August 30, 2026 12 files · +557 −143 issue #521

The board list was picked sporadically and contradicted the research on real NES/Famicom motherboard revisions (e.g. “NES-101 (NESN-101 PCB)” does not exist; all Famicom boards were marked RP2A03G/RP2C02G regardless of era). The database was aligned with the revision document from the breaks repository — 31 real boards with the correct chip markings per era.

What changed

  • Famicom HVC-CPU-01…08 and GPM, AV Famicom HVCN-CPU, NES-001 NES-CPU-01…11, NES-101 NESN-CPU/JIO/AV, regional boards (PAL, Comboy, Playtronic) — with the right chips for each era.
  • Unsupported chip revisions are now resolved table-driven to the closest supported model instead of degrading the board to Bogus — logged at board creation.
  • PPUSim: RP2C02H support — previously an uninitialized H/V decoder produced a black picture.
  • The SDL2 port defaults to a real board, NES (NES-CPU-07, 1987); NESBoard became the debug board “one PPU on two TVs”.
  • Minor fixes: JSON configs are copied to the output directories; if a saved board name is gone from the database, the first board is used.

Links: PR #522 · issue #521

#524

Project icon

author: ogamespec August 31, 2026 10 files · +1558 −0 issue #523

The project gained a branded icon based on DALL-E artwork. The generator (Artwork/gen_breaknes_icon.py) square-crops the source and produces a 256×256 PNG master, a multi-size Windows .ico (16–256 px) and a C++ header with 64×64 pixels embedded for the SDL2 port: the window icon needs no image loader and works the same on Windows and Linux.

What changed

  • The icon is set on the managed app window and the SDL2 port window.
  • The generator script regenerates all artifacts (PNG, ICO, C++ header) from a single source image.

Links: PR #524 · issue #523

#526

CartPcb: scroll jumper, glue logic as chips, iNES fallback

author: ogamespec August 31, 2026 23 files · +883 −106 issues #525, #514

Three connected reworks of the cartridge PCB model. (1) There is no “mirroring” attribute on a PCB — only a solder jumper that selects the scrolling arrangement, and the concrete H/V value is a cartridge-instance parameter derived from the iNES header. (2) The UNROM/AOROM glue logic is modeled with real chips instead of a generic latch. (3) Dumps absent from the nescartdb database (homebrew, rare dumps) now run: the board type is inferred from the iNES header.

What changed

  • “Mirroring” → Scroll: the board declares the jumper as "mirroring": {"mode": "scroll"}; H/V comes from Flags6 bit 0 (inverted); the legacy "hardwired" mode remains as a compatibility alias.
  • UNROM: the bank register is a 74LS161 (counter loading on the /ROMSEL rising edge), the PRG address multiplexer is a 74LS32; net+chip simulation runs in two passes so chip outputs propagate through nets within one tick.
  • InesTranslator for “wild” dumps: 0→NROM, 1→SGROM/SHROM, 2→UNROM, 3→CNROM, 7→AOROM (new cnrom.json, shrom.json); they run through the same CartPcb path with a warning logged.

Links: PR #526 · issue #525 · issue #514