How to Set Up Reverse-Engineered Ultima Online Server on Linux 2025
How to Set Up Reverse-Engineered Ultima Online Server on Linux 2025
The release of the fully reverse-engineered 1998 Ultima Online demo server (ouo) in 2026 opened a unique opportunity for developers interested in legacy MMORPG architecture, binary analysis, and retro game server infrastructure. This guide walks you through compiling and running the C99 port on modern Linux systems—a significant technical achievement given the original code was Windows x86 MSVC compiled from 1998.
Why Reverse-Engineer the UO Demo Server?
The original UoDemo.exe was compiled with Microsoft Visual C++ 5.0 (Visual Studio 97) and contained approximately 5,000 functions representing actual production Ultima Online server code from mid-1998. The reverse-engineered C99 version maintains:
- Instruction-level accuracy: Each function was hand-translated and re-disassembled to verify binary equivalence
- Original class hierarchy: Preserved vtable dispatch (CEntity → CResourceEntity → CItem → CMobile → CPlayer)
- Playable game state: Full Ocllo island map with NPCs, combat, trading, and quest mechanics
For developers studying game architecture, this is invaluable reference material. For emulator developers, it provides the canonical implementation.
Prerequisites
Before starting, ensure you have:
- Linux system (Ubuntu 22.04+ or equivalent)
- Build tools: GCC/Clang, Make, autotools
- Development libraries: Standard C99 libc, platform-specific APIs
- Disk space: ~500MB for source, build artifacts, and server data
- Git: To clone the repository
sudo apt-get update
sudo apt-get install build-essential git gcc make autoconf automake libtool
Optional but recommended:
- radare2: For binary verification and disassembly comparison
- gdb: Debugging reverse-engineered functions
Step 1: Clone the Reverse-Engineered Repository
The source code is hosted at https://github.com/draxinar/ouo:
git clone https://github.com/draxinar/ouo.git
cd ouo
git log --oneline | head -20 # Verify commit history
Inspect the directory structure:
ouo/
├── src/ # C99 source files (5,000+ functions)
├── data/ # Server data files (items, NPCs, spawn tables)
├── tools/ # Data format manipulation utilities
├── Makefile
└── README.md
Key source layout:
src/entity.c: Core CEntity class and vtable dispatchsrc/item.c: CItem and CContainer implementationssrc/mobile.c: CMobile and CPlayer logicsrc/world.c: Map loading, region management (Ocllo island + reconstructed world)
Step 2: Review Platform-Specific Adaptations
The reverse-engineered code includes Windows→Linux adaptations. Critical sections to understand:
1. Virtual Function Dispatch Original vtable indices are preserved:
// From src/entity.h
struct CEntity {
void **vtable; // vtable[0x18] = IsPlayer, [0xD0] = IsMobile, [0xE4] = IsNPC
uint32_t serial; // Entity unique identifier
uint16_t graphic; // Sprite/appearance ID
// ... 0x10 bytes base size
};
2. Endianness Handling Ultime Online uses network byte order (big-endian). Check conversions:
grep -r "htonl\|ntohl" src/ # Host-to-network long conversions
3. Memory Layout Verification Each struct has explicit size assertions:
grep -r "sizeof(struct" src/ | grep -E "0x[0-9A-Fa-f]+"
Expected sizes (from original binary):
CEntity: 0x10 bytesCItem: 0x50 bytesCMobile: 0x37C bytesCPlayer: 0x458 bytes
Step 3: Compile the Server
Standard Build
./configure
make clean
make -j$(nproc)
Verification Build (with binary comparison)
To verify your compilation matches the original UoDemo.exe:
make clean
CC=gcc CFLAGS="-O2 -march=native" make
# Compare against disassembly (requires radare2)
radare2 -a x86 -b 32 ./bin/uodemo > build/disasm_new.txt
radare2 -a x86 -b 32 /path/to/UoDemo.exe > build/disasm_orig.txt
diff build/disasm_orig.txt build/disasm_new.txt | head -50
Expect minimal differences (typically platform-specific syscalls, not logic).
Step 4: Load Server Data
The demo ships with Ocllo island data extracted from the June 2, 1998 production database. The reverse-engineered source includes tools to load and manipulate this data:
# Convert and verify server data files
cd tools
./uodataconv ../data/UoDemo.dat --output ../data/processed/
# Inspect loaded world state
./worlddump ../data/processed/ --region ocllo
Critical data files:
map0.mul: Terrain heightmap for Ocllostatics0.mul: Static object placement (trees, buildings, decorations)itemid.txt: Item definitions and propertiestiledata.mul: Tile and static properties
Step 5: Run the Server
Basic Startup
./bin/uodemo --config config/default.ini
With Logging
./bin/uodemo --config config/default.ini --loglevel debug --logfile server.log
Connection Details
- Default port: 2593 (standard UO login port)
- Server address: 127.0.0.1 (local testing)
- Playable account: Username:
demo, Password:demo(bundled with data)
Verification Checklist
| Component | How to Verify | Expected Output |
|-----------|---------------|------------------|
| World load | ./bin/uodemo --dump-world | Ocllo island with 50+ NPCs |
| Item database | ./bin/uodemo --dump-items | 5,000+ item definitions |
| Spawn system | telnet localhost 2593 then observe | NPCs appear in expected locations |
| Quest state | In-game, talk to Lord British | Dragon quest available on Ocllo |
| Combat mechanics | Engage NPC in combat | Damage calculations match 1998 formulas |
Step 6: Known Fixes Applied
The reverse-engineered version includes stability improvements flagged in source comments:
Fixed issues:
- Spawn system: Originally disabled for demo; re-wired dispatch to enable persistent creature spawning
- Decay system: Reactivated item decay (was stubbed in shipping demo)
- Skill gain: Corrected formula to match production behavior
- Fame/notoriety: Fixed directional calculation (was inverted in some cases)
- Memory issues: Fixed buffer overflows, uninitialized variables (x86 assembly-level bugs)
Each fix is tagged:
grep -r "FIX:" src/ | head -20
Step 7: Extending the World
The original demo only included Ocllo island. The reverse-engineered tooling allows reconstruction of the full Britannia map:
# Reconstruct doors, signs, teleporters for remaining regions
./tools/reconstruct_world ../data/processed/ --regions all
# Verify reconstructed data
./tools/worlddump ../data/processed/ --verify-integrity
Troubleshooting
Compilation Errors
Error: undefined reference to htonl
# Link against libc network functions
CFLAGS="-D_GNU_SOURCE" make
Error: struct size mismatch (expected 0x458, got 0x450)
# Verify GCC uses same struct padding as MSVC
CC=gcc CFLAGS="-mno-ms-bitfields" make
Runtime Errors
Segfault on world load
# Enable bounds checking and logging
./bin/uodemo --config config/debug.ini --sanitize=address
NPCs don't spawn
- Check spawn system re-wiring:
grep -A 5 "SpawnMgr::Init" src/world.c - Verify data files loaded:
./bin/uodemo --dump-spawns
Performance Considerations
The 1998 code was optimized for Pentium II hardware (233 MHz). On modern systems:
- Single-threaded execution (no multithreading in original code)
- Estimated throughput: 10,000+ concurrent players on modern CPU
- Memory footprint: ~50MB for full Britannia with 1,000 NPCs
Next Steps
- Binary verification: Use radare2 to compare function-by-function against original
- Feature expansion: Study the codebase to implement missing 1998 features (PvP balancing, item rarity)
- Network analysis: Extend to handle modern UO client versions
- Emulator integration: Port specific modules into RunUO, ServUO, or custom frameworks