Grafik

Räumliche Grafik auf dem C 64

Gerade auf dem Gebiet von Film- und Fernsehproduktionen werden Computergrafiken immer öfter eingesetzt, da es hiermit möglich ist, Dinge zu zeigen, die mit herkömmlichen Methoden nicht gefilmt werden konnten.

Ob nun Raumschiffe gezeigt werden, die eigentlich unmögliche Bewegungen durchführen oder der »Anflug« eines Logos (wie zum Beispiel die »1«bei der ARD), die Realisierung vereinfacht sich durch den Einsatz von Grafik-Computern enorm. Diese müssen jedoch — bedingt durch die anfallenden Datenmengen — enorm schnell sein, so daß zur Zeit nur »Supercomputer« Echtzeitsimulation erlauben.

Wenn man sich allerdings etwas mehr Zeit läßt, dann reicht auch ein Homecomputer wie der C 64 aus, um solche Grafiken (mit bestimmten Einschränkungen) zu erzeugen.

Das hier vorgestellte Grafikpaket geht über das übliche Punkte setzen und Linien ziehen weit hinaus. Es erlaubt die Erzeugung von plastischen Bildern ohne größeren Aufwand, wie zum Beispiel in Bild 1 und 2 dargestellt.

Bild 1. Eindrucksvolle räumliche Wirkung durch Kombination verschiedener Shapes
Bild 2. Verblüffende Effekte lassen sich erzielen. Beachten Sie den Lichteinfall.

Das eigentliche Grafikpaket nimmt nur 3 KByte (I) des Speichers in Anspruch und steht im Bereich ab $C000. Damit bleibt der Basic-Speicher für die eigentlichen Programme frei. Auch das DOS 5.1 von Commodore kann parallel zu den Grafikroutinen verwendet werden. Aufgrund der Kompaktheit dieses Grafikpakets mußten allerdings bestimmte Dinge, wie zum Beispiel die Abfrage auf legale Koordinaten, in den Hintergrund treten; die Software fängt also solche Fehler nicht ab. Das macht das Schreiben eines eigenen Programms zwar etwas komplizierter, hat man aber erst einmal alle Fehler beseitigt, so würde eine Fehlerabfrage den Ablauf nur verlangsamen.

Beginnen wir mit den Grundlagen zur Erzeugung der Grafik. Da stellt sich zunächt einmal die Frage, wie man die verschiedenen Helligkeitswerte und Schattierungen eines darzustellenden Objektes berechnet. Danach müssen diese verschiedenen Grauwerte in einzelne Punkte umgesetzt werden, denn auf dem HiRes-Bildschirm können diese ja nur gesetzt und gelöscht werden. Dazu muß die gesamte Software selbst geschrieben werden, da der C 64 diese Art der Grafik vom Betriebssystem her nicht unterstützt.

Schnelle Rechenroutinen

Das Maschinenprogramm, das für den Aufbau der Grafik zuständig ist, besteht aus mehreren Unterprogrammen. Beginnen wollen wir mit einem Unterprogrammpaket, das für schnelles Rechnen notwendig ist.

Integer Arithmetik (Listing 1)

Diese Unterroutinen stellen schnelle Algorithmen für Multiplikation, Division, Wurzelziehen und Zufallszahlen zur Verfügung. Diese sind zwar schon im normalen Basic-Interpreter vorhanden, für unsere Anwendung sind sie jedoch aus Geschwindigkeitsgründen ungeeignet. Die Basic-Routinen sind nämlich nicht auf Geschwindigkeit, sondern auf Kürze optimiert worden, wie zum Beispiel die Funktion SQR. Die Wurzelberechnung in Basic teilt den Logarithmus durch 2 und potenziert das Ergebnis anschließend wieder. Das hat den Vorteil, daß der Interpreter auf bereits vorhandene Unterprogramme zugreifen kann, aber den Nachteil, daß diese Berechnungsweise relativ langsam ist. Wenn man für alle 64000 Bildschirmpunkte die Quadratwurzel mit den vorhandenen Routinen berechnen würde, ergäbe sich eine Zeichenzeit von mehr als einer Stunde (und dies trotz Maschinenspracheprogramm)! Man benötigt diese Berechnung zwar nicht für jeden Punkt, aber gerade bei der Berechnung der Schattierungswerte spielt die Quadratwurzel eine große Rolle. Eine Möglichkeit, die Wurzelberechnung zu beschleunigen bietet die Newton-Methode, mit der man Fließkommawurzeln in einem Bruchteil der sonst benötigten Zeit berechnen kann. Da wir, um die einzelnen Grafikpunkte zu adressieren, nur ganze Zahlen benötigen, beschleunigt sich die Abarbeitungszeit nochmals. Auch die Routine für die Erzeugung von Zufallszahlen, die später bei der »Random«-Schattierung erforderlich ist, wurde neu geschrieben.

Grafik Utilities (Listing 2)

Die nächste Unterprogrammsammlung beinhaltet Basisroutinen für die Verwaltung der Bitmap wie zum Beispiel löschen, Farbe setzen und Punkte plotten. Diese Unterroutinen sind als einzige Commodore 64-spezifisch, so daß man — möchte man das Programm auf andere 6502-Computer übertragen — nur diese an das jeweilige Gerät anpassen muß.

Ferner wurden noch zwei Schattierungsroutinen »SHADE« und »RSHADE« implementiert. »SHADE« arbeitet im Prinzip ganz einfach: Man definiert eine 8 x 8 Graustufenmatrix, in der Werte von 0 bis 63 enthalten sind (Tabelle 1). Mit Hilfe dieser Daten wird nun ein — ebenfalls 8 x 8 Pixel großes — Feld erstellt, daß dann an einer bestimmten Stelle in den HiRes-Bildschirm kopiert wird. Um eine gleichmäßige Grauschattierung zu erreichen, müssen die Pixels auch möglichst einen gleichmäßigen Abstand voneinander haben. Wenn das Programm nun einen Grauwert in die Grafik setzen will, so übergibt es einfach einen Wert zwischen 0 und 63 an diese Unterroutine. Nun werden innerhalb dieser Matrix die einzelnen Punkte der Reihe nach gesetzt, also zuerst der Punkt mit der Nummer 0 (oben links), dann 1 (4. von links und 4. von oben) und so weiter. Also, je größer die Zahl ist, desto mehr Punkte werden gesetzt (und um so dunkler wird das Ganze). Durch diese festgelegte Reihenfolge wird sichergestellt, daß die Schattierung gleichmäßig ist. Die RSHADE-Unterroutine hat genau die gleiche Aufgabe, sorgt aber für etwas ungleichmäßigere — durch den Zufallsgenerator gesteuerte — Grauwerte.

0 8 53 61 2 10 55 63
16 24 37 45 18 26 39 47
49 57 4 12 51 59 6 14
33 41 20 28 35 43 22 30
3 11 54 62 1 9 52 60
19 27 38 46 17 25 36 44
50 58 7 15 48 56 5 13
34 42 23 31 32 40 21 29
Tabelle 1. Matrix der Grauwerte

Ein weiteres zu lösendes Problem ist das etwas merkwürdige rechteckige Bildschirmformat des C 64. Die Auflösung von 320 x 200 Punkten entspricht einem Teilungsverhältnis von 8:5, wodurch es bei einem normalen Bildschirm — mit einem Verhältnis von 4:3 — zu einer horizontalen Verzerrung kommen kann (eine Kugel würde dann etwa wie ein plattgedrückter Ball aussehen). Die Unterroutine »SCALE« (in Listing 2) sorgt für diese darstellungs- und maßstabsgerechte Aufbereitung der Koordinaten.

Linien und Facettenzeichnen

Die Routinen in Listing 3 komplettieren die elementaren Grafik-Funktionen für das Ziehen von Linien und das Zeichnen von schattierten Polygonnetzen. Ein solches räumliches Polygonnetz ist in Bild 3 zu sehen; es besteht nur aus aneinander gesetzten und entsprechend schattierten Dreiecken. Diese Figuren können einfacher und schneller gezeichnet werden, da die Schattierung auf ebenen Flächen einfacher darzustellen ist als auf gekrümmten. Neben der üblichen Darstellungsweise (in der geschlossenen, schattierten Form) ist auch die Zeichnung von Grafiken ohne verdeckte Linien möglich.

Bild 3. Ein weiteres Beispiel für die 3D-Wirkung

Mit diesen Routinen gerüstet, können wir uns nun auf das eigentliche Shape-Unterprogramm konzentrieren, mit dem es möglich ist, gekrümmte, schattierte Figuren in kurzer Zeit zu erstellen.

Hier geht es wiederum als erstes um die Berechnung der verschiedenen Oberflächenreflexe, Brechungen, Streuungen und Absorptionen des Lichtes auf einer Oberfläche. Um diese, teilweise sehr komplizierten Berechnungenn, zu vereinfachen, geht man einen anderen Weg: Man beschränkt sich auf einige einfache symmetrische Figuren (Bild 4), aus denen alle zu zeichnenden Objekte zusammengesetzt werden. Weiterhin werden die Figuren nur in der Frontsicht, also von vorn, dargestellt; Drehungen sind nicht möglich. Durch diese Einschränkungen braucht man bei der Programmierung nicht auf komplizierte Vektorberechnungen zurückzugreifen.

Bild 4. Die zur Verfügung stehenden Shapes, aus denen alle Figuren zusammengesetzt werden

Für die Berechnung des Lichteinfalls stelle man sich einfach eine Lampe vor, die an der rechten Schulter des Beobachters angebracht ist und das Objekt von dieser Position anleuchtet. Dementsprechend errechnet das Programm die Helligkeitswerte für jeden Punkt des Objektes. Ein Flag (Adresse 898) dient dazu, den Standort der »Lampe« (0= Frontbeleuchtung, 1 = Beleuchtung von hinten) festzulegen.

Zeichenroutinen für Shapes

Listing 4 beinhaltet eine Sammlung von Routinen, die die acht Grundshapes (siehe Bild 4) zeichnen. Da dieses Unterprogramm auf die — an den C 64 angepaßten — Lower-Level-Routinen der Grafik-Utilities (Listing 2) zugreift, ist es selbst nicht vom jeweiligen Computer abhängig. Zusammen mit dem, in Listing 5 abgebildeten Programm, wird der Kontakt zum Basic hergestellt. Die Übergabe der Parameter geschieht mittels »SYS«-Befehl:
SYS <KOMMANDO>, <PARAM. 1,>, <PARAM. 2>, …, wobei <KOMMANDO> die Adresse des jeweiligen Grafikbefehls ist (Tabelle 2 zeigt die komplette Befehlsübersicht dieses Grafikprogramms). Über <PARAMETER 1> und <PARAMETER 2> müssen die Koordinaten des Shapes angegeben werden, wobei zu beachten ist, daß der Ursprung (dort wo die X- und Y-Koordinate null ist) in der linken unteren Bildschirmecke liegt. Die einzusetzenden Werte gehen in der Horizontalen von 0 bis 255, in der Vertikalen von 0 bis 239.

Grafikspeicher:40960-48959
Farbspeicher. 33792-34791
Shape-Fenster
893: Linker Rand
894: Rechter Rand
895; Unterer Rand
896: Oberer Rand
Style Flags
838: Schattierungsart (0 = zufällig, 1 = Halbton)
839: Skalierungsflag (0 = normal 1:1, 1 = skaliert 4:3)
868: Eck Flag bei Polygonen (0 = Normal, 1 = zeichnet Linien an den Ecken)
871: Eckenmodus (0 = zeichnet Linie, 1 = löscht Rand)
898: Beleuchtungsflag (0 = von vorne, 1 = von hinten)
Funktionsadressen
49378: Auf den Grafikmodus umschalten
49411: Zurück zum Textbildschirm
51979: Bitmap löschen
52001: Bitmap färben
52023: PLOT (Parameter X,Y) setzt einen Punkt
52026: UNPLOT löscht einen Punkt mit den Koordinaten X und Y
52049: LINE (Parameter X1,Y1,X2,X2) zieht Linie von / bis
52052: FACET X1,Y1,X2,Y2,X3,Y3,SA zeichnet dreieckige Facetten mit den Koordinaten X1,Y1, X2,... und schattiert sie (SA: 0 = schwarz, 64 = weiß)
Shapes
52119: Kugel
52141: Ring
52150: vertikaler Zylinder
52153: horizontaler Zylinder
52186: vertikaler Ring
52189: horizontaler Ring
52203: vertikale Rolle
52206: horizontale Rolle
Tabelle 2. Befehlsübersicht

Alle Shapes, mit Ausnahme der Kugel, können durch die Eingabe von insgesamt vier Parametern in ihrer Position und Form beeinflußt werden. Die ersten zwei bestimmen, wie oben erläutert, die Koordinaten des Figurmittelpunktes. Mit dem dritten und vierten Paramter kann man die Verzerrung in X- und Y-Richtung einstellen. Doch hier ist Vorsicht geboten, denn der X-Wert sollte hierbei immer größer als der Y-Wert sein, sonst zeichnet das Programm unerwünschte Figuren.

Eine weitere Besonderheit sind die Shape-Fenster. Damit ist es möglich, auch einzelne Teile eines Shapes auf dem Bildschirm zu bringen. Diese Funktion wurde zum Beispiel bei der Erstellung der Grafik in Bild 1 verwendet. Der Henkel dieser Kafffeetasse ist aus drei verschiedenen Shapes zusammengesetzt, die mit Hilfe des Fensters in ihrer Ausdehnung eingeschränkt wurden. Diesen Begrenzungsfenstern sind die Adressen 893 bis 896 zugeordnet, wobei sich die POKE-Werte auf den Mittelpunkt der Figur beziehen.

Die Kommandos, um die Bitmap zu löschen oder mit Punkten zu füllen, benötigen auch alle nur einen Parameter. So sieht zum Beispiel das Kommando zum Initialisieren des Farbspeichers so aus:

POKE 52001,16*DC + BC

wobei DC die Farbe der zu setzenden Punkte und BC die Hintergrundfarbe ist. Auch Texte können nach Wunsch auf dem Grafikbildschirm ausgegeben werden. Die dafür zuständigen Routinen sind in Listing 2 enthalten.

Die in Listing 10 und 11 abgedruckten Demonstrationsprogramme sollen helfen, die Arbeitsweise und die Kombinationsmöglichkeiten der einzelnen Shapes aufzuzeigen. Auch alle hier gezeigten Bilder stammen von diesem Programm. Die Bilder stehen im Speicher übrigens »unter« dem Basic-ROM im Bereich zwischen $A000 und $BFFF.

Um den Platz für das DOS 5.1 freizuhalten, wurde das Grafikpaket in zwei Teile aufgespalten. Der eine Teil mit dem Namen GRAPHICS (Listing 8) befindet sich im Bereich zwischen $C000 und $CBFC. Der zweite Teil, auf den im folgenden noch kurz eingegangen werden soll, muß nach Adresse $CF59 geladen werden. Dieser Programmteil enthält eine schnelle Sortierroutine (Listing 6) und ermöglicht die Darstellung von Text auf dem Grafikbildschirm (Listing 7). Die beiden Unterprogramme sind in dem MSE-Listing 9 zusammengefaßt worden und müssen gemeinsam mit »GRAPHICS« in den Speicher geladen werden.

Hinweise zum Abtippen

Sie müssen als erstes die MSE-Listings 8 und 9 eingeben und anschließend natürlich auch abspeichern. Die Listings 1 bis 7 dienen nur zur Dokumentation und brauchen nicht eingegeben werden. Nachdem Sie auch die Demos abgetippt und auf Diskette oder Band gespeichert haben, müssen die einzelnen Programmteile nacheinander in den Speicher geladen werden. Begonnen wird mit GRAPHICS, das mit LOAD-"GRAPHICS",8,1 in den Speicher gelesen werden muß. Nachdem man anschließend NEW eingegeben hat, muß das zweite Maschinenprogramm, wie oben, geladen werden (auch hier das NEW nicht vergessen). Anschließend kann wahlweise eines der beiden Demonstrationsprogramme (Listing 10 oder11) geladen und ganz normal gestartet werden.

(Richard Rylander/Christoph Sauer/ev)
Bild 5. Aus einfachen Figuren lassen sich verblüffend »lebendige« Bilder zusammensetzen
; INTEGER ARITHMETIC ROUTINES
;
; RICHARD L. RYLANDER    8/12/84
;
; REVISED 10/29/84 TO ADD FULL DOUBLE
; PRECISION ARGUMENTS IN DIVIDE ROUTINE
;
;*****************************************
;
; USE PAGE ZERO LOCATIONS WHERE POSSIBLE FOR
; ITERATIVE PROCEDURE WORK SPACE
;
MLPCND =$AC    ; MULTIPLICAND
MLPLER =$AD    ; MULTIPLIER
PROD   =$AE    ; PRODUCT
;
DVDND  =$FD    ; DIVIDEND/QUOTIENT
DVSOR  =$FB    ; DIVISOR
RMNDR  =$B4    ; REMAINDER
;
RADCND =$AC    ; RADICAND
ROOT   =$033C  ; SQUARE ROOT
;
TEMP   =$FB
;
; SET UP SEED VALUES FOR PSEUDO-RANDOM NUMBERS
      *=$C000
RNDM   .BYTE $FF,$55
RTEMP  .BYTE $00,$00
;
;
;*****************************************
;
; MULTIPLY SINGLE PRECISION MULTIPLICAND
; BY SINGLE PRECISION MULTIPLIER GIVING
; DOUBLE PRECISION PRODUCT (ENTER AT "MULT")
;
; SPECIAL CASE: ENTER AT "SQUARE" TO FIND
; SQUARE OF SIGNED 8-BIT NUMBER
;
SQUARE LDA MLPCND  ; ENTRY TO SQUARE
       BPL POSITV  ; USE ABSOLUTE VALUE
       SEC         ; NEGATE IF NEEDED
       LDA #$00
       SBC MLPCND
       STA MLPCND
POSITV STA MLPLER
MULT   LDA #$00    ; ENTRY TO MULTIPLY
       LDX #$08
MLOOP  LSR MLPLER
       BCC NOADD
       CLC
       ADC MLPCND
NOADD  ROR A
       ROR PROD
       DEX
       BNE MLOOP
       STA PROD+1
       RTS
;
;*****************************************
;
; DIVIDE DOUBLE PRECISION DIVIDEND
; BY DOUBLE PRECISION DIVISOR GIVING
; DOUBLE PRECISION QUOTIENT
;
; DIVIDEND IS REPLACED BY QUOTIENT
; IN THE PROCESS
;
; QUOTIENT IS ROUNDED TO NEAREST INTEGER
;
DIVIDE LDA #$00
       STA RMNDR
       STA RMNDR+1
       LDX #$10
DLOOP  ROL DVDND
       ROL DVDND+1
       ROL RMNDR
       ROL RMNDR+1
       SEC
       LDA RMNDR
       SBC DVSOR
       TAY
       LDA RMNDR+1
       SBC DVSOR+1
       BCC DECCNT
       STY RMNDR
       STA RMNDR+1
DECCNT DEX
       BNE DLOOP
       ROL DVDND     ; CHECK IF REMAINDER
       ROL DVDND+1   ; IS >= 1/2 OF DIVIDEND
       ASL RMNDR     ; FOR ROUNDING
       ROL RMNDR+1
       BCS ROUND
       SEC
       LDA DVSOR
       SBC RMNDR
       LDA DVSOR+1
       SBC RMNDR+1
       BCS NOCHNG
ROUND  INC DVDND
       BNE NOCHNG
       INC DVDND+1
NOCHNG RTS
;
;*****************************************
;
; TAKE INTEGER SQUARE ROOT OF A
; DOUBLE PRECISION RADICAND GIVING
; SINGLE PRECISION ROOT ( <= REAL ROOT )
;
SQRT   LDX #$08
       LDA #$00
       STA ROOT
       STA ROOT+1
       STA TEMP
       STA TEMP+1
SQRT1  ASL ROOT
       ROL ROOT+1
       INC ROOT    ; ASSUME CURRENT LSB OF
       BNE NEXT1   ; ROOT WILL BE 1
       INC ROOT+1
NEXT1  ASL RADCND  ; SHIFT RADICAND LEFT
       ROL RADCND+1 ; TWICE INTO TEMP
       ROL TEMP
       ROL TEMP+1
       ASL RADCND
       ROL RADCND+1
       ROL TEMP
       ROL TEMP+1
       SEC         ; SUBTRACT ROOT ESTIMATE
       LDA TEMP    ; FROM TEMP
       SBC ROOT
       TAY
       LDA TEMP+1
       SBC ROOT+1
       BCC RESTOR
       STA TEMP+1  ; SUBTRACTION OK
       STY TEMP
       INC ROOT
       BNE NEXT2
       INC ROOT+1
NEXT2  DEX
       BNE SQRT1
       JMP FINI
RESTOR SEC         ; IGNORE SUBTRACTION
       LDA ROOT    ; AND RESET LSB OF ROOT
       SBC #$01
       STA ROOT
       BCS NEXT3
       DEC ROOT+1
NEXT3  DEX
       BNE SQRT1
FINI   ROR ROOT+1  ; FINAL /2 TO NORMALIZE
       ROR ROOT
       RTS
;
;*****************************************
;
; GENERATE PSEUDO-RANDOM BYTES
; EXIT WITH P-R BYTE IN ACCUM.
;
RANDOM LDA RNDM
       STA RTEMP
       EOR RNDM+1
       ROL RTEMP+1  ; RTEMP+1 PRESERVES
       ROR A        ; CARRY BIT FOR CYCLING
       ROR RTEMP+1  ; RANDOM NUMBERS
       STA RNDM
       LDA RTEMP
       STA RNDM+1
       RTS
.END
Listing 1. Assembler-Quelltext der schnellen Integer-Arithmetik
; GRAPHICS UTILITIES
;
; RICHARD L. RYLANDER   11/4/84
;
; LOAD ARITHMETIC UTILITIES FIRST
;
RAM=$033E
ORIGIN=$C0E2
;
MLPCND=$AC     ; MULTIPLICAND (S)
MLPLER=$AD     ; MULTIPLIER (S)
PROD=$AE      ; PRODUCT (D)
MULT=$C011    ; CALL FOR MULTIPLY
;
RNDM=$C000    ; RANDOM NUMBER
RANDOM=$C0C8  ; CALL FOR RANDOM
; NOTE - A CALL TO 'RANDOM' LEAVES A RANDOM BYTE
; IN THE ACCUMULATOR
;
       *=RAM
PLTFLG *=*+1  ; PLOT/UNPLOT FLAG
XPLT   *=*+2  ; ABSOLUTE PLOT COORD
YPLT   *=*+1  ; ABSOLUTE PLOT COORD
VIC1   *=*+1  ; REGISTER STORAGE
VIC2   *=*+1  ; REGISTER STORAGE
VALUE  *=*+2  ; FINAL NORMALIZED SHADE VALUE
HTORRN *=*+1  ; SHADE FLAG, 1=HALFTONE
NOSCAL *=*+1  ; SCALE FLAG, 1=NO SCALE
TEMP   *=*+2  ; TEMPORARY STORAGE
;
       *=ORIGIN
;
;*****************************************
;
; TURN ON BIT MAP GRAPHICS MODE,
; SAVING REGISTER VALUES FOR
; RETURN TO TEXT MODE LATER.
;
GRFON  LDA $D011
       ORA #$20
       STA $D011
       LDA $DD00
       STA VIC1
       AND #$FC
       ORA #$01
       STA $DD00
       LDA $D018
       STA VIC2
       LDA #$19
       STA $D018
       RTS
;
;*****************************************
;
; RETURN TO TEXT SCREEN
;
GRFOFF LDA $D011
       AND #$DF
       STA $D011
       LDA VIC1
       STA $DD00
       LDA VIC2
       STA $D018
       RTS
;
;*****************************************
;
; FILL COLOR MAP FOR BLACK DOTS ON WHITE
;
COLOR  LDA #$01    ; POKE NEW COLORS HERE
       LDX #0
COL1   STA $8400,X
       STA $8500,X
       STA $8600,X
       STA $8700,X
       DEX
       BNE COL1
       RTS
;
;*****************************************
;
; CLEAR HI-RES GRAPHICS SCREEN
;
CLEAR  LDA #$A0
       STA $FC
       LDY #0
       STY $FB
       LDA #0      ; CLEAR BYTE
       LDX #$20
CLRLP  STA ($FB),Y
       INY
       BNE CLRLP
       INC $FC
       DEX
       BNE CLRLP
       RTS
;
;*****************************************
;
; PLOT AND UNPLOT POINTS ON HI-RES GRAPHICS
; SCREEN. ABSOLUTE X AND Y SCREEN COORDINATES
; ARE POKED INTO XPLT, XPLT+1, AND YPLT
;
PLOT   LDA #0
       .BYTE $2C
UNPLOT LDA #$80
       STA PLTFLG
       LDA $01    ; BASIC ROM OUT
       AND #$FE
       STA $01
       SEC        ; INVERT Y COORDINATE TO
       LDA #$C7   ; PUT ORIGIN IN LOWER LEFT
       SBC YPLT   ; CORNER OF SCREEN
       TAX        ; (199.-YPLT)
       LSR A
       LSR A
       LSR A
       TAY
       LDA TABLE1,Y
       STA $FB
       LDA TABLE2,Y
       STA $FC
       TXA
       AND #$07
       CLC
       ADC $FB
       STA $FB
       LDA XPLT
       AND #$F8
       ADC $FB
       STA $FB
       LDA XPLT+1
       ADC $FC
       STA $FC
       LDA #$A0
       ADC $FC
       STA $FC
       LDA XPLT
       AND #$07
       EOR #$07
       TAX
       LDA #$01
PLOTLP DEX
       BMI PLOT2
       ASL A
       BNE PLOTLP
PLOT2  LDY #0
       BIT PLTFLG
       BPL NOPLOT
       EOR #$FF
       AND ($FB),Y
       .BYTE $2C
NOPLOT ORA ($FB),Y
       STA ($FB),Y
       LDA $01     ; BASIC ROM RESTORED
       ORA #$01
       STA $01
       RTS
;
TABLE1 .BYTE $00,$40,$80,$C0
       .BYTE $00,$40,$80,$C0
       .BYTE $00,$40,$80,$C0
       .BYTE $00,$40,$80,$C0
       .BYTE $00,$40,$80,$C0
       .BYTE $00,$40,$80,$C0,$00
;
TABLE2 .BYTE $00,$01,$02,$03
       .BYTE $05,$06,$07,$08
       .BYTE $0A,$0B,$0C,$0D
       .BYTE $0F,$10,$11,$12
       .BYTE $14,$15,$16,$17
       .BYTE $19,$1A,$1B,$1C,$1E
;
;*****************************************
;
; SHADING BY HYBRID DITHER/DOT-GROWTH
;
SHADE  LDA XPLT     ; USE BITS -----***
       AND #$07     ; OF 'X' SCREEN COORD
       STA TEMP
       LDA YPLT     ; AND BITS -----***
       AND #$07     ; OF 'Y' SCREEN COORD
       ASL A        ; SHIFTED INTO --***---
       ASL A        ; POSITION TO DETERMINE
       ASL A        ; 6-BIT OFFSET IN
       ORA TEMP     ; THRESHOLD TABLE
       TAX
       LDA THRESH,X ; SCREEN-POSITION-WEIGHTED
       CMP VALUE    ; THRESHOLD VALUE
       BPL GREATR
       JMP UNPLOT
GREATR JMP PLOT
;
;*****************************************
;
; SHADING BY RANDOM HALFTONE
;
RSHADE JSR RANDOM
       LSR A         ; REDUCE RANDOM BYTE
       LSR A         ; TO 6 BITS FOR SHADE
       CMP VALUE     ; VALUE COMPARISON
       BPL MORE
       JMP UNPLOT
MORE   JMP PLOT
;
;*****************************************
;
; PLOT A POINT WEIGHTED BY SHADING SCHEME
; AND SHADE VALUE
; CHECK 'NOSCAL' FLAG FOR SCALING OF Y COORD
; CHECK 'HTORRN' FLAG FOR TYPE OF SHADING
;
PLTSHD LDA NOSCAL
       BEQ NORM
;
; SCALE Y FROM 0-239 PSEUDO-COORDINATES
; TO 0-199 TRUE SCREEN COORDINATES BY
;     Y = (Y+1)*213/256
;
SCALE  LDY YPLT
       INY
       STY MLPLER
       LDA #$D5      ; 213.
       STA MLPCND
       JSR MULT      ; RETURN WITH HIGH BYTE
       STA YPLT      ; IN ACCUMULATOR
NORM   LDA HTORRN
       BEQ RPLT
       JMP SHADE
RPLT   JMP RSHADE
;
;
;
THRESH .BYTE $00,$08,$35,$3D
       .BYTE $02,$0A,$37,$3F
       .BYTE $10,$18,$25,$2D
       .BYTE $12,$1A,$27,$2F
       .BYTE $31,$39,$04,$0C
       .BYTE $33,$3B,$06,$0E
       .BYTE $21,$29,$14,$1C
       .BYTE $23,$2B,$16,$1E
       .BYTE $03,$0B,$36,$3E
       .BYTE $01,$09,$34,$3C
       .BYTE $13,$1B,$26,$2E
       .BYTE $11,$19,$24,$2C
       .BYTE $32,$3A,$07,$0F
       .BYTE $30,$38,$05,$0D
       .BYTE $22,$2A,$17,$1F
       .BYTE $20,$28,$15,$1D
.END
Listing 2. Assembler-Quelltext der Grafik-Utilities
; FACET - DRAW SHADED TRIANGULAR FACETS
; AND STRAIGHT LINES.
;
; RICHARD L. RYLANDER   11/4/84
;
; LOAD "ARITH.HEX" AND "GRAPH.HEX"
; BEFORE USING
;
ORIGIN = $C26F
RAM    = $034A
;
XPLT   = $033F
YPLT   = $0341
NORM   = $C224
NOSCAL = $0347
PLOT   = $C143
UNPLOT = $C146
;
MLPCND = $AC
MLPLER = $AD
PROD   = $AE
MULT   = $C011
;
DVDND  = $FD
DVSOR  = $FB
QUOT   = $FD
DIVIDE = $C025
;
      *=RAM
;
XMIN   *=*+2
YMIN   *=*+1
XMID   *=*+2
YMID   *=*+1
XMAX   *=*+2
YMAX   *=*+1
YTOP   *=*+1
YBOT   *=*+1
YBASE  *=*+1
DLTAX1 *=*+2
DLTAX2 *=*+1
DLTAX3 *=*+1
DELTAX *=*+1
DLTAY1 *=*+1
DLTAY2 *=*+1
DLTAY3 *=*+1
DELTAY *=*+1
XDIFF  *=*+1
FLAG1  *=*+1
FLAG2  *=*+1
FLAG3  *=*+1
FLAG   *=*+1
EDGES  *=*+1
ERROR  *=*+2
MODE   *=*+1
COUNT  *=*+2
;
;
      *=ORIGIN
;
;*****************************************
;
; SCALE ALL Y COORDINATES FROM 0..239
; PSUEDO-COORDINATE RANGE TO 0..199
; TRUE SCREEN COORDINATE RANGE
;
SCALE  LDY #6
       LDA #$D5
       STA MLPCND
SCLP   LDA YMIN,Y
       STA MLPLER
       JSR MULT
       STA YMIN,Y
       DEY
       DEY
       DEY
       BPL SCLP
       RTS
;
;
;*****************************************
;
; EXCHANGE 'MIN' AND 'MID' COORDINATES
;
SWAP12 LDY #2
LOOP1  LDA XMIN,Y
       PHA
       LDA XMID,Y
       STA XMIN,Y
       PLA
       STA XMID,Y
       DEY
       BPL LOOP1
       RTS
;
;*****************************************
;
; EXCHANGE 'MID' AND 'MAX' COORDINATES
;
SWAP23 LDY #2
LOOP2  LDA XMID,Y
       PHA
       LDA XMAX,Y
       STA XMID,Y
       PLA
       STA XMAX,Y
       DEY
       BPL LOOP2
       RTS
;
;*****************************************
;
; SORT COORDINATES ACCORDING TO X COMPONENTS
;
SORTX  LDX #2
SORTLP SEC
       LDA XMID
       SBC XMIN
       LDA XMID+1
       SBC XMIN+1
       BCS NOSWP1
       JSR SWAP12
NOSWP1 DEX
       BEQ SORTED
       SEC
       LDA XMAX
       SBC XMID
       LDA XMAX+1
       SBC XMID+1
       BCS SORTLP
       JSR SWAP23
       JMP SORTLP
SORTED RTS
;
;*****************************************
;
; DRAW A LINE BETWEEN XMIN,YMIN AND XMID,YMID
; USING FAST DDA (DIGITAL DIFFERENTIAL ANALYZER)
; TECHNIQUE
;
LINE   LDA #2        ; ENSURE XMAX IS
       STA XMAX+1    ; LARGEST BEFORE
       JSR SORTX     ; ORDERING 'MIN' AND 'MID'
       LDA NOSCAL
       BEQ OUTLN
       JSR SCALE
OUTLN  JSR FINDXY    ; ENTRY POINT TO
       LDA XMIN       ; OUTLINE FACETS
       STA XPLT
       LDA XMIN+1
       STA XPLT+1
       LDA YMIN
       STA YPLT
       LDA DLTAX1+1  ; CHECK FOR DX>DY
       BNE STEPX
       SEC
       LDA DLTAX1
       SBC DLTAY1
       BCS STEPX
STEPY  LDA DLTAY1
       STA ERROR
       STA COUNT
       LSR ERROR
       SEC
       LDA DLTAX1
       SBC ERROR
       STA ERROR
       LDA DLTAX1+1
       SBC #0
       STA ERROR+1
       INC COUNT
LNLP1  LDA MODE      ; 0 = DRAW, 1 = ERASE
       BNE ERASE1
       JSR PLOT
       JMP SK1
ERASE1 JSR UNPLOT
SK1    LDA FLAG1     ; 0 = POSITIVE SLOPE
       BNE NSLOPE
       INC YPLT
       BNE SK2     ; ALWAYS BRANCH
NSLOPE DEC YPLT
SK2    BIT ERROR+1
       BMI SK3
       INC XPLT
       BNE NOINC1
       INC XPLT+1
NOINC1 SEC
       LDA ERROR
       SBC DLTAY1
       STA ERROR
       LDA ERROR+1
       SBC #0
       STA ERROR+1
SK3    CLC
       LDA ERROR
       ADC DLTAX1
       STA ERROR
       LDA ERROR+1
       ADC DLTAX1+1
       STA ERROR+1
       DEC COUNT
       BNE LNLP1
       RTS
;
STEPX  LDA DLTAX1
       STA ERROR
       STA COUNT
       LDA DLTAX1+1
       STA ERROR+1
       STA COUNT+1
       LSR ERROR+1
       ROR ERROR
       SEC
       LDA DLTAY1
       SBC ERROR
       STA ERROR
       LDA #0
       SBC ERROR+1
       STA ERROR+1
LNLP2  LDA MODE
       BNE ERASE2
       JSR PLOT
       JMP SKP1
ERASE2 JSR UNPLOT
SKP1   INC XPLT
       BNE NOINC2
       INC XPLT+1
NOINC2 BIT ERROR+1
       BMI SKP3
       LDA FLAG1
       BNE NGSLP
       INC YPLT
       BNE SKP2    ; ALWAYS BRANCH
NGSLP  DEC YPLT
SKP2   SEC
       LDA ERROR
       SBC DLTAX1
       STA ERROR
       LDA ERROR+1
       SBC DLTAX1+1
       STA ERROR+1
SKP3   CLC
       LDA ERROR
       ADC DLTAY1
       STA ERROR
       LDA ERROR+1
       ADC #0
       STA ERROR+1
       SEC
       LDA COUNT
       SBC #1
       STA COUNT
       BCS TEST
       DEC COUNT+1
TEST   BIT COUNT+1
       BPL LNLP2
       RTS
;
;*****************************************
; DRAW A SHADED VERTICAL LINE AT
; XPLT FROM YTOP TO YBOT
;
VLINE  SEC         ; MAKE SURE YTOP>YBOT
       LDA YTOP
       SBC YBOT
       BCS DRAW
       LDA YTOP
       PHA
       LDA YBOT
       STA YTOP
       PLA
       STA YBOT
DRAW   LDA YTOP
       STA YPLT
       JSR NORM    ; PLOT A SHADE-WEIGHTED
       LDA YTOP    ; PIXEL CHECKING ONLY
       CMP YBOT    ; FOR SHADE STYLE
       BEQ DONE
       DEC YTOP
       JMP DRAW
DONE   RTS
;
;*****************************************
;
; FIND ENDPOINTS FOR VERTICAL LINES
; BETWEEN FACET EDGES
;
ENDPTS LDA XDIFF
       STA MLPCND
       LDA DELTAY
       STA MLPLER
       JSR MULT
       STA DVDND+1
       LDA PROD
       STA DVDND
       LDA #0
       STA DVSOR+1
       LDA DELTAX
       STA DVSOR
       JSR DIVIDE
       LDA FLAG
       BNE NEGSLP
       CLC
       LDA YBASE
       ADC QUOT
       BCC SKIP2
NEGSLP SEC
       LDA YBASE
       SBC QUOT
SKIP2  RTS
;
;*****************************************
;
; FIND COORDINATE DIFFERENCES
;
; ALL "DELTA X" VALUES POSITIVE,
; SINGLE PRECISION (JUST LOWER BYTE)
;
FINDXY SEC
       LDA XMID
       SBC XMIN
       STA DLTAX1
       LDA XMID+1
       SBC XMIN+1
       STA DLTAX1+1
       SEC
       LDA XMAX
       SBC XMID
       STA DLTAX2
       SEC
       LDA XMAX
       SBC XMIN
       STA DLTAX3
;
; USE ABS(DELTA Y) VALUES,
; FLAGS INDICATE SLOPE OF LIMIT LINES
;
       LDA #$00
       STA FLAG1
       STA FLAG2
       STA FLAG3
       SEC
       LDA YMID
       SBC YMIN
       BCS STORE1
       INC FLAG1
       LDA YMIN
       SBC YMID
STORE1 STA DLTAY1
       SEC
       LDA YMAX
       SBC YMID
       BCS STORE2
       INC FLAG2
       LDA YMID
       SBC YMAX
STORE2 STA DLTAY2
       SEC
       LDA YMAX
       SBC YMIN
       BCS STORE3
       INC FLAG3
       LDA YMIN
       SBC YMAX
STORE3 STA DLTAY3
       RTS
;
;*****************************************
;
; DRAW A SHADED TRIANGULAR FACET
;
FACET  JSR SORTX
       LDA NOSCAL
       BEQ YSOK
       JSR SCALE
YSOK   JSR FINDXY
       LDA XMIN
       STA XPLT
       LDA XMIN+1
       STA XPLT+1
FCETLP SEC
       LDA XPLT
       SBC XMIN
       STA XDIFF
       LDA DLTAX1
       BEQ CONT
       STA DELTAX
       LDA DLTAY1
       STA DELTAY
       LDA FLAG1
       STA FLAG
       LDA YMIN
       STA YBASE
       JSR ENDPTS
       STA YTOP
       LDA DLTAX3
       BEQ CONT
       STA DELTAX
       LDA DLTAY3
       STA DELTAY
       LDA FLAG3
       STA FLAG
       JSR ENDPTS
       STA YBOT
       JSR VLINE
       LDA XPLT+1
       CMP XMID+1
       BNE NEXTX1
       LDA XPLT
       CMP XMID
       BEQ CONT
NEXTX1 INC XPLT
       BNE SKIP3
       INC XPLT+1
SKIP3  JMP FCETLP
CONT   SEC
       LDA XPLT
       SBC XMIN
       STA XDIFF
       LDA DLTAX3
       BEQ FINI
       STA DELTAX
       LDA DLTAY3
       STA DELTAY
       LDA FLAG3
       STA FLAG
       LDA YMIN
       STA YBASE
       JSR ENDPTS
       STA YBOT
       SEC
       LDA XPLT
       SBC XMID
       STA XDIFF
       LDA DLTAX2
       BEQ FINI
       STA DELTAX
       LDA DLTAY2
       STA DELTAY
       LDA FLAG2
       STA FLAG
       LDA YMID
       STA YBASE
       JSR ENDPTS
       STA YTOP
       JSR VLINE
       LDA XPLT+1
       CMP XMAX+1
       BNE NEXTX2
       LDA XPLT
       CMP XMAX
       BEQ FINI
NEXTX2 INC XPLT
       BNE SKIP4
       INC XPLT+1
SKIP4  JMP CONT
FINI   LDA EDGES
       BEQ FINISH
       JSR OUTLN
       JSR SWAP23
       JSR OUTLN
       JSR SWAP12
       JSR SWAP23
       JSR SWAP12
       JSR OUTLN
FINISH RTS
.END
Listing 3. Assembler-Quelltext zum Zeichnen von Linien und Dreiecken
; PRIMITIVE SOLID SHAPE DRAWING
;
; RICHARD L. RYLANDER   11/7/84
;
; LOAD ARITHMETIC AND GRAPHIC UTILITIES FIRST
;
;*****************************************
RAM=$036A
ORIGIN=$C5EA
;
MLPCND=$AC     ; MULTIPLICAND (S)
MLPLER=$AD     ; MULTIPLIER (S)
PROD=$AE      ; PRODUCT (D)
MULT=$C011    ; CALL FOR MULTIPLY
;
DVDND=$FD     ; DIVIDEND (D)
DVSOR=$FB     ; DIVISOR (D)
QUOT=$FD      ; QUOTIENT (D)
DIVIDE=$C025  ; CALL FOR DIVIDE
;
ARG=$AC       ; ARGUMENT (S)
SQR=$AE       ; SQUARE OF ARG (D)
SQUARE=$C004  ; CALL FOR SQUARE
;
RADCND=$AC    ; RADICAND (D)
ROOT=$033C    ; SQUARE ROOT (S)
SQRT=$C064    ; CALL FOR SQRT
;
RNDM=$C000    ; RANDOM NUMBER
RANDOM=$C0C8  ; CALL FOR RANDOM
; NOTE - A CALL TO 'RANDOM' LEAVES A RANDOM BYTE
; IN THE ACCUMULATOR
;
XPLT=$033F
YPLT=$0341
NORM=$C224
PLTSHD=$C20F
VALUE=$0344   ; FINAL NORMALIZED SHADE VALUE
HTORRN=$0346  ; SHADE FLAG, 1=HALFTONE
NOSCAL=$0347  ; SCALE FLAG, 1=NO SCALE
;
       *=RAM
XCENT  *=*+2  ; CENTER COORD
XREL   *=*+1  ; RELATIVE (TO CENTER)
XSHD   *=*+2  ; USED IN SHADE CALC
YCENT  *=*+1  ; CENTER COORD
YREL   *=*+1  ; RELATIVE (TO CENTER)
YSHD   *=*+2  ; USED IN SHADE CALC
ZREL   *=*+2  ; RELATIVE (TO CENTER)
ZWX    *=*+2  ; Z WITH X (+ OR -)
;
RADIUS *=*+2  ; LOCAL RADIUS OF SURFACE
TONE   *=*+2  ; USED IN SHADE CALC
TNTMP  *=*+2  ; USED IN SHADE CALC
;
CLIPL  *=*+1  ; LEFT CLIPPING BOUND
CLIPR  *=*+1  ; RIGHT CLIPPING BOUND
CLIPU  *=*+1  ; UP CLIPPING BOUND
CLIPD  *=*+1  ; DOWN CLIPPING BOUND
;
HEMI   *=*+1  ; PLOTTING HEMISPHERE
;
BAKLIT *=*+1  ; BACKLIT FLAG
HVFLAG *=*+1  ; HORIZONTAL/VERTICAL FLAG
TEMP   *=*+2  ; TEMPORARY STORAGE
CNTX   *=*+1   ; LOOP COUNTER
CNTY   *=*+1   ; LOOP COUNTER
MAX    *=*+1   ; LOOP LIMIT
;
HLEN   *=*+1   ; HALF-LENGTH OF CYLINDERS
RS     *=*+2   ; SQUARE OF TOROID RADIUS
RT     *=*+1   ; TOROID (RING) RADIUS
RC     *=*+1   ; CENTER RADIUS OF TOROID
RO     *=*+1   ; OUTER RADIUS OF TOROID
RI     *=*+1   ; INNER RADIUS OF TOROID
XSQR   *=*+2
XMAX   *=*+1
;
R0=HLEN
;
       *=ORIGIN
;*****************************************
;
; DIVIDE WITH SINGLE PRECISION DIVISOR
; (USED OFTEN IN SHAPE ROUTINES)
;
SDIV   LDA #0
       STA DVSOR+1
       JMP DIVIDE
;
;*****************************************
;
; CALCULATE SHADE VALUE (0-63) BY
; MULTIPLYING 'TONE' BY 26 THEN
; DIVIDE RESULT BY RADIUS OF SURFACE
;
GETVAL BIT TONE+1
       BPL CNTNU   ; IF 'TONE'<0, THEN
       LDA BAKLIT  ; MAKE VALUE 0 OR ABS(TONE)
       BNE NEGATE  ; DEPENDING ON BAKLIT FLAG
       STA VALUE
       RTS
NEGATE SEC
       LDA #$00
       SBC TONE
       STA TONE
CNTNU  LDA TONE
       STA MLPCND
       LDA #$1A
       STA MLPLER
       JSR MULT
       STA DVDND+1
       LDA PROD
       STA DVDND
       LDA RADIUS
       STA DVSOR
       JSR SDIV
       LDA QUOT
       STA VALUE
       RTS
;
;*****************************************
;
; POINT PLOTTING BY QUADRANTS USING
; THE FOUR-FOLD SYMMETRY OF SIMPLE OBJECTS
;
; DEPENDING ON STATUS OF 'HVFLAG', EXCHANGE
; X AND Y COORDINATES TO ROTATE OBJECTS 90 DEG
; SINGLE SHAPE ROUTINE CAN THEN BE USED TO
; DRAW 'HORIZONTAL' OR 'VERTICAL' VERSIONS
; OF AN OBJECT
;
; THE FOLOWING IS A 'BASIC SUBROUTINE'
; EQUIVALENT TO EXPLAIN ITS OPERATION
;
; NOTE THAT LABELS ARE USED IN PLACE OF
; LINE NUMBERS
;
; 'PTPLOT' IF HVFLAG<0 THEN GOTO 'NOROT'
;          (STACK)=XREL:XREL=YREL:YREL=(STACK)
;          (STACK)=XSHD:XSHD=YSHD:YSHD=(STACK)
; 'NOROT'  GOSUB 'GETZ'
;          REM CALCULATE 2*Z FROM X,Y AND RADIUS
;          HEMI = 1
;          IF XREL>CLIPL THEN GOTO 'RHEMI'
;          ZWX=2*Z-XSHD
;          XPLT=XCENT-XREL:REM LEFT HEMISPHERE
; 'CHCLUP' IF YREL>CLIPU THEN GOTO 'DHEMI'
;          TONE=ZWX+YSHD
;          GOSUB 'GETVAL':REM NORMALIZE SHADE VAL
;          YPLT=YCENT+YREL
;          GOSUB 'PLTSHD':REM PLOT OR UNPLOT
;          REM   POINTS WEIGHTED BY SHADE VALUE
; 'DHEMI'  IF YREL>CLIPD THEN GOTO 'RHEMI'
;          TONE=ZWX-YSHD
;          GOSUB 'GETVAL'
;          YPLT=YCENT-YREL
;          GOSUB 'PLTSHD'
; 'RHEMI'  IF HEMI=0 THEN RETURN
;          HEMI=0
;          IF XREL>CLIPR THEN RETURN
;          ZWX=2*Z+XSHD
;          XPLT=XCENT+XREL
;          GOSUB 'CHCLUP'
;          RETURN
;
PTPLOT BIT HVFLAG
       BPL NOROT
       LDA XREL
       PHA
       PHA
       LDA YREL
       STA XREL
       PLA
       STA YREL
       LDA XSHD
       PHA
       PHA
       LDA YSHD
       STA XSHD
       PLA
       STA YSHD
       LDA XSHD+1
       PHA
       PHA
       LDA YSHD+1
       STA XSHD+1
       PLA
       STA YSHD+1
NOROT  JSR GETZ
PTPLT2 LDA #$01
       STA HEMI
       SEC
       LDA CLIPL  ; CHECK LEFT HEMISPHERE
       CMP XREL
       BCC RHEMI
       SEC
       LDA ROOT
       SBC XSHD
       STA ZWX
       LDA ROOT+1
       SBC XSHD+1
       STA ZWX+1
       SEC
       LDA XCENT
       SBC XREL
       STA XPLT
       LDA XCENT+1
       SBC #$00
       STA XPLT+1
;
CHCLUP SEC
       LDA CLIPU  ; CHECK FOR UP CLIPPING
       CMP YREL
       BCC DHEMI
       CLC
       LDA ZWX
       ADC YSHD
       STA TONE
       LDA ZWX+1
       ADC YSHD+1
       STA TONE+1
       JSR GETVAL
       CLC
       LDA YCENT
       ADC YREL
       STA YPLT
       JSR PLTSHD
;
DHEMI  SEC
       LDA CLIPD  ; CHECK FOR DOWN CLIPPING
       CMP YREL
       BCC RHEMI
       SEC
       LDA ZWX
       SBC YSHD
       STA TONE
       LDA ZWX+1
       SBC YSHD+1
       STA TONE+1
       JSR GETVAL
       SEC
       LDA YCENT
       SBC YREL
       STA YPLT
       JSR PLTSHD
;
RHEMI  LDA HEMI
       BEQ PLDONE
       DEC HEMI
       SEC
       LDA CLIPR  ; CHECK FOR RIGHT CLIPPING
       CMP XREL
       BCC PLDONE
       CLC
       LDA ROOT
       ADC XSHD
       STA ZWX
       LDA ROOT+1
       ADC XSHD+1
       STA ZWX+1
       CLC
       LDA XCENT
       ADC XREL
       STA XPLT
       LDA XCENT+1
       ADC #$00
       STA XPLT+1
       JMP CHCLUP
PLDONE BIT HVFLAG
       BPL NORSTR
       LDA XSHD+1    ; RESTORE COORDS
       STA YSHD+1
       PLA
       STA XSHD+1
       LDA XSHD
       STA YSHD
       PLA
       STA XSHD
       LDA XREL
       STA YREL
       PLA
       STA XREL
NORSTR RTS
;
;*****************************************
;
; CALCULATE Z FROM LOCAL X,Y BY
; PYTHAGOREAN SUM
;
GETZ   LDA RADIUS
       STA ARG
       JSR SQUARE
       STA TNTMP+1
       LDA SQR
       STA TNTMP
       LDA XSHD
       STA ARG
       JSR SQUARE
       SEC
       LDA TNTMP
       SBC SQR
       STA TNTMP
       LDA TNTMP+1
       SBC SQR+1
       STA TNTMP+1
       LDA YSHD
       STA ARG
       JSR SQUARE
       SEC
       LDA TNTMP
       SBC SQR
       STA RADCND
       LDA TNTMP+1
       SBC SQR+1
       STA RADCND+1
       BMI ZEROOT
       JSR SQRT
       ASL ROOT
       ROL ROOT+1
       RTS
ZEROOT LDA #$00
       STA ROOT
       STA ROOT+1
       RTS
;
;*****************************************
;
; SET UP PARAMETERS FOR TOROIDS
;
; RT=(RO-RI)/2   RS=RT*RT   RC=RT+RI
;
TPARM  LDA RO
       SEC
       SBC RI
       LSR A
       STA RT
       STA RADIUS
       CLC
       ADC RI
       STA RC
       LDA RT
       STA ARG
       JSR SQUARE
       LDA SQR
       STA RS
       LDA SQR+1
       STA RS+1
       LDA #0
       STA CNTX
       RTS
;
;*****************************************
;
; DRAW A SHADED SPHERE
;
; 'BASIC SUBROUTINE' EQUIVALENT
;
; 'SPHERE' FOR CNTX=0 TO RADIUS/SQR(2)
;          XREL=CNTX:XSHD=CNTX
;          FOR CNTY=CNTX TO SQR(RAD*RAD-CNTX*CNTX)
;          YREL=CNTY:YSHD=CNTY
;          HVFLAG=0
;          GOSUB 'PTPLOT'
;          REM EXCHANGE X & Y TO USE 8-FOLD SYM
;          HVFLAG=-128
;
;          GOSUB 'PTPLOT'
;          NEXT CNTY
;          NEXT CNTX
;          RETURN
;
;
SPHERE LDA RADIUS
       STA ARG
       JSR SQUARE
       ASL SQR
       ROL SQR+1
       LDA SQR
       STA RADCND
       LDA SQR+1
       STA RADCND+1
       JSR SQRT
       LSR ROOT+1
       ROR ROOT
       LDA ROOT
       STA XMAX
       LDA #$00
       STA CNTX
       STA XSHD+1
       STA YSHD+1
       LDA RADIUS
       STA ARG
       JSR SQUARE
       STA TEMP+1
       LDA SQR
       STA TEMP
LOOPX  LDA CNTX
       STA CNTY
       STA ARG
       STA XREL
       STA XSHD
       JSR SQUARE
       SEC
       LDA TEMP
       SBC SQR
       STA RADCND
       LDA TEMP+1
       SBC SQR+1
       STA RADCND+1
       JSR SQRT
       LDA ROOT
       STA MAX
LOOPY  LDA CNTY
       STA YREL
       STA YSHD
       LDA #0
       STA HVFLAG
       JSR PTPLOT
       LDA #$80
       STA HVFLAG
       JSR PTPLOT
       LDA CNTY
       CMP MAX
       BEQ DONEY
       INC CNTY
       JMP LOOPY
DONEY  LDA CNTX
       CMP XMAX
       BEQ DONE
       INC CNTX
       JMP LOOPX
DONE   RTS
;
;*****************************************
;
; DRAW SHADED CYLINDERS
;
; 'BASIC SUBROUTINE' EQUIVALENT
;
; 'CYLNDR' XSHD=0
;          FOR YREL=RADIUS TO 0
;          YSHD=YREL
;          FOR XREL=HLEN TO 0
;          GOSUB 'PTPLOT'
;          NEXT XREL
;          NEXT YREL
;          RETURN
;
CYLNDR LDA #0
       STA XSHD
       STA XSHD+1
       STA YSHD+1
       LDA RADIUS
       STA YREL
CYLOOP LDA HLEN
       STA XREL
       LDA YREL
       STA YSHD
CXLOOP JSR PTPLOT
       DEC XREL
       BPL CXLOOP
       DEC YREL
       BPL CYLOOP
       RTS
;
;*****************************************
;
; DRAW EDGE-VIEW TOROIDS
;
; 'BASIC SUBROUTINE' EQUIVALENT
;
; 'EDGTOR' GOSUB 'TPARM':REM SET UP RADII
;          FOR CNTX=0 TO RT
;          XREL=CNTX:XSHD=CNTX
;          R0=SQR(RT*RT-CNTX*CNTX)
;          FOR CNTY=0 TO R0+RC
;          YREL=CNTY
;          YSHD=(R0*CNTY)/(R0+RC)
;          GOSUB 'PTPLOT'
;          NEXT CNTY
;          NEXT CNTX
;          RETURN
;
EDGTOR JSR TPARM
       LDA #$00
       STA XSHD+1
       STA YSHD+1
LOOPX4 LDA CNTX
       STA XREL
       STA XSHD
       STA ARG
       JSR SQUARE
       SEC
       LDA RS
       SBC SQR
       STA RADCND
       LDA RS+1
       SBC SQR+1
       STA RADCND+1
       JSR SQRT
       LDA ROOT
       STA R0
       CLC
       ADC RC
       STA MAX
       LDA #$00
       STA CNTY
LOOPY4 LDA CNTY
       STA YREL
       STA MLPLER
       LDA R0
       STA MLPCND
       JSR MULT
       STA DVDND+1
       LDA PROD
       STA DVDND
       LDA MAX
       STA DVSOR
       JSR SDIV
       LDA QUOT
       STA YSHD
       JSR PTPLOT
       LDA CNTY
       CMP MAX
       BEQ DONE4
       INC CNTY
       JMP LOOPY4
DONE4  LDA CNTX
       CMP RT
       BEQ DONEHT
       INC CNTX
       JMP LOOPX4
DONEHT RTS
;
;*****************************************
;
; DRAW A SHADED, TOP-VIEW TOROID
;
; 'BASIC SUBROUTINE' EQUIVALENT
;
; 'TOROID' GOSUB 'TPARM'
;          FOR CNTX=0 TO RO/SQR(2)
;          REM 8-FOLD SYMMETRY USED
;          XREL=CNTX
;          MAX=SQR(RO*RO-CNTX*CNTX)
;          IF CNTX>RI THEN GOTO 'GRTR'
;          CNTY=SQR(RI*RI-CNTY*CNTY)
;          GOTO 'LLPY1'
; 'GRTR'   CNTY=CNTX
; 'LLPY1'  YREL=CNTY
;          R0=SQR(CNTY*CNTY+CNTX*CNTX)
;          XSHD=CNTX-(CNTX*RC)/R0
;          YSHD=CNTY-(CNTY*RC)/R0
;          HVFLAG=0:GOSUB 'PTPLOT'
;          HVFLAG=-128:GOSUB 'PTPLOT'
;          IF CNTY=MAX THEN GOTO 'DDNY1'
;          CNTY=CNTY+1
;          GOTO 'LLPY1'
; 'DDNY1'  NEXT CNTX
;          RETURN
;
TOROID JSR TPARM
       LDA RO
       STA ARG
       JSR SQUARE
       ASL SQR
       ROL SQR+1
       LDA SQR
       STA RADCND
       LDA SQR+1
       STA RADCND+1
       JSR SQRT
       LSR ROOT+1
       ROR ROOT
       LDA ROOT
       STA XMAX
LLPX1  LDA CNTX
       STA XREL
       STA ARG
       JSR SQUARE
       STA XSQR+1
       LDA SQR
       STA XSQR
       LDA RO
       STA ARG
       JSR SQUARE
       SEC
       LDA SQR
       SBC XSQR
       STA RADCND
       LDA SQR+1
       SBC XSQR+1
       STA RADCND+1
       JSR SQRT
       LDA ROOT
       STA MAX
       SEC
       LDA RI
       SBC CNTX
       BCC GRTR
       LDA RI
       STA ARG
       JSR SQUARE
       SEC
       LDA SQR
       SBC XSQR
       STA RADCND
       LDA SQR+1
       SBC XSQR+1
       STA RADCND+1
       JSR SQRT
       LDA ROOT
       STA CNTY
       JMP LLPY1
GRTR   LDA CNTX
       STA CNTY
LLPY1  LDA CNTY
       STA YREL
       STA ARG
       JSR SQUARE
       CLC
       LDA SQR
       ADC XSQR
       STA RADCND
       LDA SQR+1
       ADC XSQR+1
       STA RADCND+1
       JSR SQRT
       LDA ROOT
       STA R0
       STA DVSOR
       LDA CNTX
       STA MLPLER
       LDA RC
       STA MLPCND
       JSR MULT
       STA DVDND+1
       LDA PROD
       STA DVDND
       JSR SDIV
       SEC
       LDA CNTX
       SBC QUOT
       STA XSHD
       LDA #$00
       SBC QUOT+1
       STA XSHD+1
       LDA CNTY
       STA MLPLER
       LDA RC
       STA MLPCND
       JSR MULT
       STA DVDND+1
       LDA PROD
       STA DVDND
       LDA R0
       STA DVSOR
       JSR SDIV
       SEC
       LDA CNTY
       SBC QUOT
       STA YSHD
       LDA #$00
       STA HVFLAG
       SBC QUOT+1
       STA YSHD+1
       JSR PTPLOT
       LDA #$80
       STA HVFLAG
       JSR PTPLOT
       LDA CNTY
       CMP MAX
       BEQ DDNY1
       INC CNTY
       JMP LLPY1
DDNY1  LDA CNTX
       CMP XMAX
       BEQ DUNTOR
       INC CNTX
       JMP LLPX1
DUNTOR RTS
;
;*****************************************
;
; DRAW "INSIDE VIEW" TOROIDS
;
; 'BASIC SUBROUTINE' EQUIVALENT
;
; 'SPOOL'  GOSUB 'TPARM'
;          FOR CNTX=0 TO RT
;          XREL=CNTX:XSHD=CNTX
;          MAX=RC-SQR(RS-CNTX*CNTX)
;          FOR CNTY=0 TO MAX
;          YREL=CNTY
;          YSHD=(RC*CNTY/MAX)-CNTY
;          GOSUB 'PTPLOT'
;          NEXT CNTY
;          NEXT CNTX
;          RETURN
;
SPOOL  JSR TPARM
LLPX2  LDA CNTX
       STA XREL
       STA ARG
       SEC
       LDA #$00
       SBC CNTX
       STA XSHD
       LDA #$00
       SBC #$00
       STA XSHD+1
       JSR SQUARE
       SEC
       LDA RS
       SBC SQR
       STA RADCND
       LDA RS+1
       SBC SQR+1
       STA RADCND+1
       JSR SQRT
       SEC
       LDA RC
       SBC ROOT
       STA MAX
       LDA #$00
       STA CNTY
LLPY2  LDA CNTY
       STA YREL
       STA MLPLER
       LDA RC
       STA MLPCND
       JSR MULT
       STA DVDND+1
       LDA PROD
       STA DVDND
       LDA MAX
       STA DVSOR
       JSR SDIV
       LDA QUOT
       SEC
       SBC CNTY
       STA YSHD
       LDA QUOT+1
       SBC #$00
       STA YSHD+1
       JSR PTPLOT
       LDA CNTY
       CMP MAX
       BEQ DDNY2
       INC CNTY
       JMP LLPY2
DDNY2  LDA CNTX
       CMP RT
       BEQ DUNHSP
       INC CNTX
       JMP LLPX2
DUNHSP RTS
.END
Listing 4. Assembler-Quelltext zum Zeichnen ausgefüllter Flächen, sogenannter Shapes
; INTERFACE - EASY PARAMETER SETTING FOR SHAPE
; DRAWING ROUTINES FROM BASIC.
;
; RICHARD L. RYLANDER  11/23/84
;
;****************************************
ORIGIN=$CAC8
RAM   =$0393
;
; PARAMETER LOCATIONS FOR VARIOUS SHAPES
;
XCENT =$036A
YCENT =$036F
XPLOT =$033F
YPLOT =$0341
XMIN  =$034A
YMIN  =$034C
XMID  =$034D
YMID  =$034F
XMAX  =$0350
YMAX  =$0352
RADIUS =$0377
HLEN  =$0389
RI    =$038F
RO    =$038E
;
HVFLAG =$0383
VALUE =$0344
PLTFLG =$033E
;
DEFLAG =$FB
;
;****************************************
;
; FUNCTION LOCATIONS
;
GRFON =$C0E2      ; SWITCH TO GRAPHICS MODE
GRFOFF =$C103      ; RETURN TO TEXT DISPLAY
;
CLEARR=$C12C       ; CLEAR BITMAP
CLRBYT=$C135       ; CLEAR (FILL) BYTE
COLORR=$C118       ; LOAD COLOR MAP
COLBYT=$C119       ; COLOR BYTE
;
PLOTR =$C14B      ; POINT PLOT ROUTINE
LINER =$C2DB       ; DRAW A LINE
FACETR =$C4E1       ; DRAW A SHADED FACET
;
;****************************************
;
; SHADED SHAPE DRAWING ROUTINES
;
SPHERR=$C7C7       ; SPHERE
CYLNDR=$C864       ; CYLINDER
TORUSR=$C90F       ; TOP-VIEW TOROID
EDGTOR=$C88F       ; EDGE-VIEW TOROID
SPOOLR=$CA3B       ; INSIDE-VIEW TOROID
;
;****************************************
;
; BASIC ROM ROUTINES
;
CHKCOM=$AEFD       ; CHECK FOR COMMA
EVAEXP=$AD9E       ; EVALUATE EXPRESSION
FLTFIX=$B1AA       ; CONVERT TO FIXED
;
*=RAM
LINFAC *=*+1       ; LINE OR FACET FLAG
;
*=ORIGIN
;
;****************************************
;
; GET PARAMETERS FROM BASIC CALLING STATEMENT
; OF THE FORM:
; SYS(FNCTN),PARAM1,PARAM2,PARAM3[OPT]
; WHERE THE THIRD PARAMETER (FOR EXAMPLE)
; MAY BE OPTIONAL (A DEFAULT VALUE IS USED
; IF THE PARAMETER IS NOT SPECIFIED)
;
GETNUM JSR CHKCOM   ; LOOK FOR COMMA
       JSR EVAEXP   ; EVALUATE EXPRESSION
       JSR FLTFIX   ; CHANGE TO INTEGER WITH
; HIGH BYTE IN "A" AND LOW BYTE IN "Y"
       RTS
;
; CHECK FOR ADDITIONAL (OPTIONAL) PARAMETERS
;
PCHECK LDA #$2C     ; "," COMMA
       LDY #0
       STY DEFLAG
       CMP ($7A),Y
       BNE NOMORE   ; NO COMMA - USE DEFAULT
       JMP $0073
NOMORE LDY #$80
       STY DEFLAG
       RTS
;
; GET TWO ADDITIONAL PARAMETERS FOR TOROIDS
;
GETTWO JSR PCHECK
       BIT DEFLAG
       BMI DFAULT
       JSR EVAEXP
       JSR FLTFIX
       STY RI
       JSR GETNUM
       STY RO
DFAULT RTS
;
;****************************************
;
; SET CENTER COORDINATES
;
CENTER JSR GETNUM
       STY XCENT
       STA XCENT+1
       JSR GETNUM
       STY YCENT
       RTS
;
;****************************************
;
; CLEAR THE BITMAP, FILLING WITH (OPTIONAL)
; FILL VALUE SPECIFIED OR WITH (DEFAULT) "0"
;
CLEAR2 JSR PCHECK
       BIT DEFLAG
       BMI DEFCLR
       JSR EVAEXP
       JSR FLTFIX
       .BYTE $2C
DEFCLR LDY #0
       STY CLRBYT
       JMP CLEARR
;
;****************************************
;
; FILL COLOR MAP WITH (OPTIONAL) COLOR BYTE
; SPECIFIED OR WITH (DEFAULT) "$01"
; (BLACK DOTS ON WHITE BACKGROUND)
;
COLOR2 JSR PCHECK
       BIT DEFLAG
       BMI DEFCOL
       JSR EVAEXP
       JSR FLTFIX
       .BYTE $2C
DEFCOL LDY #$01
       STY COLBYT
       JMP COLORR
;
;****************************************
;
; PLOT OR UNPLOT POINTS
;
PLOT2  LDA #0
       .BYTE $2C
UNPLT2 LDA #$80
       STA PLTFLG
       JSR GETNUM
       STY XPLOT
       STA XPLOT+1
       JSR GETNUM
       STY YPLOT
       JMP PLOTR
;
;****************************************
;
; DRAW LINES BETWEEN (X1,Y1) AND (X2,Y2)
; OR SHADED FACETS BETWEEN THREE POINTS
; (X1,Y1), (X2,Y2) AND (X3,Y3)
;
LINE2  LDA #0
       .BYTE $2C
FACET2 LDA #$80
       STA LINFAC
       JSR GETNUM
       STY XMIN
       STA XMIN+1
       JSR GETNUM
       STY YMIN
       JSR GETNUM
       STY XMID
       STA XMID+1
       JSR GETNUM
       STY YMID
       BIT LINFAC
       BPL LDRAW
       JSR GETNUM
       STY XMAX
       STA XMAX+1
       JSR GETNUM
       STY YMAX
       JSR GETNUM
       STY VALUE
       JMP FACETR
LDRAW  JMP LINER
;
;****************************************
;
; DRAW A SPHERE CENTERED AT (XCENT,YCENT)
; DEFAULT RADIUS IS LAST VALUE USED
;
SPHER2 JSR CENTER
       JSR PCHECK
       BIT DEFLAG
       BMI SKIP1
       JSR EVAEXP
       JSR FLTFIX
       STY RADIUS
SKIP1  JMP SPHERR
;
;****************************************
;
; DRAW A TOP-VIEW TOROID AT (XCENT,YCENT)
; DEFAULT INNER AND OUTER RADII ARE LAST USED
;
TORUS2 JSR CENTER
       JSR GETTWO
       JMP TORUSR
;
;****************************************
;
; DRAW CYLINDERS WITH AXES HORIZONTAL OR
; VERTICAL.  DEFAULT RADIUS AND "HALF-LENGTH"
; ARE LAST VALUES USED.
;
VCYL2  LDA #$80
       .BYTE $2C
HCYL2  LDA #0
       STA HVFLAG
       JSR CENTER
       JSR PCHECK
       BIT DEFLAG
       BMI SKIP2
       JSR EVAEXP
       JSR FLTFIX
       STY RADIUS
       JSR GETNUM
       STY HLEN
SKIP2  JMP CYLNDR
;
;****************************************
;
; DRAW EDGE-VIEW TOROIDS WITH AXES HORIZONTAL
; OR VERTICAL
; INNNER AND OUTER RADII ARE OPTIONAL
;
VTOR2  LDA #$80
       .BYTE $2C
HTOR2  LDA #0
       STA HVFLAG
       JSR CENTER
       JSR GETTWO
       JMP EDGTOR
;
;****************************************
;
; DRAW INSIDE-VIEW TOROIDS, "SPOOLS",
; WITH AXES HORIZONTAL OR VERTICAL
; INNER AND OUTER RADII ARE OPTIONAL
;
VSPL2  LDA #$80
       .BYTE $2C
HSPL2  LDA #0
       STA HVFLAG
       JSR CENTER
       JSR GETTWO
       JMP SPOOLR
.END
Listing 5. Assembler-Quelltext des »Basic-Interfaces« zum einfachen Ansprechen aller Assembler-Routinen per SYS-Befehl
; KEYSORT - RELOCATABLE BUBBLE SORT USING KEY ARRAY
; POINTING TO INTEGER ARRAY
;
;  RICHARD L. RYLANDER    1/12/85
;
ORIGIN=$CF59  ; 53081. (FOLLOWING DOS 5.1)
;
KB     = $FB  ; 251. POINTER TO KEY ARRAY
ZB     = $FD  ; 253. POINTER TO DATA ARRAY
MAX    = $8C  ; 140. POKE WITH MAX ARRAY INDEX
TOP    = $AC
TOPDIS = $AD
FLAG   = $AE
NXTFLG = $61
CRRNT  = $62
REPEAT = $64
;
      *=ORIGIN
;
INIT   LDY #$FF     ; INITIALIZE KEY ARRAY
INLOOP INY
       TYA
       STA (KB),Y
       CMP MAX
       BNE INLOOP
;
SORT   STA TOPDIS   ; 'A' HOLDS 'MAX'
LOOP1  LDA TOPDIS
       STA TOP
       LDX #0
       STX NXTFLG
       STX FLAG
LOOP2  STX REPEAT
;
; GET BOTH BYTES OF INTEGER POINTED TO BY
; 'KEY' ELEMENT.  RETURN WITH MSB ON STACK
; AND LSB IN THE ACCUMULATOR
;
GETINT TXA
       TAY
       LDA (KB),Y
       ASL A
       BCC LOAD
       DEC NXTFLG
       INC ZB+1
LOAD   TAY
       LDA (ZB),Y
       PHA
       INY
       LDA (ZB),Y
       BIT NXTFLG
       BPL NODEC
       INC NXTFLG
       DEC ZB+1
NODEC  CPX REPEAT
       BNE ORDER
       STA CRRNT
       PLA
       STA CRRNT+1
       INX
       BNE GETINT
;
; COMPARE INTEGERS OBTAINED THROUGH KEY ARRAY
; IF 'CURRENT' <= 'NEXT' THEN SWAP KEY
; ELEMENTS, ELSE CONTINUE
;
ORDER  CMP CRRNT
       PLA
       SBC CRRNT+1
       BVC TEST
       EOR #$80
TEST   BPL NOSWAP
SWAP   TXA
       TAY
       STX TOPDIS
       LDA (KB),Y
       PHA
       DEY
       LDA (KB),Y
       INY
       STA (KB),Y
       PLA
       DEY
       STA (KB),Y
       INC FLAG
NOSWAP CPX TOP
       BNE LOOP2
       LDA FLAG
       BNE LOOP1
;
; UNPACK THE BYTE ELEMENTS OF THE 'KEY' ARRAY
; INTO BASIC'S NORMAL 2-BYTE INTEGER FORMAT
;
UNPACK LDX MAX
       INX
PKLOOP DEX
       TXA
       TAY
       LDA (KB),Y
       PHA
       TXA
       ASL A     ; MOVE TO 2*I+1
       ORA #1
       BCC STORE
       INC NXTFLG
       INC KB+1
STORE  TAY
       PLA
       STA (KB),Y
       LDA #0
       DEY
       STA (KB),Y
       LDA NXTFLG
       BEQ OK
       DEC NXTFLG
       DEC KB+1
OK     TXA
       BNE PKLOOP
DONE   RTS
.END
Listing 6. Assembler-Quelltext der schnellen Bubble-Sort-Routine
;   "WRITE"   RICHARD L. RYLANDER
;             12/30/84
; REVISED  1/19/85  - ORIGIN MOVED TO $CFE5 (53221.)
;
;  PUT TEXT CHARACTERS ON GRAPHIC SCREEN
;  (UNDER BASIC ROM) IN VARIOUS STYLES
;
*=$CFE5  ; PUT CODE AFTER DOS 5.1
WRITE  LDA $01     ; SWITCH OUT BASIC ROM
       AND #$FE
       STA $01
       LDY #7
LOOP   LDA ($FD),Y ; READ CHARACTER BYTE
       AND ($FB),Y ; MODIFY W/SCREEN BYTE
       STA ($FB),Y ; STORE IN SCREEN
;
; POKE NEW LOGICAL OPERATOR TO REPLACE
; 'AND' (53231.) FOR DIFFERENT STYLES
; ORA=17.  BIT (NOP)=36.  AND=49.  EOR=81.
;
       DEY
       BPL LOOP
       LDA $01     ; RESTORE BASIC ROM
       ORA #1
       STA $01
       RTS
.END
Listing 7. Assembler-Quelltext der Routine zum Beschreiben des HiRes-Bildschirmes unterhalb des Basic-ROMs
PROGRAMM : GRAPHICS       C000 CBFC
-----------------------------------
C000 : FF 55 00 00 A5 AC 10 07   B8
C008 : 38 A9 00 E5 AC 85 AC 85   86
C010 : AD A9 00 A2 08 46 AD 90   71
C018 : 03 18 65 AC 6A 66 AE CA   40
C020 : D0 F3 85 AF 60 A9 00 85   9F
C028 : B4 85 B5 A2 10 26 FD 26   D7
C030 : FE 26 B4 26 B5 38 A5 B4   50
C038 : E5 FB A8 A5 B5 E5 FC 90   99
C040 : 04 84 B4 85 B5 CA D0 E5   25
C048 : 26 FD 26 FE 06 B4 26 B5   E0
C050 : B0 0B 38 A5 FB E5 B4 A5   56
C058 : FC E5 B5 B0 06 E6 FD D0   FB
C060 : 02 E6 FE 60 A2 08 A9 00   B2
C068 : 8D 3C 03 8D 3D 03 85 FB   80
C070 : 85 FC 0E 3C 03 2E 3D 03   1B
C078 : EE 3C 03 D0 03 EE 3D 03   02
C080 : 06 AC 26 AD 26 FB 26 FC   F0
C088 : 06 AC 26 AD 26 FB 26 FC   F8
C090 : 38 A5 FB ED 3C 03 A8 A5   21
C098 : FC ED 3D 03 90 12 85 FC   E4
C0A0 : 84 FB EE 3C 03 D0 03 EE   06
C0A8 : 3D 03 CA D0 C5 4C C1 C0   7B
C0B0 : 38 AD 3C 03 E9 01 8D 3C   84
C0B8 : 03 B0 03 CE 3D 03 CA D0   67
C0C0 : B1 6E 3D 03 6E 3C 03 60   EE
C0C8 : AD 00 C0 8D 02 C0 4D 01   B4
C0D0 : C0 2E 03 C0 6A 6E 03 C0   28
C0D8 : 8D 00 C0 AD 02 C0 8D 01   A9
C0E0 : C0 60 AD 11 D0 09 20 8D   4F
C0E8 : 11 D0 AD 00 DD 8D 42 03   26
C0F0 : 29 FC 09 01 8D 00 DD AD   A5
C0F8 : 18 D0 8D 43 03 A9 19 8D   41
C100 : 18 D0 60 AD 11 D0 29 DF   4A
C108 : 8D 11 D0 AD 42 03 8D 00   7A
C110 : DD AD 43 03 8D 18 D0 60   93
C118 : A9 01 A2 00 9D 00 84 9D   12
C120 : 00 85 9D 00 86 9D 00 87   AF
C128 : CA D0 F1 60 A9 A0 85 FC   92
C130 : A0 00 84 FB A9 00 A2 20   D6
C138 : 91 FB C8 D0 FB E6 FC CA   93
C140 : D0 F6 60 A9 00 2C A9 80   E2
C148 : 8D 3E 03 A5 01 29 FE 85   CA
C150 : 01 38 A9 C7 ED 41 03 AA   1B
C158 : 4A 4A 4A A8 B9 AB C1 85   7A
C160 : FB B9 C4 C1 85 FC 8A 29   5E
C168 : 07 18 65 FB 85 FB AD 3F   C1
C170 : 03 29 F8 65 FB 85 FB AD   2A
C178 : 40 03 65 FC 85 FC A9 A0   5B
C180 : 65 FC 85 FC AD 3F 03 29   97
C188 : 07 49 07 AA A9 01 CA 30   79
C190 : 03 0A D0 FA A0 00 2C 3E   63
C198 : 03 10 05 49 FF 31 FB 2C   E0
C1A0 : 11 FB 91 FB A5 01 09 01   1B
C1A8 : 85 01 60 00 40 80 C0 00   D1
C1B0 : 40 80 C0 00 40 80 C0 00   6C
C1B8 : 40 80 C0 00 40 80 C0 00   74
C1C0 : 40 80 C0 00 00 01 02 03   87
C1C8 : 05 06 07 08 0A 0B 0C 0D   D7
C1D0 : 0F 10 11 12 14 15 16 17   DE
C1D8 : 19 1A 1B 1C 1E AD 3F 03   9B
C1E0 : 29 07 8D 48 03 AD 41 03   A2
C1E8 : 29 07 0A 0A 0A 0D 48 03   89
C1F0 : AA BD 2F C2 CD 44 03 10   C8
C1F8 : 03 4C 46 C1 4C 43 C1 20   11
C200 : C8 C0 4A 4A CD 44 03 10   2F
C208 : 03 4C 46 C1 4C 43 C1 AD   3C
C210 : 47 03 F0 10 AC 41 03 C8   89
C218 : 84 AD A9 D5 85 AC 20 11   F8
C220 : C0 8D 41 03 AD 46 03 F0   53
C228 : 03 4C DD C1 4C FF C1 00   CD
C230 : 08 35 3D 02 0A 37 3F 10   DA
C238 : 18 25 2D 12 1A 27 2F 31   6A
C240 : 39 04 0C 33 3B 06 0E 21   43
C248 : 29 14 1C 23 2B 16 1E 03   C9
C250 : 0B 36 3E 01 09 34 3C 13   6F
C258 : 1B 26 2E 11 19 24 2C 32   FC
C260 : 3A 07 0F 30 38 05 0D 22   0C
C268 : 2A 17 1F 20 28 15 1D A0   CB
C270 : 06 A9 D5 85 AC B9 4C 03   41
C278 : 85 AD 20 11 C0 99 4C 03   0E
C280 : 88 88 88 10 F0 60 A0 02   09
C288 : B9 4A 03 48 B9 4D 03 99   75
C290 : 4A 03 68 99 4D 03 88 10   D8
C298 : EF 60 A0 02 B9 4D 03 48   C2
C2A0 : B9 50 03 99 4D 03 68 99   37
C2A8 : 50 03 88 10 EF 60 A2 02   2E
C2B0 : 38 AD 4D 03 ED 4A 03 AD   0B
C2B8 : 4E 03 ED 4B 03 B0 03 20   6F
C2C0 : 86 C2 CA F0 15 38 AD 50   E2
C2C8 : 03 ED 4D 03 AD 51 03 ED   C3
C2D0 : 4E 03 B0 DC 20 9A C2 4C   E2
C2D8 : B0 C2 60 A9 02 8D 51 03   0E
C2E0 : 20 AE C2 AD 47 03 F0 03   14
C2E8 : 20 6F C2 20 6F C4 AD 4A   DD
C2F0 : 03 8D 3F 03 AD 4B 03 8D   46
C2F8 : 40 03 AD 4C 03 8D 41 03   56
C300 : AD 57 03 D0 7D 38 AD 56   31
C308 : 03 ED 5B 03 B0 74 AD 5B   55
C310 : 03 8D 65 03 8D 68 03 4E   58
C318 : 65 03 38 AD 56 03 ED 65   C3
C320 : 03 8D 65 03 AD 57 03 E9   19
C328 : 00 8D 66 03 EE 68 03 AD   82
C330 : 67 03 D0 06 20 43 C1 4C   C9
C338 : 3D C3 20 46 C1 AD 60 03   39
C340 : D0 05 EE 41 03 D0 03 CE   D7
C348 : 41 03 2C 66 03 30 1A EE   DB
C350 : 3F 03 D0 03 EE 40 03 38   13
C358 : AD 65 03 ED 5B 03 8D 65   05
C360 : 03 AD 66 03 E9 00 8D 66   D5
C368 : 03 18 AD 65 03 6D 56 03   8A
C370 : 8D 65 03 AD 66 03 6D 57   09
C378 : 03 8D 66 03 CE 68 03 D0   1A
C380 : AE 60 AD 56 03 8D 65 03   CD
C388 : 8D 68 03 AD 57 03 8D 66   50
C390 : 03 8D 69 03 4E 66 03 6E   16
C398 : 65 03 38 AD 5B 03 ED 65   93
C3A0 : 03 8D 65 03 A9 00 ED 66   43
C3A8 : 03 8D 66 03 AD 67 03 D0   30
C3B0 : 06 20 43 C1 4C BA C3 20   B9
C3B8 : 46 C1 EE 3F 03 D0 03 EE   23
C3C0 : 40 03 2C 66 03 30 20 AD   E7
C3C8 : 60 03 D0 05 EE 41 03 D0   25
C3D0 : 03 CE 41 03 38 AD 65 03   78
C3D8 : ED 56 03 8D 65 03 AD 66   55
C3E0 : 03 ED 57 03 8D 66 03 18   58
C3E8 : AD 65 03 6D 5B 03 8D 65   85
C3F0 : 03 AD 66 03 69 00 8D 66   5D
C3F8 : 03 38 AD 68 03 E9 01 8D   2E
C400 : 68 03 B0 03 CE 69 03 2C   13
C408 : 69 03 10 A0 60 38 AD 53   30
C410 : 03 ED 54 03 B0 0E AD 53   58
C418 : 03 48 AD 54 03 8D 53 03   25
C420 : 68 8D 54 03 AD 53 03 8D   61
C428 : 41 03 20 24 C2 AD 53 03   64
C430 : CD 54 03 F0 06 CE 53 03   30
C438 : 4C 24 C4 60 AD 5F 03 85   C0
C440 : AC AD 5E 03 85 AD 20 11   23
C448 : C0 85 FE A5 AE 85 FD A9   A1
C450 : 00 85 FC AD 5A 03 85 FB   D3
C458 : 20 25 C0 AD 63 03 D0 08   92
C460 : 18 AD 55 03 65 FD 90 06   99
C468 : 38 AD 55 03 E5 FD 60 38   6D
C470 : AD 4D 03 ED 4A 03 8D 56   E2
C478 : 03 AD 4E 03 ED 4B 03 8D   A6
C480 : 57 03 38 AD 50 03 ED 4D   8C
C488 : 03 8D 58 03 38 AD 50 03   01
C490 : ED 4A 03 8D 59 03 A9 00   69
C498 : 8D 60 03 8D 61 03 8D 62   F1
C4A0 : 03 38 AD 4F 03 ED 4C 03   EB
C4A8 : B0 09 EE 60 03 AD 4C 03   79
C4B0 : ED 4F 03 8D 5B 03 38 AD   C1
C4B8 : 52 03 ED 4F 03 B0 09 EE   A9
C4C0 : 61 03 AD 4F 03 ED 52 03   E7
C4C8 : 8D 5C 03 38 AD 52 03 ED   A1
C4D0 : 4C 03 B0 09 EE 62 03 AD   54
C4D8 : 4C 03 ED 52 03 8D 5D 03   84
C4E0 : 60 20 AE C2 AD 47 03 F0   57
C4E8 : 03 20 6F C2 20 6F C4 AD   1B
C4F0 : 4A 03 8D 3F 03 AD 4B 03   D8
C4F8 : 8D 40 03 38 AD 3F 03 ED   2A
C500 : 4A 03 8D 5F 03 AD 56 03   18
C508 : F0 53 8D 5A 03 AD 5B 03   62
C510 : 8D 5E 03 AD 60 03 8D 63   5E
C518 : 03 AD 4C 03 8D 55 03 20   35
C520 : 3C C4 8D 53 03 AD 59 03   95
C528 : F0 33 8D 5A 03 AD 5D 03   7A
C530 : 8D 5E 03 AD 62 03 8D 63   9E
C538 : 03 20 3C C4 8D 54 03 20   BB
C540 : 0D C4 AD 40 03 CD 4E 03   01
C548 : D0 08 AD 3F 03 CD 4D 03   49
C550 : F0 0B EE 3F 03 D0 03 EE   0A
C558 : 40 03 4C FB C4 38 AD 3F   F0
C560 : 03 ED 4A 03 8D 5F 03 AD   88
C568 : 59 03 F0 63 8D 5A 03 AD   FE
C570 : 5D 03 8D 5E 03 AD 62 03   AB
C578 : 8D 63 03 AD 4C 03 8D 55   EB
C580 : 03 20 3C C4 8D 54 03 38   33
C588 : AD 3F 03 ED 4D 03 8D 5F   35
C590 : 03 AD 58 03 F0 39 8D 5A   A4
C598 : 03 AD 5C 03 8D 5E 03 AD   1D
C5A0 : 61 03 8D 63 03 AD 4F 03   33
C5A8 : 8D 55 03 20 3C C4 8D 53   6B
C5B0 : 03 20 0D C4 AD 40 03 CD   24
C5B8 : 51 03 D0 08 AD 3F 03 CD   3C
C5C0 : 50 03 F0 0B EE 3F 03 D0   C6
C5C8 : 03 EE 40 03 4C 5D C5 AD   D5
C5D0 : 64 03 F0 15 20 EB C2 20   41
C5D8 : 9A C2 20 EB C2 20 86 C2   26
C5E0 : 20 9A C2 20 86 C2 20 EB   D9
C5E8 : C2 60 A9 00 85 FC 4C 25   00
C5F0 : C0 2C 7A 03 10 12 AD 82   13
C5F8 : 03 D0 04 8D 44 03 60 38   64
C600 : A9 00 ED 79 03 8D 79 03   DC
C608 : AD 79 03 85 AC A9 1A 85   6F
C610 : AD 20 11 C0 85 FE A5 AE   6E
C618 : 85 FD AD 77 03 85 FB 20   83
C620 : EA C5 A5 FD 8D 44 03 60   DE
C628 : 2C 83 03 10 2D AD 6C 03   D1
C630 : 48 48 AD 70 03 8D 6C 03   6A
C638 : 68 8D 70 03 AD 6D 03 48   C6
C640 : 48 AD 71 03 8D 6D 03 68   3D
C648 : 8D 71 03 AD 6E 03 48 48   B5
C650 : AD 72 03 8D 6E 03 68 8D   65
C658 : 72 03 20 45 C7 A9 01 8D   E5
C660 : 81 03 38 AD 7D 03 CD 6C   27
C668 : 03 90 7D 38 AD 3C 03 ED   BE
C670 : 6D 03 8D 75 03 AD 3D 03   09
C678 : ED 6E 03 8D 76 03 38 AD   CB
C680 : 6A 03 ED 6C 03 8D 3F 03   14
C688 : AD 6B 03 E9 00 8D 40 03   5C
C690 : 38 AD 7F 03 CD 70 03 90   6D
C698 : 23 18 AD 75 03 6D 71 03   49
C6A0 : 8D 79 03 AD 76 03 6D 72   7A
C6A8 : 03 8D 7A 03 20 F1 C5 18   4A
C6B0 : AD 6F 03 6D 70 03 8D 41   5B
C6B8 : 03 20 0F C2 38 AD 80 03   E0
C6C0 : CD 70 03 90 23 38 AD 75   2E
C6C8 : 03 ED 71 03 8D 79 03 AD   8B
C6D0 : 76 03 ED 72 03 8D 7A 03   1E
C6D8 : 20 F1 C5 38 AD 6F 03 ED   A7
C6E0 : 70 03 8D 41 03 20 0F C2   50
C6E8 : AD 81 03 F0 34 CE 81 03   FA
C6F0 : 38 AD 7E 03 CD 6C 03 90   6C
C6F8 : 28 18 AD 3C 03 6D 6D 03   77
C700 : 8D 75 03 AD 3D 03 6D 6E   3D
C708 : 03 8D 76 03 18 AD 6A 03   6E
C710 : 6D 6C 03 8D 3F 03 AD 6B   BF
C718 : 03 69 00 8D 40 03 4C 90   F0
C720 : C6 2C 83 03 10 1E AD 6E   C3
C728 : 03 8D 72 03 68 8D 6E 03   A2
C730 : AD 6D 03 8D 71 03 68 8D   F2
C738 : 6D 03 AD 6C 03 8D 70 03   84
C740 : 68 8D 6C 03 60 AD 77 03   42
C748 : 85 AC 20 04 C0 8D 7C 03   1C
C750 : A5 AE 8D 7B 03 AD 6D 03   78
C758 : 85 AC 20 04 C0 38 AD 7B   37
C760 : 03 E5 AE 8D 7B 03 AD 7C   33
C768 : 03 E5 AF 8D 7C 03 AD 71   75
C770 : 03 85 AC 20 04 C0 38 AD   E7
C778 : 7B 03 E5 AE 85 AC AD 7C   31
C780 : 03 E5 AF 85 AD 30 0A 20   D7
C788 : 64 C0 0E 3C 03 2E 3D 03   F4
C790 : 60 A9 00 8D 3C 03 8D 3D   03
C798 : 03 60 AD 8E 03 38 ED 8F   D1
C7A0 : 03 4A 8D 8C 03 8D 77 03   3E
C7A8 : 18 6D 8F 03 8D 8D 03 AD   68
C7B0 : 8C 03 85 AC 20 04 C0 A5   25
C7B8 : AE 8D 8A 03 A5 AF 8D 8B   55
C7C0 : 03 A9 00 8D 86 03 60 AD   A7
C7C8 : 77 03 85 AC 20 04 C0 06   E9
C7D0 : AE 26 AF A5 AE 85 AC A5   47
C7D8 : AF 85 AD 20 64 C0 4E 3D   B9
C7E0 : 03 6E 3C 03 AD 3C 03 8D   6E
C7E8 : 92 03 A9 00 8D 86 03 8D   9A
C7F0 : 6E 03 8D 72 03 AD 77 03   13
C7F8 : 85 AC 20 04 C0 8D 85 03   F1
C800 : A5 AE 8D 84 03 AD 86 03   AE
C808 : 8D 87 03 85 AC 8D 6C 03   B9
C810 : 8D 6D 03 20 04 C0 38 AD   9B
C818 : 84 03 E5 AE 85 AC AD 85   EC
C820 : 03 E5 AF 85 AD 20 64 C0   A1
C828 : AD 3C 03 8D 88 03 AD 87   CC
C830 : 03 8D 70 03 8D 71 03 A9   3A
C838 : 00 8D 83 03 20 28 C6 A9   F2
C840 : 80 8D 83 03 20 28 C6 AD   82
C848 : 87 03 CD 88 03 F0 06 EE   83
C850 : 87 03 4C 2E C8 AD 86 03   4C
C858 : CD 92 03 F0 06 EE 86 03   45
C860 : 4C 05 C8 60 A9 00 8D 6D   19
C868 : 03 8D 6E 03 8D 72 03 AD   02
C870 : 77 03 8D 70 03 AD 89 03   A4
C878 : 8D 6C 03 AD 70 03 8D 71   EA
C880 : 03 20 28 C6 CE 6C 03 10   F3
C888 : F8 CE 70 03 10 E7 60 20   66
C890 : 9A C7 A9 00 8D 6E 03 8D   EC
C898 : 72 03 AD 86 03 8D 6C 03   1C
C8A0 : 8D 6D 03 85 AC 20 04 C0   B3
C8A8 : 38 AD 8A 03 E5 AE 85 AC   FD
C8B0 : AD 8B 03 E5 AF 85 AD 20   BE
C8B8 : 64 C0 AD 3C 03 8D 89 03   38
C8C0 : 18 6D 8D 03 8D 88 03 A9   CF
C8C8 : 00 8D 87 03 AD 87 03 8D   0F
C8D0 : 70 03 85 AD AD 89 03 85   17
C8D8 : AC 20 11 C0 85 FE A5 AE   35
C8E0 : 85 FD AD 88 03 85 FB 20   6D
C8E8 : EA C5 A5 FD 8D 71 03 20   8F
C8F0 : 28 C6 AD 87 03 CD 88 03   9E
C8F8 : F0 06 EE 87 03 4C CC C8   EF
C900 : AD 86 03 CD 8C 03 F0 06   1C
C908 : EE 86 03 4C 9A C8 60 20   35
C910 : 9A C7 AD 8E 03 85 AC 20   1A
C918 : 04 C0 06 AE 26 AF A5 AE   A8
C920 : 85 AC A5 AF 85 AD 20 64   6A
C928 : C0 4E 3D 03 6E 3C 03 AD   EF
C930 : 3C 03 8D 92 03 AD 86 03   61
C938 : 8D 6C 03 85 AC 20 04 C0   CA
C940 : 8D 91 03 A5 AE 8D 90 03   AB
C948 : AD 8E 03 85 AC 20 04 C0   0B
C950 : 38 A5 AE ED 90 03 85 AC   55
C958 : A5 AF ED 91 03 85 AD 20   D6
C960 : 64 C0 AD 3C 03 8D 88 03   DC
C968 : 38 AD 8F 03 ED 86 03 90   FB
C970 : 23 AD 8F 03 85 AC 20 04   F4
C978 : C0 38 A5 AE ED 90 03 85   0E
C980 : AC A5 AF ED 91 03 85 AD   4B
C988 : 20 64 C0 AD 3C 03 8D 87   E1
C990 : 03 4C 9A C9 AD 86 03 8D   CF
C998 : 87 03 AD 87 03 8D 70 03   61
C9A0 : 85 AC 20 04 C0 18 A5 AE   C5
C9A8 : 6D 90 03 85 AC A5 AF 6D   60
C9B0 : 91 03 85 AD 20 64 C0 AD   5D
C9B8 : 3C 03 8D 89 03 85 FB AD   B2
C9C0 : 86 03 85 AD AD 8D 03 85   3D
C9C8 : AC 20 11 C0 85 FE A5 AE   25
C9D0 : 85 FD 20 EA C5 38 AD 86   9B
C9D8 : 03 E5 FD 8D 6D 03 A9 00   94
C9E0 : E5 FE 8D 6E 03 AD 87 03   37
C9E8 : 85 AD AD 8D 03 85 AC 20   B0
C9F0 : 11 C0 85 FE A5 AE 85 FD   84
C9F8 : AD 89 03 85 FB 20 EA C5   D3
CA00 : 38 AD 87 03 E5 FD 8D 71   B8
CA08 : 03 A9 00 8D 83 03 E5 FE   77
CA10 : 8D 72 03 20 28 C6 A9 80   FC
CA18 : 8D 83 03 20 28 C6 AD 87   AA
CA20 : 03 CD 88 03 F0 06 EE 87   96
CA28 : 03 4C 9A C9 AD 86 03 CD   E8
CA30 : 92 03 F0 06 EE 86 03 4C   08
CA38 : 35 C9 60 20 9A C7 AD 86   1A
CA40 : 03 8D 6C 03 85 AC 38 A9   77
CA48 : 00 ED 86 03 8D 6D 03 A9   E4
CA50 : 00 E9 00 8D 6E 03 20 04   7E
CA58 : C0 38 AD 8A 03 E5 AE 85   16
CA60 : AC AD 8B 03 E5 AF 85 AD   73
CA68 : 20 64 C0 38 AD 8D 03 ED   21
CA70 : 3C 03 8D 88 03 A9 00 8D   3B
CA78 : 87 03 AD 87 03 8D 70 03   41
CA80 : 85 AD AD 8D 03 85 AC 20   48
CA88 : 11 C0 85 FE A5 AE 85 FD   1C
CA90 : AD 88 03 85 FB 20 EA C5   EB
CA98 : A5 FD 38 ED 87 03 8D 71   B1
CAA0 : 03 A5 FE E9 00 8D 72 03   AF
CAA8 : 20 28 C6 AD 87 03 CD 88   1C
CAB0 : 03 F0 06 EE 87 03 4C 7A   41
CAB8 : CA AD 86 03 CD 8C 03 F0   8A
CAC0 : 06 EE 86 03 4C 3E CA 60   E2
CAC8 : 20 FD AE 20 9E AD 20 AA   C4
CAD0 : B1 60 A9 2C A0 00 84 FB   B5
CAD8 : D1 7A D0 03 4C 73 00 A0   1C
CAE0 : 80 84 FB 60 20 D2 CA 24   B9
CAE8 : FB 30 0F 20 9E AD 20 AA   F0
CAF0 : B1 8C 8F 03 20 C8 CA 8C   B8
CAF8 : 8E 03 60 20 C8 CA 8C 6A   0E
CB00 : 03 8D 6B 03 20 C8 CA 8C   92
CB08 : 6F 03 60 20 D2 CA 24 FB   21
CB10 : 30 07 20 9E AD 20 AA B1   8A
CB18 : 2C A0 00 8C 35 C1 4C 2C   11
CB20 : C1 20 D2 CA 24 FB 30 07   F0
CB28 : 20 9E AD 20 AA B1 2C A0   31
CB30 : 01 8C 19 C1 4C 18 C1 A9   D6
CB38 : 00 2C A9 80 8D 3E 03 20   E0
CB40 : C8 CA 8C 3F 03 8D 40 03   1C
CB48 : 20 C8 CA 8C 41 03 4C 4B   04
CB50 : C1 A9 00 2C A9 80 8D 93   67
CB58 : 03 20 C8 CA 8C 4A 03 8D   39
CB60 : 4B 03 20 C8 CA 8C 4C 03   96
CB68 : 20 C8 CA 8C 4D 03 8D 4E   F0
CB70 : 03 20 C8 CA 8C 4F 03 2C   B6
CB78 : 93 03 10 18 20 C8 CA 8C   21
CB80 : 50 03 8D 51 03 20 C8 CA   C9
CB88 : 8C 52 03 20 C8 CA 8C 44   A0
CB90 : 03 4C E1 C4 4C DB C2 20   B9
CB98 : FB CA 20 D2 CA 24 FB 30   79
CBA0 : 09 20 9E AD 20 AA B1 8C   4E
CBA8 : 77 03 4C C7 C7 20 FB CA   B0
CBB0 : 20 E4 CA 4C 0F C9 A9 80   65
CBB8 : 2C A9 00 8D 83 03 20 FB   33
CBC0 : CA 20 D2 CA 24 FB 30 0F   A9
CBC8 : 20 9E AD 20 AA B1 8C 77   00
CBD0 : 03 20 C8 CA 8C 89 03 4C   28
CBD8 : 64 C8 A9 80 2C A9 00 8D   46
CBE0 : 83 03 20 FB CA 20 E4 CA   43
CBE8 : 4C 8F C8 A9 80 2C A9 00   73
CBF0 : 8D 83 03 20 FB CA 20 E4   64
CBF8 : CA 4C 3B CA               22
Listing 8. Assembler-Routinen aus Listing 1 bis 5
PROGRAMM : SORT_WRITE     CF59 CFFF
-----------------------------------
CF59 : A0 FF C8 98 91 FB C5 8C   67
CF61 : D0 F8 85 AD A5 AD 85 AC   FC
CF69 : A2 00 86 61 86 AE 86 64   9A
CF71 : 8A A8 B1 FB 0A 90 04 C6   FE
CF79 : 61 E6 FE A8 B1 FD 48 C8   E0
CF81 : B1 FD 24 61 10 04 E6 61   E6
CF89 : C6 FE E4 64 D0 08 85 62   BC
CF91 : 68 85 63 E8 D0 DA C5 62   71
CF99 : 68 E5 63 50 02 49 80 10   63
CFA1 : 13 8A A8 86 AD B1 FB 48   DD
CFA9 : 88 B1 FB C8 91 FB 68 88   CD
CFB1 : 91 FB E6 AE E4 AC D0 B6   34
CFB9 : A5 AE D0 A8 A6 8C E8 CA   06
CFC1 : 8A A8 B1 FB 48 8A 0A 09   9E
CFC9 : 01 90 04 E6 61 E6 FC A8   83
CFD1 : 68 91 FB A9 00 88 91 FB   B8
CFD9 : A5 61 F0 04 C6 61 C6 FC   78
CFE1 : 8A D0 DC 60 A5 01 29 FE   1B
CFE9 : 85 01 A0 07 B1 FD 31 FB   C0
CFF1 : 91 FB 88 10 F7 A5 01 09   67
CFF9 : 01 85 01 60 01 08         97
Listing 9. Assembler-Routinen aus Listing 6 und 7
10 rem        shapes demo
20 :
30 rem     richard l. rylander    11/23/84 (revised 1/20/85 to add labeling)
40 :
50 gr=49378    :rem graphik modus
60 tx=49411    :rem text modus
70 :
80 lb=893      :rem linke grenze
90 rb=894      :rem rechte grenze
100 ub=895     :rem obere grenze
110 db=896     :rem untere grenze
120 :
130 rem   flags fuer verschiedene grafikmodi
140 :
150 sh=838     :rem schattierung: 0=random, 1=halbton
160 sc=839     :rem skalierung:0=normal (1:1), 1=skal. (4:3) fuer darstellung
170 lt=898     :rem lichteinfall: 0=normal, 1=von hinten beleuchtet
180 :
190 bo=53280   :rem  rahmenfarbe
200 :
210 rem   funktionsadressen
220 :
230 cl=51979   :rem bitmap bereich loeschen
240 co=52001   :rem colorbereich fuellen
250 :
260 sp=52119   :rem  sphere
270 tr=52141   :rem  ring von oben
280 vc=52150   :rem  zylinder (vertikale achse)
290 hc=52153   :rem  zylinder (horizontale achse)
300 vt=52186   :rem  ringschnitt (vertikale achse)
310 ht=52189   :rem  ringschnitt (axis horizontale achse)
320 vs=52203   :rem  spule (vertikale achse)
330 hs=52206   :rem  spule (horizontale achse)
340 :
350 rem  einzelne shapes zeichnen
360 :
370 poke sh,1 :rem halbtonschattierung
380 poke sc,1 :rem skalierung
390 poke lt,0 :rem normalbeleuchtung
400 sys(cl)   :rem bildschirm loeschen
410 sys(co),17*11+1  :rem farbkombination - dunkelgrau (11) weisse punkte (1)
414 rem  auf den meisten farbmonitoren
420 poke bo,1 :rem weisser rahmen
430 sys(gr)   :rem grafik einschalten
432 rw=12:cm=14:md=1:a$="shapes demo":gosub 1900:rem  titel
434 x1=110:y1=120:x2=210:y2=120:bc=1:dc=7:gosub 1700:rem  color titel
440 poke lb,38:poke rb,38:poke ub,38:poke db,38       :rem shape fenster
450 sys(sp),40,199,38
455 rw=9:cm=2:md=1:a$="kugel":gosub1900
460 sys(hc),120,199,38,38
465 cm=11:a$="h-zylnd.":gosub1900
470 sys(vc),200,199 :rem voreingestellte parameter werden benutzt
475 cm=21:a$="v-zylind.":gosub1900
480 sys(tr),280,199,15,38
485 cm=32:a$="  ring":gosub1900
490 sys(vt),40,64
495 rw=23:cm=1:a$="h-ring":gosub1900
500 sys(ht),120,64
505 cm=11:a$="v-ring":gosub1900
510 sys(hs),200,64,5,100
515 cm=22:a$="h-spule":gosub1900
520 sys(vs),280,64
525 cm=32:a$="v-spule":gosub1900
530 poke 198,0:wait 198,1:poke 198,0
540 rem  auf taste warten
550 :
560 rem  zwei "pokale", einer mit halbton-, der andere mit "random"-schattierung
570 :
580 sys(cl):sys(co),16*11+1
582 rw=14:cm=14:a$="vergleich":gosub 1900:rw=15:cm=16:a$="zweier":gosub 1900
584 rw=16:cm=12:a$="schattierungen":gosub 1900:rw=18:cm=14:a$="<-- halbton"
586 gosub 1900:rw=20:cm=15:a$="random -->":gosub 1900
590 poke lb,255:poke rb,255:poke ub,49:poke db,255: rem an den oberen rand
600 sys(sp),80,190,80
610 poke ub,51:poke db,51: rem weitern sprite-teil anhaengen
620 sys(vs),80,69,10,130
630 poke db,9:poke ub,8
640 sys(vt),80,9,25,45
650 poke sh,0  :rem auf random schattierung umschalten
660 poke lb,255:poke rb,255:poke ub,49:poke db,255
670 sys(sp),240,190,80
680 poke ub,51:poke db,51
690 sys(vs),240,69,10,130
700 poke db,9:poke ub,8
710 sys(vt),240,9,25,45
720 poke 198,0:wait 198,1:poke 198,0
740 :
750 rem  zeichne "wein" szene
760 poke lt,1 :rem hintergrungbeleuchtung
770 poke sh,1 :rem halbtonschattierung fuer flaschenetikett
780 sys(co):sys(cl),255: rem bitmap fuellen
790 poke bo,0 : rem schwarzer hintergrund
792 rw=0:cm=0:md=2:a$="zeichenen mit":gosub 1900:rw=1:cm=0:a$="rueckbeleuchtung"
794 gosub 1900:rw=2:cm=0:a$="gegen gesetzten":gosub 1900
796 rw=3:cm=0:a$="hintergrund":gosub 1900
798 rw=1:cm=26:a$="farben werden":gosub 1900
800 rw=2:cm=26:a$="nachgezeichnet":gosub1900
810 rem  zeichne flasche
820 poke ub,0:poke db,255:poke lb,255:pokerb,255
830 sys(vt),150,10,30,50
840 poke ub,255:sys(vc),150,70,50,60
850 poke db,0:sys(vt),150,130,6,50
860 poke db,55:poke ub,0:sys(vs),150,204,15,181
870 poke ub,255:sys(vc),150,221,16,17
880 :
890 rem  zeichene weinglas
900 poke ub,20:sys(sp),80,120,60
910 poke ub,35:poke db,34:sys(vs),80,34,10,110
920 :
930 rem  zeichent ein paar trauben
940 sys(sp),8,8,8:
950 sys(sp),20,8:sys(sp),40,8:sys(sp),12,20:sys(sp),30,20:sys(sp),25,16
960 :
970 rem zeichnet apfel bestehend aus 2 ringen und einem kugelfragment
980 poke ub,255:poke db,255:poke lb,255:poke rb,59
990 sys(vt),260,29,0,50:sys(vt),260,79
1000 poke ub,43:poke db,43:sys(sp),260,54,60
1010 rem   apfelstiel zeichnen
1020 poke rb,0:poke db,0:sys(tr),272,104,10,15
1030 rem   blatt zeichnen
1040 poke db,255:poke rb,0:sys(sp),256,119,15
1050 rem  "random"-schattiertes ettikett hinzufuegen !
1060 poke ub,255:poke rb,255:poke lb,6
1070 poke sh,0:sys(vc),150,72,50,48
1080 :
1090 rem  bild nachcolorieren
1100 sys(co),12
1110 x1=200:y1=1:x2=315:y2=100:dc=0:bc=2:gosub 1700
1120 x1=240:y1=110:x2=255:y2=150:bc=5:gosub 1700
1130 x1=260:y1=110:x2=270:y2=135:bc=9:gosub 1700
1140 x1=1:y1=1:x2=48:y2=30:bc=4:gosub 1700
1150 x1=140:y1=205:x2=180:y2=235:bc=7:gosub 1700
1160 x1=145:y1=25:x2=195:y2=115:bc=6:gosub 1700
1170 poke 198,0:wait 198,1:poke 198,0
1190 :
1200 rem   "kaffee und plaetzchen"
1210 poke sh,0 :rem random-schattierung fuer plaetzchen
1220 sys(co),16*11+1:sys(cl):poke bo,1
1230 poke lb,255:poke rb,255:poke ub,255:poke db,255 :rem kein shape-fenster
1240 sys(vt),60,20,20,60
1250 poke rb,29:sys(vt),99,60:poke rb,255
1260 sys(tr),188,180
1270 rem halbtonschattierte kaffeetasse hinzufuegen.
1280 poke sh,1:poke ub,0:sys(vt),188,20:poke ub,255
1290 poke db,0:sys(tr),278,110,20,40
1300 poke db,255:poke ub,0:poke lb,0
1310 sys(tr),248,90,50,70:poke lb,255:sys(sp),248,110,10:poke ub,255
1320 sys(vc),308,100,10,10
1330 sys(vc),188,77,60,57
1340 poke db,0:sys(vt),188,134,40,60
1360 sys(co),1+16*9 :rem 1=weisser hintergrund, 9=braune punkte
1370 x1=130:y1=1:x2=319:y2=136:bc=1:dc=5:gosub 1700
1380 x1=250:y1=144:x2=319:y2=144:gosub 1700
1390 poke 198,0:wait 198,1:poke 198,0
1410 :
1420 rem  zeichne "verbundene" ringe durch ueberlappung der fenster
1430 poke lt,0 :rem blaue punkte auf weiss, keine hintergrundbeleutung
1440 sys(cl):sys(co),1+16*6: rem 1=weisser intergrund, 6=blaue punkte
1450 poke ub,255:poke db,255:poke lb,255:poke rb,255: rem keine fenster
1460 poke sh,0  :rem zufaellige schattierung
1470 sys(tr),244,84,48,70
1480 sys(tr),160,84:sys(tr),76,84
1490 sys(tr),118,156:sys(tr),202,156
1500 rem  ueberlappende zonen hinzufuegen
1510 poke rb,0:poke db,0:sys(tr),160,84:poke rb,255:poke lb,0
1520 sys(tr),76,84:poke db,255:poke ub,0:sys(tr),118,156
1530 poke lb,255:poke rb,0:sys(tr),202,156:poke lb,27
1540 poke db,0:poke ub,255:sys(tr),160,84
1550 poke db,0:poke ub,255:sys(tr),160,84
1560 poke lb,255:poke ub,27:sys(tr),244,84
1570 poke lb,0:poke rb,27:poke ub,255:sys(tr),244,84
1580 poke 198,0
1590 get a$:if a$= "" then 1590
1600 sys(tx):poke bo,14:rem rueckkehr zum textmodus
1610 end
1620 :
1630 rem unterprogramm zu nachcolorieren verschiedener zonen
1640 rem achtung: es kann jeweils nur eine rechteckige flaeche
1650 rem von 8x8 punkten eingefaerbt werden !!
1660 rem (x1,y1)=unterer linker punkt, (x2,y2)=oberer rechter punkt
1690 rem die y-koordinaten muessen "unskalliert" sein. falls scale-flag gesetzt:
1700 if peek(sc)then y1=(y1+1)*213/256:y2=(y2+1)*213/256
1710 rem uebergabevariable ist cc.
1720 rem cc=16*dc + bc [dc=punkt farbe, bc= hintergrundfarbe]
1730 cc=16*dc+bc
1740 for ix=int(x1/8) to int(x2/8)
1750 for iy=int(y1/8) to int(y2/8)
1760 poke 34752+ix-40*iy,cc
1770 next:next:return
1780 :
1790 rem "text"-unterroutine ermoeglicht einfuegen von text in die bilder.
1800 rem "rw" und "cm" sind die zeilen(0-24) und spalten(0-39) koordinaten des
1810 rem ersten buchstaben des zu druckenden textstrings.
1820 rem uebergabevariable fuer text ist a$
1830 rem "md" zeigt den druckmodus an:
1840 rem  1 - normal ("schwarze" buchstaben auf "weissem" hintergrund)
1850 rem  2 - inverse ("weisse" buchstaben auf "schwarzem" hintergrund)
1860 rem  3 - buchstaben werden mit logischem oder mit hintergrund verknuepft.
1870 rem  4 - buchstaben werden mit logischem und mit hintergrund verknuepft.
1880 rem  5 - buchstaben werden mit logischem exor mit hintergrund verknuepft.
1890 :
1900 sb=40952:tb=54272:if(md and 1)then tb=53248:rem basisadressen
1910 os=320*rw+8*cm:rem  adresse des zeichengenerators
1920 poke 56334,peek(56334)and 254:rem disable irq timer
1930 poke 1,peek(1)and 251:rem character rom einschalten
1940 l=len(a$):for n=1 to l:n8=n*8+os+sb
1950 x=asc(mid$(a$,n,1)):if x>63 then x=x-64
1960 tc=tb+8*x
1970 on md goto 1980,1980,1990,2000,2010
1980 poke 53231,36:goto 2020
1990 poke 53231,17:goto 2020
2000 poke 53231,49:goto 2020
2010 poke 53231,81
2020 poke252,n8/256:poke251,n8-256*int(n8/256)
2030 poke254,tc/256:poke253,tc-256*int(tc/256)
2040 sys(53221):next
2050 poke 1,peek(1)or 4:poke 56334,peek(56334)or 1:rem normal schalten
2060 return
Listing 10. Demo-Programm »Shapes«
10 rem "stellation"
20 rem  by richard l. rylander     12/5/84
30 :
40 gr=49378    :rem graphik modus
50 tx=49411    :rem text modus
60 bo=53280    :rem rahmenfarbe
70 :
80 rem  style parameters
90 poke 839,1  :rem skalierung (3:4)
100 poke 871,0 :rem facettenraender (0=nachzeichnen, 1=loeschen)
110 sh=838     :rem schattierung (0=random, 1=halbton)
120 eg=868     :rem randflag (0=normal, 1=linien am rand hinzufuegen)
130 :
140 rem   funktions adressen
150 cl=51979   :rem bitmap loeschen
160 co=52001   :rem color map fuellen
170 fc=52052   :rem schattierte facetten zeichnen
180 ks=53081   :rem sortierroutine
190 :
200 xc=160:yc=120  :rem zentrierungskoordinaten
210 :
220 print"{clr}***************************************"
230 print"* kleiner sternfoermiger dodekahedron *"
240 print"***************************************"
250 print"{down}{down} schattierung:"
260 print" r=random, h=halbton"
270 input"{down} ihre wahl     h{left}{left}{left}";a$
280 poke sh,0:if a$="h" then poke sh,1
290 print"{down}{down} rand-stil :"
300 print"{down} n - normal":print"{down} e - eckenbetonung"
310 print"{down} w - drahtgitter"
320 input"{down} ihre wahl     n{left}{left}{left}";a$
330 poke eg,0:wi=0:if a$="n" then 360
340 poke eg,1:if a$="w" then wi=-1
350 :
360 print"{down} lese scheitel daten"
370 vn=32:dim p%(vn-1,2)
380 for n=0 to vn-1:read p%(n,0),p%(n,1),p%(n,2):next
390 :
400 print"{down} geben sie x, y, und z winkel ein"
410 print"       (winkel in grad)"
420 input x,y,z
430 j=3.14159265/180:x=x*j:y=y*j:z=z*j
440 x0=cos(y)*cos(z)-sin(x)*sin(y)*sin(z):x1=cos(y)*sin(z)+sin(x)*sin(y)*cos(z)
450 x2=-cos(x)*sin(y):y0=-cos(x)*sin(z):y1=cos(x)*cos(a):y2=sin(x)
460 z0=sin(y)*cos(z)+sin(x)*cos(y)*sin(z)
470 z1=sin(y)*sin(z)-sin(x)*cos(y)*cos(z):z2=cos(x)*cos(y)
480 print"{down} rotationsberechnung"
490 for n=0 to vn-1
500 x=p%(n,0):y=p%(n,1):z=p%(n,2)
510 p%(n,0)=x0*x+x1*y+x2*z:p%(n,1)=y0*x+y1*y+y2*z:p%(n,2)=z0*x+z1*y+z2*z:next
520 :
530 fa=60: rem  anzahl der facetten
540 dim f%(fa/2,2),sh(fa/2),z%(fa/2),k%(fa/2)
550 print" lese verbindungsdaten              "
560 vf=-1: rem  vf = anzahl der sichtbaren facetten
570 for n=1 to fa
580 vf=vf+1
590 for i=0 to 2 :read f%(vf,i):next
600 rem  berechnung der normalenvektoren
610 z=(p%(f%(vf,2),0)-p%(f%(vf,1),0))*(p%(f%(vf,0),1)-p%(f%(vf,1),1))
620 z=z-(p%(f%(vf,0),0)-p%(f%(vf,1),0))*(p%(f%(vf,2),1)-p%(f%(vf,1),1))
630 if z=<0 then 720:rem  facette nicht sichtbar
640 x=(p%(f%(vf,2),1)-p%(f%(vf,1),1))*(p%(f%(vf,0),2)-p%(f%(vf,1),2))
650 x=x-(p%(f%(vf,0),1)-p%(f%(vf,1),1))*(p%(f%(vf,2),2)-p%(f%(vf,1),2))
660 y=(p%(f%(vf,2),2)-p%(f%(vf,1),2))*(p%(f%(vf,0),0)-p%(f%(vf,1),0))
670 y=y-(p%(f%(vf,0),2)-p%(f%(vf,1),2))*(p%(f%(vf,2),0)-p%(f%(vf,1),0))
680 nc=sqr(x*x+y*y+z*z):rem  laenge des normalenvektors
690 sh(vf)=26*(2*z+x+y)/nc
700 sh(vf)=(sh(vf)+64)*(sh(vf)+64)/256:rem schattierung
710 goto 730
720 vf=vf-1
730 next
740 :
750 print" berechnung der darstellungsgroesse"
760 y=0:for n=0 to vn-1:if abs(p%(n,1))>y then y=abs(p%(n,1))
770 next:s=119/y
780 for n=0 to vn-1:p%(n,1)=s*p%(n,1)+yc:p%(n,0)=s*p%(n,0)+xc:next
790 :
800 :
810 for n=0 to vf
820 z%(n)=(p%(f%(n,0),2)+p%(f%(n,1),2)+p%(f%(n,2),2))/3:next
830 :
840 print" sortierung der facetten"
850 poke 140,vf
860 k%(0)=k%(0):poke 251,peek(71):poke 252,peek(72)
870 z%(0)=z%(0):poke 253,peek(71):poke 254,peek(72)
880 sys(ks)
890 :
900 rem zeichne facetten
910 sys(gr):sys(co):sys(cl):poke bo,1
920 for n=0 to vf:fa=k%(n)
930 if wi then sh(fa)=64
940 x0=p%(f%(fa,0),0):y0=p%(f%(fa,0),1):x1=p%(f%(fa,1),0):y1=p%(f%(fa,1),1)
950 x2=p%(f%(fa,2),0):y2=p%(f%(fa,2),1)
960 sys(fc),x0,y0,x1,y1,x2,y2,sh(fa)
970 next
980 poke198,0
990 get a$:if a$="" then 990
1000 sys(tx):poke bo,14:end
1010 :
1020 rem    scheiteldaten
1030 data 1000,618,0, 1000,-618,0, -1000,618,0, -1000,-618,0
1040 data 0,1000,618, 0,1000,-618, 0,-1000,618, 0,-1000,-618
1050 data 618,0,1000, -618,0,1000, 618,0,-1000, -618,0,-1000
1060 data 618,0,236, 618,0,-236, -618,0,236, -618,0,-236
1070 data 236,618,0, -236,618,0, 236,-618,0, -236,-618,0
1080 data 0,236,618, 0,-236,618, 0,236,-618, 0,-236,-618
1090 data 382,382,382, 382,382,-382, 382,-382,382, 382,-382,-382
1100 data -382,382,382, -382,382,-382, -382,-382,382, -382,-382,-382
1110 :
1120 rem    verbindungsdaten
1130 data 0,12,13, 0,13,25, 0,25,16, 0,16,24, 0,24,12
1140 data 1,12,26, 1,26,18, 1,18,27, 1,27,13, 1,13,12
1150 data 2,15,14, 2,14,28, 2,28,17, 2,17,29, 2,29,15
1160 data 3,14,15, 3,15,31, 3,31,19, 3,19,30, 3,30,14
1170 data 4,16,17, 4,17,28, 4,28,20, 4,20,24, 4,24,16
1180 data 5,17,16, 5,16,25, 5,25,22, 5,22,29, 5,29,17
1190 data 6,19,18, 6,18,26, 6,26,21, 6,21,30, 6,30,19
1200 data 7,18,19, 7,19,31, 7,31,23, 7,23,27, 7,27,18
1210 data 8,20,21, 8,21,26, 8,26,12, 8,12,24, 8,24,20
1220 data 9,21,20, 9,20,28, 9,28,14, 9,14,30, 9,30,21
1230 data 10,23,22, 10,22,25, 10,25,13, 10,13,27, 10,27,23
1240 data 11,22,23, 11,23,31, 11,31,15, 11,15,29, 11,29,22
Listing 11. Demo-Programm »Stellation«
10 rem  "view"   display 'images.pic'
20 rem  graphics package need not be
30 rem  installed for this program.
40 :
50 if a=1 then 200
60 rem save 'vic' chip registers for
70 rem return to text display later.
80 :
90 v1=peek(53265):v2=peek(53272):v3=peek(56576)
100 :
110 rem initialize color map bytes for dark gray dots (11) on white (1)
120 cb=16*11+1
130 for i=33792 to 34791:poke i,cb:next
140 :
150 rem switch to graphics display and load 'images.pic' from disk
160 poke 53265,v1 or 32:poke 53272,25:poke 56576,(v3 and 252)or 1
170 poke 53280,1:a=1:load"images.pic",8,1
180 :
200 rem wait for key to be pressed then return to text screen
210 poke 198,0:wait 198,1:poke 198,0
220 poke 53265,v1:poke 53272,v2:poke 56576,v3:poke 53280,14
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →