Crusader_Decomp/docs/phar-lap-extender.md
MaddoScientisto 3daffbf113 Add extractor for Crusader's EUSECODE.FLX container
- Implemented a Python script to extract data from the EUSECODE.FLX file format.
- Defined data structures for candidate entries and extracted chunks using dataclasses.
- Added functions to read and parse the FLX table, extract candidate data, and generate human-readable output files.
- Included functionality for analyzing extracted data, including generating summaries, descriptors, and event family reports.
- Implemented utilities for calculating printable ratios, zero ratios, and identifying text-like data.
- Added support for writing various output formats, including JSON, TSV, and Markdown.
2026-03-22 14:27:38 +01:00

6.2 KiB

Crusader: No Remorse — Phar Lap DOS Extender Analysis

This file covers the Phar Lap 286 DOS extender code portion of CRUSADER.EXE — the outer MZ/P2 stub that bootstraps the NE game image.

Architecture Notes

Correction: The Game Ships As A Bound NE Executable

Important: The installed copy does not contain a separate .EXP file. CRUSADER.EXE is a bound executable with an outer DOS MZ stub and an internal NE executable image. The Phar Lap loader/runtime code and the game's real segment layout are both described inside this same file.

The flow is:

  1. entry → checks DOS version, CPU type
  2. init_dos_extender → sets up protected mode (VCPI/DPMI)
  3. load_exp_file → opens the game's .EXP file
  4. load_executable_image → parses P2/MZ headers, creates segments, applies relocations
  5. task_switch_to_child → transfers control to the actual game code

For the installed retail copy, this means the currently loaded Ghidra program is only one interpretation of CRUSADER.EXE. The next import should target the NE layer of the same file, not a missing external .EXP.

Segment 1339: Fast Memory Operations

FUN_1339_02a8 contains an unrolled loop (Duff's device pattern with 57 iterations) — a hand-optimized fast memory fill/add routine, typical in DOS game graphics engines.

EMS Memory (Segment 1677)

The game uses EMS (Expanded Memory Specification) via INT 67h for additional memory beyond the 1MB real-mode limit. Functions in segment 1677 manage EMS page frames and handle allocation/deallocation.

Named Functions

Entry & Startup

Address Name Description
10da:7c40 entry Program entry point — checks CPU, parses command line, launches game
10da:1816 main_init_and_run Main initialization — loads child EXP, sets up subsystems, runs game
1760:1432 parse_cmdline_and_run Parses command-line args and invokes main_init_and_run
1760:42fa init_dos_extender Initializes Phar Lap 286 DOS extender (CPU check, VCPI/DPMI setup)

Executable Loading

Address Name Description
1760:2cdf load_exp_file Loads .EXP executable — opens file, reads headers, allocates memory
1760:1dfc load_executable_image Parses P2/MZ headers, loads segments, creates LDT entries
1760:24a6 apply_relocations Applies segment relocations to loaded executable
1760:5eca exec_child_process Executes child process with command-line arguments
1760:5fee exec_program_with_args Builds command line, locates and executes a program
10da:1f7e load_and_run_child Wrapper: loads child EXP and initializes it

System Services

Address Name Description
10da:2330 dos_exit Calls INT 21h AH=4Ch (terminate program)
1760:42aa detect_cpu_type Detects CPU: 0=8086, 2=286, 3=386+
1339:04a6 dpmi_set_interrupt_vector INT 31h — DPMI set interrupt vector
1339:06ca switch_to_real_mode Switches CPU from protected to real mode
1339:06f2 switch_to_protected_mode Switches CPU from real to protected mode
1339:0076 setup_interrupt_handlers Configures interrupt vectors via INT 21h
1339:0a38 dos_int21h_wrapper Simple INT 21h call wrapper
1339:0a82 dos_int21h_with_regs INT 21h call with register parameters
10da:2360 get_flags_register Returns CPU FLAGS register
10da:2363 set_flags_register Sets CPU FLAGS register

Memory Management

Address Name Description
1677:0d12 cleanup_ems_memory Frees EMS (INT 67h) memory handles
10da:14fc init_stack_fill_cc Fills stack with 0xCC (INT 3) for debugging/guard
10da:1706 get_segment_base_addr Computes linear base address from segment descriptor

Task Management

Address Name Description
10da:19ca task_switch_to_child Context switch to child process
10da:1946 task_switch_from_child Context switch back from child process
10da:1af4 call_termination_handler Calls registered termination callback

I/O & Output

Address Name Description
10da:00d6 flush_output_buffer Flushes buffered output via function pointer
10da:0132 putchar_buffered Writes character to buffer, flushes on newline
10da:0808 memcopy_to_buffer Copies N bytes from source to destination buffer
10da:178c print_error_message Formats and prints load error (references "not loaded: %s")
10da:09e4 print_fatal_error Prints "Fatal Error" prefix + message
10da:192a print_internal_error Prints "Internal Error" message

Interrupt Management

Address Name Description
10da:1ec0 restore_interrupt_vectors Restores INT 2Fh and INT 67h vectors
10da:2249 restore_int_2f_67 Restores INT 15h vector if saved
1760:3d86 init_system_check Validates system (CPU, DOS version, VCPI/DPMI, memory)

Utility

Address Name Description
10da:15ea check_ds_segment Returns true if DS == 0x10 (checks data segment selector)
1760:3c9e nop_stub Always returns 0 (unused hook)

Key String References

Address String Context
13fc:0016 $Id: comhighc.c 1.1 91/08/06... Phar Lap C runtime source ID
13fc:0048 $Id: comutils.c 1.1 91/08/06... Phar Lap utility functions source ID
13fc:0078 Serial Number DOS extender serial validation
13fc:14ca Internal Error Error class prefix
13fc:14da Fatal Error Fatal error class prefix
13fc:156a-1628 File error messages Not found, bad format, no memory, etc.
1760:665c Copyright (C) 1986-93 Phar Lap Software, Inc. DOS extender copyright
1760:73da -LDTSIZE 4096 -EXTHIGH D0_0000h -NI 18 -ISTKSIZE 3 Default extender config
1760:76fc-7c5a Numbered error messages System requirement errors (1000-2170)