Skip to content

Captive Disassembly

Daniel Nylander edited this page Aug 13, 2026 · 5 revisions

Captive DOS Disassembly Reference

Documentation baseline: v1.1.126.

Complete reverse-engineered data from CAPPO.EXE v1.06 (Oct 7 1992), PC conversion by TAG, original by RATT.

  • Unpacked binary SHA-256: fa7d5ca76d26f614476ed41f27cf737084942e9216b20b4605734df9ede9aee4
  • Compressed size: 73,379 bytes (LZEXE v0.91)
  • Unpacked size: 144,556 bytes
  • Entry point: CS:IP = 0000:0000, Stack: SS:SP = 230B:0200
  • Executables: CAPPO.EXE (main), GM.EXE (sound), INTRO.EXE (intro), FILEPLAY.EXE (utility)

PRNG Algorithms

Three distinct pseudo-random number generators recovered from the binary.

Main PRNG (offset 0x8A8E)

uint16_t prng_main(uint16_t state) {
    state = state * 0x5E5 + 0x29;
    state = ror16(state, 3);
    state ^= 0x0800;
    return state;
}

Combat PRNG (offset 0x9815)

Same LCG constants but different rotation and no XOR:

uint16_t prng_combat(uint16_t state) {
    state = state * 0x5E5 + 0x29;
    state = ror16(state, 2);
    return state;
}

Map Generation (Architect) PRNG (Amiga MapGen HUNK, offsets 0x44A0-0x44B8)

uint16_t prng_mapgen(uint16_t state) {
    state = state * 0x5E5 + 0x29;
    state = ror16(state, 4);
    state ^= 0x0800;
    return state;
}

All three share the LCG state * 0x5E5 + 0x29 but differ in rotation count and post-XOR.

Creature Stats

25 creature types with HP, category, and speed data.

HP Table (DS:0xA1BF, file offset 0x189AF)

4 bytes per type: min_hp, max_hp.

Type HP Min HP Max Category Speed
0 0 0 0 0
1 10 150 1 2
2 20 200 1 3
3 30 300 2 2
4 50 400 2 3
5 80 600 3 2
6 100 800 3 3
7 150 1000 4 2
8 200 1200 4 3
9 300 1500 4 4
10 400 2000 5 2
11 500 2500 5 3
12 600 3000 5 4
13 800 4000 5 3
14 1000 5000 6 2
15 1500 6000 6 3
16 2000 7000 6 4
17 3000 8000 6 3
18 5000 10000 7 2
19 7000 12000 7 3
20 10000 15000 7 4
21 19000 22000 7 3
22 12000 18000 7 4
23 15000 20000 7 5
24 20000 25000 7 5

Category table at DS:0x9A42 (file 0x18232), 1 byte per type. Speed table at DS:0xA1A4 (file 0x18994), 1 byte per type.

HP Calculation Formula (offset 0x9B12)

base = min_hp + ((max_hp - min_hp) * difficulty) / 8;
hp = ((base * 2 * creature_modifier) >> 8) + 6;

Sprite Assignments (DS:0xA16E, file 0x1895E)

2 bytes per entry: graphic_id, frame_index. Maps the 25 creature types to sprite sets in ALIEN1-ALIEN6.PL5.

Combat Formulas

Droid Weapon Damage (offset 0x9BF4)

base_damage = weapon_lo_byte * weapon_hi_byte
damage = base_damage << min(shift_count, 3)   // max x8
if (damage > 0xFFFD) damage = 0xFFFD          // sign overflow cap

Creature Attack Damage (offset 0x5380)

base = min(20, combat_val / divisor + 1)
Type 0x60: damage = base * 4
Type 0x61: damage = base * 8

Category acts as a scaling tier.

Armor Reduction

reduction = body_part_hp / 32
body_part_damage = incoming_damage / 4

Combat Constants

Constant Value Source
Energy per attack 3 combat.c:238
XP per kill hp_max / 10 combat.c:263
Gold per kill hp_max / 5 + 1 combat.c:265
Item drop chance 1 in 3 combat.c:267
Level-up HP bonus +10 combat.c:276
Level-up energy bonus +5 combat.c:278

XP and Leveling

Per-Skill Base XP (DS:0xB708, file 0x19EF8)

Skill Base XP Max Level
ROBOTICS 10 0x42 (66)
BRAWLING 8 0x18 (24)
SWORDS 30 0x18
HANDGUNS 72 0x18
RIFLES 216 0x18
AUTOMATICS 648 0x18
LASERS 1,944 0x18
CANNONS 3,888 0x18
SPAYGUNS 7,776 0x18
EXPERIENCE 7,960 0x18

Geometric progression: each weapon tier is roughly 3x the previous.

XP Threshold Formula (subroutine at 0xAB92)

ROBOTICS:     threshold += threshold >> 3 + 8     (per level)
Other skills: threshold += threshold >> 4 + round  (per level)

XP Award Formula (offset 0x9621)

dx = xp_value + 3 + difficulty
result = skill_level * dx * 12    // via (4+8) shift

Display level = xp >> 10. XP maximum: 0xF8FFFFFF. Overflow-safe addition from 0x87EC.

Items and Shop

Item Database (file offset 0x1A090)

46+ items with type codes:

Type Code Category Examples
0x27 / 0x65 Body part HEAD, CHEST, ARM, LEG, FOOT, HAND
0x08 Consumable BATTERY
0x21 Equipment OPTIC, CAMERA, BATTLE-GLOVE, WAR-BLADE
0x30 Ranged weapon PISTOL, COLT, MAGNUM, RIFLE, SHOTGUN, HAND-LASER
0x60 Explosive EXPLOSIVES
0x10 Ammunition CARTRIDGES, A51 MISSILES, SHELLS, LASER PACK
0x20 Chip/data DROID CHIP, CLIPBOARD
0x00 Special DEV-SCAPE, MINE, DIE, BALL, MAP

Weapon Damage Tables

  • Melee damage: 18 entries at file 0x1A006, 2 bytes each (lo, hi; damage = lo × hi)
  • Ranged damage: 20 entries, 4 bytes each (base, modifier, flag, 0)
  • Upgrade tier prices: 23 entries at file 0x1A220

Item Variants

23 variants with type code and base price. Melee tiers 1-5 (indices 1-5), ranged tiers 1-14 (indices 6-19), plus named variants A12, L22, X42.

Price Formula (offset 0xBB63)

Uses ROL16 operations on game_level_hi/lo + base_val + shop_tier + difficulty. Early game (level ≤ 5): fixed price 0x80.

Availability Gating (offset 0xB8D6)

Grade and tier gating based on difficulty (capped at 100) and shop material level.

Complete Item List

HEAD, CHEST, ARM, LEG, FOOT, HAND, GOLD, BATTERY, EXPLOSIVES,
DEV-SCAPE, OPTIC, CAMERA, KNUCLE-DUSTER, BATTLE-GLOVE, WAR-BLADE,
LIGHT-BLADE, FIRE-AXE, PISTOL, COLT, MAGNUM, RIFLE, SHOTGUN,
HUNTER, UZIE, RAPEDO, BOOSTER, HAND-LASER, LYTE-ZAPPER, ION-PULSE,
MONO-CANNON, A51-LAUNCHER, TWIN-CANNON, AIROSOLL, ACID-DISPERSER,
FLAME-THROWER, A12-, L22-, X42-2-, CARTRIDGES, A51 MISSILES,
SHELLS, LASER PACK, SONIC PACK, POISON, ACID, FLAMBOS,
PLANET PROBE, CLIPBOARD, MINE, DIE, BALL, SUPER BALL, MAP,
DROID CHIP, MESSAGE FROM RATT, SHIT

Spawn System

8 Spawn Categories (3 creature types each)

Category-to-creature-type mapping table with difficulty offsets and modifiers (16 entries each).

Spawn Patterns

Pattern Type Range Behavior
Single < 0x0A One creature
Single + flag 0x0A-0x0B One creature with subcell flag 0x20
Paired 0x0C Two creatures
Triple 0x0D-0x0E Three creatures
Flanking trio 0x0F Opposite + perpendicular directions
Paired + flag 0x15 Two creatures with flag

Subcell position: two 16-entry tables for placement within cells based on facing direction.

Map Generation

Map Dimensions

  • Grid: 64 wide × 32 tall
  • Up to 15 levels per base
  • Mission seed: ((mission - 1) * 11) + base_id

Cellular Automata System

  • Grid: 10 wide × 56 tall, 5 bytes per cell
  • Four CA types selected by (seed + level_num) & 3:
Type Name
0 MAZE
1 ROOMS
2 OPEN
3 MIXED

CA Maze Rules

Wall connectivity using bits 0x101 / 0x808, producing 0x10 flag. Wall thickness codes: 0x10, 0x18, 0x80, 0xC0.

Architect Base Generation

  • 4×4 grid of 16×8 sections in a flattened 64×32 allocation
  • Section unlocking is progressive per seed (hard-coded masks for seeds 0-4)
  • Floor 0 root at column 30 for seed 0
  • Carving: random walk with up to 12,289 moves, 720 cell cap
  • Room injection: 1-in-31 chance during carving
  • Door placement: max 8 per base, guaranteed minimum 1

Generator Placement (offset 0x1C3C)

count    = (PRNG & 7) + 1
position = PRNG & 0x7F   // capped at 0x6F
width    = (PRNG & 7) + 1

Viewport Rendering

Screen Geometry (verified from blit at 0x485F)

di = 0x44E0   → row 55, column 32  (55*320 + 32)
bp = 0x70     → 112 lines
cx = 0x48     → 72 words = 144 bytes/line
dx = 0xB0     → stride skip (320 - 144)
Constant Value
Original resolution 320×200 (DOS/ST), 320×256 (Amiga)
Viewport width 144 pixels
Viewport height 112 pixels
Viewport X offset 32
Viewport Y offset 55

19-Cell Trapezoid View

Not a full 5×5 grid. The viewport samples 19 cells in a trapezoidal frustum:

Range 4: 5 cells  (-2, -1, 0, +1, +2)
Range 3: 5 cells  (-2, -1, 0, +1, +2)
Range 2: 3 cells  (-1, 0, +1)
Range 1: 3 cells  (-1, 0, +1)
Range 0: 3 cells  (-1, 0, +1)

Canonical cell order:

{4,-2}, {4,-1}, {4,0}, {4,1}, {4,2},
{3,-2}, {3,-1}, {3,0}, {3,1}, {3,2},
{2,-1}, {2,0}, {2,1},
{1,-1}, {1,0}, {1,1},
{0,-1}, {0,0}, {0,1}

Visibility Occlusion Rules

7 rule groups with cascading logic. Walls at specific cells occlude other cells:

Wall at cell Hides cells
9 4, 5, 10
5 0, 1, 6
6 1, 2
7 2, 3
8 3, 4, 9

(Additional rules in the 7-group cascade documented in captive_view_window.c:32-87.)

Panel-Based Compositor

The renderer copies pre-projected panels via masked blits into a 144×112 view buffer. No texture mapping or runtime scaling — all perspective is pre-baked into the panel graphics.

DOS Descriptor Table

8-byte runtime descriptor at segment:0x00C0 + (graphic_id * 8). Source bank via relocated word table at code-segment:0x423C.

Fields: source_offset, destination_offset, width_bytes, height, flags, source_bank, source_segment.

Audio System

Sound Driver Files

File Purpose
NEW_ADL.BIN AdLib driver
NEW_ROL.BIN Roland driver
NEW_BEP.BIN PC beeper driver
CAP_A.BIN AdLib instrument patches
CAP_R.BIN Roland instrument patches
_SBNEW.DAT Sound Blaster driver
SB15.CTV SB 1.5 Creative Voice
SB20.CTV SB 2.0 Creative Voice
SBPRO.CTV SB Pro Creative Voice

OPL2 Instrument Patches

26 patches extracted from CAP_A.BIN, 16 bytes each:

Byte layout per patch:
  [0-1]  AM/VIB/EG/KSR/MULT (operator 1, 2)
  [2-3]  KSL/TL (operator 1, 2)
  [4-5]  AR/DR (operator 1, 2)
  [6-7]  SL/RR (operator 1, 2)
  [8-9]  Waveform (operator 1, 2)
  [10]   FB/CON
  [11]   Volume mask

SFX System

  • 49 SFX entries as bytecode programs for OPL2 register writes
  • Total bytecode: 2,132 bytes
  • All sound is FM synthesis — no PCM samples
  • OPL2 frequency table: 128 entries

SFX Player Architecture

4 simultaneous voices. Per-voice state:

  • Data pointer and position
  • Delay counter
  • Channel and note offset
  • Loop table
  • Subroutine return address
  • Per-voice PRNG state

Music Track Categories

14 categories with up to 11 variations each (numbered 0-9, A, B):

Category Context
BATT Battle
COMPROOM Computer room
ESCAPED Mission success
FCBASE Fast combat
FINAL2 Final mission / endgame
GENBASE General exploration
HOLOMAP Holamap navigation
LONGNT Long night / exploration
MAIN2 Main title screen
RUNNING Chase sequence
SHOPKEEP Shop interaction
TRAPPED Game over
VCBASE Varied combat
W World / ambient

File format: SOUND\{CATEGORY}{NUMBER}.MID

Graphics Files

File Content Dimensions
GAMESCRN.PL5 Main game screen / HUD 320×200
ROOFS.PL5 Ceiling/floor textures
WALLA-WALLE.PL5 Wall texture sets A-E
DOORS1.PL5 Door textures
DOORS2.PL5 Alternative door textures
SHOP1.PL5 Shop background
SHOP2.PL5 Alternative shop background
ICONS.PL5 UI icons (inventory, HUD)
ALIEN1-ALIEN6.PL5 Creature sprites (6 sets)
OBJECTS.PL5 Item/object sprites 16×16 frames, 20×12 grid
ANIM1-ANIM3.PL5 Animation frames
KEYBOARD.PL5 On-screen keyboard

PL5 Format

  • Resolution: 320×200 pixels
  • Palette: 32 colors
  • Raw file size: 40,000 bytes
  • No compression header

Animation Files

16 intro/cutscene animations: TEST0.ANM through TEST15.ANM.

Name Generation

Droid Names

48 syllables in 4-character slots. Names are 2-3 syllables concatenated:

VI   RUP  YUL  SCO  PHY  RAT  QUE  CHA
SY   POC  E    EX   DE   LAP  EL   MID
SO   SI   LE   NE   SIC  THA  ENE  INS
OO   ES   GIN  CEP  LTE  PE   DER  S
DON  S    ING  ST   Y    ED   BERY SY
LUME TON  FAR  HAM  KAL  APE  BEE  INK

Planet Names

Pattern: "STATION " + generated_suffix

Consonants: Z
Vowels 1:   Q U P
Vowels 2:   T R S L M
Vowels 3:   B
Suffix 1:   G R L
Suffix 2:   S

Holamap System

  • Version string: HOLAMAP SYSTEM V5
  • Coordinate format: CO-OD 150N-150W
  • Location types: PLANET, MOON, SPACE-STATION
  • Surface types: LAND-MISS, LAND-LEV0, LAND

Droid System

Materials (10 grades)

Grade Name
0 SHIT
1-3 (unnamed)
4 HUMAN
5 TINDRON
6 COPPATOR
7 BRONZITE
8 IRONIDE
9 CROMIZE

Combat Skills (10)

ROBOTICS, BRAWLING, SWORDS, HANDGUNS, RIFLES, AUTOMATICS, LASERS, CANNONS, SPAYGUNS, EXPERIENCE

Devices (12)

AG-SCAN, ROOT-FINDER, MAPPER, RADAR, MAGNA-SCAN, BODY-SCAN, VISION-CORRECTOR, VISOR, ANTI-GRAV, SHIELD, FIRE-SHIELD, GREASER

Body Parts (6)

HEAD, CHEST, ARM, LEG, FOOT, HAND

Initial Droid State

Field Value
HP 100
Energy 100
Starting XP 1024
Weapon damage 0x050A (lo×hi encoding)
Body part HP 255 (all 6 parts)
Starting gold 100

Game Messages

Mission Messages

"DESTROY THE GENERATORS."
"TOP-LEFT, BOTTOM-LEFT, TOP-RIGHT, BOTTOM-RIGHT."
"PUT PLANET-PROBE IN HOLAMAP."
"BASE HAS BEEN DESTROYED!"
"TRILL HAS BEEN RESCUED!"
"DROID'S HAVE FAILED!"
"TRILL HAS BEEN LEFT TO DIE."
"DROID'S ARE TO BE WASTED"
"TRILL HAS BE KILLED!"
"DROIDS BRUTALLY OUTWITTED"

Navigation Messages

"SWAN NOT YET IN ORBIT"
"LANDER NOT IN DOCK"
"LANDING SUCCESSFUL"
"DOCKING COMPLETE"
"LANDER LAUNCHED"
"FLIGHT PATH SET"
"ARRIVED AT DESTINATION"
"PROBE REVEALS A BASE"
"PROBE LAUNCHED"

Shop Dialogue

"WELCOME STRANGER TO MY"
"'HUMBLE SHOP"
"HOW MAY I BE OF ASSISTANCE"
"CALL AGAIN LATER"
"THIS WILL COST YOU"
"FOR NEXT LEVEL IN"
"YOU DO NOT HAVE ENOUGH!"
"ACCEPT"
"I DON'T STOCK THIS OBJECT"
"MODEL OF"
"PLEASE REMOVE"
"GRADE OF THE"
"REPAIR"

Save/Load Messages

Save filename: CAPTIVE1.SAV

"RESTORE SAVED GAME"
"RE-LOAD"
"FILE EXISTS"
"SHALL I REPLACE FILE?"
"LOADING SAVED GAME"
"FILE ERROR" / "FILE NOT FOUND"
"LOADING" / "SAVING" / "FORMATTING"
"LOADING RESTRAINT"

On-Screen Keyboard Layout

Q W E R T Y U I O P
A S D F G H J K L
Z X C V B N M = . /

VGA Reference

  • Mode 13h framebuffer at physical 0xA0000
  • Resolution: 320×200
  • Size: 64,000 bytes
  • Memory dump size: 0x100000

Executable Structure

Field Value
Compression LZEXE v0.91
Compressed size 73,379 bytes
Unpacked size 144,556 bytes
Code+data 143,532 bytes
DOS API calls 28 (file I/O, memory management)
Entry point CS:IP = 0000:0000
Stack SS:SP = 230B:0200

Clone this wiki locally