1998년 Ultima Online 데모 서버 역공학
(draxinar.github.io)- OUO는 1998년
Ultima Online데모 서버를 완전히 리버스 엔지니어링한 프로젝트로, MSVC x86 바이너리의 약 5,000개 함수를 디스어셈블해 휴대 가능한 C99로 옮김 UoDemo.exe는Ultima Online: The Second Age첫 릴리스에 포함된 독립 실행형 데모였고, 클라이언트와 Windows로 포팅된 전체 서버 코드·데이터를 함께 담고 있었음- 각 함수는 원본 바이너리와 명령어 단위로 비교됐으며, 클래스 계층과 vtable 레이아웃을 맞춘 뒤 원본과 같은 제어 흐름·구조체 레이아웃·분기를 유지하도록 수동 변환됨
- 복원본은 1998년 중반 실제 라이브
Ultima Online서버 코드에 가깝지만, 충돌·오버플로·초기화되지 않은 변수 같은 안정성 문제와 스킬 상승·스폰 밀도 같은 게임플레이 문제가 태그와 함께 수정돼 있음 - 원래 데모는 클라이언트 1.25.33만 지원했지만, 복원본은 1.25.30부터 5.0.9.1까지의 클라이언트를 암호화 유무와 관계없이 지원하며, 1997~2003년 서버 데이터 파일도 요청 중
데모 파일의 출처와 범위
- 각 함수는 원본 바이너리와 명령어 단위로 비교됐으며, 10년에 걸친 간헐적 작업 끝에 최근 LLM 발전으로 마무리할 수 있었음
UoDemo.exe의 날짜는 1998-09-02이며, 서버 데이터는 1998년 6월 2일 운영 서버에서 추출된 것이었음- 데모용으로 일부 기능이 스텁 처리되고 플레이 가능한 지도는 Ocllo 섬으로 줄었지만, 나머지는 1998년 중반 실제 라이브
Ultima Online에서 돌던 운영 서버 코드였음 Ultima Online은 Origin Systems Inc.가 개발한 1997년 MMORPG였고, 상업적으로 성공한 초기 MMORPG 중 하나였음- Windows에서 클라이언트가 실행됐고, 서버인 “shards”는 여러 Solaris 머신에서 돌아갔으며 지도는 지역별로 나뉨
- 데모는 Ocllo 섬에서 드래곤을 죽이는 간단한 퀘스트를 제공했고, 대화, 거래, 전투 등 기본 게임 메커니즘을 둘러볼 수 있게 구성됨
- 여러
UO서버 에뮬레이터가 이 데모의 일부를 재사용했지만, 지금까지 완전히 역공학한 경우는 없었음 UoDemo.exe는 Microsoft Visual C++ 5.0, 즉 Visual Studio 97로 컴파일됐고, C++98 이전 방언의 C++를 대상으로 했음
역공학 방법
-
디스어셈블과 심볼 추정
- 디스어셈블에는 radare2를 사용함
- 심볼 이름은 C++ 심볼이 포함된 실험적 Linux 포트
UO클라이언트 1.25.37에서 유추함
-
C99 수동 변환
- 각 함수는 원본 바이너리와 같은 제어 흐름, 구조체 레이아웃, 분기를 유지하도록 손으로 C99로 번역됨
- 차이가 있는 부분은 데모의 실제 버그 수정 또는 플랫폼 적응이며, 소스에 표시돼 있음
-
검증 방식
- C 빌드를 다시
r2로 디스어셈블해 원본과 비교함 - 두 결과가 일치할 때만 함수가 완료된 것으로 표시됨
- 헬퍼 함수는 반복되는 인라인 패턴에만 쓰였고, 헬퍼가 인라인 버전과 같은 코드로 다시 확장될 때만 사용됨
- C 빌드를 다시
-
클래스 계층 복원
- 초기에 가장 중요했던 작업은 클래스 계층을 정확히 맞추는 것이었음
- 핵심 계층은
CEntity (0x10) -> CResourceEntity (0x1C) -> CItem (0x50) -> CContainer (0x5C) -> CMobile (0x37C) -> CPlayer (0x458)였음 - 가상 디스패치는 vtable 슬롯을 통해 이뤄졌고, 예를 들어
vtable[0x18]은IsPlayer,[0xD0]은IsMobile,[0xE4]는IsNPC였음 - 이 레이아웃이 확정된 뒤에는 바이너리 대부분을 비교적 직접적으로 번역할 수 있었음
복원 결과와 원본과의 차이
- 결과물은 1998년
Ultima Online서버의 거의 완벽한 복제에 가깝지만, 일부 차이가 있음 - 원본 코드 대비 충돌, 오버플로, 초기화되지 않은 변수 같은 안정성 문제가 수정됨
- 스킬 상승, fame/notoriety 방향, 스폰 밀도 같은 게임플레이 문제도 고쳐짐
- 각 수정은 소스에 태그가 붙어 있어,
UoDemo.exe와 비교하는 사람이 무엇이 왜 바뀌었는지 정확히 확인할 수 있음 - 스폰 시스템과 decay 시스템 같은 일부 기능은 깨져 있었고, 데모 릴리스를 위해 부분적으로 비활성화되거나 스텁 처리됐을 가능성이 있음
- 해당 기능들의 코드는 남아 있었지만 라이브 호출 지점이 도달하지 않았고, 따로 디컴파일한 뒤 디스패치를 다시 연결하는 것만으로 동작시킬 수 있었음
- 게임 지도는 Ocllo 섬만 담는 등 일부 데이터가 빠져 있었음
- 서버 데이터 포맷을 조작하는 전체 도구 모음을 만들었고, 나머지 세계의 문, 표지판, 장식, 텔레포터, 함정, 상자, 스폰 위치를 완전히 재구성함
남아 있던 생태계 시스템
- 은퇴한 유명한 ecology system은 함수 호출이 끊긴 상태였지만 코드 안에 여전히 남아 있었음
- 포식자, 먹이, 청소동물 시스템을 다시 연결해 늑대가 토끼를 쫓거나 까마귀가 아이템을 먹는 모습을 볼 수 있게 됨
- 다만 정확한 데이터가 부족해 전체 자원·생산 시스템까지 구현하지는 않음
- 관련 배경 자료로 Raph Koster의
UOecology system 및UO자원 시스템 글 1, 2, 3가 연결돼 있음
추가 기능과 클라이언트 호환성
- OSI가 1999년 2월 추가한 Meditation, Stealth, Remove Trap 스킬이 새로 들어감
- 이 기능들의 일부 초기 흔적은 이미 코드에 남아 있었음
- 대부분의 새 기능은 시작 시
-features매개변수로 켜거나 끌 수 있음 - 데모 서버에는 계정 시스템이 완전히 없었기 때문에, 원 개발자들이 구현했을 방식을 추정해 약간 현대화된 형태로 다시 구현함
- 원래 데모 서버는 클라이언트 1.25.33만 지원했지만, 1.25.30부터 5.0.9.1, 즉 2007-03-27까지의 모든 클라이언트를 암호화 유무와 관계없이 지원하도록 확장됨
- 여러 해 동안 완전히 다른 암호화 방식이 다섯 가지 있었기 때문에, 각 방식을 클라이언트 바이너리에서 역공학해야 했음
32비트 원본과 64비트 기본 빌드
- 원본 바이너리는 32비트였지만, 현재 기본 빌드는 64비트를 대상으로 함
- 클래스 계층은 C 구조체 임베딩으로 원래 C++ 상속을 재현함
- 이 방식 덕분에
CMobile*을CContainer*가 필요한 곳에 전달할 수 있음 - 64비트에서 포인터 폭이 넓어지면 상속된 필드 위치가 밀릴 수 있기 때문에, 일부 구조체는 32비트와 64비트 모두에서 상속 및 vtable 레이아웃이 바이너리와 맞도록 의도적으로 패딩됨
공개 리소스
- https://github.com/draxinar/ouo: 코드
- https://github.com/draxinar/rundir:
UoDemo.dat기반 데이터, 수정, 완성된 데이터, 새 기능 포함 - https://uo.serpent-isle.com/: Test Center, 실제 shard는 아니며 1998년
Ultima Online서버에 매우 충실한 재현을 시험할 수 있는 환경 - UO:98: Batlin과 Derrick의 프로젝트로, 2016년에 이 작업을 시작하게 만든 영감의 출처
OUO는 아직 초기 단계이며 문제가 남아 있을 수 있음- 발견한 문제는 issue로 보고할 수 있고, 기여도 환영됨
Ultima Online 커뮤니티에 대한 요청
- 1997~2003년 무렵 원래
Ultima Online서버의dynamic0.mul,dynamic0.bkp,regions.txt,resbank.mul파일을 가진 사람이 있다면 전달을 요청함 dynamic0.mul과dynamic0.bkp는 서버 저장 파일이고,regions.txt는 스폰 정의,resbank.mul은 자원 정의 파일임- 원본
dynamic0.mul이나dynamic0.bkp가 완전히 사라졌을 가능성은 낮아 보임 dynamic0.mul파일에서 플레이어 데이터를 제거해 개인정보를 보존한 뒤 배포할 수 있는 도구는 이미 갖춰져 있음- 이 파일들은
Ultima Online세계 콘텐츠를 매우 정확하게 재현하는 데 큰 가치가 있음
Hacker News 의견들
-
원본 Ultima Online 서버의 dynamic0.mul, dynamic0.bkp, regions.txt, resbank.mul 파일을 가진 사람이 있다면 보내주면 정말 고마울 듯함
1997~2003년 무렵 서버 저장 게임, 스폰 정의, 리소스 정의 파일이고, 특히 dynamic0.mul이나 dynamic0.bkp가 여러 안전한 장소에 백업됐을 테니 완전히 사라졌다고 보긴 어려움
이 파일들은 Ultima Online 세계 콘텐츠를 매우 정확하게 재현하는 데 극도로 가치 있음 -
정말 멋짐. 마침 옛 Ultima 게임 사운드트랙을 듣고 있다가 이걸 봤다는 게 신기함
원본에서 쓰던 C++98 이전 C++ 방언으로 디스어셈블리 결과를 작성하고 원래 컴파일러를 대상으로 삼는 걸 고려했는지 궁금함
빈티지 시스템에서 돌던 바이너리를 디스어셈블한 적이 있는데, 가능했다면 원래 툴체인을 목표로 했을 것 같음. 꽤 흥미로운 철학적 질문임 -
eqclassic의 마지막 생존 개발자로서 흥미롭게 읽었지만, 도구를 어떻게 썼고 전체 과정이 어땠는지에 대한 더 깊은 이야기를 기대했음. 그래도 좋은 글임
당시에는 LLM이 없었지만, 3년 뒤의 PowerPC 바이너리에서 나온 일부 디버그 심볼이 있어서 조금 도움이 됐음
packet_handler나 entitylist 같은 파일 이름이 묘하게 익숙함 :D
마지막 관문은 나머지를 다듬기 전에 사실상 완벽한 네트워크 코드를 갖추는 일인데, 이미 여기에 수백 시간을 날렸음
소스를 조금 훑어봤을 뿐이지만, 전부 TCP 기반이라 그 위에 별도의 신뢰성 메커니즘을 얹은 것 같지는 않아 보임. 그렇다면 당시 MMO치고는 꽤 “느린” 선택처럼 느껴져서 흥미로움 -
UO를 해보고 싶은 사람이라면 아직도 활성 플레이어 기반이 있는 게임. UO Outlands 같은 서드파티 서버는 원래 게임플레이에 더 가까운데, 요즘 MMO에 익숙한 기준으로는 꽤 가혹함
다른 플레이어가 와서 갱킹할 수 있고 장비를 잃을 수도 있음
지금도 해당 서버에 2500명 이상이 접속 중이라 여전히 매우 활발함- UO Outlands는 원래 UO보다 운영이 더 잘되는 느낌임. Discord도 꽤 활발하고 사용자가 약 2만 명쯤 있음
-
내 첫 진짜 프로그래밍 성취는 Ultima Online 샤드 웹사이트를 만든 일이었음
형편없는 PHP와 HTML을 썼지만, 이후 20년 넘게 동작했음. 좋은 추억임
UO 주변에 아직도 활발한 커뮤니티가 있다는 점이 놀라웠고, 어쨌든 이 프로젝트는 정말 멋짐- 비슷하게 웹사이트 제작을 돕고, 포럼 설치를 관리하다가, 샤드를 운영하던 사람들이 나중에는 에뮬레이터 코드도 맡겨줬음
당시 12~13살이었고 90년대 말~2000년대 초였음. 에뮬레이터 이름은 이제 기억나지 않지만 아마 POL이었을 가능성이 큼
샤드의 목표는 UO:Renaissance 이전 공식 서버에 최대한 가깝게 만드는 것이어서, T2A처럼 보이고 느껴지게 하려고 꽤 많이 작업했음
많은 걸 배웠고, 이후 RunUO가 나오고 2003년쯤 어느 정도 안정화되자 POL에서 만든 것들을 RunUO용 C# 코드로 옮기는 작업도 도왔고, 따라가려면 더 많이 배워야 했음
그 샤드에서 함께 일하던 사람들은 모두 대학에서 컴퓨터과학을 공부하거나 이미 프로그래머로 일하고 있었고, 나는 스크립트 몇 개 쓸 줄 아는 어린애였음
이 경험이 나중에 프로가 되는 데 결정적이었다고 봄. 실제 기술 회사에서의 첫 직장도 그중 한 명이 인턴 자리가 났을 때 추천해줘서 얻게 됨
어떤 의미에서는 UO와 사설 샤드 덕분에 지금의 커리어가 생긴 셈임 - 내 경우는 UOInject라는 보조 도구로 광석 채굴을 자동화한 것이 시작이었음. 그 언어는 Visual Basic이었던 것 같음
순전히 필요해서 프로그래밍을 시작했음 - MMO나 온라인 게임이었다면 사설 서버 커뮤니티는 끝없이 생김
게임 이름은 잊었지만 아마 City of Heroes였던 것 같고, 몇 년 동안 종료돼 있다가 어느 날 누군가 사설 서버를 다시 띄웠음
예전 Shockwave 온라인 게임들도 틈새 커뮤니티가 서버를 재구축하고, Shockwave 런타임과 디컴파일러를 만들고 있음
서로 비슷한 문제를 풀다 보니 게임 간 커뮤니티도 겹침 ;) - 나도 첫 진짜 프로그래밍 성취가 Ultima Online 샤드 웹사이트였음
두 번째는 지도를 바꾸는 일이었고, 정적 아이템 제거, 새 섬과 건물 추가 같은 걸 했음
세 번째는 verdata.mul을 바꿔 새 애니메이션과 아이템 그래픽을 추가하는 일이었음
비공식 POL 서버에서 Ultima Online을 한 덕분에 말 그대로 IT에 들어오게 됐음. 그전에는 회계사가 되려고 공부하고 있었음 - 내 첫 웹사이트는 Chesapeake의 내 길드용이었고, 각종 스킬을 매크로로 올리는 스크립트를 엉성하게 만든 것이 첫 “실제 프로그래밍” 프로젝트였음
이것 때문에 처음 IRC에 들어갔고, 나중에는 freenode까지 이어졌음
- 비슷하게 웹사이트 제작을 돕고, 포럼 설치를 관리하다가, 샤드를 운영하던 사람들이 나중에는 에뮬레이터 코드도 맡겨줬음
-
UO 에뮬레이터 씬이 나를 네트워크 프로그래밍으로 이끌었음
온라인 게임 중에서 이렇게 많은 부수적·창발적·우연적 게임플레이 메커니즘을 잘 담아낸 사례를 본 적이 없음
이후 3D MMO들은 UO가 제공했던 흥미로운 경제, 건축, 탐험 요소를 많이 낮춰버린 것 같음
PvP나 퀘스트류는 다른 게임들이 더 나을 수 있지만, UO는 여전히 매력적이었고 혼자 하거나 그룹으로 하거나 낯선 사람과 가볍게 상호작용하다가 기분에 따라 자연스럽게 전환할 수 있었음- 아쉽게도 두 가지가 사실로 드러났음
대부분의 사람은 이런 걸 원하지 않고 정해진 레일 위에 있는 걸 선호함
그리고 이런 게임에 가장 끌리는 두 집단은 한쪽이 있으면 다른 한쪽이 게임을 떠나는 역학에 빠짐. 그런데 두 번째 집단은 첫 번째 집단이 플레이하기를 필요로 함 - 몇몇 오래된 3D MMORPG는 그런 메커니즘을 넣으려 했음
예를 들면 Asheron's Call은 모드 커뮤니티가 매우 활발했고 지금은 에뮬레이터 씬도 있음. 다만 서버 인기는 UO만큼은 아닌 것 같음
Shadowbane은 길드 중심이 강했지만, 약간 무법자처럼 굴면서 임의의 사람이나 길드와 PvP하는 재미가 있었음 - 그쪽에 기회가 있을지도 모름. 솔직히 지금 MMO 시장에는 별로 움직임이 없음
WoW, Old School RuneScape, Final Fantasy Online 정도 말고는 크게 할 만한 게 많지 않음
- 아쉽게도 두 가지가 사실로 드러났음
-
10년 동안 간헐적으로 이 프로젝트를 진행하다가, 최근 LLM 발전 덕분에 끝이 없어 보이던 작업을 마침내 완료할 수 있었다는 대목이 인상적임
나도 MFC C++ 디컴파일 프로젝트를 하고 있는데, 이런 작업에서 LLM이 말도 안 되게 유용함- 이 작업에 LLM을 자동화된 방식으로 쓰고 있는지 궁금함. 로컬인지 클라우드인지도 궁금함
-
예전에 Ultima Online을 즐겼음
최근에는 TazUO 게임 클라이언트에서 Python 스크립팅을 재미있게 하고 있음. 약간 오래된 Python 3 버전이지만 Razor나 SteamUO에서 스크립트 짜는 것보다는 훨씬 나음
조용한 싱글플레이어 샤드에서 이것저것 해보고 싶다면 Memento가 괜찮았음 -
Ultima 4 NES 버전의 스페인어 또는 프랑스어 현지화 모바일판을 찾고 있었음. 다른 작품들도 마찬가지임
FF 시리즈의 Pixel Remaster처럼 처리된 형태를 원함
현재는 에뮬레이터로만 플레이할 수 있음
텍스트가 많은 현지화 RPG는 외국어를 “놀면서 배우는” 데 아주 쉬운 방법이고, 읽기에도 좋음
이런 게 만들어지면 좋겠음 -
아, UO… 정말 좋은 추억임. 카드가 있을 나이가 아니라 Palo Alto의 Cybersmith까지 자전거를 타고 가서 선불 시간을 사던 기억이 남
예전에는 Napa Valley 샤드에서 꽤 열심히 했음. Catskills에 갈 만큼 용감하진 않았음
요즘은 UO 같은 경험이 그립지만, 그런 게임에 쏟을 시간이 도저히 없음- 왜 Catskills는 안 됐는지 궁금함. 달랐나? 더 어려운 규칙 세트가 있던 Siege Perilous를 떠올린 건 아닌가?