BeamNG.Earth
BeamNG.drive용 1:1 비율 실시간 지구, 실제 고도·위성 이미지·부동 원점·보조 서버에서 LOD 스트리밍
콘솔 게임을 역어셈블해 읽기 쉽고 수정 가능한 JavaScript로 변환합니다 각 ROM 루틴을 검증된 JS 함수로 제공합니다
Hand-translating console games from disassembly into readable, modifiable JavaScript, not emulation. Every ROM routine becomes a JS function you own, verified frame-by-frame against the real ROM runni
게임JavaScript · PythonGitHub @Fabulu온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Hand-translating console games from disassembly into readable, modifiable JavaScript, not emulation. Every ROM routine becomes a JS function you own, verified frame-by-frame against the real ROM running in an emulator. Batman (Game Boy) complete; Gradius (NES) plays end to end; DoDonPachi DaiOuJou (arcade) in progress. No ROM included.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Hand-translating console games from their disassembly into readable, modifiable
JavaScript - not emulation. There is no CPU interpreter here. Every ROM
routine is read out of the original machine code and rewritten as a JS function
you own, carrying the address it came from, so the game can be read, retuned and
modded like any other source code.
Fidelity is not a claim, it is a measurement: an emulator runs the real ROM
headless beside the port and the two are diffed field by field, frame by frame.README 전문 보기 ↗Hand-translating console games from their disassembly into readable, modifiable JavaScript - not emulation. There is no CPU interpreter here. Every ROM routine is read out of the original machine code and rewritten as a JS function you own, carrying the address it came from, so the game can be read, retuned and modded like any other source code.
Fidelity is not a claim, it is a measurement: an emulator runs the real ROM headless beside the port and the two are diffed field by field, frame by frame.
| game | machine | state |
|---|---|---|
| Batman: Return of the Joker - Sunsoft, 1992 | Game Boy | complete - title screen to end credits, bit-exact |
| Gradius - Konami, 1986 | NES | all seven stages play, the game ends and loops; no known divergences |
| DoDonPachi DaiOuJou (Black Label) - Cave / AMI, 2002 | IGS PGM arcade | W533 closes the all-five-stage static preflight and W532 supplies periodic exact-harness checkpoints; six-pair round-2 progression now resumes from local frontiers instead of logic frame 2,000 |
Each game lives in its own directory behind games/index.json, and the launcher
picks a game before it loads any game code. That structure exists for a reason
beyond tidiness: the long-term goal is games that can be combined - Batman
playable inside Gradius, the Vic Viper playable in Batman.
Three cartridges, three rights holders, and none of their material is here: no
ROM, no disassembly listing, no extracted graphics, level maps, sprite art or
music. .gitignore enforces it, and it is checked rather than assumed -
tools/verify_assets.py and the asset-integrity gate stage both operate on
files that only exist after you run an exporter against your own copy.
The published site is a separate question, and the answer is not the same.
tools/build-dist.mjs reads every ROM present and blocks any file that appears
byte-for-byte inside one - against 12 ROM files, 333 files checked, 58 of them
also checked decompressed. It is not, however, absolute: six files are
published verbatim on purpose, each enumerated in PUBLISH_VERBATIM with its
own line of reasoning, and the list is printed on every single build. They are
Batman's player animation tile pool and five DaiOuJou sprite colour shards -
art the ports cannot draw their own characters, enemies or death explosions
without. That is a deliberate owner decision: the live site may serve real
cartridge art; the repository may not, and does not.
The exceptions exist because of what the guard actually measures, which is
packing order, not provenance: every sprite these pages draw is cartridge
art, and a shard trips the check only when its streams happen to sit
consecutively in the ROM so the packed buffer is one contiguous run. Decoding
the colour data to one pixel per byte would retire all six at once, and is
recorded in build-dist.mjs with its measured cost.
The guard blocks everything not named in that list, and the load-bearing rule is unchanged - nothing ROM-derived is ever committed here.
A parallel asset-free release is live at https://mixup.pages.dev/. Asset-free
build 20260827171726 was deployed through
https://f6d2e284.mixup.pages.dev. It ships only the setup shell and translated
source. Players select legally owned local ROM files or a folder, exact
identities unlock the matching game cards, and all three games boot from those
local inputs. Checksums and extraction run in the browser; ROM bytes are neither
uploaded nor saved. The separate asset-backed site at gbtman.pages.dev is live
at build 20260827170519, deployed through
https://7a0dd914.gbtman.pages.dev.
The asset-free package is built by tools/build-rom-dist.mjs into dist-rom/.
Its closed module allowlist rejects generated assets, cartridge extensions,
unexpected files, symlinks, and verbatim cartridge slices with no publication
exceptions. tools/publish-rom.mjs deploys only that directory to the Cloudflare
Pages project mixup and verifies the existing site remains on its prior build.
Everything derived is regenerated from ROMs you legally own:
# Batman - put your own copy at the repo root, named exactly:
# Batman - Return of the Joker (USA, Europe).gb
python tools/export_assets.py # -> games/batman/assets/
python tools/gen_tunables.py # -> games/batman/src/tunables.js
# Gradius - "Gradius (USA).nes" at the repo root
python games/gradius/tools/export_assets.py
# DoDonPachi DaiOuJou - the ddpdojblk MAME set
python games/ddpdoj/tools/export-tables.py
node games/ddpdoj/tools/export-web.mjs
The copies this was built against: Batman SHA-1
345a332175f58304f91111a13b770662e5ea92c3, Gradius SHA-1
92645fe142861c3d3fda209bb906ad2b0e353988, DaiOuJou MAME set ddpdojblk
(the maincpu region is 6 MiB; its FNV-64 is recorded in
games/ddpdoj/game.json). Each game's game.json carries the full identity
block, so a differently-dumped copy announces itself instead of silently
diverging.
Export the assets from your own cartridges first, then:
python -m http.server 8000 # module imports and fetch need a real server
# then open http://localhost:8000
The launcher lists whichever games have assets present. Gradius has its own
start screen (games/gradius/start.html) with level select, a starting
power-up picker, mod presets and the mod catalogue.
This is the part worth reading even if you never touch the code.
The oracle. An emulator runs the real ROM headless, dumps a per-frame state vector, and the port's own vector is diffed against it field by field. The rule is to report the first divergence per field, not the loudest one - a downstream symptom is not the bug. One emulator per machine:
| game | emulator | driven by |
|---|---|---|
| Batman | PyBoy | Python |
| Gradius | Mesen 2.1.1 | Lua |
| DaiOuJou | MAME 0.288, -video none -sound none -nothrottle | Lua |
It exists so that "faithful" is a checkable property rather than a vibe, and it
has caught a long list of bugs that reading the disassembly did not - from an
unsigned-byte terminal-velocity clamp, to Batman being drawn mirrored for his
entire run, to a carry that failed to propagate through an RTS and borrowed
1/256 of a pixel on 243 of 3,826 frames.
Enumerate statically, validate dynamically. The ROM is the inventory -
it tells you what exists. The oracle is the verdict - it tells you what is
right. Neither substitutes for the other, and confusing them is how this project
has produced its most confident wrong answers. docs/knowledge/09.
Coverage is branches, not frames. A million frames through one arm of a
dispatch is not coverage. docs/knowledge/10.
docs/knowledge/ is the cross-game distillation - the oracle method, the eight
trap shapes, what makes a check capable of failing, clocks and frame rates, lag
and slowdown, rank and dynamic difficulty. docs/00-MASTER-REFERENCE.md is the
authoritative Batman spec; docs/worklog/ is the per-wave record for the two
games in flight.
Two traps are worth knowing before reading any of this code:
| path | what |
|---|---|
games/index.json | the registry the launcher reads before it loads any game code |
games/<id>/game.json | the manifest: ROM identity, screen, frame rate, entry point, levels, options |
games/<id>/src/ | the port |
games/<id>/tests/ | unit tests - they run without any ROM, on synthetic fixtures |
games/<id>/assets/ | extracted from your own copy; never committed |
games/<id>/tools/ | that game's extractors, oracle and gates |
tools/ | Batman's extractors and disassembler, the shared build and publish path |
tools/oracle/ | Batman's PyBoy oracle (a test tool; it never ships) |
docs/knowledge/ | the cross-game lessons - read this before starting a new game |
docs/worklog/ | the per-wave record for Gradius and DaiOuJou |
SAVEPOINT.md | the working map: what is done, what is not, and the traps |
HANDOVER.md | the whole project in one file, for picking it up cold |
Two files in games/batman/src/ are load-bearing for ORDER and say so in their
headers: game/frame.js (the $0567 main-loop body - call order here is
shadow-OAM order, which is DMG sprite priority and the ten-sprites-per-line cut)
and enemies/driver.js (the $FFA7 parity that reverses the slot walk). Each
names the test that guards it.
There is one gate per game, and they are separate runners:
npm test # Batman unit tests only
npm run test-all # Batman gate - 27 stages
node games/gradius/tools/test-all.mjs # Gradius gate - 13 stages
node --test games/gradius/tests/ # Gradius unit tests
node --test games/ddpdoj/tests/ # DaiOuJou unit tests
npm run typecheck # tsc over the ports - no ROM needed
node tools/publish.mjs is the only thing that runs all of them, and it
refuses to publish on a red gate or an unexpected gate skip. --only gradius /
--only ddpdoj gate one game; --dry gates and builds without deploying.
At published DDPDOJ W531, its unit suite records 4,414/4,414 passing.
The same publication passed all 748/748 Gradius units, the 13/13
Gradius gate with zero skips, the DDPDOJ bundle and web-fetch gates, the 27/27
Batman gate with zero skips, the distribution build, and the repository ROM-leak
guard. Production build 20260823165848 carries W527 through W531 and passed
deployment plus three consecutive live confirmations. The published export has 791
windows, 449,329 bytes, and 77 overlap pairs. The source commits are 33240de,
a9ff556, 20cfc12, 292af08, and 2873487; repairs 4110255 and f3b8b85
reconcile the exact registries and publication assertions. The leak guard checked 336
files, including 58 decompressed payloads, and the deployed distribution contains 342
files totalling 20,500 KB.
A skip is not a pass. Both gate runners tell apart a legitimate
environmental skip (no emulator, no cartridge) from a skip caused by a moved
path, which is a failure - because ALL GREEN - 2 passed, 24 skipped is the
most dangerous output a test runner can produce. docs/knowledge/03.
A new check must be seen to fail. Revert the fix, watch it go red, restore. Checks here have sat green through the very bug they were written for, in four different ways: one asserted only that rendering did not throw, one set up state the application never has, one sampled frames that never changed, and one took the answer in as an argument.
27/27 gate stages with zero skips, 50/50 oracle scenarios bit-exact over 14,519 frames, 96.023% mean pixel match across the 73-frame visual suite. All fourteen levels playable, every boss, title screen through to the end credits.
Bit-exact and covered by the gate: player physics, collision and slopes, camera,
wall-cling and wall-jump, the bat-rope, punch and batarangs; all 13 enemy AI
states and every boss; all 11 map-object types, the door sequencer, breakables
and pickups; the six sub_00_2CBE subsystems; both death sequences at their
real length; all eight arms of the $0857 raster program; the sound driver and
DMG APU across all 47 ROM sound ids, 52 recordings and 29,800 ticks; and every
screen from the SUNSOFT copyright card to the ending.
Nothing is captured. Every screen is BUILT from ROM data and diffed against
the cartridge's own VRAM. src/ contains no ROM data at all - every table
travels through assets/manifest.json, and tools/verify_assets.py re-reads
each one from raw file offsets so the exporter cannot verify itself.
Two deliberate deviations, both documented, neither to be "fixed": the water's 50% dither is reproduced spatially rather than as the hardware's 30 Hz alternation (on a modern display that alternation is a photosensitivity hazard rather than the translucency a DMG's slow LCD made of it), and a parallax feeder race kept the way that measured better - the lookahead costs 6,288 bad scanlines, dropping it costs 8,112.
All seven stages, the ending, and the loop back round. Measured, not assumed:
598 of 598 wave records spawn a ported handler across all seven stages; 41 of 42
$AE1C enemy-dispatch entries; all 16 play sub-states; all 7 $80D4 game
modes. $1A is no longer pinned, so the game wraps to loop 2 - and loops 2, 3
and 6 sweep frame-for-frame identically, because every gameplay reader of $1A
has three tiers, so difficulty tops out at loop 3 rather than at the ending
table's 7.
Six crashes that had shipped were found and fixed after stageledger.py's
RUNNABLE column turned out to mean "statically guarded", not "plays" - the
replacement, stagesweep.mjs, actually runs 112,000 frames in 2.7 s.
19 mods in three categories (physics, combat, chaos) and 4 presets, on a
start screen with level select and a starting power-up picker. They include
heal-gradius-syndrome (respawn in place with your loadout, instead of the
checkpoint death-spiral) and always-on-enemies, which lifts the NES
sprite-per-scanline cap without removing the flicker the game uses deliberately.
The active translation targets Black Label Version-B first. Its source now spans
the main loop, player and all three weapon systems, bombs, bullets, enemies,
bosses, items and bees, stage and result flow, score and chaining, hypers, rank,
HUD, sound posts, and high-score name entry. The browser port and generated
asset path are live, and W531 published as production build 20260823165848
after all 4,414 DDPDOJ unit tests passed. W477 shipped the first
15 optional mods, including explicit Invincibility, while an empty loadout remains
vanilla. W492 through W496 raise the catalogue to 30 with Hyper Overdrive, Adaptive Slow
Motion, Bee Magnet, Boss Enrage, Graze Reactor, Glass Cannon, Auto Deathbomb,
Resurrection in Place, Revenge Bullets, Bullet Polarity, Score Multiplier Mayhem,
Friendly Converted Bullets, Loop 2 From Stage 1, Boss Rush, and Stage Remix. Each
remains behind explicit state-local simulation seams or an ordinary-launch copy, and
all fifteen block replay v1.
W478 ports the loop-aware hyper contribution to enemy-bullet speed, with its
zero-power flag branch corrected during the W481 publication gate. W479
restores the mirrored player bonus followers, and W480 closes the final type-5
frame call with the hyper-stock animation. W481 follows corrected live stage-5
evidence into type $4C's first runtime-selected child, type $52. W482 follows
the next runtime blocker into type $4E, whose expiry emits two independently
positioned type $4F children. W483 completes that nested type $4F lifecycle:
it decelerates, reverses, rank-accelerates, selects either zoom sprite bucket,
and retires with effect kind $04. W484 ports type $50, type $4C's part-4
runtime child: it moves and draws for a $30-frame lifetime, then emits type
$51, while sharing type $4F's parent-gated effect retirement. W485 completes
that terminal type $51 lifecycle: it arms retirement once seen, moves without a
freeze gate, decelerates, reverses, rank-accelerates, animates through either zoom
bucket, and frees after leaving the screen. W486 restores type $4C state 4's
live step-1 steering gate at $26FD8C..$26FD98 and paired fall-through arm at
$26FDF4..$26FEC7. Step 1 now holds until arrival at $3200/$1C00; only then
does record +$1E begin ramping by $40 to $600. Eight every-eighth-frame
passes each enqueue a paired type $58 emission with separate packed biases and
headings. W487 ports type $58 init body $270BE4 and handler $270C66. The
16-child queue now drains successfully; each child inherits heading, moves with
vertical acceleration, cadence-filters a three-heading fan, draws with the
existing art table, and retires on a fatal hit, parent loss, or its signed
off-screen bound. W488 restores the shared front-end label printer : both
screen slots now draw each side's two cartridge strings in side order through
, using the two fixed descriptors at . W489 removes the fly-around
oracle's embedded hold from ordinary browser launches, so vanilla play
is mortal and has no persistent invulnerability aura. Labelled progression and replay
seeds remain exact, explicit Invincibility still starts and stays at , and sound is
now enabled by default on the first browser gesture while SOUND remains an explicit
mute/on control. W490 makes replay and recording banners transient: arm, save, playback,
verdict, and operation-error notices clear after four seconds, while replacement invalidates
the old timer so a stale callback cannot hide newer text. W491 lets every layout hide and
restore the menu, gives the aspect-preserving canvas all available viewport area, top-aligns
it when the other axis cannot grow, overlays translucent mobile controls, and shows the
floating stick's origin and bounded displacement only while held. Coverage is 101 ported,
25 unknown, and 130 null, with 94 init bodies. Type emits no enemy child,
and the remaining static edge is disabled behind Version B's
return, so no next runtime blocker has been established. W492 through W521
are live in production build ; W492 through W496 supplied all fifteen requested transformative
mods. W497 is the first substantial D26 cartridge-choice slice: ordinary browser starts
can select Type-A or Type-B with numeric style selectors 2, 4, or 6, independently
of mods. Both ships have their complete browser-packed 17-image animation, attached
shadow/glow, shot, option, regular-laser, ordinary-bomb, and laser-bomb dependencies.
The cartridge does not yet prove the human pilot-name mapping, so the UI does not
guess it. Empty and default launches remain byte-exact. The coordinator repeated W497's
159/159 bounded affected set, and its regenerated bundle remains
15,955,968/15,955,968 pixel-identical while containing 4,898 validated sprite streams
in 12,623.9 KiB. W498 restores authentic Game Over art and shared mobile P1 COIN/START
with lifecycle-safe first-controller coin edges. W499 completes D106: browser Gamepad
index 0 drives P1, index 1 drives P2 through the existing two-half machine
word, and each controller has its own active-low coin path. Standard,
PlayStation, Nintendo/Switch, and conservative generic DirectInput profiles are
supported; mobile remains P1-only. W500 advances D34's cartridge state-7 path:
now draws both one/two-round labels from ROM, applies the last joined
side's directional input while OR-ing both sides for confirmation, blinks the chosen
mode for 32 ticks, stores it to , and queues the cartridge clear before
retirement. Its exact data window raises the registry to 634 windows
without changing 76 overlap pairs. W501 closes state 7's remaining counted head:
selects P1 or falls back to P2, and installs each record's palettes,
draws the main sequence and zoomed detail pair, advances the pause satellites, and retires
at sequence . Three exact disjoint animation windows at , ,
and raise the published registry to 637 windows and 444,613 bytes without moving the
76 overlap pairs. W502 removes D34's sole counted per-record edge by porting
. Both live and dead records take its exact side selection, announcement
and active-record label exits, credit-message carry path, coordinate adjustment,
art-offset selection, and bucket-7 enqueue. The exact disjoint windows
and raise the registry to 639 windows and 444,733 bytes while
preserving 76 overlap pairs. W503 ports dispatch type at , restoring the
bounded stage-5 ending tally and type-7 handoff. W504 through W516 follow that natural
loop-2 edge through variant 0's complete five-script list and sequence list A's first eight entries,
emitting 325 visible pool records and completing thirteen resource lifecycles. W509's
script proves : operands 1 and 3 publish banner 1, select W372's
existing two-node mode-0 resource, run its two exact 32-word palettes for 32 animation
steps, and free it. W510 adds , W511 adds , W512 adds
, W513 adds , W514 adds , W515
adds , and W516 adds , all without a new opcode arm.
W516's four groups emit 38 records: the first 26 arrive on consecutive cadence, then
spaces the final 12 by three frames. After the wait, completes its
one-node primary resource while runs the two-node
first phase for 32 steps and returns directly to idle because banner 0 is already live.
advances the cursor from 28 to 32, clears the pool, and reaches entry 8 at . W517 finishes
sequence list A. W518 follows the normal handoff through slot [15]'s complete credits-text lifecycle, W519
through slot [14]'s normal Game Over lifecycle, W520 through slot [12]'s zero-score no-name exit, and W521
into slot [8]'s first stable state-2 high-score presentation. Production build publishes
W517 through W521 with 783 windows, 448,021 bytes, and 77 overlap pairs after 4,404/4,404 DDPDOJ units,
all bundle and web gates, the cross-game gates, the distribution build, the ROM-leak guard, deployment, and
three consecutive live confirmations. The source commits are , , , ,
and ; publication repairs are and . W522 starts the six authentic-pair loop-2
matrix by porting stage-3 type ; W523 fixes the shared round-2 slot-[17] stall. W524 registers Type-B's
exact ordinary-shot sound wrapper. W525 exports its normal-shot table and
pointed descriptors. W526 closes Type-A style 6's hit descriptor, and W527 exports Type-B's exact
hit family. W528 ports kind-16 flying-bee waypoint movement. W529 ports deferred type
; W530 applies the 68000's 24-bit bus wrap to type 's RAM-backed animation read; W531 ports the
kind-19 target-tracking arm. Pair now reaches logic frame 41,031 in raw stage 3. Production build
publishes W527 through W531 with 791 windows, 449,329 bytes, and 77 overlap pairs after
4,414/4,414 DDPDOJ units and every cross-game gate. W532 adds periodic exact-harness checkpoints and a static
round-2 preflight over all five stage scripts, all five BGELEM lists, top objects, type-5 calls, deferred children,
and carrier movement children. W533 proves the two remaining top-object rows are operator-only diagnostics and
that type 's mandatory init jumps directly to free , making its alternate handler
unreachable. The progression closure therefore reports 18/18 required top objects, zero unresolved dependencies,
and . D109 is complete
ahead of deadline: the separate asset-free site boots all three games from exact local inputs without shipping
cartridge assets. Remaining ending variants will be batched by complete family or variant rather than split into
one commit per understood script.
That breadth does not mean the game is finished. The authoritative docket still tracks explicit defects and gaps, front-end screens, remaining enemy coverage, and behavior through the complete second loop. All 23 type-5 frame calls now run, while enemy-handler coverage is 103 ported, 23 unknown, and 130 null. The duplicate scanners still report 16 narrow heads, 71 widened heads, 28 body pairs, and 22 body-only findings, now deliberately deferred until functional completion.
The completion order is deliberate: finish Black Label through the full second
loop, finish functional White Label, then close the duplicate-only audit rows. Current status
lives in docs/DOCKET.md and docs/NEXT_AGENT_HANDOFF.md; old numbered
worklogs are historical snapshots. games/ddpdoj/README.md contains setup,
asset, oracle, testing, and fidelity details.
CONTRIBUTING.md has the rules that actually matter. The short version:
measure it against the ROM, or don't change it. There is a correct answer to
every question in this repository and it is available, so "I think it works like
this" is never the standard.
Two habits that are not optional: cite the ROM address on every non-obvious line, and make a new check fail before you trust it.
MIT - see LICENSE. That covers this repository's own work: the ports, the
tooling, the tests and the docs.
It grants nothing over Batman: Return of the Joker, Gradius or DoDonPachi
DaiOuJou, which remain the property of Sunsoft, Konami and Cave respectively.
No ROM, listing or extracted asset is distributed here, and nothing runs without
ROM images you supply yourself. NOTICE.md sets out exactly what is and is not
included, and what this project is legally.
$270972$25F2D0$25A14C$25F43A$810424=$FF$FF$58$48 -> $54$2714AE20260823074549$C08000$C08004$25FAA4$80393A$25FC68+$20$25F530$25F592$9C$25F7C8+$A0$25F880+$78$25F8F8+$40$25E72E..$25E7B7$25F1EC$23E08C$25E716+$18$25F270+$60$13$28EE88$8003$2914F0..$291549$8005$290E1C$29154A..$29159F$2915A0..$291603$291604..$29166B$29166C..$291691$291692..$2916D9$2916DA..$2916FF$291700..$29177B$0000$0202$C0$8003 $0003$290E76$8005 $0000 $0003$290D42$FFFF$29177C20260823074549e28336bf2266f87918d8a4ce25364c6a8c2e55af96b2e671c$3D$28C3D4$24E512..$24E5ED$24DFA2$24E5EE..$24E723$A5$9C{0,4}20260823165848$9A$29EAE2$263762CLOSED