Skip to content

Releases: crashtheuniverse/chatgbc

v1.0.0 - the engine sealed, and Rei

Choose a tag to compare

@crashtheuniverse crashtheuniverse released this 28 Sep 18:06

v1.0 seals the engine and adds a second cartridge: Rei, a small being who talks to you, asks your name and keeps it.

chatgbc.gbc - the story model, unchanged. The wait before the first token is what changed: the encoder is exact and a hundred times faster, and prompt tokens only feed the state. 1.8 s from START to the first token (v0.9: 6.8 s), then 0.46 s a token.

rei.gbc - Rei v1. Pick a line from ten topics or type your own. She keeps your name for the whole conversation and across power-off, says your words back, and brings up the keyboard when she asks you something. START shows the log; leave her alone and she goes for a walk.

She is small (374K parameters): sentences blend, she can mix facts up, and now and then she takes a word that isn't a name as your name. Tell her again.

Runs on a Game Boy Color or any CGB emulator (double speed, MBC5, battery save for Rei).

file sha256
chatgbc.gbc 502838bfe3d63cfb2107768c7a47f3ec716861d98c21acdd554243c5a5b71d08
rei.gbc 074255c67f5a18b37f3f34720f5232b04954bd90e103d5c587e884e5ff5e1341

ChatGBC v0.9 - the speed release

Choose a tag to compare

@crashtheuniverse crashtheuniverse released this 14 Sep 06:16

ChatGBC v0.9 is the v0.4.1 model on a faster cartridge. Nothing was retrained: the weights are the same checkpoint, the integer twin is unchanged, and the ROM emits the same tokens byte for byte. A token takes 0.46 s where v0.4.1 took 1.08 s, because an audit of every stage of the token found that most of its arithmetic could only ever produce a few hundred distinct values, and a stage like that is a table, not a computation.

Measured (VERSIONS.md has every release scored the same way, on the same held-out TinyStories):

v0.4.1 v0.9
M-cycles / token (the ROM's own counter, teletype running) 2,259,829 963,792
seconds / token 1.08 0.46
seconds / character (held-out text) 0.31 0.133
bits / character, as shipped 1.146 1.126
bits / character, the float checkpoint 1.123 1.123
ROM 256 KB 512 KB

What changed, all of it exact against the twin (the golden sequence did not move; 33 tests):

  • The block matvecs go output-major: the 22 tables of 27 sums of an input vector are built once, each row is a stream of table addresses summed in a register pair at 12 cycles per three multiply-accumulates, and the requant happens in registers. wz and wh share one build; the router rides on w1's tables.
  • w2 walks only the nonzero (activation, weight) pairs, listed by the ReLU² loop as it finds them: 82% of the activations are zero, and so are a third of the weights.
  • The classifier keeps only the running best in registers: no logits stored, no zero pass, no rescan.
  • The minGRU gate is one byte table with the sigmoid folded in, after a proof over all 16,646,400 inputs that its saturation never fires.
  • The norm's sum of squares stays in registers, its shifts peel whole bytes, and its multiply goes through two 16-entry nibble tables rebuilt per norm.
  • Embedding rows are stored on the stream's grid; the residual add is a 34-cycle page loop; the debug copies are out of the shipping ROM.

61 KB of new lookup tables. v0.5 to v0.8 do not exist as releases: what was planned for them landed on the tree as options, and the audit said the cheaper token came first. docs/ROADMAP.md has the per-stage before and after, and what v1.0 is.

chatgbc.gbc (524,288 bytes) SHA-256: 7dda7135db9112a1147b87c9aff944dc1bfd81aa0d2c24d88c5aaef6dedc7c18

ChatGBC v0.4.1 - a model trained for the machine

Choose a tag to compare

@crashtheuniverse crashtheuniverse released this 04 Sep 16:06

ChatGBC v0.4.1 replaces the borrowed transformer with a model trained for the Game Boy Color: a minGRU core, four ternary experts per layer, and a kernel that retires three multiply-accumulates per table lookup — all in SM83 assembly, all decided by a bit-exact integer twin before the assembly ran.

Measured (VERSIONS.md has every release scored the same way, on the same held-out TinyStories):

v0.3 v0.4.1
seconds / token 6.16 1.08
seconds / character (held-out text) 2.94 0.31
bits / character, as shipped 1.149 1.146
bits / character, the float checkpoint 0.876 1.123
ROM 512 KB 256 KB

Level with v0.3 in quality per character, seven times the characters per second, half the ROM. The honest row is the float one: stories260K is the better model in float and lost 31% getting through 4-bit tables and a 24-token window; ours loses 2%. The gap the cartridge used to cause is closed. The model-side gap is what the freed cycles are for.

Also new in v0.4.1

  • The screen is a teletype: one character every 0.3 s, fed from a queue on the VBlank interrupt while the next token computes.
  • A story runs until you press SELECT. The recurrent state has no window to fall off.

Train it yourself: py/tinystories.py → py/tokenizer.py → py/fit.py (3.5 hours on a laptop GPU) → py/export5.py → py/score5.py → test.ps1. Corpus: TinyStories (Eldan & Li, CDLA-Sharing-1.0). The Arenas residual from Sherry is what makes ternary converge.

ROM: chatgbc.gbc, 256 KB, CGB only (MBC5). SHA-256 38a0a735b7f3cd0058e7b8f4db9de6fce334854b5e7bc8cac615dfbf43be5352.

ChatGBC v0.3 - a transformer on the Game Boy Color

Choose a tag to compare

@crashtheuniverse crashtheuniverse released this 31 Aug 09:01

A language model running on real Game Boy Color hardware: 512 KB cartridge,
8 MHz SM83, 32 KB RAM, written entirely in assembly. No C anywhere.

  • 6.16 s/token (12,918,757 M-cycles), ~2.3 s/character — measured by the
    cartridge's own timer, wherever it runs
  • 78.1% top-1 agreement with fp32; a bit-exact integer twin stands behind
    every kernel
  • 4-bit Lloyd–Max weights, int8 activations, 19-cycle multiply-accumulate by
    table lookup
  • 24-position sliding-window attention in a ring buffer — output never stops

chatgbc.gbc is attached
(SHA-256 34c17ac06fd29b15321d3ee85a057fa35aeb71a8d127a9efcfd7728234152815).
CGB only. Flash it, or run it in SameBoy. A types, SELECT flips case,
START generates.

Verified on original hardware by the #gbdev community on Discord, who were
kind enough to flash it days after the first build.