Reconstructed source code for SphereServer 0.99 — a game server emulator for Ultima Online 2D, originally developed by Menasoft (Dennis Robinson). The 0.99 branch was proprietary and never officially open-sourced. This project aims to reconstruct a fully functional 0.99-compatible server from available partial sources.
The server is fully functional — login, character creation, and game entry all work with a real ClassicUO client (tested with ClassicUO 3.0.6.0).
| Metric | Value |
|---|---|
| Compile errors | 0 |
| Link errors | 0 |
| Test suite | 9/9 passing |
| Script files loaded | 304 |
| Remaining stubs | 9 (Windows-only: registry + GUI, N/A on Linux) |
| Binary | sphere99svr — ~2.0 MB, 32-bit ELF (Linux x86) |
| Source files | 148 (.cpp + .h), ~101,500 lines |
| World load | 509K items, 22K chars, 3K player chars linked to 1.7K accounts |
| Network | Login → CharList → Character creation → Game entry works |
| Encryption | NoCrypt + 17 client key versions (XOR rotation) |
# Prerequisites (Ubuntu/Debian)
sudo apt-get install -y gcc-multilib g++-multilib make
# Build
make # produces sphere99svr (32-bit ELF binary)
make clean # removes build artifacts# Prerequisites (Ubuntu/Debian)
sudo apt-get install -y gcc-multilib g++-multilib make python3
# Build
make -j$(nproc) # produces sphere99svr (32-bit ELF binary)
# Deploy
cp sphere99svr /path/to/your-shard/
# Test (with server running)
python3 tools/test_suite.py localhost 2593 # 9/9 tests passingTested with ClassicUO 3.0.6.0 client. The server loads 304 script files at startup.
The server needs UO data files and scripts to run (not included in this repo):
# Directory structure expected:
your-shard/
├── sphere99svr # compiled binary
├── sphere.ini # server configuration
├── spheretables.scp # script loading order
├── muls/ # UO MUL data files (map0.mul, tiledata.mul, etc.)
├── scripts/ # .scp script files
├── save/ # world save data
└── accounts/ # player accounts
cd your-shard && ./sphere99svr
# Output: "Press '?' for console commands"Note: paths in sphere.ini and spheretables.scp must use forward slashes (/) on Linux.
SphereServer had two parallel development branches that are not sequential versions:
1998 GrayWorld (Dennis Robinson / Menasoft)
│
├─→ 0.55 → 0.56a → 0.56b → 0.56d (community, open-source)
│
└─→ 0.99a → 0.99f → 0.99z8 → 0.99zl (Menasoft, proprietary, closed)
Scripts between 0.99 and 0.56 are fundamentally incompatible — different expression
syntax (<?...?> vs <...>), trigger systems, dialog APIs, and variable mechanisms.
This project reconstructs the 0.99 source from:
- Partial 0.99f source from Sphereserver/Source-Archive
- Gap-filling with compatible code from JakubLinhart/Sphere99-56
- Linux/GCC port and implementations (this fork)
spherelib/ Base library (strings, files, arrays, sockets, threads, expressions)
SphereCommon/ Shared UO data structures (maps, tiles, crypto, regions)
SphereAccount/ Account management
SphereSvr/ Main server (game logic: characters, items, clients, world)
Makefile GNU Make build system (Linux/GCC)
CLAUDE.md Technical documentation and development instructions
- CScript parser (ReadLine, FindSection, ReadKeyParse, WriteKey)
- CGVariant (tagged union: string/int/DWORD/UID/ref/array)
- CExpression evaluator (right-to-left, no precedence — 0.99 behavior)
- CVarDefArray (key-value variable storage with CVarDefStr/CVarDefNum)
- CAtomRef (reference-counted atom strings)
- Str_Parse, Str_Match, Str_ParseCmds and other string utilities
- CLog (configurable level and group mask logging)
- CResourceDef / CResourceLink / CResourceScript
- CResourceMgr (AddResourceFile, LoadResources, OpenScriptFind, AddResourceDir)
- CGFile helpers (ExtractPath, GetFileNameTitle, GetFileNameExt)
- sphere.ini property dispatch (s_PropSet virtual chain fix)
- Script path resolution (SCPFILES base dir, backslash normalization)
- CScriptExecContext (ExecuteScript with IF/ELSE/WHILE/FOR/RETURN control flow)
- CResourceLock (open resource sections for reading)
- CResourceTriggered::OnTriggerScript (trigger dispatch)
- Table lookup functions (FindTable, FindTableHead, s_FindKeyInTable)
- CScriptPropArray::AddProps (merged function tables)
- 11 extended combat triggers (@BeforeSwing, @AfterSwing, @finalBlow, etc.)
- CGSocket (full POSIX TCP socket: create, bind, listen, accept, send/recv)
- CSocketAddress / CSocketNamedAddr (address parsing, DNS resolution)
- CGSocketSet (fd_set wrapper for select() multiplexing)
- CLogIP / CLogIPArray (connection tracking, flood protection)
- CCryptBase (passthrough crypto — real UO encryption TBD)
- Real UO client encryption (17 key versions, XOR rotation cipher)
- Huffman compression for game-mode packets
- CVarDefArray tag persistence (s_PropSetTags, s_WriteTags)
- s_FixExtendedProp (compound property keys: Tag.xyz, Attr_xxx)
- String utilities (Str_ahextou, Str_GetBare, Str_Match, etc.)
- Unicode conversion (CvtUNICODEToSystem, CvtSystemToUNICODE)
- World save loading (sphereworld.scp, spherechars.scp)
- World save writing (SaveStage/SaveForce — staged sector-by-sector save)
- Fix static init crash (custom operator new/delete with malloc/free)
- Fix AddSortKey argument order (21 call sites)
- Fix FOR_HASH macro (proper iteration)
- Fix s_PropSet vtable dispatch (const/non-const signature mismatch)
- Fix script path double-prefix (scripts/scripts/ → scripts/)
- Single-threaded mode on Linux (avoids QEMU threading issues)
- CServTimeMaster first-tick time delta fix
- Fix UID system — SetUIDIndex after AllocUID/LoadUID (objects survive loading)
- Fix hex number parsing (strtol base 16 for 0-prefixed values)
- SIGSEGV crash handler with backtrace
- Multi-threaded mode (native Linux, not under QEMU)
- UO client login encryption (seed, keys, handshake)
- Login → ServerList → ServerSelect → Relay flow
- Character list with real char names from world save
- Character creation (new characters)
- Character selection → game world entry
- Game entry packets (XCMD_Start, view, items, light, weather)
- Walk/movement event handling
- Item display, click, pickup, drop, equip packets
-
<?...?>escaped macro evaluation (0.99-specific) -
argo.dialog construction API (15K+ calls in Erebor scripts) - Full
var()global variable system -
safe()error-safe expression wrapper - Complete trigger dispatch for all game events
- NPC AI and pathfinding
- Combat calculations
- Skill and spell systems
Contributions welcome! All changes go through Pull Requests with code review.
When implementing features, use SphereServer 0.56d source as reference, but adapt to the 0.99 class interfaces (they differ significantly).
| Resource | Description |
|---|---|
| Sphereserver/Source-Archive | Partial 0.99f source code |
| JakubLinhart/Sphere99-56 | Original reconstruction effort |
| SphereServer Source-X | Active 0.56d+ development (reference only) |
| SphereCommunity | Community forums and documentation |
| Sphere99.VsCode | VS Code extension for 0.99 script editing |
Server engine code derived from sources published under Apache License 2.0 by the Sphereserver organization.
Original code copyright Menace Software (www.menasoft.com).