DOS Wing Commander 리버싱 10년, 메모리 주소 13D3:A9C2 찾아 협동 플레이 구현
- 2015년 DOSBox에서 Wing Commander를 하다 게임 상태가 64K 데이터 세그먼트에 모두 들어간다는 걸 깨닫고, 정지 및 이동 스냅샷을 교차 비교해 후보 바이트를 413개에서 132개로 좁혀 플레이어 좌표 13D3:A9C2를 찾아냄
- 64개 슬롯 배열(슬롯당 12바이트)에서 카메라가 엔티티 슬롯 0x3D에 있고 같은 값이 0x2DC 바이트 떨어진 곳에 복사돼 있어 좌표와 속도가 두 번 나타남
- 게임 함수에 호출을 주입하고 게임 상태를 네트워크로 동기화해 형제와 스토리 미션을 함께 비행하는 협동 플레이를 구현, 브라우저 DOSBox에서 바로 실행 가능
- TCP 네트워킹 스택을 WebRTC로 포팅하고 음성은 게임 패킷과 혼잡이 엮이지 않도록 별도 데이터 채널로 분리
- Wing Commander 게임 파일은 호스팅하지 않아 설치 파일을 직접 드래그해야 하고, 없으면 오픈소스 RetroVega(Vega Strike 기반)를 로드함
Hacker News opinions
2015년에 DOSBox로 Wing Commander 하다가 게임 상태가 64k 데이터 세그먼트에 다 들어간다는 걸 알았어. 10년 동안 정지, 이동, 회전, 통신 실험을 돌리면서 변수 위치랑 함수 호출 주입, 네트워크 동기화를 다 알아냈고. 카메라가 엔티티 슬롯 0x3D에 있는 게 원작자들의 3D 장난 같아서 제일 마음에 듦. 지금 로비에 있으니 같이 날 사람 오면 좋겠다.
도메인 전문가가 길을 다 뚫어놓고 AI로 구현을 자동화하는 건 진짜 멋진 활용법이지. 설계는 사람이 하고 반복 작업은 AI한테 맡기는 거.
결과도 대단한데 10년 동안 계속 이 문제로 돌아온 집념이 더 놀랍다.
Go는 multipath tcp 사건 이후로 다시 믿기가 어렵더라.
그건 리눅스 커널 버그였고 Go 문제가 아님. 원하면 lobbylink를 러스트로 포팅해줄 수 있는데 외부 인터페이스는 비슷할 거야.
음성은 왜 데이터 채널로 보내? WebRTC 스트림 쓰면 되는데.
혼잡 결합이 걸려서 일부러 분리했어. 음성이 버스트해질 때 게임 패킷이 밀리면 안 되니까 게임 데이터에 우선순위를 주려고.
8비트 시절에 세이브 파일에서 한 번에 하나씩 바꿔보고 뭐가 달라지는지 보면서 인벤토리, 스탯, 퀘스트 단계 주소를 다 찾아내던 것과 같은 방식이네. WozMon으로 램 값 직접 고쳐서 무료 힐링도 썼고.
Sim City 세이브에서 돈이 어떤 정수인지 찾아낸 기억 난다. Star Trek Armada 2 빌드 순서를 고쳐서 보그 AI를 3명 상대로도 못 이길 수준으로 만들었던 것도.
WozMon은 처음 듣는데 나는 Game Wizard 쓰던 세대였음.
치트를 막을 이유가 뭐가 있나 싶다. 어차피 게임 전체를 리버싱당하는데 난독화로 작업만 불편해지지. 비기술 C레벨이 시키는 대로 잠그는 거겠지.
이 접근법으로 다른 게임도 만들 수 있나?
Privateer나 X-Wing, TIE Fighter도 노릴 수 있어. 근데 사람들은 원클릭 플레이를 원해서 설치 파일 찾아서 1990년 향수를 겪는 것보다 오픈소스 RetroVega를 더 선호하더라. 아무도 안 하면 옛 게임 살리는 데 시간 쓰는 게 의미가 있나 싶기도 하고.
DOSBox 안 쓰고 네이티브 ARM64랑 WASM으로 돌리는 비슷한 프로젝트도 있다(wc-decomp). 멀티플레이는 아직 기초 수준.
CheatEngine을 dosbox 프로세스에 붙여서 바뀐 영역만 찾으면 되지 않나. 실제 메모리 시작점 기준 오프셋을 못 구하는 문제는 덤프랑 비교하면 되고.