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.
Link strategy and overlay file generation
Toolchain profile (IDE options or linker settings) decides which procedures/units are overlayed and how overlay binaries are produced. The critical discipline is consistency:
- freeze overlay policy per build profile
- version overlay config with source
- verify overlay file presence in packaging
- 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:
- clean boot profile with minimal drivers
- typical user profile with expected TSR stack
- stress path that traverses many overlayed modules
- 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:
- map hot vs cold code first
- overlay one cold subsystem at a time
- measure latency impact
- adjust buffer size and boundaries
- stop when stability/perf tradeoff turns negative
Do not “overlay everything.” Selective overlays beat maximal overlays.
Related crosslinks
- Turbo Pascal Toolchain, Part 2: Objects, Units, and Binary Investigation
- Latency Budgeting on Old Machines
- Turbo Pascal Units as Architecture
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.