

                             Overlays!
                             

Kommen wir ein wenig zur Speicherverwaltung eines Programms in
Pascal. Wenn man bedenkt, da fr ein Programm im Real-Mode (der
Mode, in dem man unter DOS wohl am hufigsten programmiert) nur
der momentan freie Hauptspeicher zur Verfgung steht, sollte man
sich bei aufwendigeren Programmen und Routinen mit einer sehr 
groen Datenstruktur schon mal berlegen, woher man den ntigen
Speicher nimmt (EMS und XMS mal ausgeschlossen). Bei 450 kByte
freiem Hauptspeicher darf das Programm mit all' seinen Daten-
strukturen auch nur 450 kByte gro sein. Wenn der Hauptspeicher
aber nicht mehr reicht, kann man sich die Overlay-Technik zu 
Nutze machen: Wichtige Programmteile knnen an andere Speicher-
stellen im Hauptspeicher verschoben bzw. ausgelagert werden. 
Natrlich werden diese Stellen im Speicher auch schon gebraucht,
aber wohlmglich nicht so oft wie die momentan bentigte Rou-
tine. Folgendes Beispiel soll das vereinfachen:

Speicher A (64 kByte gro)          Speicher B (64 kByte gro)
enthlt:                            enthlt:
--------------------------          --------------------------
Init-Routine (33 kByte              Bildschirm-Routine (86 kByte
gro; wird auch nur wenige          gro; wird hufig benutzt)
Male benutzt)

Die Init-Routine wird einmal aufgerufen und danach nicht mehr 
so oft bentigt. Wenn nun die Bildschirm-Routine (mglicherweise
eine Unit) aufgerufen wird, mten nach 64 kByte 22 kByte nach-
geladen werden (also von der langsamen Festplatte), um die Rou-
tine zur Vollendung zu bringen. Bei der Overlay-Technik werden
jetzt aber diese 22 kByte schon im voraus in den Speicher A ge-
laden, der vorher frei gemacht wurde. So hngt ein Teil des 
Speichers B in den Speicher A herein. Ntigenfalls wird dieser
Teil wieder mal gelscht und die Init-Routine zu Ausfhrung ge-
bracht, aber das wird nicht so schlimm sein wie jedesmal die 
22 kByte von der Platte zu lesen. Soviel dazu, jetzt die Durch-
fhrung:

Man knnte sich ja denken, da bei manuelle Programmierung das 
Ganze sehr aufwendig ist, doch wie schon so oft stellt Borland
einige kleine Prozeduren und Variablen zur Verfgung, die die 
Sache steuern.

Es sei hier gesagt, das man nur komplette Units als Overlays de-
finieren kann, also keine einzelnen Prozeduren aus dem Hauptpro-
gramm heraus. Man mu bei den Units den Compilerschalter {$F+}
setzen um zu zeigen, da diese Unit FAR programmiert wird. Dies
mu natrlich sein, denn wenn die Unit in ein anderes Speicher-
segment berhngt, mu sie FAR kodiert sein. Weiters mu der
Compilerschalter {$O+} in jeder Unit angegeben werden um dem Com-
piler zu zeigen, da diese Unit als Overlay bersetzt werden 
soll. Das Hauptprogramm darf den Compilerschalter {$O+} nicht 
enthalten, mu aber in der USES-Anweisung die Standard-Unit 
"OVERLAY" enthalten, und zwar als ERSTE definierte Unit. Als 
letzte Anweisung mu im Hauptprogramm nach der USES-Anweisung an-
gegeben werden, welche Units als Overlays compiliert wurden. Das 
geschieht mit {$O Unitname} {$O Unitname} ...
Als letztes mu im Menu unter "Option | Compiler" das Kstchen
"Overlays allowed" bzw. "Overlays mglich" akitviert werden.

Also:
1. Compiler-Schalter {$F+} in allen Teilen eines Programms ange-
   ben (smtliche Units sowie das Hauptprogramm)
2. Units, die als Overlays compiliert werden sollen, mssen den
   Schalter {$O+} enthalten. Damit werden sie beim Compilieren in
   Overlays bersetzt (NIEMALS im Hauptprogramm diese Anweisung
   eintragen)
3. In die USES-Anweisung im Hauptprogramm die Unit "OVERLAY" an 
   die erste Stelle eintragen.
4. Unter der USES-Anweisung im Hauptprogramm mu mit {$O Unit-
   name} angegeben werden, welche Units zuvor als Overlays compi-
   liert worden sind.
5. "Option | Compiler | Overlays allowed" aktivieren

Die als Overlays definierten Units werden zu einer Datei zu-
sammengefat, die den Namen des Hauptprogramms plus die Endung 
".OVR" trgt. Diese Datei mu mit der Prozedur

 OvrInit( FileName : STRING );

initialisiert werden, wobei Fehler in der globalen Variablen 
"OvrResult" gespeichert werden:

 Wert  Name             Bedeutung
 
   0   ovrOk            fehlerfreie Initialisierung  
  -1   ovrError         Overlay-Fehler  
  -2   ovrNotFound      Overlay-Datei nicht gefunden
  -3   ovrNoMemory      zu wenig Speicher fr Overlay
  -4   ovrIOError       Ein-/Ausgabefehler
  -5   ovrNoEMSDriver   EMS-Treiber nicht installiert
  -6   ovrNoEMSMemory   kein EMS fr Overlays verfgbar
   

Nachdem also die Overlay-Datei initialisiert worden ist, z.B. mit

 OvrInit( 'MyProg.OVR' );

mu eine Fehlerberprfung stattfinden

 IF OvrResult <> ovrOk THEN Halt(1);

Einige weitere Prozeduren werden aber so gut wie nie bentigt:
Da wre die Prozedur OvrClearBuf, die alle momentan geladenen 
Overlays aus dem Speicher lscht. Dies erzwingt ein neues nachla-
den aller als Overlays definierten Units; es wird also alles neu
geordnet. Doch wozu ? Tja, es soll ordnungswtige Programmierer
geben...

Eine andere Funktion liefert die Gre des momentanen Overlay-
Buffers zurck. FUNCTION OvrGetBuf : LONGINT; liefert diese Gr-
e in Bytes zurck. Doch sie ist nur sinnvoll im Zusammenhang mit
der Prozedur OverSetBuf( Groesse : LONGINT);
Bei der Initalisierung legt die Overlay-Verwaltung einen zustz-
lichen Puffer fr die Overlays an, damit sie nicht nachgeladen
werden mssen. Dieser Puffer ist so gro wie die grte als Over-
lay definierte Unit. Wenn also diese Unit 85 kByte gro ist, ist
dieser Puffer auch 85 kByte gro. Doch bei Programmen und Units 
mit Querverweisen und Zeigern kann man schon mal 2-3 kByte mehr
brauchen, die dann aber fehlen. Also erhht man den Puffer manu-
ell: 

BEGIN
 ...
 OvrSetBuf( OvrGetBuf + $2500 );
 ...
END;

So wird der Overlay-Puffer erhht.

Nun kann zustzlich auch noch der EMS-Speicher fr die Overlays 
zur Verfgung stehen. Mit der Prozedur OvrInitEMS wird versucht,
die Overlays in den EMS-Speicher zu verlagern, um sie von dort 
aus fr das Overlaying bereitzuhalten. Dies ist natrlich von
Vorteil, weil der EMS-Speicher schneller ist. Diese Prozedur kann
immer aufgerufen werden, auch wenn gar kein EMS-Speicher zur 
Verfgung steht. Sie gibt dann eben nur einen Fehler zurck und
ldt die Overlays standardmig von der Platte und nicht aus dem
EMS-Speicher.

BEGIN
 ...
 OvrInit( 'C:\DATEN\MYPROG.OVR' );
 IF OvrResult <> ovrOk THEN Halt(1);
 OvrInitEMS;
 IF ((OvrResult = ovrNoEMSDriver) OR (OvrResult = NoEMSMemory)) 
 THEN BEGIN
  WriteLn('Kein EMS-Speicher. Overlays sind nicht im EMS!');
  REPEAT
  UNTIL KeyPressed;
 END;
 ...
END;

Weiterhin gibt es noch einige andere Variablen und Konstanten, 
die direkt zur Laufzeit des Programms initalisiert werden. Die
typisierte Konstante "OvrFileMode : BYTE" besagt, wie das Overlay
geffnet werden soll. Bei "0" ist dies standardmig "ReadOnly".
Bei einer "1" ist "NurLesen" definiert, bei einer "2" ist beides
zulssig. Die typisierte Konstante "OvrLoadCount : WORD" enthlt,
wie oft die Overlays geladen werden. Sie ist mit "0" vorbelegt
und erhht sich bei jedem laden eines Overlays. Die Variable
"OvrTrapCount : WORD" stellt einen Fehlerzhler dar, der jedesmal
um 1 erhht wird, wenn ein Overlay angefordert wird, das sich 
momentan nicht im Speicher befindet, also nachgeladen werden mu.
Sonst enthlt die Unit Overlay nur noch die Variable 
"OvrReadBuf : OvrReadFunc". Der Typ "OvrReadFunc" stellt dabei 
einen "TYPE OvrReadFunc = FUNCTION(OvrSeg : WORD) : INTEGER; dar.
Diese Variable speichert die Ladeadresse der Overlays in "OvrSeg"
und die Ausfhrung des Ladevorgangs selbst in der Variablen. Bei
erfolgreichem Ladevorgang ist die Variable OvrReadBuf 0, sonst
entsteht der Laufzeitfehler 209.

 _______________________________________________________________
|  Zusammenfassung aller Prozeduren, Funktionen und Variablen:  |   
|                                                               |
|  PROCEDURE OvrInit( FileName : STRING );                      |
|  VAR       OvrResult;                                         |
|  PROCEDURE OvrClearBuf;                                       |
|  FUNCTION  OvrGetBuf : LONGINT;                               |
|  PROCEDURE OverSetBuf( Groesse : LONGINT);                    |
|  PROCEDURE OvrInitEMS;                                        |
|  TCONST    OvrFileMode : BYTE;                                |
|  TCONST    OvrLoadCount : WORD;                               |
|  VAR       OvrTrapCount : WORD;                               |
|  VAR       OvrReadBuf : OvrReadFunc;                          |
 ---------------------------------------------------------------


                                 Eric der Schreckliche
                                Ŀ
                                
                                
                                ٳ
                                  
                                  


