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.


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 |
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.

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.

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 |
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)
; 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
; 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
; 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
; 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
; 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
; 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
; "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
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
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
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
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
