Turbo Pascal Toolchain, Part 3: Overlays, Memory Models, and Link Strategy

Turbo Pascal Toolchain, Part 3: Overlays, Memory Models, and Link Strategy

If you never fought DOS memory ceilings directly, overlays can sound exotic. In period-correct Turbo Pascal work they were practical engineering: move less-frequently-used code out of always-resident memory, load on demand, survive within tight conventional memory budgets.

This article covers how overlay objects worked conceptually and how teams used them safely.

Memory model context first

Overlay discussion is meaningless without memory model context:

  • 16-bit segmented addressing
  • near vs far calls/pointers
  • conventional memory pressure from drivers/TSRs/runtime

You were constantly trading resident footprint, call overhead, and complexity.

What overlays actually are

At runtime, overlayed routines are loaded from an overlay file/region when needed, replacing other overlay content in buffer space. Think of it as demand-paged code at application level, managed by runtime support rather than OS virtual memory.

When used well:

  • larger applications fit constrained memory
  • rarely-used modules do not occupy resident space

When used badly:

  • random pauses during code fetch
  • fragile call graphs
  • hard-to-debug ordering assumptions

Practical selection criteria

Good overlay candidates:

  • menu branches not used every frame
  • report/export modules
  • setup/config screens
  • infrequent tooling/maintenance code

Poor overlay candidates:

  • hot render/audio loops
  • tight interrupt-driven paths
  • tiny helper functions called everywhere

Overlaying hot paths is performance self-sabotage.

Typical runtime init pattern

Exact APIs and setup details vary by TP/BP profile, but the usual pattern is:

uses Ovr;

begin
  OvrInit('APP.OVR');
  if OvrResult <> ovrOk then Halt(1);
  OvrSetBuf(65520); { tune buffer size to workload/memory budget }
  { main program }
end.

Treat this as operational shape. Names and limits can differ slightly by distribution and memory manager context.

Toolchain profile (IDE options or linker settings) decides which procedures/units are overlayed and how overlay binaries are produced. The critical discipline is consistency:

  1. freeze overlay policy per build profile
  2. version overlay config with source
  3. verify overlay file presence in packaging
  4. test on representative memory-constrained boot profile

Many “random crashes” were simply missing/mismatched overlay assets in deployment.

Call graph awareness

Overlay systems reward explicit call graph design:

  • resident core invokes overlay modules
  • overlay modules avoid deep cross-calls into many other overlay modules
  • shared low-level helpers remain resident

If overlay modules depend chaotically on each other, load churn spikes and performance collapses.

Instrumenting overlay behavior

Even lightweight telemetry helps:

  • count overlay loads per major action
  • track worst-case response path
  • log missing overlay/init failures explicitly

If one menu action triggers ten overlay swaps, you likely have boundary design issues rather than “slow disk” issues.

Interaction with other memory consumers

Overlay planning was never isolated. You also had:

  • mouse drivers
  • network stacks
  • sound drivers
  • disk caches
  • TSR utilities

That is why CONFIG.SYS as Architecture is not separate from application design. Boot profile and application memory strategy are coupled systems.

Testing overlays the right way

Baseline test strategy:

  1. clean boot profile with minimal drivers
  2. typical user profile with expected TSR stack
  3. stress path that traverses many overlayed modules
  4. repeat same script on slow storage profile

If it only passes in the clean profile, it is not production-ready for period-correct hardware conditions.

A migration mindset for existing code

For retro-maintenance projects:

  1. map hot vs cold code first
  2. overlay one cold subsystem at a time
  3. measure latency impact
  4. adjust buffer size and boundaries
  5. stop when stability/perf tradeoff turns negative

Do not “overlay everything.” Selective overlays beat maximal overlays.

These viewpoints combine into one operational rule: memory policy is architecture policy.

Next part

Part 4 covers graphics drivers and graphics pipeline choices: BGI drivers, external driver assets, and how graphics tooling integrated with Turbo Pascal development.

Overlays were not a hack. They were an explicit answer to hard memory economics. The teams that succeeded with them were the teams that designed boundaries intentionally.

2026-02-22