Repository navigation
GameFrame 1.1.0
GameFrame 1.1.0 brings the lessons of POD, Hardwar and Tyrian into the framework: a know-how
layer of failure modes and context with a hook for every agent, tools for 32-bit and 1990s games
(a 32-bit emulator, Watcom register arguments, export gaps, card-library probes, recordings and
replays), tools that spend a plan's monthly API credits, guides for MMX, 3D cards, versions and
the story, a website for each project, and one GameFrame checkout per machine.
Added
-
tools/llm/, tools that spend a Max or Team plan's monthly API credits
(API credits):name_functions.pysuggests names for every
unnamed function in one Message Batch;skillcheck.pygives an agent one skill and a task
on the sample game and checks the answer against ground truth (tests/skill-tasks.json);
headless.pyruns an agent unattended under a budget, anddocs-checkrunsre-checker
andre-editorover the documents;ask.pyanswers a question from the know-how entries.
fake_api.pystands in for the API intests/run.sh. The SDK is optional, in
requirements-llm.txt. Know-how:api-credits-refused, the messages a refused run gives
and the fix for each. -
ghidra-run.sh ... callargs regs=watcom: the constant each register gets before every call,
in Watcom's order (EAX, EDX, EBX, ECX) or any list, where the decompiler shows no arguments. -
ghidra-run.sh ... fill-gaps: makes a function at each startexportcovfinds, goes on past
a bad one, and exports the binary again. The sample DLL gains a routine Ghidra misses. -
tools/verify/replay.py: checks a port's trace against a recording read from outside, where
one sample can mix frames; a value passes when any state in its window holds it. -
tools/triage/axes.py: the up axis, its sign and the handedness of a 3D game, from a recorded
path over the level's vertices. -
tools/pe/probegen.py: a probe library for a DLL a 32-bit game imports, exporting the same
names (decorated__stdcallones too) and logging every call with its arguments. -
The
gameframe-scalecrate: nearest, Scale2x (EPX) and a CRT look, for a finished frame. -
re-browsesection 5: growing the viewer into an editor. -
tools/triage/buildid.py: everything a copy says about its own version (the disc's mastering
date, link dates, VERSIONINFO, version strings, readme and setup lines), written into the
project'sdocs/versions.md.re-inventory,re-startand the versions guide check on day one
whether the copy is the latest official build, and where to search for later official
releases; the template has a "Build identity" and an "Is this the latest official version?"
section. -
Versions and their deltas: the versions guide now starts with
finding every edition, takes the last version released as the default reference, and has the
steps for moving to a newer edition mid-project. A project template,docs/versions.md,
records each edition, its checksums, languages, content and builds, the data and code
deltas, the extras and the reference.re-inventoryandre-starthave the step. -
tools/triage/versiondiff.py: two editions compared as folders or disc images: files added,
removed and changed by folder, PE link dates and languages, as Markdown. -
Know-how:
context-newer-edition-mid-project, from POD's first edition and POD Gold. -
ExportAll.javawritesbodies.tsv, every piece of every function (start, end, entry), and
exportcov.pyreads it besidefunctions.tsv(or with--bodies). Before, a function whose
body lies in several pieces counted as one run from its entry: Hardwar's export measured
93.7% where 98.0% of its code is in functions. -
Know-how: a project whose
./gameframeruns a second clone or another project's copy of
GameFrame (pin the machine's one checkout in.env), and scripted edits that stop matching
after a formatter reflows the code. -
Three guides from the POD: Planet of Death project:
Recording the original, and replaying it,
Replacement libraries for a 1990s game and
Writers, editors and mods; and a section on the emulated-PC route in
Running the original. -
scripts/zcc.sh: rustc's linker for 32-bit Windows DLLs throughzig cc, exporting exactly
the names in a.deffile. -
pe32_emu:array,putandgetlay out the game's structures; the sample DLL gains
sum_listandheaviest_pathto test them. -
tools/formats/derived.py: which fields next to geometry are bounds, centres, normals or
plane distances. -
Reading the story, from the Hardwar project: the guide
Reading the story for design decisions, which makes the case that a
game's manual and its own text say what each system is for and which must be exact, with
Hardwar as the worked example.re-inventoryhas a new step, "Read the story", and
re-start,re-surveyorand the games taxonomy point to it. New projects get a
docs/lore.mdtemplate with the table "in the story → in the code → evidence". -
A case study of Hardwar (1998), and Hardwar in the vehicle simulations' reference games.
-
tools/triage/sentences.py: the sentences in a program or a Ghidrastrings.txt, ASCII and
UTF-16, with addresses, for reading the story. -
tools/formats/shadetable.py: a palette game's shade, fog or light table, with the levels
that are black, unchanged and white, the colour it fades toward, the shift that reaches
normal light, and a picture. -
xorscan.py --recordsand--key-in: a key XORed into one field of every directory record,
read from the names' zero padding and completed from the executable. -
rawimage.pyandcatalog.py --dac shift: 6-bit palettes shifted left by 2 (63 is 252).
The catalogue fills a palette of fewer than 256 colours with magenta. -
constants.pyreports Park-Miller's 16807 without--allwhen its modulus 0x7fffffff, or
Schrage's 127773 or 2836, is beside it. -
new-site.sh --manual: a Pages workflow that runs only when started by hand. New sites get a
theme to colour from the game and apublic/folder;re-siteasks for figures and diagrams
in every diary entry from the first.re-browsedescribes the viewer's--exportmode for
agents. -
Know-how from Hardwar: Watcom pseudocode that drops register arguments, the x87 control word
0x0c7f, a variable frame step in replays, 6-bit palettes shifted by 2, light tables with an
unchanged level, worktrees without the ignored folders and Ghidra's project lock, and
reading the story. The entries on missed functions and on Watcom nameexportcovand Hardwar. -
Know-how entries for GameFrame's own tools: unmapped memory under the emulators, an import
with no handler, a tool run without the.venv, and Ghidra refusing a path in a dot folder. -
dos_envhas a keyboard:env.press(scan, at, hold)andenv.key_script('10:39:3')put
make and break codes on port 0x60 and raise IRQ 1 through the game's INT 9 handler, which
acknowledges through port 0x20. The BIOS's INT 9 feeds the INT 16h queue, and INT 16h waits
for a key still to come. The DOS sample gainswait_keysand a keyboard handler. -
tools/triage/exportcov.py: how much code a Ghidra export covers, its largest gaps, and the
likely starts of the functions it missed (call targets, starts after a return or padding),
written for the batch decompile. -
pe32_emu:fpu_cw=loads an x87 control word before a call,fpu_modes()lists the cases
whose result depends on the rounding mode, anduntil=stops at an address and returns the
stack there, as for a call tosprintf. The sample's 32-bit DLL gainsfix_mul(a magic-number
fadd) andreport(a call towsprintfA). -
validate.py --write: decode, encode and compare every file, naming the first differing byte.
The sample decoder has anencode. -
tools/live/memlog.py(read a recording back: summary, CSV),tools/live/emulock.py(who
uses a shared emulator) andtools/live/loopcut.py(a recorded path cut into one loop). -
Thirty-five know-how entries promoted from the POD: Planet of Death project. They cover
replacement card libraries under Wine (Glide 2, the S3D Toolkit, ViRGE surfaces, missing
card libraries), mods (the install folder first, values replaced at run time, mods in a
reference recording),
recording a run from memory and replaying it (samples that straddle frames, stand-ins for
unported logic, a game clock that is not real time, waiting for a phase), x87 rounding and
truncating helpers, functions Ghidra missed and claims that need an address scan, editors
and writers (one edit type, float views, derived geometry data, round trips of every file,
axes measured in the running game), input drivers (held keys, click timing, closed racing
lines), shared VMs (pkill,sudoandDISPLAY), keeping every dialog, and the emulated-PC
route (CD drives under Wine on Linux, Xvfb and a window manager, SSH, a script that shadows a
standard module). The card builds' context now says to measure what the card is given. -
tools/triage/refs.py: every instruction that refers to an address, found in the code bytes
(32-bit immediates and displacements, 64-bit RIP-relative). Each hit is marked as a read, a
write or a value. Hits outside any function are marked too. The sample's 32-bit DLL has a
table with two writers to test it. -
tools/live/memrec.py: snapshots of a running game's writable memory formemscan.py. It
also records named values and arrays as JSON Lines. It reads/proc/PID/mem.--waitwaits
for a phase. -
discinfo.py --iso: the data track of a BIN/CUE as a plain ISO. -
tools/live/emupc.py: the files that run the original in an emulated PC (QEMU, a Debian
cloud image, cloud-init with Wine and 32-bit Mesa, Xvfb, openbox, SSH, the disc as a CD-ROM). -
tools/live/shot.py: captures kept under names of their own, with their text. It never
overwrites a capture. -
tools/live/modfolder.py: install, list and clear a folder of changed files in an install
folder. -
winput: keys held bydownare released at exit. New stepsrelease,pointand
button, and a new option--hold MS. -
A case study of POD: Planet of Death.
-
Know-how:
pgrep-wait-matches-itself. A wait loop withpgrep -fnever ends, because the
pattern matches the waiting shell's own command line. -
re-observe: a capture script prints its usage for--helpand runs nothing, and never
overwrites an earlier capture. Seen when checking a script's usage started a 15-minute run
over the saved data. -
gameframe progress: every agent keeps a progress log, one line per step, in
derived/progress/<agent>.log(gameframe progress <agent> --add TEXT).gameframe progress
shows each log's last lines, newest first, so the main session can answer "how is it going?"
without reading an agent's transcript. Each agent's file has a Progress section that says
when to write. -
Know-how: a taxonomy of failure modes and context, one Markdown entry per failure, each with
its symptoms, cause, evidence, status (solved, workaround, dead end, open) and what was tried
(the design, the entries).
gameframe advise "<error text or topic>"finds entries by error signature, facet, alias and
word. It reads a log on stdin.--checkchecks every entry. It reads a project's own
docs/knowhow/too. -
A Claude Code hook,
scripts/hooks/advise.py. It names the matching entries after a shell
command (PostToolUseandPostToolUseFailure), once per session. It names the context
entry for Wine when a command starts Wine. -
Eighteen seed entries from the POD: Planet of Death project. The failure entries cover
privileged port probes under Wine, DirectDraw mode tables, windowed mode on a 16-bit desktop,
16-bit back surfaces, "insert the CD", ini paths, VirtualSize 0,SuspendThread, DirectInput
focus, input inside Wine,DYLD_*on macOS,wineserver -w, leftover processes, winedbg,
and the openwow64cpufault under Rosetta with every attempt. The context entries cover
Windows 95 DirectDraw games, Wine on macOS and Watcom programs. -
The know-how hook for Codex (
PostToolUse), Gemini CLI (AfterTool), Cursor (postToolUse)
and GitHub Copilot (postToolUse,postToolUseFailure).
scripts/hooks/gates/post_events.pyreads and answers each agent in its own format. A plugin
project runs the hook through./gameframe advise-hook AGENT. -
gameframe serve, GameFrame's own MCP server, with the toolsadvise,knowhow_entry,
knowhow_listandfind..mcp.jsonnames itgameframe. -
tools/live/winput.pyandwinput.c, a small Windows program built with zig. It sends keys
as scancodes, relative mouse moves and clicks to a game from inside Wine. A--dry-runbuild
serves the tests. -
Context entries for DOS games in DOSBox-X, games with a build per 3D card, and 16-bit
Windows programs. -
The skills (
re-start,re-observe,re-land's new "Know-how" step), every agent and the
project template suggestgameframe advisewhen a command fails or the work turns to a new
era, runtime or hardware. -
Two hardware guides from the POD: Planet of Death (1997) project:
MMX and other SIMD code (finding hand-written MMX routines,
matching each to its plain version through its callers, measuring both, porting exactly) and
The card makers' 3D APIs (Glide 2.x, ATI3DCIF and the S3D
Toolkit: reading their state calls, how textures reach each card, games with one build per
card, and renderer profiles for viewers). -
Two crates:
gameframe-mmx, the MMX instructions bit for bit, andgameframe-gpu-1997, the
texture formats and API constants of Glide 2.x (with NCC), ATI3DCIF and the S3D Toolkit,
with one texel decoder. -
Two specialist task agents:
re-vectoriser(SIMD code and CPU builds) andre-accelerator
(3D card APIs and per-card builds). -
tools/emu/pe32_emu.pyruns routines of 32-bit (x86) Windows games under Unicorn, with
inputs in registers or on the stack, MMX included. It stops at any import without a handler
and names it. The sample game builds a 32-bit DLL (mixer32.c) to test it. -
tools/triage/insns.pylists the pattern for MMX code among its groups.
Changed
-
The plugin has an icon,
.claude-plugin/icon.png, and the tests read the plugin validator's
own warning counts, allowing only GameFrame's ownCLAUDE.md(Claude Code 2.1.310). -
One GameFrame checkout per machine. A project made by
new-project.shpins it with
GAMEFRAME_ROOTin its.env, and./gameframereads that from the project and from its main
checkout, so worktrees use the same one. The launcher no longer looks in../game-framenext
to a project, where projects side by side shared a stale symlinked clone. A game's session
changes GameFrame in a worktree of that checkout, never in a second clone
(environments). -
ExportAddressBatch(ghidra-run.sh decompile) reports a bad address and goes on, and makes
no function at an address that nothing refers to unless it follows aretor padding, so a
call site no longer splits the function around it. -
The know-how hook reads only
stdout,stderrand the error of a Claude Code command. The
desktop app adds notes on changed files to the result. Those notes had matched the text of
the entries themselves. -
peinfo --imports,--exportsand--stringslist their items again. The section loop had
reused the name of the flags. -
The hook matches context patterns against the first line of a command only.
-
A project's entry replaces GameFrame's entry of the same id.
-
peinfoandvtableuse a section's raw size when its VirtualSize is 0, as Watcom's linker
writes it.peinfomarks such a section. -
re-site,re-publisher,re-landanddocs/OUTPUTS.mdnow allow screenshots of the
original game and of the project's viewer in documents and on the site, a few at a time,
each captioned with its source. The game's files, extracted assets in bulk and decompiled
code still stay out of git.
Fixed
-
pe32_emuzeroes a section whose file pointer is 0, as Windows does. Watcom marks.bssthis
way, and the emulator had filled it with the file's first bytes, so flags read as code
(from Hardwar). It also starts the x87 at the control word 0x037f, as Windows starts a program;
Unicorn alone starts at 0, which rounds every result to 24 bits (from POD). -
Thirteen know-how entries from POD and Hardwar: the AI's chance from the frame clock, a missed
key tap, a 3D card that draws part of the frame, measuring library calls that lock mutexes, a
screen that closes while a key is held, decompiled switches that drop cases, painter's order
with big faces, a pointer the game draws, recording sound in a VM with no sound card, a
replay that plays too fast, the emulator's x87 start state, one multiply for two channels,
and the.bssfile pointer. The taxonomy gains the symptomwrong-result. -
tools/site/check.pyand the gates no longer take the English word "undefined" in prose for
decompiled code. The pattern now matches Ghidra's sized types, pointers and variables of
those types, and statements withFUN_andDAT_names (calls, assignments and
declarations). Names cited in a sentence pass, as before. -
The animated diagrams: in every animated diagram the static labels are drawn last, so a
moving token or highlight passes under the text it crosses instead of hiding it. Tokens that
loop start with a negativebegin, so none waits in the card's top-left corner before its
path starts. Each "original" label in the function-swap diagram hides while its new tile
shows. The raster-split and Atari 2600 beams now keep step with what they trigger, and the
raster scroll loops with no seam. -
site/diagrams/animcheck.py(run by the tests) fails on loops that drift apart, animations a
browser would drop and elements shown before their turn.site/diagrams/animrender.html
plays every animated diagram in a browser and lists shapes over labels, tokens off the card
and boxes that light up when the playhead is elsewhere. -
readseg.pystops with a clear message when an argument is not an address, such as a count
written without--count. It printed the first value and then crashed. -
The Claude Code commit and push gates check the command's own git verbs. Claude Code's
if: Bash(git commit *)also matches commands it cannot parse (a heredoc, a shell variable,
a for loop), so the gates fired on commands that neither commit nor push. -
./gameframe run decomp_querywithout--exportreads the project'sanalysis/export
(the folderGAMEFRAME_PROJECTnames), and itslabels/names.tsvafter the current
folder's. Before, it read GameFrame's own sample export. -
dosinfo.py --pstringsprints a Pascal string's length byte address, the address code
uses, instead of the text's. It finds a string right after another one when the second's
length byte is a printable character. -
tdinfo.py:typesandglobalsprint the fields of anonymous records inside a type or
a variable's declaration.labelsleaves out imported procedures, whose segment numbers
are past the program's (procsmarks them). A scope's parameters and locals go to the
procedure in the scope's own segment, not the first procedure at the same offset in any
segment.