Exentt Systems · format recovery · Granny 1 .grn
1,063 of 1,063 shipped files across two games parse with zero failures.
Every model below — meshes, skeletons, skinning, animations, and for Employee of the
Month the original textures — was decoded by
the published parser from the games'
own .grn files. Pick a model, pick an animation, drag to orbit.
the demonstration215 models · 862 animation clips · decoded by the parser, not captured from the game
grn2gltf.py, which is ~500 lines on top of the
parser and does no format work of its own. No texture here came out of a .grn: every
model file embeds its skin behind RAD's proprietary image codec, which this project deliberately
does not reproduce — see the boundary. The art is recovered from the same
games' other files instead. EotM's ships a second time in the .omt containers, already
decodable thanks to awefan's published work. Jimmy Neutron vs. Jimmy
Negatron's comes from three places — the installed game's own png\ directory, its
.omt canvases, and textures its runtime handed out during a capture — matched to each
model by the original bitmap path the .grn records beside the texture. That covers
55 of its 87 models. The other 32 use artwork that only ever existed inside the codec; they
are left untextured rather than dressed in a plausible-looking substitute, and the model panel says
so.whythe business problem underneath
The Exentt home page lists a situation many teams will recognise: "Your data is trapped in a file or program that is difficult to reuse." This project is that situation with every difficulty turned up at once: a proprietary binary format with no documentation, no public parser — Granny 2 has several community readers, Granny 1 had none — and the only software on earth able to read these files being a vendor DLL that cannot be redistributed and runs only on 32-bit Windows.
The transferable claim is not about old games. It is: given an undocumented binary format and a corpus of files, we can recover its structure, prove the recovery, and hand back a specification, a working reader, and your data in a modern format. The same situation walks into laboratories and businesses as an instrument's proprietary result file or a discontinued product's database. The proof that a recovery like this can be trusted is everything on this page.
what shippedthe deliverables
grn.py — a
one-file, standard-library-only parser: drop it into a project and read Granny 1
files. Library first, CLI on top. Mirrored on
GitHub.grn2gltf.py — skinned, animated glTF 2.0 conversion, plus OBJ.ca5ewhat the format turned out to be
The container was solved first — a 64-byte magic, three sections, and directories of 12-byte records whose third field turned out to be a subtree size, making each section a tree. The payload work then landed the rest:
flags is the parent
index; the resolved hierarchies are textbook 3ds Max Biped rigs, hat and eyelash
attachments included.The full detail, tag by tag and with a standing section for what is still open, is in SPEC/GRN-V1.md.
methodwhy the numbers can be trusted
For a client evaluating this work, the method matters more than the format, because the method is why the numbers mean something.
Every claim is stated with the number of files it holds for; the standing target was all 674, then all 1,063.
The record tree, the bone parents and the animation-to-bone mapping were each settled by eliminating alternatives. The last is the cautionary tale: resolved the plausible way, the one track everyone checks first — the walk bounce — matched perfectly, and applying it to a whole rig keyed limbs with other limbs' transforms. Scoring every candidate mapping against every track's bind pose separated truth from coincidence instantly: 57 of 58 versus 6 of 58. One good-looking match is a hypothesis, not a mapping.
Sixty-frames-per-second sample times read as deltas produced a two-second climb animation that lasted 115 seconds — arithmetic that only announces itself if durations are checked against something. Wrong turns like these are kept in the spec on purpose; they are the evidence that the right answers were earned rather than assumed.
scopea deliberate boundary
This work documents a file format, so that files can be read. It is not a
description of the vendor's library: no function of RAD Game Tools' granny.dll is
described, listed or reproduced in the repositories. Every claim came from the data files, except
the mesh-layer cross-checks, which name a live capture of the running game as their oracle — the
spec marks which is which, claim by claim.
The boundary was tested for real this time. Each model file embeds its texture
behind the FourCC BIKi — RAD's own image codec. Reproducing a proprietary codec is a
materially different act from documenting a container, so the parser reads the texture's header
and stops, exactly as the project's scope rules said it would before the case arose. It
is why the Jimmy Neutron models above render as geometry only, and it is the kind of line a
careful reverse-engineering engagement declares in advance rather than crosses quietly.
creditwhose work this stands on
awefan (github.com/awefan4524 ·
awefan.neocities.org) published the parsers for the
.omt container — the other half of these games' asset layer, built through years of
modding AWE Games titles. Every EotM texture in the viewer above, and most of the Jimmy Neutron
ones, was decoded from an .omt by his published toolkit.
.omt plus .grn is essentially
the complete asset story of an AWE Games title; one half already existed because of him, and this
project is the other half.
Sandmanfan, the AWE Games and Jimmy Neutron specialist whose QA reports against the JN engine work on this site have already shaped that project, is who the cross-title results are aimed at — the Jimmy Neutron side of this corpus is now fully readable.