Felipe E. Harker

Custom Firmware

Charmera

Four new effects for the Kodak Charmera keychain camera, patched into its stock firmware

The camera’s 160 by 80 viewfinder with the yellow pixel text HI and a heart, rotated 45 degrees, over the picture

Text Stamp

The viewfinder with a caption set up on the camera: typed, colored, placed, turned 45° and sized. Rendered by the firmware’s own drawing code in an emulator, over a test gradient where the live picture would be.

Abstract

Four effects added to the Charmera’s own firmware, after the eleven it ships with. Sepia, Cyanotype and Faded are color looks the camera’s image processor applies, so they show live in the viewfinder. Text is a pixel-font caption typed, colored, placed, rotated and sized with the camera’s buttons, drawn on the viewfinder and stamped into every photo. Every stock filter and frame still works. The patch is built from a public dump of the stock firmware and checked in an emulator. Version 3 runs on an original Charmera, where the text editor works; a stamped photo and the strength of the color looks are still to be checked there.

The Effects

In photo mode, Down steps forward through the effects and Up back; the four new ones follow the last Pixel filter, and Up from Standard goes straight to Text. The camera returns to Standard each time photo mode opens.

No.EffectHow it worksIn the viewfinder
0StandardImage processorLive
1–3Warm, Cool, B&WImage processorLive
4–7Four framesOverlay composited after the shotPreview overlay
8–11Pixel red, blue, yellow, grayCode after the shotLive, in code
12–14Sepia, Cyanotype, FadedImage processorLive
15TextCode after the shotLive, in code

Color Looks

The stock Warm, Cool and B&W are four numbers each, sent to the image processor: a shift and a gain for each of the two color axes, blue–yellow and red–cyan. The new looks are three more sets of the same four numbers, so they behave exactly like the stock ones, live in the viewfinder and in the photo. Their values are read from looks.json.

LookBlue–yellow shiftRed–cyan shiftGainsResult
Warm (stock)−20+205, 20Colors muted, warmed
Sepia−14+120, 0Brown monochrome
Cyanotype+22−140, 0Blue monochrome
Faded−8+612, 12Colors at about a third, a slight warm cast

Gains in 32nds: 32 leaves a color axis as it is, 0 removes it.

A test chart of gray ramps, hue bands and color patches in Standard, Warm, Cool and B&W, then in the new Sepia, Cyanotype and Faded

The Looks on a Test Chart

A preview made from the four numbers, not from the camera: what each number does is worked out from the stock looks, so the real tint may be a step stronger or weaker.

Four 16-pixel icons: a brown, a blue and a pale gray half circle, and a white T

New Icons

Each effect shows a 16-pixel icon in the corner of the viewfinder. The looks reuse the B&W half circle in their own colors; Text is a T. They fill four icon slots the firmware ships empty.

Text Stamp

The Charmera has five buttons: Shutter, On/Off, Up, Down and Play/OK. With Text selected, Play/OK opens an editor in the viewfinder; in every step Up and Down change the value and Play/OK confirms it and moves on.

Open
Up or Down to the T icon, then Play/OK. With no text yet the viewfinder says OK:EDIT.
Letters
A–Z, 0–9, space and ! ? . , - & : ’ ♥; Play/OK keeps a letter and moves to the next, up to twelve. The tick at the end of the list finishes the text.
Color
White, yellow, red, blue, green, pink or black, with a contrasting outline.
X and Y
Up moves the text right or up, Down left or down, in steps of 5% of the frame.
Rotation
15° a press; Up turns it counter-clockwise.
Size
10% a press, from 10% to 400%, starting at 200%. Play/OK here closes the editor.
Shoot
The Shutter takes the photo with the text stamped in. Video is not stamped.
Memory
The setup stays until the camera is switched off. Opening the editor again starts from the current text.
Viewfinder with OK:EDIT in white
Text selected, nothing set yet
Viewfinder labeled TEXT, with HI and a heart typed and the tick highlighted
Letters: the tick ends the text
Viewfinder labeled COLOR, with the text in yellow
Color: yellow
Viewfinder labeled X 70, the text moved right
X: 70%
Viewfinder labeled Y 35, the text moved up
Y: 35%
Viewfinder labeled ROT 45, the text turned 45 degrees
Rotation: 45°
Viewfinder labeled SIZE 250, the text larger
Size: 250%
Viewfinder with the finished caption and no label
Editor closed, ready to shoot
An 800 by 600 test photo, a blue gradient, with HI and a heart in yellow outlined pixel letters, turned 45 degrees

The Stamped Photo

The same setup stamped into an 800 by 600 test photo by the code that runs after the shot, before the camera encodes the JPEG. The viewfinder and the photo are drawn by one routine, so the text lands where it showed.

How It Works

The camera mounts on a computer as its SD card only; the firmware sits on a separate 2 MB flash chip that USB cannot read. The work started from two independent public dumps of that chip, identical in all their code, and from photos taken with the stock frames, which match the dumped frame art pixel for pixel.

Hardware
A Generalplus GPCV1235F (ARM7, no memory protection), a 2 MB SPI flash chip and a 160 by 80 screen. Firmware JH5408 20250520, built 14 Oct. 2025.
Memory
The first megabyte of flash is copied into RAM at power-on, 512 bytes lower: RAM address = flash offset − 0x200. Frames, icons and sounds are in a compressed resource pack at 0x120000.
Effect index
One byte at 0x10FBC5 selects everything. Down and Up, messages 0x7002 and 0x7003 in photo mode, step it; Play/OK is 0x7061.
Color looks
The routine at 0x2D368 sends the image processor its four numbers. It is rewritten as a table with three more rows; the stock four send the same values as before.
Frames
Four 800 by 600 overlays, three compressed strips each, composited onto the photo after the shot (0xECF0), with a 112 by 80 preview on the screen.
Pixel filters
Code that runs after the shot (0x6E2DC) and on every viewfinder frame (0x15EB8): brightness 124 and up becomes the palette color, darker becomes black.
New code
About 3.5 KB of C, compiled for the ARM7 and linked into four stretches of firmware code that nothing calls — the largest a disabled USB-webcam handler — found by a reachability analysis of the whole image, and checked byte for byte before each build writes over them.
Hooks
Five redirected branches: Up, Down and Play/OK reach the editor first and pass through when it is closed; the display task draws the text on each viewfinder frame (0x160E0); after the shot the text is stamped into the photo before JPEG encoding (0x6E458).

The SD Card Updater

The camera updates itself from its SD card at power-on, with code that lives in the firmware itself. Read from the disassembly:

File
JH_5408<YYYYMMDDhhmm>_<8 hex digits>.bin in the root of the card. The hex is the sum of every byte in the file.
Trigger
The date stamp in the name differs from the one the firmware carries. This build writes its own stamp into itself, so the file can stay on the card without flashing again at every power-on.
Writing
From the start of flash, 64 KB at a time, every 256-byte page read back and checked.
Last erase
One more 64 KB block is erased after the file’s end. A full 2 MB file wraps round and erases the start of the firmware, so every package here stops 128 KB short, and the extra erase lands on an empty block.

Verification

Without a way to read the flash over USB, the check is an emulator: tools/emu_test.py runs the real ARM code of the stock and the patched firmware in Unicorn and compares them, 100 checks in all.

Status and Risks

Build and Flash

No firmware is published here, original or patched: it is Kodak’s. The build takes a public dump of the stock firmware and patches it on your own computer.

Dump
Clone keychain-camera-plus and Project-Sirius into third_party/; the build checks the dump’s code against a known hash before it changes anything.
Build
pip install -r requirements.txt, then python tools/build_fx.py. It writes the update package and a stock package to restore with.
Test
python tools/emu_test.py must end with ALL PASS.
Flash
Copy the one .bin to the root of the FAT32 card, insert it in the camera while it is off, switch on and wait for Upgrade 100%, then take the card out. Only one JH_5408 file on the card at a time.
Change it
The looks are in looks.json, the text stamp in fx_text/fx_text.c, the font in tools/fx_tables.py. Rebuild with a new stamp, test, flash.

Sources