home *** CD-ROM | disk | FTP | other *** search
/ Profi Club / Profi_Club_2_1992_-_de.d64 / grafik-2.txt < prev    next >
Text File  |  2023-02-26  |  25KB  |  268 lines

  1.      HiRes-Grafik-Programmierung
  2.  
  3. Teil 2
  4.  
  5. 760 Pixel setzen, l{CBM-C}schen:
  6. Mit dieser Routine k{CBM-C}nnen an Koordinatenpunkten, ausgedr{CBM-X}ckt durch X- und Y-Werte, Pixels gesetzt oder gel{CBM-C}scht werden. Beim Setzen erscheint der Bildpunkt in der Vordergrundfarbe, beim L{CBM-C}schen in der Hintergrundfarbe. Die X-Koordinate darf Werte von null bis 319 annehmen, die Y-Koordinate Werte von null bis 199. X geht von links nach recht, Y von oben nach unten. Ist die Variable LO gleich null, wird das Pixel gesetzt, besitzt LO den Wert eins, wird das Pixel gel{CBM-C}scht. Ist FA gleich null, erscheint das Pixel in der am angegebenen Ort definierten Farbe, ist FA gleich eins, werden die Farben VF und HF am angegebenen Ort neu gesetzt. FA und LO werden nicht nur beim Setzen einzelner Punkte, sondern auch bei den darauf aufbauenden Gebilden Linie, Rechteck und Kreis wirksam.
  7.  
  8. X=0:Y=0:FA=1:LO=0:GOSUB760
  9.  
  10. In der linken oberen Bildschirmecke erscheint ein Punkt in der Farbe VF. Auch eventuelle andere im Bereich von X=0 bis X=7 und Y=0 bis Y=7 liegende gesetzte Punkte werden in der neuen Farbe eingef{CBM-F}rbt. Nichtgesetze Punkte des genannten Bereiches erscheinen in der Hintergrundfarbe HF.
  11.  
  12. 820 Linie:
  13. Als Parameter sind die Anfangskoordinaten X1,Y1 und die Endkoordinaten X2,Y2 zu {CBM-X}bergeben:
  14.  
  15. X1=0:Y1=0:X2=319:Y2=199:GOSUB820
  16.  
  17. Eine diagonale Linie wird von der linken oberen bis zur rechten unteren Bildschirmecke gezeichnet.
  18.  
  19. 880 Rechteck:
  20. Als Parameter sind die Koordinaten X1,Y1 und X2,Y2 zweier diagonal gegen{CBM-X}berliegender Ecken des Rechtecks zu {CBM-X}bergeben. Mit GOSUB880 wird dann die Darstellung des Rechtecks veranla{CBM-V}t.
  21.  
  22. 930 Kreis:
  23. Hier sind die Mittelpunktskoordinaten XM und YM sowie der Radius R zu {CBM-X}bergeben, etwa:
  24.  
  25. XM=160:YM=100:R=50:GOSUB930
  26.  
  27. Ein Kreis mit dem Mittelpunkt in der Bildschirmmitte und dem Radius 50 w{CBM-X}rde hier gezeichnet werden.
  28.  
  29. 1000 Cursor:
  30. Nach {SHIFT--}bergabe des X- und Y-Wertes wird mit GOSUB 1000 die Position f{CBM-X}r nachfolgende Textausgaben bestimmt. Die Koordinaten orientieren sich nicht am Text, sondern am Grafikbildschirm:
  31.  
  32. X=0:Y=0:GOSUB1000
  33. X=5:Y=5:GOSUB1000
  34. X=8:Y=8:GOSUB1000
  35.  
  36. Obwohl sich in den ersten beiden F{CBM-F}llen die Koordinaten unterscheiden, hat dies keine Auswirkung auf die Positionierung des nachfolgenden Textes, denn auch im zweiten Beispiel befinden sich die Koordinaten innerhalb des Raumes f{CBM-X}r ein und denselben Buchstaben. Der erste Buchstabe k{CBM-F}me in die erste Zeile und die erste Spalte zu liegen. Erst im dritten Fall w{CBM-X}rden die zweite Zeile und die zweite Spalte festgelegt werden.
  37.  
  38. 1030 Textausgabe:
  39. Text wird an der durch die Cursorpositionierung bestimmten Stelle ausgegeben. Der Text mu{CBM-V} der Variablen TX$ {CBM-X}bergeben werden. Die Variable FA bestimmt, ob die Farbinformationen VF und HF zum Tragen kommen. Mit der Variablen GZ, die Werte von null bis drei annehmen darf, wird der Zeichensatz ausgew{CBM-F}hlt. Dabei bedeuten:
  40.  
  41. 0 Gro{CBM-V}/Grafik
  42. 1 Gro{CBM-V}/Grafik invers
  43. 2 Klein/Gro{CBM-V}
  44. 3 Klein/Gro{CBM-V} invers
  45.  
  46. Nach der Ausgabe eines Textes befindet sich die neue Cursorposition automatisch hinter dem letzten Zeichen des ausgegebenen Textes.
  47.  
  48. 1020 Cursor, Textausgabe:
  49. Die Positionierung des Cursors und die Textausgabe k{CBM-C}nnen auch durch einen einzigen Routinenaufruf veranla{CBM-V}t werden.
  50.  
  51. X=0:Y=0:TX$="TEXT":GOSUB1020
  52.  
  53. GOSUB 1020 ist gleichbedeutend mit GOSUB1000:GOSUB1030.
  54.  
  55. Mit diesen Informationen steht der Erstellung eigener Grafikanwendungen nichts mehr im Wege. F{CBM-X}r denjenigen, der weitere Details zu den angesprochenen Routinen erhalten m{CBM-C}chte, gehen wir zun{CBM-F}chst n{CBM-F}her auf die Organisation des Grafikspeichers, die BASIC- und die Maschinenroutinen ein.
  56.  
  57. --------------------------------------
  58.    Organisation des Grafikspeichers
  59. --------------------------------------
  60.  
  61. Was zur Erstellung von Grafiken ben{CBM-C}tigt wird, ist eine Routine, mit deren Hilfe sich Punkte an jede beliebige Bildschirmkoordinate setzen lassen. Um eine solche Routine zu erstellen, mu{CBM-V} uns die Organisation des Grafikspeichers bekannt sein.
  62.  
  63. Der Grafikspeicher:
  64. Der Grafikspeicher ist nicht in Punkten, sondern in Bytes organisiert. 8000 Bytes repr{CBM-F}sentieren 64.000 Bildpunkte. Da ein Byte aus acht Bits besteht, ist dies nat{CBM-X}rlich kein Wunder. Ein gesetztes Bit steht f{CBM-X}r einen Punkt in der Vordergrundfarbe, ein nichtgesetztes Bit f{CBM-X}r einen Punkt in der Hintergrundfarbe. Damit k{CBM-C}nnen wir schon anfangen, etwas zu experimentieren. Wir ben{CBM-X}tzen das Programm GRAFIK-ROUTINEN und schreiben ein kurzes Hauptprogramm. Wir f{CBM-X}llen den Grafikbereich mit Nullbytes:
  65.  
  66. 1050 GOSUB530:GOSUB560:GOSUB430
  67. 1060 FORI=GA TO GA+7999
  68. 1070 SYS912,GA,0:NEXT
  69. 1080 GOSUB480
  70.  
  71. SYS912,GA,0 entspricht einem POKEGA,0 mit dem Unterschied, da{CBM-V} hier auch unter das I/O geschrieben werden kann. Nach dem Programmstart wird der gesamte Bildschirm schwarz eingef{CBM-F}rbt. Wenn Sie dasselbe nochmals mit dem Wert 255 statt null versuchen, nimmt jeder Bildpunkt die Vordergrundfarbe an. Sie k{CBM-C}nnen verschiedene Werte ausprobieren - nicht den ganzen Grafikbereich f{CBM-X}llen, sondern blo{CBM-V} acht oder 320 Bytes - und sollten nach Ihren Experimenten zu den gleichen Ergebnissen kommen wie wir.
  72. Ein Byte ergibt auf dem Bildschirm eine Reihe von acht nebeneinander angeordneten Punkten oder Pixels. Das linke Pixel ist dem h{CBM-C}chstwertigen Bit zugeordnet, das rechte Pixel dem niederstwertigen. Acht aufeinanderfolgende Bytes ergeben acht untereinander angeordnete solcher Pixelreihen, die denselben Raum auf dem Bildschirm einnehmen, wie im Textmodus durch ein Zeichen belegt wird. Daher ist auch der Grafikbildschirm zu 40 Spalten und 25 Zeilen organisiert.
  73. Nachdem mit acht Bytes so ein Zeichen aufgebaut wurde, geht es mit dem n{CBM-F}chsten Byte weiter zum n{CBM-F}chsten Zeichen, das sich rechts davon anschlie{CBM-V}t. Nach vierzig Zeichen oder 320 Bytes ist eine Zeile fertig, und es folgt die n{CBM-F}chste. Die Aufteilung in Zeilen, Spalten, Pixelreihen und Pixelmuster erscheint h{CBM-C}chst logisch, ist aber wohl nicht gerade das, was wir gerne vorliegen h{CBM-F}tten, wenn wir an zu erstellende Grafiken denken. F{CBM-X}r Grafiken sollte der Bildschirm einfach eine zweidimensionale Fl{CBM-F}che sein, mit einem Koordinatensystem und der M{CBM-C}glichkeit, jeden einzelnen Punkt dieses Koordinatensystems auf einfache Weise anzusprechen.
  74. Das l{CBM-F}{CBM-V}t sich durchaus realisieren, denn wozu ist ein Rechner da? Er soll uns das Kopfzerbrechen ersparen und unsere Koordinaten in sein Pixelsystem umsetzen. Der Grafikbildschirm besitzt 320 mal 200 Bildpunkte, 200 in senkrechter und 320 in waagrechter Richtung. F{CBM-X}r dieses Koordinatensystem ben{CBM-X}tzen wir X-Werte von null bis 319 und Y-Werte von null bis 199. Beim C128 ist es {CBM-X}blich, da{CBM-V} der Koordinatenursprung in der linken oberen Bildschirmecke liegt und die Y-Werte von oben nach unten gerechnet werden. Dies soll auch beim C64 so beibehalten werden. Unsere Routine hat aus dem X- und Y-Wert die Speicheradresse zu berechnen und dort das ebenfalls vom X-Wert abh{CBM-F}ngige Bit zu setzen.
  75. Aus dem Y-Wert kann leicht die Nummer der Bildschirmzeile errechnet werden:
  76.  
  77. ZN=INT(Y/8)
  78.  
  79. Wir erhalten eine Zeilennummer von null bis 24. Die Zeilennummer multipliziert mit 320 ergibt den Offset der Zeilenanfangsadresse. Als wir die Y-Koordinate durch acht teilten, blieb ein Rest {CBM-X}brig, dieser darf nicht unber{CBM-X}cksichtigt bleiben, denn er gibt die Liniennummer in der Zeile an. Diese Liniennummer zum Zeilen_offset addiert, ergibt den Offset der Linienanfangsadresse:
  80.  
  81. LA=320*ZN+(Y-8*ZN)
  82. oder
  83. LA=312*ZN+Y
  84.  
  85. Die Y-Koordinate ist verwertet. Aus der X-Koordinate erhalten wir die Spaltennummer:
  86.  
  87. SN=INT(X/8)
  88. Damit steht die Speicheradresse fest. Die Spaltennummer multipliziert mit acht braucht nur zur Linienanfangsadresse und zur Anfangsadresse des Grafikspeichers GA addiert zu werden:
  89.  
  90. AD=312*ZN+Y+8*SN+GA
  91.  
  92. Jetzt mu{CBM-V} noch das richtige Bit gesetzt werden. Die Pixelnummer ergibt sich aus dem beim Teilen verbliebenen Rest oder durch XAND7. Der Bytewert k{CBM-C}nnte durch Potenzieren gewonnen werden, etwa:
  93.  
  94. B=2^(7-(XAND7))
  95.  
  96. Das Datenbyte aus der Adresse AD w{CBM-F}re damit zu verkn{CBM-X}pfen.
  97.  
  98. SYS929,AD,N
  99.  
  100. Diese Maschinenroutine ist gleichbedeutend mit N=PEEK(AD). Das Setzen des Pixels gesch{CBM-F}he jetzt mit:
  101.  
  102. SYS912,AD,B OR N
  103.  
  104. Allerdings nehmen solche Berechnungen etwas Zeit in Anspruch. Daher verwenden wir zum Pixelsetzen eine Maschinenroutine:
  105.  
  106. SYS985,AD,XAND7
  107.  
  108. F{CBM-X}r das Pixell{CBM-C}schen gibt es das Gegenst{CBM-X}ck SYS995,AD,XAND7.
  109.  
  110. Goemetrische K{CBM-C}rper:
  111. Der Punkt ist die Grundlage der Geometrie. Linien, ob gerade, gebogen oder kreisf{CBM-C}rmig, setzen sich aus Punkten zusammen. Mit dem Punkt allein kommen wir aber nicht weit. Die Gerade, das Rechteck und den Kreis wollen wir in unsere Minimalkonfiguration mit aufnehmen.
  112.  
  113. Die Gerade:
  114. Gegeben sind Anfangs- und Endpunkt einer Strecke durch die Koordinaten X1 und Y1 sowie X2 und Y2. Daraus lassen sich die Steigung und die Geradengleichung ermitteln:
  115.  
  116. M=(Y2-Y1)/(X2-X1)
  117. M=(Y-Y1)/(X-X1)
  118. (X-X1)*M=Y-Y1
  119. Y=Y1+(X-X1)*M
  120.  
  121. Die Steigung M errechnet sich aus der Differenz der Y-Werte geteilt durch die Differenz der X-Werte. Durch Ersetzen des Endpunktes durch X und Y und eine Umstellung ergibt sich die Gleichung f{CBM-X}r den Y-Wert.
  122. Die Darstellung der Geraden ist kein Problem mehr:
  123.  
  124. M=(Y2-Y1)/(X2-X1)
  125. FOR X=X1 TO X2 STEP SGN(X2-X1)
  126. Y=Y1+(X-X1)*M:GOSUB760:NEXT
  127.  
  128. Die SGN-Funktion ist n{CBM-C}tig, weil X2 auch kleiner als X1 sein kann. Der Algorithmus liefert f{CBM-X}r Steigungen zwischen -1 und +1 eine gute Wiedergabe. Ist die Differenz der Y-Werte h{CBM-C}her als die Differenz der Y-Werte, treten unsch{CBM-C}ne Zwischenr{CBM-F}ume auf. Im Fall von X2=X1 gibt es sogar einen Programmabsturz. Dies kann aber behoben werden. Statt den X-Werten einen Y-Wert zuzuordnen, wird die Sache in diesen F{CBM-F}llen umgedreht:
  129.  
  130. IFABS(Y2-Y1)>>ABS(X2-X1)THENGOTO...
  131. M=(X2-X1)/(Y2-Y1)
  132. FOR Y=Y1 TO Y2 STEP SGN(Y2-Y1)
  133. X=X1+(Y-Y2)*M:GOSUB760:NEXT
  134.  
  135. Die Unterroutine GOSUB760 sorgt f{CBM-X}r die Wiedergabe des betreffenden Punktes. Um Rechenungenauigkeiten auszugleichen, sollte stets eine Rundung des errechneten Koordinatenwertes stattfinden, etwa Y=INT(Y+.5).
  136.  
  137. Das Rechteck:
  138. Das Rechteck besteht aus vier Linien. Es m{CBM-X}ssen daf{CBM-X}r nur viermal die richtigen Anfangs- und Endkoordinaten bereitgestellt werden. Die Rechteckroutine erwartet Koordinaten zweier gegen{CBM-X}berliegender Ecken.
  139.  
  140. Der Kreis:
  141. Zur Kreisberechnung existieren zwei M{CBM-C}glichkeiten. Die erste arbeitet mit dem Bogenma{CBM-V} und der Sinus- sowie der Cosinusfunktion. Dieses Verfahren besitzt zwei Nachteile. Winkelfunktionen ben{CBM-C}tigen viel Rechenzeit, au{CBM-V}erdem kostet die Errechnung eines Kreises mit kleinem Radius dieselbe Zeit wie ein gro{CBM-V}er Kreis, wenn mit gleichen Gradabst{CBM-F}nden gearbeitet wird. Die zweite M{CBM-C}glichkeit, mit der Wurzelfunktion zu arbeiten, erscheint sinnvoller, da hier nur die wirklich relevanten Punkte ausgerechnet werden:
  142.  
  143. KY=SQR(R*R-KX*KX)
  144.  
  145. Diese Funktion ordnet jedem KX-Wert genau einen KY-Wert zu. F{CBM-X}r einen Viertelkreis von 90 bis 45 Grad sind die Ergebnisse sehr gut. Darunter aber kommt es zu gr{CBM-C}{CBM-V}eren L{CBM-X}cken, da dort nicht jedem Y-Wert auch ein X-Wert zugeordnet wird. Die L{CBM-C}sung ist auch hier wieder die Umkehrfunktion. Wir lassen die KX-Werte nicht von null bis R, sondern nur von null bis R/SQR(2) laufen, was dem 45-Grad-Winkel entspricht. Aus dem KY-Wert lassen sich insgesamt acht Kreispunkte gewinnen, n{CBM-F}mlich einer in je einem der vier Quadranten und dasselbe nochmals f{CBM-X}r die Umkehrfunktion:
  146.  
  147. Funktion
  148. X=XM+KX:Y=YM+KY:GOSUB760
  149. X=XM-KX:Y=YM+KY:GOSUB760
  150. X=XM-KX:Y=YM-KY:GOSUB760
  151. X=XM+KX:Y=YM-KY:GOSUB760
  152.  
  153. Umkehrfunktion
  154. X=XM+KY:Y=YM+KX:GOSUB760
  155. X=XM-KY:Y=YM+KX:GOSUB760
  156. X=XM-KY:Y=YM-KX:GOSUB760
  157. X=XM+KY:Y=YM-KX:GOSUB760
  158.  
  159. Im Programm ab Zeile 820 wurden diese Berechnungen in eine komprimiertere Form gebracht. Au{CBM-V}erdem wurde bei der Funktionswertberechnung eine Rundung eingebaut, die unsch{CBM-C}ne Zacken bei Vielfachen von 90 Grad verhindert. Der Kreisroutine sind die Mittelpunktskoordinaten XM und YM sowie der Radius R zu {CBM-X}bergeben.
  160. Sie k{CBM-C}nnen auch einmal versuchen, einen gef{CBM-X}llten Kreis zu erstellen. Hierzu ist in einer Schleife der Radius R von null bis zum gew{CBM-X}nschten Endwert laufen zu lassen. Der Radius sollte nicht allzu gro{CBM-V} gew{CBM-F}hlt werden, da der Aufbau dann sehr lange dauert. Au{CBM-V}erdem sollte er nicht in Einerschritten, sondern in 0,5er-Schritten erh{CBM-C}ht werden, da ansonsten einige nicht ausgef{CBM-X}llte Punkte, besonders in diagonaler Richtung, auftreten k{CBM-C}nnen.
  161.  
  162. Schrift:
  163. Printanweisungen zeigen im Grafikmodus leider keinerlei Wirkung. Dennoch wird gew{CBM-X}nscht, Grafiken auch beschriften zu k{CBM-C}nnen. Die einzige M{CBM-C}glichkeit, Zeichen im Grafikmodus zu erzeugen, ist es, die Bitmuster der Buchstaben in den Grafikspeicher zu bef{CBM-C}rdern. Diese Bitmuster finden sich im Zeichengenerator-ROM ab Adresse $D000:
  164.  
  165. 0 $D000 bis $D3FF
  166.   Gro{CBM-V}buchstaben/Grafik
  167. 1 $D400 bis $D7FF dasselbe invers
  168. 2 $D800 bis $DBFF Klein-/Gro{CBM-V}-
  169.   buchstaben
  170. 3 $DC00 bis $DFFF dasselbe invers
  171.  
  172. Die Adresse mit dem gew{CBM-X}nschten Bitmuster berechnet sich aus dem Bildschirmcode des Zeichens multipliziert mit acht und der Addition der Anfangsadresse des gew{CBM-X}nschten Zeichensatzes. Sei BC der Bildschirmcode und GZ eine Nummer von null bis drei, die f{CBM-X}r den gew{CBM-X}nschten Zeichensatz stehen soll, so berechnen wir AD durch:
  173.  
  174. AD=BC*8+GZ*1024+53248
  175.  
  176. Mit einem PEEK-Befehl allein kann nicht aus dem Zeichengenerator-ROM gelesen werden, da die CPU sonst statt auf dieses ROM auf die I/O-Adressen zugreifen w{CBM-X}rde. Um in das darunterliegende ROM zu gelangen, mu{CBM-V} das I/O erst ausgeschaltet werden. Dazu ist Bit zwei des Prozessorports auf Adresse 1 auf null zu setzen. Doch auch dies darf nicht ohne weiteres geschehen, da die alle f{CBM-X}nfzigstel Sekunden erfolgende Interruptroutine auf die I/O-Adressen zugreifen m{CBM-C}chte und mit dem Zeichen-ROM nichts anfangen kann.
  177. In BASIC kann der Interrupt nicht mit einem simplen CPU-Befehl gesperrt werden. Wohl aber kann das Auftreten des Interrupts verhindert werden, denn dieser wird, da er zeitabh{CBM-F}ngig erfolgt, durch einen Timer im CIA-1-Baustein ausgel{CBM-C}st. Wird Bit null in der Adresse 56334 auf null gesetzt, wird der Timer gestoppt, und der Interrupt ist somit, bis der Timer wieder in Gang gebracht wird, verhindert. Den Bildschirmcode eines Zeichens k{CBM-C}nnen wir aus Speicherzelle 1024 erhalten, nachdem wir dieses Zeichen in die linke obere Bildschirmecke geschrieben haben:
  178.  
  179. PRINTCHR$(19)Z$;
  180. AD=PEEK(1024)*8+1024*GZ+53248
  181. POKE56334,PEEK(56334)AND254
  182. POKE1,PEEK(1)AND251
  183. FORI=0 TO 7
  184. SYS912,ZZ+I,PEEK(AD+I):NEXT
  185. ZZ=ZZ+8:POKE1,PEEK(1)OR4
  186. POKE56334,PEEK(56334)OR1
  187.  
  188. Die Variable ZZ ist der Zeichenzeiger, der auf die durch Zeichen zu beschreibende Stelle im Grafikspeicher weist. Nach dem Schreiben des Zeichens ist dieser Zeiger um acht zu erh{CBM-C}hen, damit er auf die Stelle f{CBM-X}r das n{CBM-F}chste Zeichen zeigt.
  189.  
  190. Maschinenroutinen:
  191. Einige {SHIFT--}berlegungen haben uns zum Verfassen von Maschinenroutinen bewogen: Es m{CBM-X}{CBM-V}te doch auch m{CBM-C}glich sein, alle 64 KByte vom RAM des C64 zu nutzen. Mit POKE-Befehlen lassen sich alle RAM-Adressen mit Ausnahme der vier KByte I/O-Bereich erreichen. Mit PEEK-Befehlen sieht die Sache sehr schlecht aus. Unter das Kernal-ROM mag man ja noch kommen, wenn man den CPU-Port entsprechend umstellt und den Interrupt sperrt. Das BASIC-ROM kann nat{CBM-X}rlich nicht von BASIC aus ausgeschaltet werden, denn dann geht nichts mehr.
  192. Dennoch w{CBM-F}re es schade, auf wertvollen Speicherbereich verzichten zu m{CBM-X}ssen. Da f{CBM-X}r schnelles L{CBM-C}schen des Grafikbildschirms Maschinenroutinen n{CBM-C}tig sind, die nat{CBM-X}rlich auf jeden RAM-Bereich zugreifen sollen, entschieden wir uns, da wir bereits dabei waren, Maschinenroutinen auch f{CBM-X}r andere Zwecke zu entwickeln. Diese Maschinenroutinen legten wir in den Kassettenpuffer, um den daf{CBM-X}r {CBM-X}blicherweise genutzen Bereich von $C000 bis $CFFF unber{CBM-X}hrt zu lassen. Mit diesen Maschinenroutinen ist es auch m{CBM-C}glich, das Video-RAM unter das I/O zu legen, so da{CBM-V} kein einziges Byte vom normal zu nutzenden Speicherbereich verlorengeht. Folgende Routinen sorgen f{CBM-X}r vollst{CBM-F}ndige RAM-Ausnutzung:
  193.  
  194. $033C bis $0345 RAM einschalten:
  195. Diese Routine darf nur von Maschinenprogrammen aufgerufen werden, da die ROMs und das I/O ausgeschaltet werden, so da{CBM-V} in BASIC gar nichts mehr gehen k{CBM-C}nnte. W{CBM-F}hrend das vollst{CBM-F}ndige RAM eingeschaltet ist, mu{CBM-V} der Interrupt gesperrt sein, damit kein Absturz erfolgt. Das Abschalten der ROMs und des I/O wird erreicht, indem die Bits null und eins des Prozessorports in Adresse $01 mit AND #$FC auf null gesetzt werden. Zum Undieren wird der Akku ben{CBM-C}tigt. Mit PHA und PLA wird daf{CBM-X}r gesorgt, da{CBM-V} sich die aufrufenden Routinen nicht um das Sichern des Akkuinhaltes zu k{CBM-X}mmern haben.
  196.  
  197. $0346 bis $034F ROM und I/O einschalten:
  198. Diese Routine darf immer aufgerufen werden. Zweckm{CBM-F}{CBM-V}igerweise geschieht dies nat{CBM-X}rlich nur von den Maschinenroutinen aus, in denen vorher ROM und I/O ausgeschaltet wurden. Durch AND #$03 werden die Bits null und eins des Prozessorports in Adresse eins wieder auf eins gesetzt. Danach kann auch der Interrupt wieder zugelassen werden, so da{CBM-V} das System sich anschlie{CBM-V}end im Normalzustand befindet.
  199.  
  200. $0350 bis $0360 Speicher f{CBM-X}llen:
  201. Diese Routine ist von BASIC nutzbar. Sie erm{CBM-C}glicht, RAM-Bereiche blockweise zu f{CBM-X}llen. Der Aufruf erfolgt von BASIC aus mit SYS848. Zuvor m{CBM-X}ssen allerdings ein paar Vorbereitungen getroffen werden. Dem Akku ist mit POKE780,W ein beliebiger F{CBM-X}llwert zu {CBM-X}bergeben. Dem X-Register ist mit POKE781,B die Anzahl der zu f{CBM-X}llenden 256-Byte-Bl{CBM-C}cke mitzuteilen. In die Speicherstellen $FB und $FC ist die Anfangsadresse des zu f{CBM-X}llenden Speicherbereiches zu schreiben, etwa POKE251,0:POKE252,VH f{CBM-X}r das Video-RAM. Diese F{CBM-X}llroutine dient im Grafikprogramm zum globalen Setzen der Farbe f{CBM-X}r den gesamten Bildschirm und zum L{CBM-C}schen des Grafikbildschirms.
  202.  
  203. Farbe setzen:
  204. POKE780,16*VF+HF:POKE781,4
  205. POKE251,0:POKE252,VH:SYS848
  206. Bildschirm l{CBM-C}schen:
  207. POKE780,0:POKE781,32
  208. POKE251,0:POKE252,GH:SYS848
  209.  
  210. Das F{CBM-X}llen eines Speicherbereiches mit Hilfe einer Laufschleife in BASIC w{CBM-F}re etwas zu langsam; in Maschinensprache geht es einige tausend Mal schneller. Die Besonderheit der Routine ist, da{CBM-V} zu Beginn mit JSR $033C die 64 KByte RAM eingeschaltet und am Ende mit BEQ $0346 wieder ausgeschaltet werden.
  211.  
  212. $0361 bis $0379 Daten einlesen:
  213. Von einem beliebigen Eingabeger{CBM-F}t k{CBM-C}nnen Daten in einen beliebigen RAM-Bereich eingelesen werden. Das Einlesen geschieht mit JSR $FFCF. In einer Laufschleife wird eingelesen, bis entweder keine Daten mehr verf{CBM-X}gbar sind, BCS $0346, oder bis die gew{CBM-X}nschte Anzahl von Bl{CBM-C}cken eingelesen wurde, BEQ $0346. Das Schreiben der Daten mit JSR $033C, STA ($FB),Y und JSR $0346 erfolgt in das RAM. Die Routine wird im Grafikprogramm zum Laden eines Grafikfiles ben{CBM-X}tzt, nachdem das File er{CBM-C}ffnet, als Eingabeger{CBM-F}t definiert und der Routine die Anfangsadresse und die Blockzahl mitgeteilt wurde. Der Aufruf in BASIC erfolgt mit SYS865:
  214.  
  215. OPEN8,8,8,"GRAFIKBILD,P,R"
  216. POKE781,8:SYS65478
  217. GETA$:GETA$
  218. POKE251,0:POKE252,GH
  219. POKE781,32:SYS865
  220. SYS65484:CLOSE8
  221.  
  222. Hier w{CBM-X}rde ein Grafikbild ohne Farbinformation geladen werden. Nach dem {CBM--}ffnen, dem Definieren des Eingabeger{CBM-F}tes mit POKE781,8:SYS65478 werden die ersten beiden Bytes, die noch keine Datenbytes sind, sondern nur die Ladeadresse darstellen, mit GETA$:GETA$ beseitigt. Nach der {SHIFT--}bermittlung der Adresse des Grafikspeichers und der Blockzahl werden mit SYS865 die Daten eingelesen. Anschlie{CBM-V}end ist mit SYS65484 der Eingabekanal und mit CLOSE8 das File zu schlie{CBM-V}en.
  223.  
  224. $0378 bis $038F Daten ausgeben:
  225. Dies ist das Gegenst{CBM-X}ck zu Daten einlesen. Das Ausgeben geschieht mit JSR $FFD2, der Aufruf in BASIC mit SYS890:
  226.  
  227. OPEN8,8,8,"GRAFIKBILD,P,W"
  228. POKE781,8:SYS65481
  229. PRINTCHR$(0)" <169>;
  230. POKE251,0:POKE252,GH
  231. POKE781,32:SYS890
  232. SYS65484:CLOSE8
  233.  
  234. Das Programmfile GRAFIKBILD wird jetzt zum Schreiben er{CBM-C}ffnet. Mit POKE781:SYS65481 k{CBM-C}nnen wir es als Eingabeger{CBM-F}t definieren. Als erstes m{CBM-X}ssen zwei Bytes gesendet werden, zweckm{CBM-F}{CBM-V}igerweise die Werte null und 32, da an Adresse $2000 beim C128 der Grafikbereich beginnt. Nachdem die Adresse des Grafikspeichers und die Blockzahl {CBM-X}bergeben sind, werden die Daten mit SYS890 auf Diskette ausgegeben.
  235. Das Schlie{CBM-V}en vollzieht sich wie beim Laden. Dieses sequentielle Einlesen und Ausgeben der Daten besitzt gegen{CBM-X}ber der {CBM-X}blichen LOAD- oder SAVE-Routine noch einen weiteren Vorteil: Video-RAM und Grafikspeicher brauchen bei Grafikfiles mit Farbinformation nicht unmittelbar aufeinander folgen. Das Laden oder Speichern l{CBM-F}{CBM-V}t sich in vier Bl{CBM-C}cke f{CBM-X}r die Farbinformation und 32 Bl{CBM-C}cke f{CBM-X}r die Grafikdaten jederzeit splitten, etwa:
  236.  
  237. POKE251,0:POKE252,VH
  238. POKE781,4:SYS890
  239. POKE252,GH:POKE781,32:SYS890
  240.  
  241. $0390 bis $03A0 Schreibzugriff:
  242. Diese Routine kann nur von BASIC aus benutzt werden. Sie ersetzt den POKE-Befehl. Statt POKEA,I sollte SYS912,A,I benutzt werden. Damit lassen sich auch Daten in das vom I/O {CBM-X}berlagerte RAM schreiben. Die Routine ist bis auf die Behandlung des dem SYS-Befehl folgenden Kommas durch JSR $AEFD und dem Einschalten des RAMs mit der Original- POKE-Routine des C64 ab Adresse $B824 im ROM identisch. JSR $B7EB bringt die POKE-Adresse in die Speicherstellen $14 und $15 sowie den zu schreibenden Bytewert in das X-Register.
  243.  
  244. $03A1 bis $03C6 Lesezugriff:
  245. W{CBM-F}hrend der PEEK-Befehl in das ROM und das I/O greift, erm{CBM-C}glicht diese Routine den Lesezugriff auf das RAM. Freilich handelt es sich hier um keine Funktion wie etwa N=PEEK(AD), doch ist die Handhabung trotzdem einfach. SYS929,AD,N ist jetzt zu schreiben, soll das Byte in der Adresse AD im RAM der Variablen N {CBM-X}bergeben werden.
  246. Ein Lesezugriff ist wegen der Parameter{CBM-X}bergabe schon etwas schwieriger zu behandeln als ein Schreibzugriff. Der Beginn ist noch fast wie beim Poken. Jedoch sind nicht zwei Werte zu holen, sondern nur die Adresse. Mit JSR $AEFD wird auch hier wieder das Komma behandelt. Das Besorgen der Adresse erfahren wir, wenn wir uns die Routine $B7EB n{CBM-F}her betrachten. Mit JSR $AD8A erhalten wir den numerischen Wert. Mit JSR $B7F7 wird er in das Adressenformat gewandelt und in den Speicherstellen $14 und $15 abgelegt.
  247. Das Lesen des gew{CBM-X}nschen Bytes ist jetzt kein Problem mehr, jedoch die {SHIFT--}bergabe an die Variable. Mit TAY und JSR $B3A2 wird der Byte-Wert in das f{CBM-X}r BASIC {CBM-X}bliche Flie{CBM-V}kommaformat gewandelt. Danach ist dieser an die Variable zu {CBM-X}bergeben. Vorher wird mit JSR $AEFD wieder das Komma behandelt. JSR $B08B stellt die Adresse der Variablen im Akku und dem Y-Register zur Verf{CBM-X}gung.
  248. Au{CBM-V}erdem wird dabei in der Speicheradresse $0E vermerkt, um welchen Variablentyp es sich handelt. Um unseren Wert in die gefundene Variable zu bringen, benutzen wir einen Teil der Let-Routine. Die Variablenadresse mu{CBM-V} an die Speicherstellen $49 und $4A {CBM-X}bergeben werden. Nachher ist das Typ-Flag in ein CPU-Register zu laden, so da{CBM-V} die Statusflags beeinflu{CBM-V}t werden. Je Vorzeichen legt die Routine $A9C2 den im Flie{CBM-V}komma-Akkumulator liegenden Wert im Integer- oder Realformat in der durch $49 und $4A adressierten Variablen ab.
  249.  
  250. $03C7 bis $03DB Bit bestimmen:
  251. Diese Routine ist eine Unterroutine f{CBM-X}r zwei weitere Routinen, Bit setzen und Bit l{CBM-C}schen. Sie stellt die Adresse, in der ein Bit manipuliert werden soll, in den Speicherstellen $14 und $15 zur Verf{CBM-X}gung. Au{CBM-V}erdem wird im Akkumulator ein Bit gesetzt, das der Nummer des zu setzenden oder zu l{CBM-C}schenden Bits entspricht. Das linke Pixel besitzt die Nummer null. Durch Hineinschieben des Carryflags in den Akku von rechts wird Bit sieben gesetzt.
  252. Bei h{CBM-C}heren Pixelnummern wandert das gesetzte Bit weiter nach rechts, bis etwa bei Pixel Nummer sieben Bit null gesetzt ist. Diese Routinen w{CBM-F}ren nicht unbedingt erforderlich gewesen, denn mit den Routinen f{CBM-X}r den Lese- und Schreibzugriff in Verbindung mit OR- oder AND-Verkn{CBM-X}pfung w{CBM-F}re das Setzen oder L{CBM-C}schen eines Bits auch von BASIC aus machbar gewesen. So aber ist es jedenfalls einfacher.
  253.  
  254. $03D9 bis $03E2 Bit setzen:
  255. Ist auf dem Grafik-Bildschirm an der Koordinate X,Y ein Pixel zu setzen, so mu{CBM-V} daraus in BASIC die Adresse im Grafikspeicher AD und die Pixelnummer, die sich durch X AND 7 ergibt, bestimmt werden. Daraufhin kann das Pixel gesetzt werden mit:
  256.  
  257. SYS985,AD,XAND7
  258.  
  259. Die Maschinenroutine st{CBM-X}tzt sich auf die Routine Bit bestimmen. Der Akkuinhalt mit dem gesetzen Bit ist nur noch mit dem Byte der gew{CBM-X}nschten Adresse durch OR zu verkn{CBM-X}pfen, um auch dort das entsprechende Bit zu setzen.
  260.  
  261. $03E3 bis $03EC Bit l{CBM-C}schen:
  262. Diese Routine ist das Gegenst{CBM-X}ck zu Bit setzen. Der Aufruf erfolgt mit:
  263.  
  264. SYS995,AD,XAND7
  265.  
  266. Um das entsprechende Bit auf null zu setzen, wird der Akkuinhalt mit EOR #$FF invertiert, so da{CBM-V} alle Bits, bis auf das gew{CBM-X}nschte, auf Eins gesetzt sind. Nach dem Verkn{CBM-X}pfen des Akkuinhaltes mit dem Byte der gew{CBM-F}hlten Speicherstelle und dem Zur{CBM-X}ckschreiben ist das Pixel auf dem Bildschirm gel{CBM-C}scht.
  267. Mit diesen Routinen ist der Kassettenpuffer fast restlos gef{CBM-X}llt, so da{CBM-V} dort nichts mehr Sinnvolles unterzubringen ist. F{CBM-X}r schnelle Zeichenfunktionen, etwa Linien, Kreise, Vielecke oder das Auff{CBM-X}llen geschlossener Figuren w{CBM-F}ren umfangreiche Routinen vonn{CBM-C}ten. Doch l{CBM-F}{CBM-V}t sich sicherlich mit diesem leicht in eigene Programme einbindbaren Minimalkonzept eine Menge anfangen. Grafik mit dem C64 sollte f{CBM-X}r Sie nicht l{CBM-F}nger ein Buch mit sieben Siegeln sein.
  268.