1993년 아마가 게임을 Godot으로 포팅하며 LLM으로 68000 어셈블리 읽기

TL;DR

Claude Fable 5는 1993년 아마가 게임 Babylonian Twins를 Godot 4로 성공적으로 포팅하여 원본 68000 어셈블리(72,758줄)와 이후 2010년 C++ 엔진(34,000줄)을 자동으로 번역했습니다. AI는 문서화되지 않은 파일 포맷을 재구성하고 원본 바이너리와 완전히 일치하는 결과물을 생성했으며, 수십 년 동안 발견되지 않은 버그를 드러냈습니다.


실험의 의미

저자는 현대 LLM이 훈련 데이터에 포함되지 않은 문서화되지 않은 68k 어셈블리를 이해할 수 있는지 테스트하고자 했습니다. Claude에게 전체 아마가 소스, 자산, 빌드 도구를 제공함으로써 AI가 생성한 포팅 버전을 원본 바이너리와 바이트 단위로 비교할 수 있었으며, 저수준 역공학 작업에서 LLM의 성능을 구체적인 기준으로 평가할 수 있었습니다.


단계 1 – 1시간 이내에 2010년 C++ 엔진 포팅

  • 결과: 21분 만에 플레이 가능한 Godot 프로젝트가 생성되어 전체 34,000줄의 C++ 코드베이스를 재현했습니다.
  • 핵심 통찰: AI는 원본 고정 타이크 로직(60Hz)을 유지했으며, Godot의 CharacterBody2D로 사용자 정의 이동 코드를 대체하지 않았습니다. 수작업으로 작성된 충돌 루틴을 유지함으로써 미묘한 물리적 불일치를 피했습니다.
  • 기술적 참고: 원본 게임은 승수적 마찰 계수(velocity.x *= 0.85)를 사용했습니다. 원본은 50Hz에서 실행되었기 때문에 60Hz에서 동일한 상수를 사용하면 느낌이 어색해졌습니다. AI는 두 타이크 레이트를 별도로 유지하여 원본의 느낌을 그대로 보존했습니다.

단계 2 – 68000 어셈블리 자동으로 재구성

  • 결과: Claude는 1993년 소스를 재구성하고 vasm으로 어셈블하여 배포된 아마가 디스크와 바이트 단위로 완전히 일치하는 바이너리를 생성했습니다.
  • 작동 방식: 모델은 ASM-One과 vasm 간의 문법 차이(예: cmp #4,d0 인코딩)를 다리 역할하는 전처리 단계를 작성하고, 2008년 전송으로 인해 손상된 파일 이름 매핑을 수정하는 스크립트를 생성했습니다.
  • org 처리: AI는 원본이 링커 없이 수동 메모리 레이아웃(org $6a000)을 사용했음을 학습했습니다. 올바르게 레이아웃을 재현했지만, ASM-One의 "스킵" 세미틱스가 다를 때 한 ds.b 800 블록에서 오류가 발생했습니다. AI는 처음에 800바이트의 0을 출력하여 이후 데이터를 944바이트만큼 이동시켰고, 재구성된 데모가 잘못된 그래픽을 렌더링하면서 오류가 발견되었습니다.
  • 변수 영역 차이: 약 108바이트가 달라졌습니다. 배포된 바이너리는 실행 후 RAM의 스냅샷이었지만, 새 어셈블리는 해당 변수들을 0으로 두었기 때문입니다. AI는 코드가 이 변수들을 읽기 전에 쓰기 때문에 차이가 무해하다고 설명했습니다.

문서화되지 않은 포맷 디코딩

레벨 맵

  • 레벨 로더는 문서화되지 않은 68000 코드 1,652줄로 구성되어 있습니다. AI는 렌더링 루틴을 추적하고 너비/높이 상수를 추출하여 타일 그리드 포맷(헤더 없음, 압축된 청크)을 추론했습니다.
  • 모든 5개 레벨을 재생성하여 PNG로 렌더링하고, 저자의 2020년 스크린샷과 픽셀 단위로 비교했습니다. 두 가지 불일치(하늘 그라데이션, 물 색상 사이클)는 누락된 코퍼리스트 데이터로 인한 것이었으며, AI는 이를 추가했습니다.

맵 셀 속성

  • 각 16비트 셀은 6비트 속성, 벤치 선택 비트, 8비트 타일 인덱스를 포함합니다. AI는 그리기 루프(하위 바이트 마스킹)와 충돌 루틴(상위 바이트 마스킹)을 분석하여 속성 비트를 발견했습니다. 고체 지면, 오를 수 있는 타일, 피해 코드, 문, 죽음 영역을 포함한 전체 속성 테이블을 재구성했습니다.

오브젝트 테이블

  • 오브젝트는 각 화면별로 사용자 정의 테이블에 저장됩니다. AI는 마커($1111 = 빈 화면, $2222 = 죽은 오브젝트)를 식별하고 hiddenwallR‑lrb와 같은 동작 오프셋을 디코딩했습니다. 이후 모든 오브젝트 좌표를 월드 공간으로 변환하고 렌더링된 맵과 검증했습니다.

코퍼리스트 하늘 그라데이션

  • 하늘 색상은 코퍼리스트가 일련의 색상 단어를 쓰는 방식으로 생성됩니다(예: dc.w $09FF,$09EF,…). AI는 레벨 2의 24단어 그라데이션을 추출하여 수직 밴드로 렌더링하고, 초기 빌드에서 누락된 후 다시 포팅에 추가했습니다.

스프라이트 시트 모호성

  • 아마가 스프라이트는 평면 비트플레인으로 저장됩니다. AI는 시트 크기(frames * width * height * 2 * 5)에 대한 모호성을 감지하고 저자에게 명확한 설명을 요청했습니다. 올바른 해석은 두 개의 겹쳐진 행(각각 방향에 하나씩)이었으며, AI는 이를 올바르게 디코딩했습니다.

단계 3 – 현대 빌드 내부에 원본을 게스트로 통합

  • 단 하루 밤 동안 AI는 1993년 게임을 50Hz로 실행하는 "게스트" 모드를 추가하여 Godot 실행 파일 내부에서 작동하게 했으며, 플레이어가 현대 버전으로 돌아올 때 60Hz로 전환했습니다.
  • 모든 자산(PNG, WAV, JSON)은 Python 스크립트로 한 번만 추출되었고, 동작은 GDScript로 재구현되었습니다.
  • 최종 Steam 출시판은 현대 게임 뿐만 아니라 1993년 아마가 버전을 두 번째 실행 옵션으로 포함합니다.

AI 기반 포팅으로 드러난 버그

버그 원본 현상 AI 생성된 수정안
경비병 밀기 범위 레벨 2에서 높은 플랫폼 위의 경비병이 플레이어를 고체 암석 안으로 밀어넣음 누락된 상한값 체크 복원(cmp.w #4,d4; bpl Sg.Far).
숨겨진 문 타일 문이 빈 하늘처럼 보였음(맵에 저장되지 않고 런타임 코드로 그려짐) 포팅에 런타임 문 그리기 루틴 추가
트램폴린 물리 현대 빌드에서 점프가 너무 높게 느껴짐 2010년 iOS 빌드의 유지 점프 플래그로 인해 눌림-해제 불일치 발생; Godot에서 입력 처리 수정
스프라이트 시트 방향 AI는 처음에 쌍둥이의 방향을 반사시켜 렌더링함 원본 시트는 왼쪽/오른쪽 각각 한 행씩 포함하며, 올바른 방향 유지
누락된 하늘 그라데이션 첫 번째 재빌드에서 평평한 하늘이 렌더링됨 코퍼리스트 색상 테이블 재추가하여 픽셀 차이 경고 제거

LLM이 자동화한 릴리스 워크플로우

  • AI는 헤드리스 테스트와 스크립트 기반 게임플레이를 가능하게 하기 위해 명령줄 플래그(--level, --pose, --drive, --probe, --screenshot)를 생성했습니다.
  • 모든 필수 스토어 해상도에서 스크린샷을 생성하고, 각 언어로 게임을 실행하며 실제 폰트를 사용해 게임 내 캡션을 캡처했습니다.
  • 스토어 메타데이터(제목, 설명, 아이콘)는 자동으로 채워졌으며, Steam 웹 대시보드에 로그인하는 것만 수동으로 필요했습니다.
  • Google Play에서 리뷰를 스크래핑하고 파싱하여 버그 보고 리뷰(예: "레벨 1에서 문을 통과할 수 없음")를 즉시 수정할 수 있도록 표시했습니다.

커뮤니티 반응 (선택된 HN 댓글)

mattjoyce: "나는 ZX81 메모리 덤프를 다운로드하고 Claude에게 Go로 재구성해 달라고 요청했습니다. 완벽하게 성공했습니다." – LLM이 레트로 컴퓨팅 고고학에 대한 광범위한 잠재력을 보여줍니다.

hedgehog: "Claude가 유사한 포팅을 위한 엔지니어링 가이드를 내보내는 것이 흥미로울 것입니다." – 워크플로우 자체가 재사용 가능한 블루프린트가 될 수 있음을 시사합니다.

robviren: "과거의 비표준적이고 해킹 같은 코드의 양은 오늘날 접하기에 불가사의할 정도로 복잡해 보입니다." – AI가 30년에 걸친 지식 격차를 어떻게 메웠는지를 강조합니다.

coder-pm: "원본과 동일한 입력으로 UAE에서 포팅된 버전을 실행해 보셨나요?" – 향후 검증 단계로 매우 유용한 점을 지적했으며, 저자는 픽셀 단위의 차이 검사를 수행했음을 확인했습니다.


미래 레트로 포팅에 대한 의미

  • 가능성: LLM은 문서화되지 않은 68k 어셈블리를 읽고, 누락된 포맷을 재구성하며, 최소한의 인간 개입으로 충실한 현대 포팅을 생성할 수 있습니다.
  • 속도: 소스 가져오기에서 작동 가능한 Godot 빌드까지의 전체 파이프라인은 약 5시간의 지속적인 AI 실행으로 완료되었으며, 수동 재작성보다 훨씬 빠릅니다.
  • 보존: 바이트 단위로 일치하는 재구성은 원본 게임이 현대 하드웨어에서 인증 없이 아카이브, 연구, 실행이 가능함을 보장합니다.
  • 버그 발견: 자동화된 역공학은 30년 동안 발견되지 않은 버그를 드러내어 단순한 코드 번역을 넘어서 실질적인 이점을 보여줍니다.

게임을 플레이할 수 있는 곳

  • 1993년 아마가 원본 버전: itch.io에서 무료 디스크 이미지 제공 (FS-UAE, WinUAE, 또는 실제 하드웨어로 실행)
  • 정식 에디션 (Godot 4): iOS, 안드로이드에서 이용 가능하며, (2026년 가을) Steam에서도 출시 예정. 1993년 버전이 보조 실행 옵션으로 포함됩니다.

포팅은 Claude Code에서 실행 중인 Claude Fable 5에 의해 주도되었으며, 저자는 노트, 저장소, 원본 바이너리를 제공했고, AI는 이 기사의 초안을 생성했으며 이후 줄 단위로 편집되었습니다.

Sources

관련

  • 프로젝트
  • Dispatch
  • Dispatch
  • Dispatch
  • Dispatch