PS2 게임을 웹어셈블리로 정적 재컴파일해 브라우저에서 실행
원제 Show HN: PS2 games statically recompiled to WebAssembly
139 포인트댓글 70
Key Point
에뮬레이터 없이 PS2 게임을 웹브라우저에서 원본 해상도의 2~3배로, 정상적인 속도(50~60fps)로 실행하는 기술이 실현되었으며, 기계 코드 정적 재컴파일이라는 접근법이 성능과 정확도를 동시에 달성했다.
핵심 요약
- PS2 게임의 Emotion Engine 기계 코드를 미리 C++로 번역하고 WebAssembly로 컴파일해, PS2 OS와 하드웨어를 재구현한 코드와 링크해 브라우저에서 에뮬레이터 없이 실행한다.
- 첫 타이틀인 Gran Turismo 4는 벡터 유닛과 정확한 부동소수점 처리, 팔레트 트릭 등 PS2의 까다로운 기능을 활용하며, 50fps로 풀속도로 재생되고 브라우저 메모리 카드에 저장된다.
- God of War II는 같은 스크립트로 포팅되었고, 재컴파일러와 벡터 유닛 타이밍의 버그, 입출력 프로세서의 누락된 기능들을 발견해 수정했으며, 60fps의 전투 성능을 낸다.
- 게임 실행 파일의 제어 흐름을 추적해 16KiB 단위로 C++를 생성하며, R5900의 128비트 레지스터, 멀티미디어 명령어, 분기 지연 슬롯, PS2의 부동소수점 유닛(무한대/비정규수 없음)을 유지한다.
- PS2 커널은 고수준 에뮬레이션으로 스레드, 세마포어, DMA와 수직동기화 인터럽트를 처리하며, 입출력 프로세서의 R3000 CPU는 인터프리터로 실행되고, 디스크는 HTTP Range 요청으로 스트리밍된다.
- 벡터 유닛 1의 마이크로프로그램은 테스트 실행 중 발견된 것들을 SIMD C++로 미리 컴파일하고, 처음 만난 프로그램은 몇 밀리초 안에 WebAssembly 모듈로 변환된다.
- Graphics Synthesizer의 4MB 비디오 메모리는 GPU의 네이티브 스위즐 레이아웃으로 유지되며, WebGPU 컴퓨트 셰이더로 삼각형을 타일로 분류하고 GS의 텍스처, 팔레트, 알파 블렌딩, 깊이 테스트 규칙으로 래스터화한다.
- 내부 해상도를 1배~3배로 설정 가능하며, 소프트웨어 래스터라이저가 GPU 출력의 기준이 된다.
- SPU2 오디오는 48개 음성의 ADPCM과 ADSR 엔벨로프로 재구현되고, IPU는 MPEG-2 디코더로 영상을 처리한다.
- 초기에는 3fps로 실행되다가, WebGPU 컴퓨트 셰이더 전환과 벡터 유닛 컴파일로 70fps에 도달했고, GPU 렌더러의 컴퓨트 디스패치를 650개에서 80개로 줄이고, 16MB 텍스처 캐시로 프레임당 데이터를 60% 감소시켰다.
- 3배 해상도에서 처음엔 23fps였지만, 셰이더 최적화와 업로드 분할 개선으로 48~50fps를 달성했으며, MessageChannel을 통한 yield로 브라우저 스케줄링을 안정화했다.
- port.sh 스크립트가 ISO 이미지를 웹 페이지로 변환하며, 정적 분석으로 찾지 못한 함수들을 동적 실행으로 보충하고 벡터 유닛 마이크로프로그램을 기록한다.
- Chrome과 Edge에서 WebGPU 지원(Windows/macOS, Linux는 플래그 활성화), 키보드 매핑(Z=크로스, X=원, A=스퀘어, S=삼각형, 화살표=D패드), 게임패드 API 지원으로 L2/R2 아날로그 트리거와 진동 기능을 제공한다.
- SDL2를 설치하면 네이티브 실행도 가능하며, 메모리 카드는 PCSX2 형식의 .ps2 파일로 내보낼 수 있고, SharedArrayBuffer로 인해 교차 출처 격리(CORP 헤더) 필요하다.