Tag: firmware

37 posts tagged with "firmware".

Reading a Game Boy cartridge through a GBFlash

The console's USB host port meets a cartridge reader that pretends to be a CH340 serial chip. By the end of the day the firmware read and validated a real cartridge header.

Speculative execution against the SNES sound chip

The SNES core was losing four million cycles a frame waiting on a sound chip on another board. Predicting the answer lifted Super Mario World from 35 to about 50 fps.

A flight recorder for firmware

Building a recorder that captures a good run and a bad run of the same firmware workload so a tool can find the first difference that matters.

Proving where the SNES bottleneck was

Days optimising the HDMI coprocessor because every symptom said it was holding the SNES back. The measurements pointed at the wire instead.

The RP2040 as a SNES sound chip, at 97 per cent of realtime

Two bodge wires taught the HDMI coprocessor to talk back and run the SNES sound chip with real Super Mario World music. It reached 97 per cent of realtime.

Profiling the SNES core on the H7

The from-scratch SNES core matches the reference emulator to the cycle. Five optimisations measured on hardware, and a profiler that says the problem is memory.

The Amiga gets a mouse and boots Turrican II

Mouse input for the emulated Amiga, then a commercial game whose custom trackloader refused to work until the floppy drive learned to spin.

The emulated Amiga boots Workbench 1.3

The Amiga core on the STM32H753 boots a real Workbench 1.3 floppy to the desktop, and what it took to get the floppy controller right.

A desktop flasher for the cartridge

A host tool that turns one ROM into the matching H7 runtime, RP2040 receiver and cartridge image, and refuses to declare success until the cart reads back the exact bytes.

Kickstart 1.3 runs under budget on the STM32H753

First hardware numbers for the Amiga core: a real Kickstart 1.3 ROM executing deterministically at a p99 of 2.51M cycles per PAL frame, against a gate of 3.35M.

Mega Drive emulation over an 8 MHz jumper-wire link

A Mega Drive emulator on a 480 MHz Cortex-M7 with perfect music beside a screen that tore in half. The fix was to make a slow frame arrive atomically.

Why Celeste sounded wrong

The cart was byte-identical to the BBS copy, so the fault was in the synth: a music clock cutting bars to a quarter, and a noise fit matched to the wrong metric.

Planning USB floppy support

Four transport dialects from 1998 and a FAT12 layer nobody ships, which is why the first firmware milestone is just reading descriptors.

The console's second shell

Two days building the console's second shell, including a crash hunt that ended eight kilobytes from the stack floor.

Cattle Crisis from 9 fps to 58

One day of hardware A/B tests on the H753. The biggest single win was a compiler flag I should have set weeks ago.

Game Boy first light

Two days from a feasibility study to DMG code on the TV, with the console's SPI video wire carrying two frame geometries at once.

A crash reporter for a bare-metal console

Giving the console a crash reporter that survives the reset and emails me, and the ways an STM32H7 loses data across a warm reset.

A 9 by 9 demoscene square in the launcher header

The launcher's blinking sparkle became a 9 by 9 pixel demoscene with seventeen tiny effects dealt from a shuffled deck.

What all the wires are for

A tour of Rusty Nail as it stands, from the OS on screen to the four breakout boards and the cartridge shell with a 16 MiB flash chip inside.

A 3x palette scanout for the HDMI picture

The HDMI picture was pixel-perfect and still looked soft. A full-resolution palette scanout fixed that, after an afternoon lost to a heap that only sometimes existed.

Why the speakers started clicking

The morning after deleting the old Lua core, everything played and then the speakers started clicking. A command trace found three lines of channel semantics and a missing crossfade.

The fixed-point Lua core becomes the default

Stage 9 of the runtime migration, ending the night at 59 fps on jumper wires after a one-byte regression that cost 19 carts.

An evening of unrelated fixes

Three unrelated fixes from one evening. The biggest was a cartridge that finally keeps its saves; the strangest was an iterator that duplicated the player.

z8lua lands behind a flag

The new Lua core measured against the old one on identical silicon, with a licensed PICO-8 as the oracle and a per-cart compatibility matrix.

A runtime baseline before the Lua swap

A permanent benchmark and input tapes recorded from real play, so the new Lua VM has numbers to beat before it lands.

Downloading PICO-8 carts over WiFi

Rusty Nail can download carts from a pop-up launcher. The WiFi reason-15 failure was my own off-by-one, and a GPIO pin really did die on the bench.

Reading the framebuffer out of RAM

The standalone build sends nothing back to a host, so before I could redesign the boot splash I had to work out how to screenshot a screen my Mac cannot see.

Planning a flash cartridge for the console

Picking a W25Q flash chip for a physical PICO-8 cartridge and mapping how the firmware would read it. Nothing is built yet.

The HDMI board I bought before reading the datasheet

I bought a 50-pin RGB888-to-HDMI board, then counted the pins. The Nucleo never had 24 to give, so the fix is probably a second microcontroller whose whole job is HDMI.

A divide per pixel

Profiling the PICO-8 runtime found a stretched-sprite blit doing an integer divide on every pixel, on a chip with no fast divide.

Moving the SPI panel to DMA

The SPI blit was a blocking row-by-row write that stalled the console for about 13 ms every frame. DMA fixed it and the data cache nearly broke it.

Swapping the ESP32 for a Bluetooth gamepad

I picked an ESP32-C6 for the controller bridge and learned that BLE-only is a property of the silicon, so the fix was a different chip and one build flag.

The SPI panel and me

I had a working HDMI path at 12:48am. The next morning I picked up the tiny SPI screen instead and spent nine hours reinventing flicker.

The SPI panel, from a blank screen to 25 MHz

Getting the desktop off the USB stream and onto a real LCD, then climbing from 1 MHz to 25 MHz without losing the audio.

Getting sound out of it

Wiring an I2S DAC to the console over SAI and DMA, and why the audio stayed silent for most of a day.

Running real PICO-8 Lua on a Cortex-M7

Vendoring Lua 5.4 into bare-metal firmware, and why a hardware watchdog beat an instruction-count hook for stopping runaway carts.

How Rusty Nail is put together

Rusty Nail is a windowed pixel desktop running bare metal on a Nucleo-H753ZI. This is the architecture, and why the display is an abstraction from the start.