정보기술 · 실감형콘텐츠 ·
디버그 심볼 없이 N64 게임 분석...개발자, 디컴파일 과정 공개
호주 개발자, 레트로 게임 '스노보드 키즈 2' 역공학 과정에서 디버깅 기법 상세히 소개
[한국정보기술신문] 호주의 소프트웨어 개발자 크리스 루이스가 닌텐도64 게임 '스노보드 키즈 2'의 디컴파일 프로젝트를 진행하면서 디버그 심볼 없이 레트로 게임을 분석하는 과정을 상세히 공개해 주목받고 있다.
루이스는 지난 23일 자신의 블로그를 통해 N64 에뮬레이터와 GDB 디버거를 활용한 게임 분석 워크플로우를 공개했다. 그는 특히 게임 내 크리스마스 테마 레벨인 '징글 타운'이 어떻게 로드되는지를 추적하는 과정을 예시로 제시했다.
디버그 심볼 부재의 난제
일반적인 소프트웨어 디버깅에서는 컴파일러가 생성한 디버그 심볼을 통해 소스코드와 메모리 주소를 매핑할 수 있다. 하지만 디컴파일 초기 단계에서는 디버그 정보를 추가하면 기존 코드와 데이터의 메모리 주소가 변경되어 게임이 부팅조차 되지 않는 문제가 발생한다.
루이스는 원본 게임이 컴파일될 때 모든 주소가 고정되어 있으며, 점프 테이블과 함수 호출이 0x80052334와 같은 절대 주소를 참조한다고 설명했다. 디버그 정보 추가로 인한 섹션 이동은 이러한 절대 참조를 무효화시켜 게임을 실행 불가능하게 만든다.
GDB와 Ares 에뮬레이터 활용
루이스가 구축한 디버깅 환경은 세 가지 핵심 구성요소로 이루어져 있다. MIPS 아키텍처를 지원하는 GDB 멀티아키텍처 버전, 사이클 정확도에 중점을 둔 N64 에뮬레이터 Ares, 그리고 원격 디버깅을 위한 SSH 터널이다.
N64는 MIPS CPU를 사용하기 때문에 일반 GDB 대신 여러 아키텍처를 지원하는 gdb-multiarch를 사용해야 한다. Ares 에뮬레이터는 성능보다 정확성을 우선시하며 GDB 원격 디버깅을 기본 지원한다.
루이스는 우분투 서버에서 개발하고 맥에서 Ares를 실행하기 때문에 SSH 역방향 터널을 통해 GDB 클라이언트와 서버를 연결했다. GDB를 MIPS 4000 아키텍처로 설정하고 디컴파일 프로젝트가 생성한 ELF 파일을 로드한 후 Ares에 연결하는 방식이다.
레벨 로딩 메커니즘 추적
디버깅 환경 구축 후 루이스는 게임이 어떻게 레벨별 오버레이를 결정하는지 분석했다. N64에서 오버레이는 메모리 절약을 위해 런타임에 로드되고 언로드되는 코드 청크를 의미한다.
그는 16개의 오버레이 중 하나를 로드하는 것으로 보이는 함수를 발견했다. 이 숫자가 스노보드 키즈 2의 레벨 수와 일치한다는 점에 주목해 해당 함수에 중단점을 설정하고 테스트를 진행했다.
첫 번째 레벨인 써니 마운틴을 로드했을 때 관련 바이트 값이 0이었고, 터틀 아일랜드는 1, 징글 타운은 2로 나타났다. 이를 통해 해당 함수가 실제로 레벨별 코드와 초기화 로직을 로드한다는 가설을 검증했다.
루이스는 이러한 수동 작업 과정이 효과적이지만 시각적 디버깅 경험이 개선될 여지가 있다고 언급했다. 그는 디버거가 바이너리를 변경하지 않고 외부 생성된 디버그 심볼을 참조할 수 있는 방법에 대해서도 의문을 제기했다.
디컴파일 프로젝트의 진전
루이스는 스노보드 키즈 2 디컴파일 프로젝트가 개별 명령어 수준이 아닌 레벨 초기화와 같은 상위 레벨 게임 동작을 이해할 수 있는 단계에 도달했다며 만족감을 표했다.
그는 프로젝트가 점진적으로 메모리 고정 위치 참조를 제거하고 있으며, 이 과정이 완료되면 최신 버전의 GCC와 전체 디버깅 기능을 사용할 수 있는 쉬프터블 빌드가 가능해진다고 설명했다.
디컴파일 프로젝트는 깃허브에서 오픈소스로 공개되어 있으며, 관심 있는 개발자들의 참여를 기다리고 있다. 루이스는 블루스카이를 통해 프로젝트 업데이트를 지속적으로 공유하고 있다.
레트로 게임 보존과 역공학 분야에서 이러한 상세한 기술 문서 공개는 유사한 프로젝트를 진행하는 개발자들에게 귀중한 참고 자료가 될 것으로 평가된다.
한국정보기술신문 실감형콘텐츠분과 장용빈 기자 news@kitpa.org