[comp.sys.amiga] Overlay Tutorial

papa@bacall.UUCP (Marco Papa) (01/03/87)

Since I finally got overlays to work with ALL versions of Lattice C and with
the latest beta MANX, I decided to put together this little tutorial on 
how to use overlays, so that other people do not have to spend endless hours
trying to figure this out.

1. Lattice C (actually Alink) overlays.
   Two days ago I got the "alink"-compatible set of libraries that will work
with Lattice C 3.10.  These are currently needed for anybody that wants to use
overlays with Lattice C 3.10, since BLINK does not yet support them (any word
from the Software Distillery?).  I basically was the first one that needed 
them, so they created these for me.  If you have Lattice C 3.10, and
need to use overlays NOW, you should call them and they'll send you a disk
with 5 files: three sets of libraries (that substitute lc, lcm and lcmffp),
and a new startup file in object and source form (that substitute c.o and c.a).
These libraries are compiled without the pc-relative option, and therefore
are compatible with Alink.  Linking went fine. Unfortunately file size went 
down only of 4K (out of 150K).  The big gain with Lattice C 3.10 comes when 
using PC-relative addressing, but at the moment that and overlays do not go 
together, until BLINK is fixed.

2. Undocumented "unloadseg" in MANX C
   Today I got a great (undocumented) fix from Gary Shultz of MicroIllusions
(the makers of Dynamic-CAD).  Overlays in MANX work differently than when 
using Alink and ovs-20 with Lattice C.  With Alink overlays in parallel 
branches of the overlay tree are mutually exclusive, and when a new overlay is
loaded, the parallel overlay gets AUTOMATICALLY unloaded (an UnloadSeg is done
by the overlay handler).  This has the benefit of transparency to the C source 
code, since the overlay info is only in the linker WITH file. On the other
hand, it limits the type of overlays to a tree structure (see the description
in the AmigaDOS Developers Manual).

In MANX 3.30x (c, d or e) overlays are supported, but the overlay structure
is not restricted to a tree. On the other hand, overlays are NOT AUTOMATICALLY
unloaded, but one has to call a particular routine.  The 3.20A docs (page 
tech.5) tell you that one should use the function UnloadSeg to unload a MANX
overlay.  NOOOOO!  Using UnloadSeg (with uppercase U and capital S) calls the 
AmigaDos function and will bomb your system.  You should instead call 
unloadseg (with lowercase u and s) with the name of a routine in the overlay
that you want unloaded (it does not matter which one) as the only parameter.

For example, in my own program A-Talk, I have 6 different terminal emulators.
Each one is in a separate overlay, since one uses only one emulator at a time.
The code looks like this:

int (*emulate)();		/* a var that will invoke the emulator
				   output function */

int OutputVT100();		/* the output functions */
int OutputH19();
int OutputVT52();
int OutputANSI();
int OutputTTY();
int OutputTalk();
int OutputTek();

int InputVT100();		/* the input functions */
etc...

LoadNewEmulator(whichone)	/* this routine unloads the old emulator 
				   and loads the new one */
{
...
#ifdef MANX			/* only needed for MANX */
	if (!firsttime)	unloadseg(emulate);
#endif

	switch (whichone) {
	case VT100:
		emulate = OutputVT100;	/* this loads the new overlay */
					/* in both MANX and Lattice */
		keyboard = InputVT100;
	break;
	case H19:
		emulate = OutputH19;
		keyboard = InputH19;
	break;
	/* the same for all other emulators/overlays */
	....
	}
}

OutChars(buffer,n)	/* this one outputs/translates input chars
			   depending on the emulators conventions */
{
	...
	(*emulate)(buffer, n);
	...
}

Now the code that goes in one of the overlays:

OutputVT100(buf,n)
{
...
}
InputVT100(buf,n)
{
...
}

Note that "unloadseg" should NOT be called the first time, since the overlay
might not be loaded yet.

Again, thanks to Gary for the "incorrectly-documented" feature.  I hope this
will save somebody a headache.

-- Marco Papa
   Felsina Software