home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1991 / 06 / cgatr / page.doc < prev    next >
Encoding:
Text File  |  1990-03-04  |  9.3 KB  |  96 lines

  1. Virtuelle Grafik-Seite für Turbo Pascal V4/5 
  2.  
  3.  
  4. Die Hardware der CGA-Karte kann keine Grafikseiten verwalten. Doch was dem Benutzer an Hardware fehlt, das simuliert er mit Software... 
  5.  
  6.  
  7. Borlands Programmierer haben den neuesten Versionen von Turbo Pascal eine mächtige Grafikbibliothek beigelegt: »GRAPH.TPU«. Hier findet der Grafikprogrammierer auch zwei Routinen zur Verwaltung von Grafikseiten, die Prozeduren »SetActivePage« und »SetVisualPage«. Diese beiden Routinen nützen dem Besitzer einer CGA-Karte allerdings herzlich wenig, denn sie arbeiten nur mit Karten, deren Hardware Grafikseiten selbst verwaltet (EGA, Hercules, VGA). Die betagte CGA-Karte gehört leider nicht dazu. 
  8. Der Grafikspeicher der CGA-Karte wird dem Programmierer wie »normaler« Hauptspeicher ab der Segment-Adresse B800hex zur Verfügung gestellt. Eine Grafikzeile ist in beiden Grafikmodi 50hex (dezimal 80) Bytes lang. Die Grafikzeilen (man zählt von Zeile 0 bis 199) wurden nicht linear, also hintereinander im Grafik-RAM untergebracht, sondern in zwei Speicherblöcke von 8000 Bytes Länge. Der erste Block, der von Adresse B800:0000hex bis B800:1F3Fhex (»Segment:Offset«-Schreibweise) reicht, beinhaltet die Zeilen mit gerader Nummer, also 0,2,4,...,198. Der zweite nimmt die ungeraden Zeilen 1,3,5,...,199 auf und reicht von B800:2000hex bis B800:3F3Fhex. Am Ende beider Blöcke befinden sich 192 ungenutzte Bytes, die 16 KByte der CGA-Karte werden also aufgeteilt in: 
  9.  
  10.  8000 Bytes      gerade Zeilen
  11.   192 Bytes      ungenutzt
  12.  8000 Bytes      ungerade Zeilen
  13.   192 Bytes      ungenutzt
  14. --------------------------------
  15.  16384 Bytes     Grafikspeicher
  16.  
  17.  
  18. Eine Grafikroutine, die einen Punkt auf den CGA-Bildschirm bringt, berechnet zunächst abhängig von den Koordinaten die Offsetadresse des Grafikzeilenbytes und maskiert den Punkt dann durch indirekten Zugriff auf den Speicher ab Segment B800hex. 
  19. Ändert man diese Adresse im Code der Maschinenroutine werden die Grafikbefehle auf einen anderen Speicherbereich »umgeleitet«, es wird unsichtbar gezeichnet. Dieser andere Speicherbereich wird als eine »virtuelle Grafikseite« bezeichnet. 
  20. Die Suche nach den Adressen, an denen sich das CGA-Speichersegment im Code von »CGA.BGI« befindet gestaltet sich diesmal etwas schwieriger als bei den Grafikbefehlen von Turbo Pascal 3.0 (siehe Heft 4/89). Dazu muß man zunächst an den Code der BGI-Routinen überhaupt herankommen, da dieser erst nach einem Vorspann mit Daten zum Treiber zu finden ist. 
  21.  
  22. type cga.bgi
  23.  
  24.  
  25. Das Ergebnis dieses MS-DOS-Befehls ist eine Copyright-Meldung Borlands. Am Ende des Textes befindet sich ein EOF-Zeichen (ASCII-Zeichen 26). Textprogramme (und »type«) achten nicht auf das reale Dateiende sondern hören einfach auf, eine Textdatei zu lesen wenn sie auf ein EOF stoßen. Der Inhalt von »CGA.BGI« kommt jetzt aber erst - es folgen Daten, die der Turbo-Pascal-Befehl »InitGraph« zur Installierung des Treibers benötigt. Die erste Word-Zahl, die auf das EOF folgt, enthält die Position des BGI-Maschinencodes relativ zum Dateianfang. 
  26. Es folgen zwar noch andere Daten, doch für unsere Zwecke benötigt man nur diese eine Information. Zum Beispiel um den Vorspann eines BGI-Treibers wegzu-»schneiden« - »BGI2BIN« erledigt diese Aufgabe. Das Ergebnis ist eine Binär-Datei, die mit einem Debugger oder Disassembler leichter analysiert werden kann. 
  27. Die Suche nach B800hex in »CGA.BIN« ist trotzdem ein hartes Brot - wie herausfinden ob überhaupt die Segmentadresse der CGA-Karte und kein Maschinenbefehl gemeint ist? »CGA.BGI« für Turbo Pascal 5.0 enthält die Byte-Kombination B800hex insgesamt an acht Positionn. Die Suche ist deshalb so schwierig, da die BGI-Routinen ihre Daten nicht direkt im Code enthalten, sondern auf ihren eigenen Datenteil indirekt zugreifen: 
  28.  
  29. ...
  30. xxxx:05C9 59            POP     CX
  31. xxxx:05CA A1B004        MOV     AX,[04B0]  <-
  32. xxxx:05CD FC            CLD
  33. xxxx:05CE 8EC0          MOV     ES,AX
  34. ...
  35.  
  36.  
  37. Die markierte Zeile aus dem Code von 5.0's »CGA.BGI« (erzeugt mit DEBUG) kopiert beispielsweise den Inhalt von Speicherstelle 4B0hex aus dem Codesegment in das AX-Register - wer käme auf die Idee, das es dasselbe wie »MOV AX,0B800h« ist (denn bei 4B0hex befindet sich die CGA-Segment-Adresse)? Wir empfehlen Ihnen deshalb die Benutzung eines selbstdokumentierenden Disassemblers zur Suche, das Programm »Sourcer« (getestet in Heft 2/89) hat sich bei dieser Aufgabe bestens bewährt: 
  38.  
  39. ...
  40. xxxx:05C9  59           pop     cx
  41. xxxx:05CA  A1 04B0      mov     ax,data_32        ; (xxxx:04B0=0B800h)
  42. xxxx:05CD  FC           cld                       ; Clear direction
  43. xxxx:05CE  8E C0        mov     es,ax
  44. ...
  45.  
  46.  
  47. Trotz eines leistungsfähigen Disassemblers als Rüstzeug werden Sie bei einer genaueren Analyse ihres BGI-Treibers nicht ohne zusätzliche Literatur ([1], hier wird ein Treiber systematisch auseinandergepult) auskommen. 
  48. In beiden vom Autor untersuchten CGA-Treibern finden sich viele ähnlicher Stellen. Der Copyright-Vorpsann von »CGA.BGI« für Turbo Pascal 4.0 meldet die Versionsnummer V1.00 und das Ausgabedatum 31.9,1987, die Treiberdatei ist 6029 Bytes groß. Hier befindet sich das Grafikspeichersegment relativ zum Code-Beginn an den Stellen 3F0hex und 59Ehex. Der untersuchte 5.0-Treiber meldet V2.00 und 21.3.1988, er ist 6253 Bytes groß. Hier kann man die gesuchte Adresse - B800hex - bei 4B0hex und 668hex finden. 
  49. In der Unit »CGAPage« wird das bisher gewonnene Wissen angewendet. Die Prozedur »InitCGAPage« sucht zunächst nach der oben angesprochenen Information über den Code-Beginn und addiert diesen Wert zur Anfangsadresse der Treiberdatei im Speicher. Der BGI-Code wird durch Graph im Speicher so umkopiert, daß er am Anfang eines Segmentes beginnt - das Ergebnis dieser Aktion kann im Listing leicht nachgeahmt werden. Schließlich prüft »InitCGAPage« noch, ob die angenommenen Patch-Adressen auch »passen«. Ist dies nicht der Fall, erscheint eine entsprechende Fehlermeldung durch die interne »Fatal«-Prozedur. Sie sollten Ihren CGA-Treiber dann selbst wie oben beschrieben auf die Patch-Adressen untersuchen. Kommen Sie zu keinem Ergebnis können Sie den Treiber auch der Redaktion zuschicken, der Autor sucht die Adressen dann für Sie und sie erscheinen in einem der auf Ihren Brief folgenden PC-Plus-Hefte. 
  50. Jetzt aber ein Überblick über die öffentlichen Routinen von »CGAPage«: 
  51. - »InitCGAPage« errechnet die Patchadressen und reserviert Speicher für »NPages« Seiten. Die Grafikroutinen greifen zu Beginn auf Seite Nummer 0 zu, den »reale« Bildschirmspeicher. 1 bis »NPages« bezeichnen die virtuellen Grafikseiten. Bis zu acht virtuelle Seiten können initialisiert werden. »InitCGAPage« muß wie der Routine »RegisterBGIDriver« ein Zeiger zum CGA-Grafiktreiber angegeben werden. 
  52. - »ClearPage« löscht eine Grafikseite schneller als »ClearViewPort«. »ClearDevice« darf nicht angewendet werden, da diese Routine immer den realen Bildschirmspeicher löscht. 
  53. - »UsePage« leitet die Grafikroutinen auf die angegebene Seite um. 
  54. - »ShowPage« kopiert den Inhalt der angegebenen Seite in den sichtbaren Bildschirmspeicher und macht die Seite damit sichtbar. 
  55. - »CopyPage« kopiert den Inhalt einer Seite auf eine andere. »CopyPage(3,0)« entspricht übrigens »ShowPage(3)«. 
  56. - »SwapPage« tauscht den Inhalt zweier Seiten aus. 
  57. - »ReInitCGAPage« gibt den durch »InitCGAPage« reservierten Speicherplatz wieder frei und läßt die Grafikbefehle wieder wie gewohnt arbeiten. 
  58.  
  59. Problematisch an diesen Routinen ist, daß sie zu nichts kompatibel sind und deshalb nur von Programmierern genutzt werden können, die ein »Nur-CGA-Programm« schreiben wollen. Wer jedoch zu Graph kompatibel bleiben möchte, der kann die zweite Unit »SetPage« sicher gebrauchen. Sie simuliert mit Hilfe der »CGAPage«-Befehle die oben angesprochenen Befehle »SetActivePage« und »SetVisualPage«. Unsere Software-Lösung ist natürlich langsamer als die Originalroutinen, funktioniert aber zuverlässig. Um einem Programm vorzutäuschen, die CGA-Karte hätte zwei Hardware-Grafikseiten, müssen Sie nur in der »uses«-Klausel in dem Hauptprogrammlisting und in jeder der Units des Programms, das Graph benutzt, direkt nach »Graph« »SetPage« anfügen. Aus 
  60.  
  61. uses
  62.   ...,Graph,...
  63.  
  64.  
  65. wird also 
  66.  
  67. uses
  68.   ...,Graph,SetPage,...
  69.  
  70.  
  71. Um diese Täuschung zu erreichen ersetzt »SetPage« die Graph-Routine »InitGraph«. Achtung: Der Ersatz lädt immer von Diskette einen Treiber nach, egal ob Sie vor einer Grafik-Initialisierung mit »RegisterBGIDriver« einen Treiber in das Programm eingebunden haben. Durch Löschen der für das Laden verantwortlichen Zeilen können Sie den Ersatz entsprechend anpassen. 
  72. Viel Spaß wünschen wir Ihnen mit den neuen Fähigkeiten Ihrer CGA-Karte. 
  73.  
  74. Literatur: 
  75. [1] Arne Schäpers: »Turbo Pascal 5.0 - Konzepte, Analysen, Tips & Tricks«, Addison-Wesley Verlag 
  76. außerdem: 
  77. »Turbo Pascal 4.0 Owner's Guide« und »Turbo Pascal 5.0 Reference Guide«, Borland 
  78.  
  79. (Hanno Ekkehard Müller) 
  80.  
  81.  
  82. Auf einen Blick 
  83.  
  84. Name: BGI2BIN 
  85. Programmiersprache: Turbo Pascal 4.0 / 5.0 
  86. Kurzbeschreibung: Kopiert den Maschinencode einer BGI-Treiberdatei in eine Binär-Datei. 
  87.  
  88.  
  89. Name: CGAPage / SetPage 
  90. Programmiersprache: Turbo Pascal 4.0 / 5.0 
  91. Kurzbeschreibung: Units zur Verwaltung von Grafikseiten auf einer Farbgrafikkarte und Nachahmung der nötigen »Graph«-Befehle. 
  92.  
  93.  
  94. Benötigte Hardware: Standard-PC, CGA-Karte oder CGA-Emulation. 
  95. Zusätzliche Software: Turbo Pascal 4.0 und »CGA.BGI«-Treiber V1.00 oder Turbo Pascal 5.0 mit Treiber V2.00. 
  96.