- 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세계 콘텐츠를 매우 정확하게 재현하는 데 큰 가치가 있음