나는 Pokemon Yellow를 TypeScript로 완전히 다시 작성했습니다 — 브라우저에서 실행되는 방법
Source: Dev.to
몇 달 동안 포켓몬 옐로우를 TypeScript로 처음부터 다시 작성했습니다. 이것은 에뮬레이터가 아니라 Z80 어셈블리를 HTML5 Canvas로 한 명령어씩 포팅한 완전한 재구현입니다.
여기서 플레이 (본인 ROM을 사용) | 소스 코드
Overview
전체 엔진은 약 280 KB의 TypeScript로 이루어져 있습니다. 게임 에셋은 전혀 포함되지 않으며, 모든 데이터는 브라우저에서 직접 사용자의 ROM 파일에서 추출됩니다. ROM은 절대 사용자의 컴퓨터를 떠나지 않으며, 배포용 빌드에는 엔진만 포함되고 저작권이 있는 콘텐츠는 전혀 들어 있지 않습니다.
Engine Architecture
ROM Validation & Extraction
- 업로드된 ROM을 SHA‑1 해시로 검증합니다.
- 원시 바이너리 데이터를 파싱하는 14개의 특수 추출기를 실행합니다:
- 포켓몬 스탯, 기술 데이터, 지도 레이아웃, 대화 텍스트, 트레이너 파티, 오디오 시퀀스.
Graphics Decompression
- 원본 압축 알고리즘(RLE + 비트‑페어 인코딩 + 델타 디코딩)을 사용해 1세대 스프라이트를 압축 해제합니다.
- Game Boy VRAM 포맷의 1bpp/2bpp 타일 그래픽을
ImageData형태로 디코딩합니다.
Caching
- 추출된 모든 데이터를 IndexedDB에 캐시하여 재방문 시 즉시 로드됩니다.
Assembly to TypeScript Translation
원본 게임은 Sharp LR35902(Game Boy CPU)에서 실행됩니다. 이를 포팅한다는 것은 다음과 같은 어셈블리를 변환하는 것을 의미합니다:
Audio1_CalculateFrequency:
ld a, [wChannelOctave]
inc a
cp 7
jr z, .done
sra d
rr e
jr .loop
TypeScript로 변환하면 다음과 같습니다:
function calculateFrequency(octave: number, freq: number): number {
let d = (freq >> 8) & 0xFF;
let e = freq & 0xFF;
for (let a = octave + 1; a > 1) | (d & 0x80)) & 0xFF; // SRA (arithmetic shift)
const carry = d & 1;
e = ((carry > 1)) & 0xFF; // RR (rotate right through carry)
d = newD;
}
return (d << 8) | e;
}
모든 디테일이 중요합니다— 논리 시프트(SRL)를 산술 시프트(SRA) 대신 사용하면 음악의 피치가 바뀝니다. 저는 이 실수를 두 번이나 했습니다.
Audio Synthesis
- Game Boy에는 네 개의 사운드 채널(두 개의 펄스, 하나의 프로그래머블 웨이브, 하나의 노이즈)이 있습니다.
ScriptProcessorNode기반 신시사이저를 구현해 44.1 kHz로 샘플을 생성하고 네 채널을 모두 에뮬레이션합니다.- 음악 엔진은 59.7 Hz(Game Boy VBlank 레이트와 동일)로 틱을 돌며 ROM에서 추출한 명령 시퀀스(템포 변화, 음표 이벤트, 듀티 사이클 전환, 비브라토, 피치 슬라이드)를 해석합니다.
- 50개 이상의 음악 트랙과 37개의 사운드 효과를 완전하게 재생할 수 있습니다.
Battle System Accuracy
배틀 시스템은 1세대의 악명 높은 버그들을 충실히 재현합니다:
- Focus Energy 버그 – 치명타 확률이 곱해지는 대신 4로 나뉩니다.
- 1/256 미스 글리치 – 정확도 100 %인 기술도 약 0.4 % 확률로 빗나갑니다.
- 배지 스탯‑부스트 누적 – 화상/마비 감소가 배지 부스트를 매번 다시 적용해 오버플로우가 발생합니다.
334개의 배틀 테스트 스위트를 통해 모든 엣지 케이스가 원본 게임과 일치함을 검증했습니다.
Demo Features
- 피카츄가 움직이는 타이틀 화면과 전체 음악.
- 오박사 소개 시퀀스.
- 팔렛 타운 → 루트 1 → 버시안 시티(12개 지도).
- 완전한 1세대 메커니즘을 갖춘 야생 및 트레이너 배틀.
- 행복도 시스템을 가진 피카츄 팔로워.
- 포켓덱스, 파티 메뉴, 아이템, 상점, PC, 저장/로드.
- 모바일/태블릿용 터치 컨트롤.
실제 데모에서는 합법적으로 얻은 ROM을 업로드하면 데스크톱과 모바일 모두에서 브라우저로 플레이할 수 있습니다.
Technical Details
- TypeScript + HTML5 Canvas – 프레임워크·의존성 없음.
- Vite를 사용한 빌드.
- Vitest를 이용한 테스트(375개).
- 약 35 000줄의 TypeScript 소스 코드.
Repository & License
- GitHub – MIT 라이선스. PR 환영.
- Claude Code와 함께 코딩 파트너로 활용해 제작했습니다.