This section documents the results of reverse-engineering CASTLE1.EXE at the binary level β disassembling the original 16-bit NE executable to reconstruct the dungeon generation algorithm, map data structures, and core game logic. Rick Saada passed away, and no source code is known to exist publicly. This work is archival in nature.
The analysis was performed using custom NE segment parsing, disassembly of x86 real-mode code, and pattern matching against known MSVC runtime signatures. All segment offsets and addresses below are from the original CASTLE1.EXE v1.1A.
CASTLE1.EXE is a 16-bit New Executable (NE) binary targeting Windows 3.x. NE is the predecessor to the PE format used by modern Windows executables. Key facts from the file header:
| Field | Value | Notes |
|---|---|---|
| Format | NE | New Executable β Windows 3.x / OS/2 1.x format |
| Version string | 1.1A | Found in data segment |
| Copyright | 1989β1993 SaadaSoft | From data segment string table |
| Compiler | Microsoft C (MSVC) | Confirmed by R6000βR6021 runtime error strings. Not Turbo Pascal as sometimes claimed. |
| Align shift | 4 | Segment alignment = 16 bytes (2^4) |
| Code segments | 32 | Segmented 16-bit model |
| Data segment | Seg 32 @ 0xC0E0 | Contains BSS + initialized data |
| Seg | File Offset | Size | Identified Role |
|---|---|---|---|
| 1 | 0x32C0 | 9,522 | Window procedures (WndProc entry points) |
| 2 | 0x5A80 | 13,874 | Color animation, game initialization |
| 3 | 0x93C0 | 11,348 | Math library (div/mul/memmove) |
| 7 | 0x15680 | 11,610 | DUNGEONWNDPROC + entity list traversal |
| 8 | 0x185F0 | 4,952 | Player movement, map reads |
| 9 | 0x19A50 | 6,248 | Tile type reads (14 refs to DS:0xCE2) |
| 11 | 0x1C640 | 9,936 | DUNGEON GENERATION (27 tile write refs) |
| 12 | 0x1EDF0 | 8,140 | Map rendering support |
| 13 | 0x20F30 | 21,408 | String formatting (printf-style) |
| 19 | 0x2FD60 | 13,605 | Entity movement (map writes at DS:0x1A50, 0x1ABB) |
| 22 | 0x372B0 | 14,702 | Map interaction (9 refs), combat resolution |
| 32 | 0xC0E0 | 20,158 | Data segment (BSS + initialized data, strings) |
Discovered via rep stosb at seg11:0x1B04 zeroing 0x3000 = 12,288 bytes = 64Γ64Γ3. Three bytes per cell:
| [+0] | Tile type. Bit 0 = floor. 0x12 = stairsβ. 0x13 = stairsβ. |
| [+1] | Flags. 0x20 = room. 0x0C = corridor. 0x40 = door junction. |
| [+2] | Entity ID of occupying monster/item. |
bx = row Γ 192 + col Γ 3
(shl row, 6 β Γ 3 in ASM)
Runtime BSS (zeroed in file). 36 bytes (0x24) per level entry. Accessed via:
ax = 0x24
imul [0x96] ; [0x96] = current level
| [+0x3D88] | Level difficulty / monster density parameter |
| [+0x3D92/93] | Down stairs column/row coordinates |
| [+0x3D96/97] | Up stairs column/row coordinates |
Entity table at DS:0x4962 β 510 bytes (0x1FE), zeroed alongside the map. Entity pointer lookup: [0x4960 + entity_id Γ 2].
The main generation function in seg11 orchestrates the entire level build. After post-generation population calls at 0x1B90 (monsters), 0x1DBC (items), and 0x1E02 (traps), the level is fully populated and ready to enter.
CotW uses the standard Microsoft C rand() implementation β a linear congruential generator. The multiplier and increment were confirmed by matching against the MSVC runtime error strings found in the data segment. The same LCG is used for all random decisions in the game: room placement, corridor drawing, monster generation, item drops, and combat rolls.
All terrain tiles, monster icons, and object graphics are stored as standard Windows 3.1 .ICO resource files embedded in the executable. The icon format was chosen deliberately β it meant Paul Canniff could create all art using standard Windows tools, and it gave the game native monochrome support for free (every icon has both a color and a monochrome version).
Multi-tile graphics (ball spell effects, town buildings) are raw bitmaps embedded in the executable's data segment. The entire palette is the Windows standard 16 colors plus transparency β no custom palette, no dithering.
The map rendering path scales a 64Γ64 tile view into the available window size. Rick Saada acknowledged in the Steam release notes that the original scaling routine "does not always work correctly" β visible as slight tile artifacts at non-integer scaling factors. The simplified map view (for performance on slow machines) avoids the scaler entirely and renders a cleaner, smaller overview.
CotW was built using the Windows 3.x API as a first-class game engine rather than bypassing it. Window scrollbars drive viewport scrolling. Icon resources hold all tile and entity graphics. The window message loop handles turn processing. This approach was intentional β Saada was learning Windows programming as he built the game, and leaning on the OS gave him a functional framework without writing a custom engine from scratch.
The segment structure reflects this: seg1 contains the WndProc entry points that handle Windows messages. seg7 contains DUNGEONWNDPROC specifically β the window procedure for the dungeon viewport. Mouse input, keyboard shortcuts, and all UI interactions flow through standard Windows message handling.
The result is a game that integrates almost seamlessly with the Windows 3.x desktop: it can be minimized, resized (within limits), and runs alongside other applications without conflict. For 1989, this was genuinely unusual for a game.