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 h„ufigsten programmiert) nur der momentan freie Hauptspeicher zur Verfgung steht, sollte man sich bei aufwendigeren Programmen und Routinen mit einer sehr groáen Datenstruktur schon mal berlegen, woher man den n”tigen 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 k”nnen an andere Speicher- stellen im Hauptspeicher verschoben bzw. ausgelagert werden. Natrlich werden diese Stellen im Speicher auch schon gebraucht, aber wohlm”glich nicht so oft wie die momentan ben”tigte Rou- tine. Folgendes Beispiel soll das vereinfachen: Speicher A (64 kByte groá) Speicher B (64 kByte groá) enth„lt: enth„lt: -------------------------- -------------------------- Init-Routine (33 kByte Bildschirm-Routine (86 kByte groá; wird auch nur wenige groá; wird h„ufig benutzt) Male benutzt) Die Init-Routine wird einmal aufgerufen und danach nicht mehr so oft ben”tigt. Wenn nun die Bildschirm-Routine (m”glicherweise eine Unit) aufgerufen wird, máten 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 h„ngt ein Teil des Speichers B in den Speicher A herein. N”tigenfalls wird dieser Teil wieder mal gel”scht 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 k”nnte 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 berh„ngt, 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 K„stchen "Overlays allowed" bzw. "Overlays m”glich" akitviert werden. Also: 1. Compiler-Schalter {$F+} in allen Teilen eines Programms ange- ben (s„mtliche 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- sammengefaát, die den Namen des Hauptprogramms plus die Endung ".OVR" tr„gt. 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 ben”tigt: Da w„re die Prozedur OvrClearBuf, die alle momentan geladenen Overlays aus dem Speicher l”scht. 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 Gr”áe 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 zus„tz- lichen Puffer fr die Overlays an, damit sie nicht nachgeladen werden mssen. Dieser Puffer ist so groá wie die gr”áte 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 erh”ht man den Puffer manu- ell: BEGIN ... OvrSetBuf( OvrGetBuf + $2500 ); ... END; So wird der Overlay-Puffer erh”ht. Nun kann zus„tzlich 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 l„dt die Overlays standardm„áig 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 ge”ffnet werden soll. Bei "0" ist dies standardm„áig "ReadOnly". Bei einer "1" ist "NurLesen" definiert, bei einer "2" ist beides zul„ssig. Die typisierte Konstante "OvrLoadCount : WORD" enth„lt, wie oft die Overlays geladen werden. Sie ist mit "0" vorbelegt und erh”ht sich bei jedem laden eines Overlays. Die Variable "OvrTrapCount : WORD" stellt einen Fehlerz„hler dar, der jedesmal um 1 erh”ht wird, wenn ein Overlay angefordert wird, das sich momentan nicht im Speicher befindet, also nachgeladen werden muá. Sonst enth„lt 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 ÚÄÄÄ¿ ³þ³þ³ À¿”ÚÙ ³ÀÄÙ³ ³ ³ ß ß