Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compilers.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ editor: markdown
dateCreated: 2025-06-11T03:08:02.505Z
---

- [Borland C/C++](/compilers/borland-cc)
- [Delphi](/compilers/delphi)
- [GCC](/compilers/GCC)
- [IDO](/compilers/ido)
- [MWCC](/compilers/MWCC)
- [Open Watcom](/compilers/open-watcom)
55 changes: 55 additions & 0 deletions compilers/borland-cc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
title: Borland C/C++
description: Turbo C / Borland C++ (16-bit DOS and 32-bit Windows compilers)
published: true
date: 2026-08-20T13:42:59.000Z
tags: compiler, borland, turbo-c, bcc32, bcc
editor: markdown
dateCreated: 2026-08-20T13:42:59.000Z
---

# Borland C/C++

Borland's C/C++ compilers span the DOS and Windows eras, and two distinct lines are relevant to matching decompilation today: the **Turbo C / Turbo C++** line (16-bit DOS compilers, 1987–1992) and **Borland C++ 5.5** (1999, the free 32-bit Windows command-line tools). Both are proprietary and run today through emulation — DOSBox for the 16-bit line, wine (or [wibo](/tools/wibo)) for 32-bit.

## Versions

- **Turbo C 1.0 (1987)** — the first Turbo C; floppy-era 16-bit DOS compiler.
- **Turbo C 2.0 (1988/89)** — the classic DOS-game compiler; e.g. id Software's early titles. C89-strict — rejects `//` comments. archive.org item `turboc20` (assembled from the original floppies).
- **Turbo C++ 3.1 (1992)** — the most-used Turbo release for 16-bit DOS development. archive.org item `turboc3.1_202112`.
- **Borland C++ 5.5 (1999)** — the free command-line tools (`bcc32`), 32-bit Windows; archive.org item `BorlandC55`. Emits OMF objects.

Borland C++ 4.5/5.0 floppies also exist but are not commonly used for matching — see the note under [The 4.5 CD](#the-45-cd).

## Running Borland C/C++

- **Turbo C line** — 16-bit DOS programs; run headless under DOSBox. The [rebrew-toolchains](https://github.com/maci0/rebrew-toolchains) images `rebrew/borland:2.0-win16` / `rebrew/borland:3.1-win16` package `TCC.EXE` with a DOSBox sandbox (sources are staged under a short FAT-safe name and the `.OBJ` is copied back). The objects are Borland 16-bit OMF.
- **bcc32 5.5** — a 32-bit Windows PE; runs under wine via `rebrew/borland:5.5-win32`. Unlike the MSVC line, it does **not** run under [wibo](/tools/wibo): bcc32 calls `GetThreadLocale` from kernel32 at startup, a WinAPI shim wibo does not implement, so wibo aborts with `call reached missing import GetThreadLocale` before any compilation happens. Use wine.

## Identifying a Borland compiled binary

- **Detect It Easy** reports Turbo C 2.0 builds as "Borland C/C++ 1991".
- **Codegen fingerprints** — verified by compiling a probe through TCC 3.1 (`-O1`) and bcc32 5.5 (`-O1`):
- **Frame pointer always** — every function starts `push ebp; mov ebp,esp` (`55 8b ec`) even at `-O1` (bcc32 probe: 18 frame prologues). MSVC `/O2` and Watcom omit it — this is the Borland signature.
- **Real division** — bcc32 emits `mov ecx,3; xor edx,edx; div ecx` for `x/3u`/`x/7u` — no magic-constant multiply. Its magic set differs from MSVC's too: `0xCCCCCCCD` for `x/10u`, but real `div` for other small divisors.
- **16-bit line (TCC)** — `push bp; mov bp,sp` framing, `mov bx,N; div bx` (divisor in BX), `fwait` (`9b`) before each x87 op, and `pop bp; ret` epilogues — never `leave` (contrast MSVC 1.5x, which ends functions with `leave`).
- **16-bit NE executables** — Borland segments carry a `[index\x00][name-string][content]` marker at the start of each code segment, and the NE signature sits at `e_lfanew` = 0x40 — versus MSVC's 16-bit linker, which places the NE header at 0x400 and starts segments with code. This cleanly separates Borland from MSVC 16-bit output.
- **Delphi / Pascal string evidence** — Borland RTL strings (length-prefixed Pascal strings) appear in data segments.
- **OMF objects** — Borland's dialect of 16-bit OMF; the compiler version can be extracted from object files (e.g. via `objconv`'s comp.id).

## Known quirks

- **bcc32 has no built-in include/lib path** — the vendored `Include/` and `Lib/` must be passed explicitly (`-I… -L…`).
- **The 4.5 CD** — the Turbo C 4.5 CD (a Windows-IDE-only release) carries **no compiler binary** despite its name: its 207 `.PAK` files are [Quantum archives](https://en.wikipedia.org/wiki/Quantum_compression) (extractable with the rebrew `pak_extract.py`), but no BCC32/BCC/TLINK anywhere. The compiler needs the actual Borland C++ 4.5/5.0 floppy set instead.
- **Turbo C 2.0 determinism** — per-run COMENT ticks in objects are masked in byte-reproducibility gates.

## Where to get it

- archive.org `turboc20` / `turboc3.1_202112` (Turbo C 2.0 / Turbo C++ 3.1 media), `BorlandC55` (official free 5.5 tools).
- The [archaic-toolchains](https://github.com/archaic-toolchains) org mirrors these in its non-MSVC C line, same tree format as its MSVC repos.

## Projects

- [decomp.me](https://decomp.me) — hosts borlandc55 as a win32 compiler.
- [rebrew](https://github.com/maci0/rebrew) — `bcc32` OMF objects are parsed and byte-matched; Turbo C 2.0/3.1 targets compile through the DOSBox images (verified `compile_and_compare` EXACT against a TCC-built object).
- id Software's early DOS titles — the classic Turbo C user.
38 changes: 38 additions & 0 deletions compilers/delphi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Delphi
description: Borland Delphi 1.0 (16-bit Windows Pascal compiler)
published: true
date: 2026-08-20T13:42:59.000Z
tags: compiler, delphi, borland, pascal
editor: markdown
dateCreated: 2026-08-20T13:42:59.000Z
---

# Delphi

Delphi is Borland's RAD (rapid application development) Pascal product. **Delphi 1.0 (1995)** targets 16-bit Windows 3.x and is the version relevant to decompilation: it compiles to genuine NE 6.01 executables via its command-line compiler `DCC.EXE`. The Borland Pascal dialect and the 16-bit NE output make it a distinct, self-contained corner of the DOS/Windows toolchain family.

## Running Delphi

`DCC.EXE` is a 16-bit DOS program, so it runs headless under DOSBox. The [rebrew-toolchains](https://github.com/maci0/rebrew-toolchains) image `rebrew/delphi:1.0-win16` packages the exact command-line toolchain: `DCC.EXE` (Delphi Compiler 8.0, Sep 1995), `DELPHI.DSL` (compiler symbol table), the `CMDLINE.PAK` tools, and the RTL/VCL units (`UNITS.PAK` + `LIB.PAK`). The sources stage under a short FAT-safe name and the produced `.EXE` is copied back.

The `.PAK` files are **Quantum archives**; the rebrew tree ships a reverse-engineered extractor (`pak_extract.py`) and documents the recipe.

### Matching caveat

Delphi's Borland ABI has **no matchable compiler profile** — the Delphi codegen cannot be reproduced from C source for byte matching, so Delphi functions are documented as blockers in tooling. The toolchain remains useful for verification-style research (compile + NE parse of the output).

## Identifying a Delphi compiled binary

- **16-bit NE executables** — Borland segments carry a `[index\x00][name-string][content]` marker at the start of each code segment, with the NE signature at `e_lfanew` = 0x40 (MSVC's 16-bit linker puts it at 0x400).
- **Pascal strings** — Delphi data segments are full of length-prefixed (Pascal) strings rather than NUL-terminated ones; string scanning tools recognize them.
- **RTL evidence** — Delphi VCL/runtime strings; `diec` reports the Delphi version.

## Where to get it

- archive.org item `delphi10` — the Delphi 1.0 media (RTL/VCL units have no public tarball, so toolchains commit the verified tree instead).
- The [archaic-toolchains](https://github.com/archaic-toolchains) org mirrors it in its non-MSVC line.

## Projects

- [rebrew](https://github.com/maci0/rebrew) — uses the Delphi 1.0 toolchain to compile and parse NE targets (validated against `holiday.exe`, a Delphi 1.0 VCL app).
53 changes: 53 additions & 0 deletions compilers/open-watcom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: Open Watcom
description: Open-sourced Watcom C/C++ (16-bit DOS and 32-bit Windows)
published: true
date: 2026-08-20T13:42:59.000Z
tags: compiler, watcom
editor: markdown
dateCreated: 2026-08-20T13:42:59.000Z
---

# Open Watcom

Open Watcom is the open-sourced continuation of Watcom C/C++, one of the dominant DOS/Windows/OS/2-era compiler suites. Its 16-bit DOS and 32-bit Windows compilers both remain usable for matching decompilation, and it is the only compiler family on this site that ships **native Linux binaries** — no emulation layer needed.

## Versions

- **Watcom C/C++ (commercial)** — widely used for 1990s DOS games; the DOS release of *Doom* was famously compiled with Watcom C/C++, and the released Doom source still carries `WATCOM`-specific code.
- **Open Watcom 1.0 (2003)** — source released under the Sybase Open Watcom Public License.
- **Open Watcom 2.0 (current)** — maintained at [open-watcom/open-watcom-v2](https://github.com/open-watcom/open-watcom-v2); the version rebrew/decomp.me tooling uses.

## Running Open Watcom

Unlike every other compiler on this site, Open Watcom ships Linux binaries, so `wcc386` (32-bit) and `wcc` (16-bit DOS) run directly on the host — the [rebrew-toolchains](https://github.com/maci0/rebrew-toolchains) image `rebrew/watcom:2.0-win32` additionally packages the 32-bit compiler behind a `wcc386` wrapper for the docker-first workflow.

The compilers emit **OMF** objects: 32-bit OMF is converted to COFF (via `objconv`) and parsed transparently; 16-bit OMF is decoded by a dedicated OMF parser. Matching is byte-exact for both.

## Identifying a Watcom compiled binary

- **Object format** — Watcom objects are OMF in a dialect distinct from Borland's; `objconv`'s comp.id extracts the compiler version from the object.
- **Detect It Easy** carries Watcom signatures.
- **Runtime** — the DOS-extender-based 16-bit output and the win32 output have distinct CRT signatures (Watcom's own runtime, not msvcrt).
- **Codegen fingerprints** — verified by compiling a probe with `wcc386 -otexan`:
- **Saves caller-saved registers** — prologues save whatever the body clobbers, including `push ecx; push edx` (`51 52`) and `push ebx` (`53`) — MSVC never saves ECX/EDX (caller-saved in its ABI), so this is a strong Watcom marker.
- **`ret N` callee cleanup** — FP-argument functions end `ret 4` / `ret 8` (`c2 04 00`): the callee cleans the stack (Watcom's own convention), where MSVC cdecl leaves cleanup to the caller.
- **No frame pointer** — leaf functions skip `push ebp` entirely.
- **Real division** — `div`/`idiv` even at `-otexan`: `push ecx; push edx; mov ecx,3; xor edx,edx; div ecx; pop edx; pop ecx`.
- **`__CHK` stack probe** — `push <amount>; call __CHK` (the `__CHK` symbol appears in OMF), distinct from MSVC's `__chkstk` (size in EAX) and MinGW's `___chkstk_ms`.
- **ALIGN 8** between functions.

## Known quirks

- **`wcc` (16-bit) rejects `-c`** with E1073 — the 16-bit compiler does not take a separate compile-only flag; the `-fo=`/`-I`/`-zq` flag shape is used instead.
- **Moving snapshot tag** — the 2.0 "Last-CI-build" release tag is a moving target, so pinned toolchains re-download and re-hash it rather than trusting the tag.

## Where to get it

- [open-watcom/open-watcom-v2](https://github.com/open-watcom/open-watcom-v2) — source and CI snapshots.
- The [archaic-toolchains](https://github.com/archaic-toolchains) org mirrors the pinned snapshot.

## Projects

- [rebrew](https://github.com/maci0/rebrew) — `watcom` (wcc386, 32-bit) and `watcom16` (wcc, 16-bit DOS) profiles with byte-exact matching, incl. the chkstk call reloc slot.
- [decomp.me](https://decomp.me) — hosts watcom as a win32 compiler.