Blog
Welcome to the Blog.
Turbo Pascal Before the Web
2026-02-22
Turbo Pascal was more than a compiler. In practice it was a compact school for software engineering, hidden inside a blue screen and distributed on disks you could hold in one hand. Long before tutorials were streamed and before package managers automated everything, Turbo Pascal taught an entire generation how to think about code, failure, and iteration. It did that through constraints, speed, and ruthless clarity.
The first shock for modern developers is startup time. Turbo Pascal did not boot with ceremony. It appeared. You opened the IDE, typed, compiled, and got feedback almost instantly. This changed behavior at a deep level. When feedback loops are short, people experiment. They test tiny ideas. They refactor because trying an alternative costs almost nothing. Slow builds do not just waste minutes; they discourage curiosity. Turbo Pascal accidentally optimized curiosity.
The second shock is the integrated workflow. Editor, compiler, linker, and debugger were not separate worlds stitched together by fragile scripts. They were one coherent environment. Error output was not a scroll of disconnected text; it brought you to the line, in context, immediately. That matters. Good tools reduce the distance between cause and effect. Turbo Pascal reduced that distance aggressively.
Historically, Borland’s positioning was almost subversive. At a time when serious development tools were expensive and often tied to slower workflows, Turbo Pascal arrived fast and comparatively affordable. That democratized real software creation. Hobbyists could ship utilities. Students could build complete projects. Small consultancies could move quickly without enterprise-sized budgets. This was not just a product strategy; it was a distribution of capability.
The language itself also helped. Pascal’s structure encouraged readable programs: explicit blocks, strong typing, and a style that pushed developers toward deliberate design rather than accidental scripts that grew wild. In education, that discipline was gold. In practical DOS development, it reduced whole categories of mistakes that were common in looser environments. People sometimes remember Pascal as “academic,” but in Turbo Pascal form it was deeply practical. ... continue
TP Toolchain 5: TP6 -> TP7
2026-02-22
Parts 1-4 covered workflow, artifacts, overlays, and BGI integration. This last part goes inside the compiler/language boundary: memory assumptions, type layout, calling conventions, and assembler integration from TP6-era practice to TP7/BP7 scope.
The TP6 to TP7 shift was less a language revolution and more an expansion of operational surface:
So the technical model below is largely continuous across this generation, with feature breadth increasing in later packaging. Borland Pascal 7 (BP7) extended this further with protected-mode compilation, built-in debugging support, and richer IDE integration, while TP7 remained primarily a real-mode product.
Version-specific nuances — TP7.0 (1990) stabilized the TP6 object model and
improved unit compilation speed. TP7.1 addressed bugs and refinements; some
teams held at 7.0 for compatibility with shared codebases. BP7 (1992) bundled
Turbo Debugger, expanded the RTL, and introduced DPMI target support. Exact
behavior of directives like {$G+} (80286 instructions), {$A+} (record
alignment), and codegen choices can vary between these builds; when precise
version behavior matters, treat claims here as a starting point and validate
against your toolchain.
Real-mode DOS assumptions drive everything: ... continue
TP Toolchain 4: BGI Integration
2026-02-22
Turbo Pascal graphics was never just “call Graph and draw.” In production-ish
DOS projects, graphics was an asset pipeline problem, a deployment problem, and
a diagnostics problem at least as much as an API problem.
This part focuses on BGI driver mechanics, practical packaging, and the exact checks that separate real faults from folklore.
Structure map: BGI architecture and operational models → Graph unit runtime
contracts and GraphResult handling → dynamic vs linked drivers, packaging and
pitfalls → font/driver matrix and memory interactions → BGI artifacts in build
and deploy pipelines → debugging rendering failures on real DOS → team checklists
and release hardening.
The Graph unit provides the API. Under it, runtime driver/font assets do the
hardware-specific work. The unit itself is statically linked; it does not
contain adapter-specific code. Instead, it loads a driver binary that knows
how to program the hardware (CGA, EGA, VGA, Hercules, etc.) and interpret
high-level drawing calls. Fonts are separate assets because they are large
and optional — you only load the ones your UI needs.
Two operational models exist: ... continue
TP Toolchain 3: Overlays
2026-02-22
This article is rewritten to be explicitly source-grounded against the Turbo Pascal 5.0 Reference Guide (1989), Chapter 13 (“Overlays”) plus Appendix B directive entries.
Structure map. 1) Why overlays existed—mechanism, DOS memory pressure, design tradeoffs. 2) TP5 hard rules and directive semantics. 3) FAR/near call model and memory implications. 4) Build and link strategy for overlaid programs. 5) Runtime initialization: OvrInit, OvrInitEMS, OvrSetBuf usage and diagnostics. 6) Overlay buffer economics and memory budget math. 7) Failure triage and performance profiling mindset. 8) Migration from non-overlay projects. 9) Engineering checklist and boundary caveats.
Version note. This article is grounded in the TP5 Reference Guide. Borland Pascal 7 and later overlay implementations may differ in details (e.g. EMS handling, buffer API). The core rules—{$O+}, FAR chain, compile-to-disk, init-before-use—tend to hold across versions, but when in doubt, consult the manual for your specific toolchain. TP6/TP7 improvements are beyond the scope of this piece; the TP5 baseline remains the most widely documented and forms a stable reference.
In TP5 real-mode DOS workflows, overlays are a memory-management strategy: keep non-hot code out of always-resident memory and load it on demand. Conventional memory in DOS is capped at roughly 640 KB; TSRs, drivers, and stack/heap shrink the usable space. A large application can easily exceed that budget if all code is resident.
Mechanism. The overlay manager maintains a buffer in conventional memory.
Overlaid routines live in a separate .OVR file on disk. On first call into
an overlaid routine, the manager loads the appropriate block into the buffer
and transfers control. Subsequent calls to already-loaded overlays execute
in-place; no disk access. When the buffer fills and a new overlay must load,
the manager discards inactive overlays first (least-recently-used policy),
then loads the requested block. ... continue
TP Toolchain 2: Binary Forensics
2026-02-22
Part 1 covered workflow. Part 2 goes where practical debugging starts: the
actual artifacts on disk. In Turbo Pascal, build failures and runtime bugs are
often solved faster by reading files and link maps than by re-reading source.
The tools are simple—TDUMP, MAP files, strings, hex diffs—but used
systematically they turn “it used to work” into “here is exactly what
changed.”
Structure map. This article proceeds in eleven sections: (1) artifact catalog and operational meaning, (2) TP5 unit-resolution behavior, (3) TPU constraints and version coupling, (4) TPU differential forensics and reconstruction when source is missing, (5) OBJ/LIB forensics and OMF orientation, (6) MAP file workflow and TDUMP-style inspection loops, (7) EXE-level checks before deep disassembly, (8) external OBJ integration and calling-convention cautions, (9) repeatable troubleshooting matrix with high-signal checks, (10) manipulating artifacts safely and team discipline for reproducibility, and (11) unit libraries and cross references.
Typical TP/BP project artifacts:
This list is not trivia. It is your debugging map. OVR files are loaded at runtime
when overlay code executes; if the OVR path is wrong or the file is missing, the
program may hang or crash on overlay entry rather than at startup. BGI and CHR
are resolved by path at runtime—Graph unit InitGraph searches the driver path.
Capture these paths in your environment documentation; “works here, fails there”
often traces to BGI/OVR path differences.
Tool availability. TDUMP ships with Borland toolchains; if missing,
omfdump (from the OMFutils project) or objdump with appropriate flags
can suffice for OBJ/LIB inspection, though output format differs. On modern
systems, strings and hexdump are standard. The workflows described here
assume TDUMP is available; adapt commands if using substitutes. ... continue
TP Toolchain 1: The Full Stack
2026-02-22
Turbo Pascal is remembered for a fast blue IDE, but that is only the surface. The real strength was a full toolchain with tight feedback loops: editor, compiler, linker, debugger, units, and predictable artifacts. Part 1 maps that system in practical terms before we dive into binary formats, overlays, BGI, and ABI-level language details.
Structure map. This article proceeds in twelve sections: (1) version and scope boundaries, (2) toolchain topology and component wiring, (3) artifact pipeline and engineering signal, (4) IDE options as architecture, (5) directory and path policy, (6) practical project layout, (7) IDE–CLI parity and reproducible builds, (8) units as compile boundaries and incremental strategy, (9) debug loop mechanics and map/debug workflow, (10) external objects and integration discipline, (11) operational checklists and failure modes, and (12) how this foundation supports the rest of the series.
When discussing “latest Turbo Pascal,” engineers usually mean Turbo Pascal 7.0 and, in many setups, Borland Pascal 7 tooling around it. Some executable names and switches vary by package and installation, so this article uses two rules:
That keeps the discussion accurate without pretending all distributions are identical. TP 5.x used a simpler unit format; TP 6 and 7 extended it with object-oriented support and richer metadata. Projects that must support both TP 5 and TP 7 need to avoid OOP extensions and test on both toolchains.
Technical mechanism. TP 7 and BP 7 share the same core compiler engine but
differ in packaging: TURBO.EXE (IDE) vs BP.EXE (Borland Pascal IDE), and
command-line variants such as TPC.EXE or BPC.EXE. The compiler emits
.TPU (Turbo Pascal Unit) files or .OBJ for linkable object code; TP 5.x
and TP 6.x used similar conventions with minor format changes. Knowing your
actual binary set (dir *.exe in the TP install directory) prevents
configuration mistakes. ... continue
Mode X (TP) IV: Tilemaps
2026-02-22
A renderer becomes a game when it can show world-scale structure, not just local effects. That means tilemaps, camera movement, and disciplined data loading. In Mode X-era development, these systems were not optional polish. They were the only way to present rich scenes inside strict memory budgets.
This final Mode X article focuses on operational structure: how to build scenes that scroll smoothly, load predictably, and remain debuggable.
Before defining map format, set your memory envelope:
Then derive map chunk dimensions from those limits. Teams that reverse the order usually rewrite their map loader halfway through the project.
A practical map record often includes: ... continue
Mode X (TP) III: Sprites
2026-02-22
Sprites are where a renderer starts to feel like a game engine. In Mode X, the challenge is not just drawing images quickly. The challenge is managing transparency, overlap order, and visual dynamism while staying within the strict memory and bandwidth constraints of VGA-era hardware.
If your primitives and clipping are not stable yet, go back to Part 2. Sprite bugs are hard enough without foundational uncertainty.
A reliable sprite pipeline separates three concerns:
Trying to “infer” transparency from arbitrary colors in ad-hoc code works until assets evolve. Use explicit conventions and document them in your asset converter notes.
A classic masked blit uses one pass to preserve destination where mask says transparent, then overlays sprite pixels where opaque. In Turbo Pascal, even simple byte-level logic remains effective if your loops are predictable. ... continue
Mode X (TP) II: Primitives
2026-02-22
After the planar memory model clicks, the next trap is pretending linear drawing code can be “ported” to Mode X by changing one helper. That works for demos and fails for games. Robust Mode X rendering starts with primitives that are aware of planes, clipping, and page targets from day one.
If you missed the foundation, begin with Part 1: Planar Memory and Pages. This article assumes you already have working pixel output and page flipping.
For old DOS rendering pipelines, primitives should optimize for correctness first:
Performance matters, but undefined writes kill performance faster than any missing micro-optimization.
A common beginner pattern is “draw first, check later.” On VGA memory that quickly becomes silent corruption. Instead, apply clipping at primitive boundaries before entering the hot loops. ... continue
Mode X (TP) I: Planar Memory
2026-02-22
Mode 13h is the famous VGA “easy mode”: one byte per pixel, 320x200, 256 colors, linear memory. It is perfect for first experiments and still great for teaching rendering basics. But old DOS games that felt smoother than your own early experiments usually did not stop there. They switched to Mode X style layouts where planar memory, off-screen pages, and explicit register control gave better composition options and cleaner timing.
This first article in the series is about that mental model. Before writing sprite engines, tile systems, or palette tricks, you need to understand what the VGA memory controller is really doing. If the model is wrong, every optimization turns into folklore.
If you have not read Mode 13h Graphics in Turbo Pascal, do that first. It gives the baseline we are now deliberately leaving behind.
The practical advantage was not raw arithmetic speed. The advantage was control over layout and buffering:
What looked like magic in magazines was mostly disciplined memory mapping plus stable frame pacing. ... continue