From 46b7abce710f175fffb9239d200743c51bd13e9e Mon Sep 17 00:00:00 2001 From: "Marcel W. Wysocki" Date: Thu, 20 Aug 2026 21:45:59 +0800 Subject: [PATCH 1/5] docs: add compilers/borland-cc --- compilers/borland-cc.md | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 compilers/borland-cc.md diff --git a/compilers/borland-cc.md b/compilers/borland-cc.md new file mode 100644 index 0000000..357949c --- /dev/null +++ b/compilers/borland-cc.md @@ -0,0 +1,51 @@ +--- +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](/tools/wibo) (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". +- **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. From 41358110d2e45fbec6274decdda5598140201353 Mon Sep 17 00:00:00 2001 From: "Marcel W. Wysocki" Date: Thu, 20 Aug 2026 21:45:59 +0800 Subject: [PATCH 2/5] docs: add compilers/open-watcom --- compilers/open-watcom.md | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 compilers/open-watcom.md diff --git a/compilers/open-watcom.md b/compilers/open-watcom.md new file mode 100644 index 0000000..fbf7b5d --- /dev/null +++ b/compilers/open-watcom.md @@ -0,0 +1,46 @@ +--- +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). + +## 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. From a80fed2db9b4beea1b058c99aa127dcc144541c2 Mon Sep 17 00:00:00 2001 From: "Marcel W. Wysocki" Date: Thu, 20 Aug 2026 21:45:59 +0800 Subject: [PATCH 3/5] docs: add compilers/delphi --- compilers.md | 3 +++ compilers/delphi.md | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 compilers/delphi.md diff --git a/compilers.md b/compilers.md index 81f001f..4a4f242 100644 --- a/compilers.md +++ b/compilers.md @@ -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) diff --git a/compilers/delphi.md b/compilers/delphi.md new file mode 100644 index 0000000..b750041 --- /dev/null +++ b/compilers/delphi.md @@ -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). From 90612e1ccf4dadde724615e9d514d9d401e896b9 Mon Sep 17 00:00:00 2001 From: "Marcel W. Wysocki" Date: Thu, 20 Aug 2026 21:46:49 +0800 Subject: [PATCH 4/5] docs: fix wine link on compilers/borland-cc --- compilers/borland-cc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compilers/borland-cc.md b/compilers/borland-cc.md index 357949c..5934da0 100644 --- a/compilers/borland-cc.md +++ b/compilers/borland-cc.md @@ -10,7 +10,7 @@ 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](/tools/wibo) (or [wibo](/tools/wibo)) for 32-bit. +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 From 05eb2a66b20dc79c19bc433a488fb8f365337cdf Mon Sep 17 00:00:00 2001 From: maci0 Date: Fri, 21 Aug 2026 11:53:10 +0800 Subject: [PATCH 5/5] docs: add verified Borland/Watcom codegen fingerprints Probe-verified codegen markers for TCC 3.1 / bcc32 5.5 (frame-pointer- always prologues, real division, 16-bit fwait + pop bp epilogue) and wcc386 (caller-saved-register saves, ret N callee cleanup, __CHK stack probe, no frame pointer). --- compilers/borland-cc.md | 4 ++++ compilers/open-watcom.md | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/compilers/borland-cc.md b/compilers/borland-cc.md index 5934da0..d03f024 100644 --- a/compilers/borland-cc.md +++ b/compilers/borland-cc.md @@ -29,6 +29,10 @@ Borland C++ 4.5/5.0 floppies also exist but are not commonly used for matching ## 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). diff --git a/compilers/open-watcom.md b/compilers/open-watcom.md index fbf7b5d..0a40119 100644 --- a/compilers/open-watcom.md +++ b/compilers/open-watcom.md @@ -29,6 +29,13 @@ The compilers emit **OMF** objects: 32-bit OMF is converted to COFF (via `objcon - **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 ; 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