Grafik für Profis
Allen Grafikbegeisterten soll dieser Kurs Tips und Programmierkniffe zum Thema hochauflösende Grafik vermitteln. Wir zeigen Ihnen leistungsstarke Grafik-Routinen mit sehr schnellen Befehlen. Außerdem bekommen Sie ein Programm für 3-D-Grafik.
Wohl jeder Assembler-Alchimist, der gerade das kleine ABC der Maschinensprache kennengelernt hat, wird bei dem Versuch, ein einfaches Basic-Programm in Assembler zu übersetzen, auf nahezu unüberwindliche Schwierigkeiten gestoßen sein. Erfordert doch schon die Multiplikation zweier 16-Bit-Zahlen ein kompliziertes Unterprogramm, so wird der Aufwand bei dem Versuch, den Sinus oder den Logarithmus aus einer Fließkommazahl zu berechnen, geradezu gigantisch. Vorausgesetzt, man will alle erforderlichen Unterprogramme selber schreiben. Glücklicherweise sind die benötigten Routinen jedoch schon im Basic-ROM des C 64 vorhanden. Woran liegt es aber, daß man auf solche Schwierigkeiten stößt, wenn man einen Algorithmus, der sich in Basic relativ einfach bewältigen läßt, in Assembler formulieren will? Nun, die Antwort liegt darin begründet, daß Basic eine sogenannte »höhere« Programmiersprache ist. Die Befehle, die Sie im Wortschatz der Sprache Basic finden, werden Sie im Wortschatz des 6510-Prozessors vergeblich suchen. Das liegt daran, daß jeder einzelne Basic-Befehl sich aus vielen Maschinenbefehlen zusammensetzt. Jedes dieser Maschinenprogramme simuliert praktisch einen Basic-Befehl. Sie werden fragen, was dies alles mit diesem Kurs zu tun hat. Wie Sie der Überschrift entnehmen können, geht es um die Programmierung von hochauflösender Grafik. Auch hier geht es darum, mit Hilfe des 6510-Wortschatzes kompliziertere Befehle aufzubauen, die dazu dienen, Punkte zu zeichnen, Linien zu ziehen etc.
Die meisten dieser Befehle enthalten bestimmte Rechenalgorithmen, die dazu dienen, die Koordinaten eines zu zeichnenden Punktes zu bestimmen. Eine gute Voraussetzung für diesen Grafikkurs sind die beiden Kurse »Reise durch die Wunderwelt der Grafik« und »Assembler ist keine Alchimie« von H. Ponnath. Wenn Sie diese beiden Kurse aufmerksam verfolgt haben, dann sind Sie mit den Grafikfähigkeiten des C 64 vertraut. Mit einigen der dort erworbenen Assemblerkenntnissen dürften Sie wohl in der Lage sein, die zum Zeichnen in der Hi-Res-Grafik wichtigen Befehle selbst in Maschinensprache zu formulieren.
Ein Ergebnis eines solchen Versuchs könnte etwa das Programm »HiRes-3« von H. Ponnath sein. Wenn Sie sich aber eine zeitlang intensiv mit diesem Programm beschäftigt haben, werden Sie merken, daß die Zeichengeschwindigkeit der meisten Befehle noch Wünsche offen läßt. Der Grund hierfür liegt nicht etwa darin, daß das Programm schlecht programmiert wurde, sondern das Problem liegt in der Berechnung der Algorithmen. Das betrifft besonders die Befehle, die mit der herkömmlichen 16-Bit-Arithmetik scheinbar nicht mehr zu bewältigen sind (Circle-Befehl). Gerade hierin aber zeigt sich die wahre Programmierkunst. Nämlich die Fähigkeit, mit einigen Programmierkniffen und mit etwas Fantasie das scheinbar Unmögliche doch noch möglich zu machen. Ich möchte versuchen, Ihnen in diesem Kurs einige dieser »Tricks« zu vermitteln. Dazu eignet sich meiner Änsicht nach nichts besser als das reizvolle Thema »Hochauflösende Grafik«. Dazu bekommen Sie nebenbei auch noch ein professionelles Grafikprogramm, mit dem es sich hervorragend arbeiten läßt. Ich möchte Ihnen nun dieses Programm, das der Hauptgegenstand dieses Kurses sein wird, etwas genauer vorstellen. »Profi-Grafik 64«, so der Name des Programms, besteht aus vielerlei Grafikroutinen, die der besseren Handhabung wegen zu einer Basic-Erweiterung zusammengefaßt wurden. Profi-Grafik 64 hat einige hervorstechende Merkmale:
- Es stehen zwei Grafikseiten zur Verfügung
- Die Befehle fallen durch ihre Leistungsstärke, Schnelligkeit und leichte Handhabung auf
- Multicolor-Grafik wurde ohne Einschränkungen verwirklicht
- Es können gleichzeitig acht Sprites interruptgesteuert über den Bildschirm bewegt werden
- Durch einfache Befehle wird 3-D-Grafik möglich
Nachdem ich Ihnen hoffentlich ein wenig den Mund wässrig gemacht habe, wollen wir nun mit der Besprechung des Programms beginnen.
In dieser Folge finden Sie ein ziemlich langes Assemblerprogramm (Listing 1) sowie ein MSE-Listing (Listing 2). Dieses Listing bildet den Grundstock für eine Basic-Erweiterung und hat eigentlich nichts mit den Grafikroutinen zu tun. Deshalb tippen Sie dieses Listing am besten erst mal ab und speichern es.
Schauen Sie sich nun einmal das Assemblerlisting an. Sie finden dort die Routinen der ersten neun Befehle von Profi-Grafik 64. Ihre Aufgabe ist es vor allem, die hochauflösende Grafik einzuschalten und die Parameter für andere Zwischenbefehle zu setzen. Die Befehle, die sich auf die Hardware beziehen, möchte ich so kurz wie möglich behandeln, weil deren Theorie schon ausführlich im Grafikkurs von H. Ponnath behandelt wurde.
1. SCREEN nr.
Da wäre als erstes der SCREEN-Befehl.
Durch ihn bestimmt man die Nummer des Bildschirms, den man anwählen will. Der Parameter »nr.« kann 0 oder 1 sein. Die Bitmap von Screen0 nimmt den Bereich von $A000-$BFFF ein und das Video-RAM den Bereich von $8C00-$8FFF.
Bei Screenl sind dies die Bereiche $E000-$FFFF für die Bitmap und $CC00-$CFFF für das Video-RAM.
Übrigens wird im Register »Scrnum« nicht die Nummer selbst abgelegt, wie man denken könnte, sondern das High-Byte der Bitmap-Anfangsadresse.
Dies ist deshalb möglich, weil die Bytes $AO und $EO bei einer Bit-Abfrage die Flags unterschiedlich beeinflussen. Dies wird beispielsweise beim HiRes-Befehl ausgenutzt.
2. HIRES
Der Befehl dient nur dazu, den Bildschirm, der mit SCREEN festgelegt wurde, einzuschalten. Das Zustandekommen der einzelnen Werte, mit denen die VIC-Register versorgt werden, soll in der nächsten Folge dieses Kurses beschrieben werden. Ganz Ungeduldige können im H. Ponnaths Grafikkurs, Ausgabe 7/84 nachschauen.
3. MULTI
Schaltet den Multicolormodus ein. Ansonsten wie HIRES.
4. TEXT
Stellt die ursprünglichen Werte in den VIC-Registern wieder her, schaltet also auf den Textbildschirm zurück. Dieser Befehl wird auch bei jedem Warmstart (Programmende) und bei einem Druck auf die RUN/STOP-Taste ausgeführt. Man kann die Grafikbefehle also nur im Programm-Modus verwenden. Der Vorteil dabei ist, daß bei einer Fehlermeldung automatisch in den Text-Modus geschaltet wird.
5. CLEAR
Dieser Befehl löscht die Bitmap des mit SCREEN angewählten Bildschirms.
6. HICOL zf,hf(,c3)
Der Befehl HICOL setzt die Farben im Video-RAM des mit SCREEN angewählten Bildschirms. Im HiRes-Modus brauchen nur die Parameter »zf« und »hf« für Zeichenfarbe und Hintergrundfarbe angegeben werden. Folgt noch ein Komma, so wird der Parameter »c3« geholt und damit das FarbRAM gefüllt. Dieser Parameter braucht nur im Multicolor-Modus angegeben zu werden. Dann gelten die drei Parameter als Zeichenfarben 1, 2 und 3.
7. MODE m
Dieser Befehl gestattet es, die Wirkungsweise des PLOT-Befehls zu beeinflußen. Der Parameter »m« darf zwischen 0 und 2 liegen, wobei bedeuten: 0 = Punkt setzen 1 = Punkt löschen 2 = Punkt invertieren Damit der PLOT-Befehl zwischen den einzelnen Modi unterscheiden kann, wird das Register »Plotmode« durch einen Bit-Befehl abgefragt. Dabei gilt folgende Definition:
0 = Punkt setzen (Z-Flag gesetzt)
64 = Punkt löschen (V-Flag gesetzt)
128 = Punkt invertieren (N-Flag gesetzt)
Das Register »Plotmode« wird im MODE-Befehl 0 entsprechend gesetzt.
8. INK co
Dieser Befehl ist nur im Multicolor-Modus wirksam. Mit ihm wird die Zeichenfarbe festgelegt. Der Parameter »co« darf zwischen 0 und 3 liegen, wobei 0 = Hintergrundfarbe bedeutet. Die Farbe wird im Register »Multicol« abgelegt.
9. PLOT x,y
So, nun endlich kommen wir zum ersten interessanten Befehl, bei dem die Rechnerei in Maschinensprache anfängt.
Der PLOT-Befehl dient dazu, ein Bit in der Bitmap, das durch die Koordinaten »x« und »y« festgelegt wird, zu setzen, zu löschen oder zu invertieren. Die x-Koordinate darf sich dabei zwischen 0 und 319 bewegen, die y-Koordinate zwischenO und 199, wobei der Ursprung des Koordinatensystems in der linken oberen Bildschirmecke liegt. Nun ist es, wie Sie wohl wissen, nicht so einfach herauszufinden, welches Bit in welchem Byte zu einer bestimmten Bildschirmkoordinate gehört. Um das festzustellen, müssen wir uns den Aufbau der Bitmap anschauen (Bild 1).

Sie sehen, daß die ersten acht Byte untereinander liegen, die nächsten acht rechts daneben und so weiter, insgesamt 40 Spalten mal 8 Byte = 320 Byte. Im gleichen Stil sind 25 Zeilen untereinander aufgebaut. Das ergibt zusammen 25 mal 320 Byte = 8000 Byte. Der Bildschirmaufbau hat also große Ähnlichkeit mit dem des Textbildschirms. Nun gilt es, einen Algorithmus zu finden, der uns zu einer Bildschirmkoordinate x, y das entsprechende Byte in der Bitmap sowie die Bitposition innerhalb dieses Bytes liefert. Überlegen wir uns zunächst, wie sich die x-Koordinate auf die Byte-Position auswirkt. Wir müssen hier zwischen HiRes- und Multicolor-Grafik unterscheiden. Während im HiRes-Modus jedes Bit einem Punkt entspricht, benötigt man im Multicolor-Modus zwei Bits, um einen Punkt darzustellen. Deshalb gibt es dort nur 160 Punkte auf der x-Achse. Die Tabellen 1 und 2 zeigen, wie sich x-Koordinate und Byte-Nummer in der Bitmap zueinander verhalten, wenn wir die y-Koordinate gleich 0 setzen.


Sie sehen, daß im HiRes-Modus die unteren drei Bit für die Byte-Nummer unwichtig sind und deshalb gelöscht werden müssen. Dies geschieht mit der AND-Funktion:
xlo and #^11111000
Da die x-Werte größer als 255 sein können, müssen wir auch ein Highbyte berücksichtigen, bei dem allerdings nur das Bit 0 gesetzt sein kann, weil der höchste x-Wert319 = $013Fist. Fürdie HiRes-Grafik sähe der vorläufige Algorithmus also so aus:
256 * xhi+(xlo and #248)
Da es im Multicolor-Modus nur 160 x-Werte gibt, brauchen wir dort kein Highbyte zu berücksichtigen. Sie sehen in Tabelle 2, daß beim Lowbyte die unteren zwei Bit keine Rolle spielen und gelöscht werden müssen: xlo and #%11111100
Mit dieser Berechnungsweise würden wir allerdings nur auf eine maximale Byte-Nummer von 156 kommen. Der Punkt würde also anstatt am rechten Bildrand in der Bildschirmmitte gesetzt. Deshalb müssen alle Byte-Nummern noch mit 2 multipliziert werden, um die richtige Byte-Nummer zu erhalten:
2 * (xlo and #252)
Wie wirkt sich nun die y-Koordinate auf die Byte-Nummer aus?
Wenn diese nicht größer als 7 wird, kann sie direkt zur Byte-Nummer addiert werden. Wird y größer als 7, gelangen wir in eine neue Bildschirmzeile und müssen jeweils 320 Byte addieren. Um zu ermitteln, in welcher Zeile wir sind, müssen wir y durch 8 teilen und gelangen so zur Formel:
(y and #7) +320 * (y/8)
Damit hätten wir die beiden Algorithmen zusammen. Sie lauten:
1. Hires-Modus:
Byte-Nummer = 256 * xhi + (xlo and #248) + (Y and #7) + 320 * (Y/8)
2. Multi-Modus:
Byte-Nummer = 2 * (xlo and #252) + (Yand #7) + 320 * (Y/8)
Nun kommen wir zur Formulierung in Maschinensprache. Dazu legen wir erst fest, wie wir der Berechnungsroutine die Koordinaten übergeben. Und zwar soll der y-Wert im x-Register und der x-Wert in den Registern $14/$15 übergeben werden. Schauen sie sich nun die Routine »Hiplot« im Assemblerlisting an. Dies ist die Unterroutine zur Berechnung der Byte-Nummer im HiRes-Modus. Das Geheimnis der Routine liegtin der Art, wie der Term 320*y/8 berechnet wird. Diese Möglichkeit besteht allerdings nur dann, wenn der Multiplikant (320) konstant und der Multiplikator (y/8) in einem gewissen Bereich (hier 0 bis 24) schwankt. In so einem Fall berechnet man alle möglichen Ergebnisse vorher und legt diese in zwei Tabellen (Low- und Highbyte) ab. In der Berechnungsroutine braucht man dann nur noch den Multiplikator als Zeiger ins y-Register zu übertragen und lädt sich das benötigte Ergebnis aus der Tabelle. Hier sind die Ergebnisse in den Tabellen »Maltab« für die Lowbyte und »Maltabl« für die Highbyte abgelegt. Entscheidend bei der Berechnungsroutine ist weiterhin die Anordnung der einzelnen Summanden. Achten Sie außerdem immer auf den Zustand des Carry-Flags, das für die Addition wichtig ist! Die Nummer des Bytes in der Bitmap wird in den beiden Byte $F7/$F8 abgelegt. Am Ende der Routine wird noch die Bitposition innerhalb des Bytes errechnet. Dazu isolieren wir die x-Position mittels (xlo and # 7) und laden den Akku mit der Zweier-Potenz, die der x-Position entspricht. Diese Zweier-Potenzen sind ebenfalls in einer Tabelle (Hochtab) abgelegt.
Im Multi-Modus sieht das Feststellen der Bitposition etwas anders aus. Da wir hier nur vier x-Positionen in einem Byte haben, isolieren wir diese mittels (xlo and # 3). Dann laden wir den Akku mit dem Wert, bei dem die beiden Bits, die dieser x-Position entsprechen, gesetzt sind. Für die x-Position 0 wäre dies der Wert %11000000. Die vier Werte finden Sie in der Tabelle »Multab«.
Jetzt kommen wir zur Besprechung der PLOT-Routine an sich. Nachdem die Koordinaten aus dem Basic-Text geholt wurden, wird auf Multicolor-Modus geprüft. Dann verlaufen in beiden Teilzweigen der Routine (HPLOT und MPLOT) die Wege ähnlich. Zuerst werden die Koordinaten auf ihre Richtigkeit überprüft. Falls sie den zulässigen Bereich überschreiten, wird die Routine frühzeitig mit gesetztem Carry-Flag verlassen. Ansonsten wird in den Unterroutinen »Hiplot« oder »Muplot« die Byte-Nummer berechnet und die Bit-Position im Akku bereitgestellt. Nun wird das Register »Plotmode« mittels BIT-Befehl abgefragt und je nach Modus verzweigt. Die einzelnen logischen Verknüpfungen machen Sie sich am besten an Hand von Beispielen klar (ausprobieren!).
Zu erklären bleibt noch, wie ein Punkt im Multicolor-Modus gesetzt wird. Sie sehen, daß, nachdem die Bit-Position auf den Stack gerettet wurde, die betreffenden beiden Bits erst einmal gelöscht werden. Dann wird die Bit-Position wiedergeholt und die aktuelle Zeichenfarbe ins x-Register geladen. Sodann wird das Bit-Muster der momentanen Farbe hergestellt, indem es mit dem Bit-Muster der aktuellen Farbe AND-verknüpft wird. Die Bit-Muster der Farben stehen in einer Tabelle »Multab«. Sie erkennen, daß das Bit-Muster an allen vier x-Positionen steht. Versuchen Sie nun herauszufinden, warum die beiden Bits zuerst gelöscht werden müssen, bevor das Muster der neuen Farbe gesetzt werden kann!
Am Ende der Plot-Routine wird dann noch das Carry-Flag gelöscht, um anzuzeigen, daß die Koordinaten in Ordnung waren. Außer den Grafikbefehlen steht Ihnen auch noch ein Mini-Toolkit zur Verfügung. Zum einen ein OLD-Befehl, mit dem Sie ein versehentlich gelöschtes Programm wiederholen können sowie ein AUTO-Befehl, der die automatische Zeilennumerierung übernimmt. Dazu geben sie ein: AUTO Zeilennummer, Schrittweite (0-255). Verlassen können Sie den AUTO-Modus durch Drücken von »RETURN« bei einer neuen Zeile. Trifft der AUTO-Befehl auf eine schon vorhandene Zeile, so wird hinter der Zeilennummer ein Pfeil nach links ausgegeben. Geben Sie danach nur RETURN ein, wird die Zeile nicht überschrieben. Wollen Sie die Zeile überschreiben, dann ist vorher der Pfeil zu löschen.
Eingabehinweise
Listing 2 ist zunächst mit dem MSE einzugben und zu speichern. Im Anschluß daran muß der C 64 aus- und wieder eingeschaltet werden. Laden Sie nun einen Assembler, tippen den Quellcode (Listing 1) ab, lassen ihn übersetzen und laden anschließend Listing 2 absolut (LOAD »PG-MSE«, 8,1). Jetzt muß der Speicherbereich von $800 bis $8574 mit einem Monitorgespeichertwerden. Das Programm läßt sich nun mit SYS 64738 aktivieren.
(Andreas Schömann/cg)990 open1,4 995 sys 9*4096 1000 .opt oo,p1 1005 ; 1010 ;grafikroutinen 'profi-grafik 64' 1015 ; 1020 *= $8390 ;startadresse 1025 ; 1030 getcom = $aefd ;prueft auf komma 1035 getbyte = $b79e ;holt byte ins x-register 1040 getadr = $b7eb ;adresswert nach $14/$15 + getbyte 1045 chrget = $0073 ;holt naechstes zeichen 1050 chrgot = $0079 ;holt letztes zeichen 1055 illegal = $b248 ;fehlermeldung 'illegal quantity' 1060 ; 1065 scrnum = $9ff1 ;aktuelle bildschirmnummer 1070 ; 1075 screen jsr getbyte 1080 cpx #2 1085 bcc scrok 1090 jmp illegal 1095 scrok lda scrtab,x 1100 sta scrnum ;merken 1105 rts 1110 ; 1115 scrtab .byt $a0,$e0 1120 ; 1125 hires lda $dd00 ;16k-bereich,den der vic adressiert 1130 and #%11111100 ;festlegen $c000-$ffff 1135 bit scrnum 1140 bvs *+4 ;bei $e0 ist das v-flag gesetzt ! 1145 ora #%00000001 ;bereich von $8000-$bfff 1150 sta $dd00 1155 lda $d018 ;position des videorams 1160 ora #%00101000 ;festlegen $0c00-$0fff 1165 sta $d018 1170 jsr tex1 1175 lda $d011 ;einzelpunktmodus einschalten 1180 ora #%00100000 ;bit5=1 1185 sta $d011 1190 rts 1195 ; 1200 multi jsr hires ;hires-modus ein 1205 lda $d016 ;multicolormodus einschalten 1210 ora #%00010000 ;bit4=1 1215 sta $d016 1220 rts 1225 ; 1230 text lda $dd00 ;vic adressiert jetzt wieder 1235 ora #%00000011 ;bereich von $0000-$3fff 1240 sta $dd00 1245 lda $d018 ;videoram ab $0400-$07ff 1250 and #%11010111 1255 sta $d018 1260 lda $d011 ;einzelpunktmodus abschalten 1265 and #%11011111 1270 sta $d011 1275 tex1 lda $d016 ;multicolormodus abschalten 1280 and #%11101111 1285 sta $d016 1290 rts 1295 ; 1300 help = $20 ;hilfszeiger 1305 ; 1310 clear lda scrnum 1315 sta help+1 1320 lda #0 1325 sta help ;zeiger auf anfang der bitmap 1330 tay 1335 ldx #32 ;32 bloecke = 8 kbyte 1340 cloop sta (help),y ;byte loeschen 1345 iny 1350 bne cloop 1355 inc help+1 ;naechster block 1360 dex 1365 bne cloop 1370 rts 1375 ; 1380 hicol jsr getbyte ;zeichenfarbe holen 1385 stx help ;merken 1390 jsr getcom 1395 jsr getbyte ;hintergrundfarbe 1400 stx help+1 ;merken 1405 lda help ;zeichenfarbe 1410 asl a 1415 asl a ;mal 16 1420 asl a 1425 asl a 1430 clc 1435 adc help+1 ;+ hintergrundfarbe 1440 jsr hic1 ;mit diesem wert videoram fuellen 1445 jsr chrgot 1450 cmp #"," ;wenn noch ein komma folgt, 1455 bne mode-1 1460 jsr chrget 1465 jsr getbyte ;dann 3.zeichenfarbe holen 1470 txa 1475 ldx #$d8 ;und das farbram ($d800-$dfff) 1480 bne hic2 ;damit fuellen 1485 ; 1490 hic1 bit scrnum 1495 bvs scr1a 1500 ldx #$8c ;screen0 videoram von $8c00-$8fff 1505 .byt $2c ;bit-opcode 1510 scr1a ldx #$cc ;screen1 videoram von $cc00-$cfff 1515 hic2 stx help+1 1520 ldy #0 1525 sty help ;zeiger auf anfang videoram 1530 ldx #4 ;4 bloecke sind zu fuellen 1535 hloop sta (help),y 1540 iny 1545 bne hloop 1550 inc help+1 ;naechster block 1555 dex 1560 bne hloop 1565 rts 1570 ; 1575 plotmode = $9ff2 ;aktueller plotmodus 1580 ; 1585 mode jsr getbyte 1590 cpx #3 1595 bcc modeok 1600 illmode jmp illegal 1605 modeok lda modetab,x 1610 sta plotmode ;modus merken 1615 rts 1620 ; 1625 modetab .byt 0,64,128 1630 ; 1635 multicol = $9ff3 ;zeichenfarbe fuer multi 1640 ; 1645 ink jsr getbyte ;zeichenfarbe setzen 1650 cpx #4 1655 bcs illmode ;>=4, dann fehler 1660 stx multicol ;merken 1665 rts 1670 ; 1675 xlo = $14 1680 xhi = $15 1685 ; 1690 ;bytenummer errechnen (hires-modus) 1695 hiplot lsr ;y-koord. schon im akku ! 1700 lsr ;(y/8) 1705 lsr 1710 tay ;ins y-register 1715 clc ;alle lobytes addieren 1720 txa 1725 and #%00000111 ;(y and #7) 1730 adc maltab,y ;+ (320*y/8)lo (c=0!) 1735 sta $f7 1740 lda xlo 1745 and #%11111000 ;+ (xlo and #248) 1750 adc $f7 1755 sta $f7 ;nach $f7 1760 ;addition der hibytes 1765 lda maltab1,y ;(320*y/8)hi 1770 adc scrnum ;+ anfang bitmap 1775 adc xhi ;+ xhi 1780 sta $f8 ;nach $f8 1785 lda xlo ;bitposition errechnen 1790 and #%00000111 ;(xlo and #7) 1795 tay 1800 lda hochtab,y ;2^(7-yregister) 1805 rts 1810 ; 1815 muplot lsr ;(y/8) 1820 lsr 1825 lsr 1830 tay 1835 lda xlo 1840 and #%11111100 ;(xlo and #252) 1845 asl ;mal 2 (bit7 ins carry !) 1850 sta $f7 ;nach $f7 1855 lda maltab1,y ;(320*y/8)hi 1860 adc scrnum ;+anfang bitmap 1865 sta $f8 ;nach $f8 1870 txa 1875 and #%00000111 ;(y and #7) 1880 adc maltab,y ;+(320*y/8)lo 1885 tay ;ins y-register 1890 lda xlo ;bitposition errechnen 1895 and #%00000011 ;(xlo and #3) 1900 tax 1905 lda multab,x ;bitwert laden 1910 sec 1915 rts 1920 ; 1925 plot jsr getadr ;koordinaten holen 1930 lda $d016 1935 and #%00010000 1940 bne mplot ;multicolormodus 1945 cpx #200 1950 bcs plot-1 ;ykoord.>199 (c=1) 1955 ldy xhi 1960 beq ok 1965 dey 1970 bne plot-2 ;xhi>1 (c=1) 1975 lda xlo ;xhi=1, dann xlo testen 1980 cmp #<320 1985 bcs plot-1 ;xlo>$40 (c=1) 1990 ok sei 1995 lda #$34 ;speicher auf ram umschalten 2000 sta 1 ;um bit-map lesen zu koennen 2005 txa 2010 pha ;y-koord. merken 2015 jsr hiplot ;bytenummer berechnen 2020 ldy #0 2025 bit plotmode 2030 bvs loesch 2035 bmi invert 2040 ora ($f7),y ;punkt setzen 2045 bne store ;unbedingter sprung 2050 ; 2055 mplot cpx #200 2060 bcs plot-1 2065 lda xhi ;xhi<>0 (c=1) 2070 bne plot-2 2075 lda xlo 2080 cmp #160 2085 bcs plot-2 ;xlo>159 (c=1) 2090 sei 2095 lda #$34 ;speicher auf ram umschalten 2100 sta 1 2105 txa 2110 pha ;ykoord. merken 2115 jsr muplot ;bytenummer errechnen 2120 bit plotmode 2125 bvs loesch 2130 bmi invert 2135 pha ;punkt setzen 2140 eor #255 ;vorher loeschen 2145 and ($f7),y 2150 sta ($f7),y 2155 ldx multicol ;zeichenfarbe laden 2160 pla 2165 and multab1,x ;bitmuster der farbe setzen 2170 ora ($f7),y 2175 bne store 2180 loesch eor #255 ;punkt loeschen 2185 and ($f7),y 2190 .byt $2c 2195 invert eor ($f7),y ;punkt invertieren 2200 store sta ($f7),y ;bitmuster setzen 2205 pla ;ykoord. wiederherstellen 2210 tax 2215 plotend lda #$37 ;normale speicherkonfiguration 2220 sta 1 2225 cli 2230 clc ;c=0 wenn punkt gesetzt 2235 rts 2240 ; 2245 maltab .byt 0,<320,<640,<960 ;multiplikationstabelle 2250 .byt $00,$40,$80,$c0 ;mal 320 2255 .byt $00,$40,$80,$c0 ;lobytes 2260 .byt $00,$40,$80,$c0 2265 .byt $00,$40,$80,$c0 2270 .byt $00,$40,$80,$c0 2275 .byt $00 2280 ; 2285 maltab1 .byt 0,>320,>640,>960 2290 .byt $05,$06,$07,$08 ;mal 320 2295 .byt $0a,$0b,$0c,$0d ;hibytes 2300 .byt $0f,$10,$11,$12 2305 .byt $14,$15,$16,$17 2310 .byt $19,$1a,$1b,$1c 2315 .byt $1e 2320 ; 2325 hochtab .byt $80,$40,$20,$10 ;zweierpotenzen 2330 .byt $08,$04,$02,$01 2335 ; 2340 multab .byt %11000000 ;xposition0 2345 .byt %00110000 ;xposition1 2350 .byt %00001100 ;xposition2 2355 .byt %00000011 ;xposition3 2360 ; 2365 multab1 .byt %00000000 ;farbe0=hintergrund 2370 .byt %01010101 ;farbe1 2375 .byt %10101010 ;farbe2 2380 .byt %11111111 ;farbe3
PROGRAMM : PG-MSE 8000 8390 ----------------------------------- 8000 : 20 80 09 80 C3 C2 CD 38 AD 8008 : 30 20 BC F6 20 E1 FF D0 09 8010 : 0C 20 76 80 20 A3 FD 20 31 8018 : 18 E5 20 7B E3 4C 72 FE 03 8020 : 20 A3 FD 20 90 FD 20 76 FC 8028 : 80 20 5B FF 58 A2 0B BD D1 8030 : 8E 80 9D 00 03 CA 10 F7 1C 8038 : 20 BF E3 A0 0F A9 00 99 B6 8040 : F0 9F 88 10 FA 85 37 85 E8 8048 : 33 A9 80 85 38 85 34 A9 F4 8050 : A0 8D F1 9F A9 5A A0 82 1C 8058 : 20 1E AB 20 30 E4 20 6F 00 8060 : 82 A2 FB 9A 20 D2 83 8A 41 8068 : 30 03 4C 3A A4 4C 74 A4 3C 8070 : 20 D2 83 4C 83 A4 20 15 6C 8078 : FD A9 9A 8D 24 03 A9 80 A4 8080 : 8D 25 03 A9 22 8D 26 03 C3 8088 : A9 81 8D 27 03 60 64 80 00 8090 : 70 80 3B 81 FE 81 33 82 0D 8098 : 86 AE A5 99 F0 03 4C 66 37 80A0 : F1 A5 D3 85 CA A5 D6 85 4A 80A8 : C9 AD F0 9F D0 03 4C 32 33 80B0 : E6 8A D0 31 18 AD FE 01 23 80B8 : 65 FE 85 14 AD FF 01 69 32 80C0 : 00 85 15 20 13 A6 08 A6 A0 80C8 : 14 A5 15 20 CD BD 28 90 85 80D0 : 07 A9 5F 20 D2 FF D0 05 02 80D8 : A9 20 20 D2 FF A9 00 A4 8A 80E0 : D6 85 CA 84 C9 20 32 E6 F0 80E8 : 08 48 C9 5F D0 14 A5 14 DF 80F0 : 8D FE 01 A5 15 8D FF 01 B1 80F8 : 68 28 A9 0D 20 D2 FF 4C B2 8100 : 7B A4 C9 0D D0 19 A4 C8 DB 8108 : 88 30 0C B1 D1 C9 3A B0 97 8110 : 0E C9 30 90 0A B0 F1 A9 62 8118 : 00 8D F0 9F 4C 74 A4 68 DB 8120 : 28 60 48 A5 9A C9 03 F0 25 8128 : 03 4C D5 F1 AD 11 D0 29 FE 8130 : 20 D0 04 68 4C 16 E7 68 AC 8138 : 4C 16 E7 A6 7A A0 04 84 24 8140 : 0F BD 00 02 10 07 C9 FF CF 8148 : F0 3E E8 D0 F4 C9 20 F0 AB 8150 : 37 85 08 C9 22 F0 55 24 CC 8158 : 0F 70 2D C9 3F D0 04 A9 02 8160 : 99 D0 25 C9 30 90 04 C9 0F 8168 : 3C 90 1D 84 71 A0 00 84 E9 8170 : 0B 88 86 7A CA C8 E8 BD C2 8178 : 00 02 38 F9 9E A0 F0 F5 65 8180 : C9 80 D0 2F 05 0B A4 71 C1 8188 : E8 C8 99 FB 01 C9 00 F0 FA 8190 : 38 38 E9 3A F0 04 C9 49 8F 8198 : D0 02 85 0F 38 E9 55 D0 76 81A0 : A0 85 08 BD 00 02 F0 E0 52 81A8 : C5 08 F0 DC C8 99 FB 01 94 81B0 : E8 D0 F0 A6 7A E6 0B C8 AE 81B8 : B9 9D A0 10 FA B9 9E A0 A3 81C0 : D0 B5 F0 0F BD 00 02 10 8D 81C8 : BD 99 FD 01 C6 7B A9 FF E0 81D0 : 85 7A 60 A0 00 B9 EF 82 51 81D8 : D0 02 C8 E8 BD 00 02 38 4D 81E0 : F9 EF 82 F0 F5 C9 80 D0 E1 81E8 : 04 05 0B D0 99 A6 7A E6 D2 81F0 : 0B C8 B9 EE 82 10 FA B9 B3 81F8 : EF 82 D0 E0 F0 C6 10 0F 1C 8200 : 24 0F 30 0B C9 FF F0 07 88 8208 : C9 CC B0 06 4C 24 A7 4C 41 8210 : F3 A6 38 E9 CB AA 84 49 58 8218 : A0 FF CA F0 08 C8 B9 EF 16 8220 : 82 10 FA 30 F5 C8 B9 EF DB 8228 : 82 30 05 20 47 AB D0 F5 09 8230 : 4C EF A6 20 73 00 20 3C 52 8238 : 82 4C AE A7 C9 CC 90 04 CE 8240 : C9 F5 90 06 20 79 00 4C 4F 8248 : ED A7 38 E9 CC 0A AA BD 97 8250 : A0 82 48 BD 9F 82 48 4C C3 8258 : 73 00 93 12 20 50 52 4F 5F 8260 : 46 49 2D 47 52 41 46 49 5A 8268 : 4B 20 36 34 20 20 00 A9 2E 8270 : 01 A8 91 2B 20 33 A5 18 F1 8278 : A5 22 69 02 85 2D A5 23 68 8280 : 69 00 85 2E 4C 63 A6 20 CB 8288 : EB B7 86 FE 38 A5 14 E5 9D 8290 : FE 8D FE 01 A5 15 E9 00 DF 8298 : 8D FF 01 EE F0 9F 60 6E AD 82A0 : 82 86 82 8F 83 A0 83 C5 CF 82A8 : 83 D1 83 F2 83 09 84 51 88 82B0 : 84 65 84 BC 84 00 00 00 E8 82B8 : 00 00 00 00 00 00 00 00 B9 82C0 : 00 00 00 00 00 00 00 00 C1 82C8 : 00 00 00 00 00 00 00 00 C9 82D0 : 00 00 00 00 00 00 00 00 D1 82D8 : 00 00 00 00 00 00 00 00 D9 82E0 : 00 00 00 00 00 00 00 00 E1 82E8 : 00 00 00 00 00 00 00 4F 87 82F0 : 4C C4 41 55 54 CF 53 43 31 82F8 : 52 45 45 CE 48 49 52 45 BB 8300 : D3 4D 55 4C 54 C9 54 45 C8 8308 : 58 D4 43 4C 45 41 D2 48 5F 8310 : 49 43 4F CC 4D 4F 44 C5 54 8318 : 49 4E CB 50 4C 4F D4 00 18 8320 : 00 00 00 00 00 00 00 00 21 8328 : 00 00 00 00 00 00 00 00 29 8330 : 00 00 00 00 00 00 00 00 31 8338 : 00 00 00 00 00 00 00 00 39 8340 : 00 00 00 00 00 00 00 00 41 8348 : 00 00 00 00 00 00 00 00 49 8350 : 00 00 00 00 00 00 00 00 51 8358 : 00 00 00 00 00 00 00 00 59 8360 : 00 00 00 00 00 00 00 00 61 8368 : 00 00 00 00 00 00 00 00 69 8370 : 00 00 00 00 00 00 00 00 71 8378 : 00 00 00 00 00 00 00 00 79 8380 : 00 00 00 00 00 00 00 00 81 8388 : 00 00 00 00 00 00 00 00 89