Resident Evil 4(GameCube), C/C++로 바이트까지 완전히 동일하게 디컴파일
요약
본 기사는 Resident Evil 4의 GameCube 버전을 C/C++로 바이트 단위까지 완벽하게 디컴파일한 과정을 다룹니다. 원본 코드를 복원하기보다는 컴파일 가능한 형태로 동작을 모방하는 코드 구조가 발견되었으며, 이는 레트로 게임 에뮬레이션 및 분석에 새로운 가능성을 제시합니다.
핵심 포인트
- RE4 GameCube 버전을 C/C++로 바이트 단위까지 디컴파일함.
- 원본 코드는 직접적인 복원보다는 컴파일 가능한 형태로 동작을 흉내냄.
- 레트로 게임 기술 분야에서 AI 활용에 대한 찬반 논쟁이 존재함.
- AI는 지루한 자동화 작업에는 유용하나, 깊은 시스템 이해 과정의 가치를 퇴색시킬 수 있다는 우려가 제기됨.
MWCC CRI 라이브러리와 SDK에는 paired-single, 캐시, SPR 커널 및 내장 연산이 남음
관련 유닛은 mpv_umc, mpv_mc, dct_fsri, cftyp422_ppc, mpv_lib이며, SDK의 mtx, vec, quat, GX 내장 연산도 포함됨
dct_ac의 dctac_Init에는 레지스터 유도 블록 하나가 남음. 공급업체의 컴파일러 빌드는 .bss만 풀링하고 함수의 8바이트 리터럴은 풀링하지 않았지만, 프로젝트의 빌드는 둘 다 풀링함
기계어를 생성하지 않는 asm { mr r11, x; mr x, r11 } 고정 구문과 asm { mr v, v } 자기 복사가 27곳에 남음. 전자는 할당 과정에서 두 이동이 제거되지만 할당 가능한 레지스터를 하나 줄이며, 후자는 컴파일러가 내부를 알 수 없는 두 번째 정의로 작용함
임의로 파일 하나를 열어 봤는데, 게임의 원래 코드를 복원하기보다는 컴파일 가능한 C 문법으로 동작을 흉내 낸 것처럼 보임. Em1eWeaponSet(cEm10* em)에서 w->mot[41]부터 w->mot[78]까지 0이나 ARC(0x26C) 같은 값을 하나씩 대입하는 식임.
다른 파일에는 더 평범한 형태의 코드도 있음. 원래 게임이 애니메이션 데이터 등을 C 코드 안에 직접 넣어 둔 것으로 보임.
놀랍지는 않음. 이제 유사 어셈블리에서 의미를 도출하는 재미있는 작업이 시작됨.
레트로 게임계의 AI 반감에도 불구하고, 이런 프로젝트와 에뮬레이션은 정말 기대됨. 다만 이 프로젝트에 AI가 쓰였는지는 모르겠음. 에뮬레이션은 깊은 기술 지식과 원본 시스템에 대한 뛰어난 이해가 필요하고, 최적화 수준도 남다르다는 점에서 기술적으로 정말 대단함.
레트로 게임 기술 분야에 깊이 관여하는 입장에서, AI를 쓰는 사람이 많아지는 건 상당히 실망스러움. 이런 취미의 핵심은 지식을 얻고 시스템의 전문가가 되는 과정이며, 작동하는 에뮬레이터라는 목표는 그 과정을 지속하게 해 주는 동기임.
Claude가 NES 에뮬레이터를 한 번에 만들어 주는 건 내게 거의 의미가 없음. 남이 작성한 소스를 읽으며 배울 수는 있지만, 게임 동작의 차이를 발견하고 추적 로그를 들여다보며 잘못 구현한 명령어를 찾아내는 것과 같은 CPU 이해를 요구하지는 않음.
AI는 조사나 명령어 디코더 작성 같은 지루한 작업의 자동화에는 유용함. 하지만 프로젝트에 들이는 노력을 통째로 건너뛰면 이런 프로젝트를 하는 목적 자체가 사라짐.
진입 장벽을 세우거나 옛날 타령을 하려는 건 아님. 다만 내 경력 전체가 프로그래밍 초보였던 십 대 시절, 몇 년에 걸쳐 NES 에뮬레이터를 만들며 익힌 지식에서 출발했기에 다음 세대가 그 학습 과정을 놓칠까 걱정됨. 레트로 게임, 특히 인기작은 유한하므로 AI로 미개척 영역을 먼저 소진하면 다른 누군가의 발견 기회와 그 게임 커뮤니티에 정착할 계기도 사라질 수 있음.
저장소에서 파일 몇 개를 임의로 살펴봤는데, 어디에나 수준 높은 코드 주석이 있었음. AI에 딱 맞는 작업임. 20년 전 개발팀이 만든 프로그램을 디컴파일한 코드 100만 줄에 사람이 일일이 문서를 붙이는 일을 상상할 수 있겠는가?
레트로 게임계의 AI 반감은 이해하기 어려움. 기존 게임을 잘 돌아가게 만드는 게 목적이라면, Claude가 반나절 만에 했든 사람이 1년을 썼든 무슨 상관인가? 오히려 Claude가 하는 편을 선호함. 사람은 지루해하거나 커뮤니티 갈등에 휘말리거나 사라질 수 있음. 평생의 기여가 데이터센터의 몇 kWh로 대체되는 당사자에게는 안타깝지만, 나머지에게는 이득임.
AI에 대한 반감은 사실 질투를 감춘 것이라고 봄. 이제 프로젝트 관리자, 기술 프로그램 관리자, 현업 관리자도 상당한 코드를 제출할 수 있게 됐고, 그만큼 개발자의 가치 일부가 줄어든 셈임. 개발 경력 25년 이상인 나도 PM이 개발자를 기다리는 대신 직접 문제를 고치는 모습을 보고 있음. 분노는 이해하지만 이 도구들은 사라지지 않을 것임.
Capcom이 RE4를 온갖 플랫폼으로 이식하는 데 워낙 진심이니, 보존 관점에서는 가장 쓸모없는 디컴파일 프로젝트 중 하나일지도 모르겠음. 물론 농담임. 유출된 디버그 빌드와 심벌을 이용했다는 점은 이런 자료를 확보하고 배포하는 게임 보존 커뮤니티의 작업이 얼마나 가치 있는지 보여 줌.
다만 원본의 레지스터 선택이나 명령어 배치를 재현하려고 자연스럽지 않은 코드를 넣고 // COMPILER-DIFF:로 표시한 부분이 644개라는 점은 꺼림칙함. 실행되지 않는 조건 검사, 빈 asm(""), 특정 레지스터에 변수를 고정하는 구문, 채우기용 문장 등이 들어감.
디컴파일의 가치는 이미 보유한 원본 바이트를 다시 만드는 것 자체가 아니라, 사람이 읽을 수 있는 소스로 게임에 대한 이해를 복원하는 데 있음. 바이트 단위 일치는 복원이 맞았다는 지표일 뿐임. 컴파일러 출력을 억지로 맞추려 잡다한 코드를 넣어야 한다면 오히려 복원이 틀렸다는 징후이며, 특히 AI에 적용되는 굿하트의 법칙의 위험을 보여 줌.
나는 바이트 일치 대신 동작 검증을 사용하는 AI 기반 PS1 게임 디컴파일을 진행 중임. 에이전트가 C 코드와 테스트를 작성하면 검증 도구가 이를 컴파일하고, 원본 기계어와 컴파일된 C 버전에 같은 테스트를 실행함.
양쪽 모두 문장·분기 커버리지 100% 를 충족해야 하며, 동일한 입력과 초기 RAM에서 반환값, RAM 상태, RAM/MMIO 읽기·쓰기 순서가 같아야 함. 작은 MIPS 시뮬레이터로 테스트를 아주 빠르게 실행할 수 있음.
정확한 컴파일러 버전과 옵션, 변수 배치 등을 찾아 레지스터 할당까지 맞추는 데 드는 시간을 줄여 기존 방식보다 훨씬 빠르게 진행하고 있음. 목표는 바이트 일치가 아니라 정확성이며, 에이전트는 원본 어셈블리를 이해하고 의미상 동등한 C 코드를 작성하는 일을 훨씬 빠르고 효과적으로 수행함.
이런 편법으로 함수를 완전히 일치시켜도 대체로 코드 이해 가능성을 크게 해치지는 않음. 오히려 전체 코드가 원본과 동일함을 확인하는 데 유용하며, 그렇지 않으면 이를 증명하기 어려움.
디컴파일은 이해나 호기심 충족을 넘어 고급 모드와 번역 패치에도 쓰임. 어셈블리가 구조체에 직접 접근하면 구조체를 바꾸기 어려우므로, 순수 어셈블리보다 나아지는 것만으로도 반가움.
물론 컴파일러가 그런 출력을 낸 원래 코드를 복원하는 편을 선호하지만, 때로는 매우 어려움. 오래된 MSVC 코드의 디컴파일을 수년간 해 왔는데, 레지스터 할당과 심벌 순서에 영향을 주는 요인 중에는 역으로 복원할 단서가 완전히 사라지는 것도 있음.
가령 인라인으로만 사용된 함수도 오브젝트 파일과 디버그 빌드에 남을 수 있고, 여러 오브젝트에 존재할 수 있도록 COMDAT any로 처리됨. 최종 실행 파일에 어느 오브젝트의 함수가 남는지, 따라서 어느 컴파일 옵션이 적용되는지도 임의적임. 유용한 단서이면서도 복원을 어렵게 만드는 요소임. 동등한 소스를 추측해 내는 것이 사실상 불가능한 예제도 만들 수 있을 듯하며, 대규모 성공 사례가 나오기 전까지 완전 일치 디컴파일을 헛수고로 여긴 이유 중 하나일 것임.
이런 코드는 정확히 맞추지 못한 부분을 우회한 것이거나, 빌드 환경이 원본과 다르다는 뜻임. 정확한 파일 구성, 변수 선언 순서, 컴파일 순서 등은 바이트 단위로 재현하기가 사실상 불가능할 수도 있음. 이런 차이가 의미는 같지만 인라인화나 최적화 선택이 다른 결과를 낳으니 완전 일치가 까다로움.
OOT와 MM 디컴파일에는 레지스터 할당이 일치할 때까지 코드 줄 순서를 바꾸는 무차별 대입 도구가 있었음.
이런 편법이 없는 편이 낫기는 함. 그래도 나라면 대부분을 복원한 시점에 공개하고 점차 다듬겠음. 다른 사람이 와서 곳곳을 도와줄 수도 있음.
멋진 디컴파일 작업들을 보면 마음이 복잡해짐. 흥미로운 작업이 주로 초기 3D 중심 콘솔 게임에 집중되는 건 아쉬움. Quake 열성 팬이지만, 저해상도 텍스처에 흐릿한 이중 선형 필터링을 결합한 화면은 쉽게 좋아하기 어려움. 아마 세대 차이인 듯함.
나도 3D 게임에는 꽤 까다로운 편이지만, GameCube 세대는 3D를 중심으로 설계된 게임기의 두 번째 세대였고, 잘 팔린 게임 대부분은 기존 장르에 눈을 찌를 듯한 3D 물체만 얹은 수준을 벗어났음.
그렇다고 내가 그 게임들을 좋아했다거나 2D였어도 더 낫지 않았을 거라는 뜻은 아님. 다만 그래픽이 게임의 재미를 방해하지 않는 단계에는 도달했다고 봄. 한편으로는 주인공이 큼직한 픽셀 덩어리에 불과한 Atari 2600 게임도 많이 즐겼음.
RE4는 초기 3D 게임으로 보기 어려움. Quake보다 거의 10년 뒤에 나온 GameCube 후기 작품임. 2D 디컴파일도 있으며, 가장 큰 사례로는 Pokémon Red/Blue가 떠오름. 다만 어셈블리보다 고급 언어로 작성된 게임이 많은 3D 콘솔에서 디컴파일의 의미가 더 클 수 있음.
N64 게임 등은 에뮬레이션 품질이 그리 좋지 않았음. 다른 플랫폼에서 마침내 쾌적하게 플레이하려는 동기는 충분히 이해됨.
HD 텍스처 프로젝트도 많이 있음.
저작권이 있는 작품을 디컴파일한 결과물에 CC0라니, 그렇게 되는 게 아님. 2차적 저작물이므로 원본의 저작권이 따라옴. 디컴파일이 늘 저작권자가 신경 쓰느냐에 달린 회색지대였던 데는 이유가 있음.
디컴파일 자체도 충분히 창의적인 과정이므로 자신의 저작권도 추가로 생길 수 있음. 하나의 작품에 저작권자가 여러 명일 수 있음. 이런 방식을 피하는 주된 이유는 실제로 무효라서가 아니라, 원저작권자가 소송을 걸고 싶어 하지 않도록 하기 위해서임.
byte-identical 은 Claude가 즐겨 쓰는 표현 중 하나임.
README 전체에서 Claude 특유의 빽빽한 문체가 문장마다 드러남.
그게 무슨 문제인가? AI는 나를 비롯한 많은 사람의 생산성을 높여 준 도구이며, 앞으로 더 좋아지고 강력해질 것임.
CC0 라이선스가 문제를 일으키지 않길 바라지만, 디컴파일한다고 Capcom의 저작권이 사라지지는 않으니 그럴 가능성도 있음. Capcom이 더는 신경 쓰지 않기를 바라는 수밖에 없을지도 모르겠음.
이 프로젝트 덕분에 언젠가 나 같은 시각장애인도 플레이할 수 있는 버전이 나올지도 모르겠음. 바이브 코딩을 하는 시각장애인들이 디컴파일된 게임의 접근성을 높이는 작업을 많이 진행하고 있음.
README 문체로 보아 AI의 도움을 받은 듯하지만, 나는 상관없음. 시간이 갈수록 AI 사용 여부보다 프로젝트의 품질이 더 중요해질 것임.
AI의 도움을 특별히 드러내지 않고 활용하는 일이 점점 보편화되고 있음. 강경한 회의론자들도 조용히 반대를 줄여 갈 것으로 봄. 잘 쓰는 사람이든 못 쓰는 사람이든 AI 사용 사실을 굳이 알리지 않으려는 경향이 있으며, 잘 활용하는 사람은 무조건 반대하는 이들에게 자신을 해명할 필요를 느끼지 않음.
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기