C 64
Grafik

Bilder aus einer anderen Dimension

Kunst aus dem Computer ist auf Großrechnern im Kommen. Daß es auch mit dem C 64 geht, zeigt dieses Programm.

Mit Hilfe einer einfachen Formel lassen sich die erstaunlichsten Grafiken erzeugen. Das Apfelmännchen, wie man diese Grafiken auch bezeichnet, wurde zuerst von dem Mathematiker Mandelbrot entdeckt. Das Apfelmännchen stellt einen Ausschnitt aus der Ebene der komplexen Zahlen dar. Die mathematischen Grundlagen dazu werden in Bild 1 erläutert.

Hinweise zum Abtippen. Tippen Sie das Maschinenprogramm (Listing 1) mit dem MSE ein und speichern Sie es unter dem Namen »APFELROUTINEN«. Dann geben Sie das Basic-Programm (Listing 2) mit dem Checksummer ein und speichern es ebenfalls. Die REM-Zahlen können weggelassen werden, da sie im Programm nicht angesprungen werden. Nach dem Starten des Basic-Programms wird das Maschinenprogramm automatisch nachgeladen. Außerdem werden die Zeiger für den Beginn der Variablen verändert. Wenn man eine Grafik geladen hat und erneut das Basic-Programm speichert, wird die Grafik daran angehängt.

Die Bedienung des Programms

Vom Menü aus lassen sich folgende Unterpunkte anwählen:

Programmbeschreibung

Die wesentlichen Routinen sind im Maschinenprogramm enthalten, das den Bereich von $C800 bis $CBlE belegt. Es gibt folgende Einsprungadressen:

AdresseVariableRoutineFunktion der Routine
51200USRINübergibt Werte an Maschinenprogramm
51207USROUTübergibt Werte an Basic
51214M1MULTIONGrafik einschalten
51217MOMULTIOFFGrafik ausschalten
51220SCSETCOLFarben setzen
51223BGBEGINBerechnen der Grafik
51226SASAVEPICBild speichern
51229L0LOADPICBild laden
51232CLCLRSCRGrafikbildschirm löschen

Die Adressen der Variablen, die im Assemblerprogramm verwendet werden, können Sie dem Source-Code (Listing 3) entnehmen. Für die Arithmetik des Berechnungsteils werden die Routinen des Basic-Interpreters benutzt. Der Berechnungsteil des Maschinenprogramms folgt dem Algorithmus des Struktogramms (Bild 2). Das Basic-Programm enthält folgende Unterprogramme:

Bild 2. Struktogramm des Berechnungs-Algorithmus
Ab ZeileFunktion
1000Eingabe neuer Werte
2000Ausschnitt
3000Grafik ansehen
4000Bild speichern
5000Bild laden
5500Directory
7000Bewegungseffekt

Die Übergabe der Werte für die Ränder an das Assemblerprogramm erfolgt über die USR-Funktion. Dabei werden die Zahlen von Basic aus in den Fließkomma-Akku geschrieben. Eine kurze Unterroutine speichert die Zahlen dann an ihre richtige Adresse. Dazu wird von Basic aus direkt in das Maschinenprogramm die jeweilige Adresse gePOKEt (Variable XI, XA, Y1, YA). Auf ähnliche Weise werden auch die Parameter eines geladenen Bildes an Basic übergeben.

Die Demo-Bilder

Die Demo-Bilder sind auf der Programmservice-Diskette enthalten. Sie können diese laden und gleich mit der Erstellung eines Ausschnitts beginnen. Wir hoffen, daß die Beispielbilder Sie ein wenig auf den Geschmack gebracht haben und wünschen Ihnen viel Spaß auf Ihrer Entdeckungsfahrt durch die unendlichen Weiten der Mathematik.

(Gerhard Pehland/og)

Eine komplexe Zahl besteht aus zwei Zahlen, dem Real- und dem Imaginärteil. Bei diesem Programm werden die beiden Anteile durch die X- und Y-Koordinate auf dem Grafikbildschirm repräsentiert. Das heißt die Koordinaten jedes Punktes auf dem Bildschirm stehen für eine komplexe Zahl, die im folgenden »C« genannt wird.

Wie entstehen nun diese fantastischen Grafiken?

Es beginnt mit der komplexen Zahl 0. Davon wird die Zahl C abgezogen. Es ergibt sich eine neue komplexe Zahl, die jetzt quadriert wird. Vom Ergebnis wird wieder C abgezogen, dann quadriert und so weiter. Dabei entsteht eine Folge von Zahlen, die eine merkwürdige Eigenschaft hat: Für manche Werte von C ergibt sich, daß die Elemente der Folge immer kleiner werden, bei anderen Werten steigt sie schnell an. Dazwischen gibt es aber Werte, bei denen die Folge lange unschlüssig hin und her pendelt, bis sie steigt oder fällt. Die Farbe eines Punktes auf dem Bildschirm wird bestimmt, indem man den dazugehörigen Wert C in die Folge einsetzt und so lange immer wieder abzieht und quadriert, bis die Elemente der Folge eine gewisse Grenze überschreiten. Aus der Anzahl der Iterationen ergibt sich die Farbe des entsprechenden Punktes. Natürlich muß man die Berechnung irgendwann beenden. Das geschieht zum einen, wenn die Folge das Grenzkriterium überschritten hat, oder wenn die maximale Tiefe erreicht ist. Führt man diese Berechnungen für alle Punkte des Bildschirms durch, entstehen typische Grafiken (siehe Seite 169). Das Struktogramm (Bild 2) zeigt Ihnen den genauen Ablauf und die verwendeten Formeln. Die Bedeutung der Variablen können Sie dem Source-Code (Listing 3) entnehmen. Ein typisches Beispiel ist das Ausgangsbild mit den oben angegebenen Werten. In der Bildschirmmitte liegen die Werte von C, bei denen die Folge sofort sinkt. Ganz außen steigt die Folge schnell an. Interessant ist die Grenzschicht dazwischen. Hier gibt es die bizarrsten Muster, die Sie mit »Ausschnitt« (siehe Text) herausvergrößern können. Bei der Vergrößerung zeigt sich eine weitere Eigenschaft dieser Bilder: Am Rande des großen Apfelmännchens sitzen nämlich noch unzählige weitere, kleinere Männchen, auf denen noch kleinere Figuren sitzen. Diese Eigenschaft wird Selbstähnlichkeit genannt. Aber auch andere Muster tauchen immer wieder auf, mal größer, mal kleiner.

Zum Schluß noch ein Wort zur Rechenzeit: Obwohl die Berechnungsroutine in Assembler geschrieben ist, muß man auf die fertige Grafik manchmal bis zu 8 (acht!) Stunden warten, da ja für 32 000 Punkte bis zu 250 mal quadriert, subtrahiert und verglichen wird.

Bild 1. Die mathematischen Grundlagen

Man glaubt es kaum, was man aus dem C 64 herausholen kann. Bestes Beispiel sind diese Grafiken, die Sie natürlich auch selbst erstellen können. Das Programm dazu finden Sie in dieser Ausgabe.

Bild 1. Die Urform aller Apfelmännchen
Bild 2. Das ist keine Verkleinerung, sondern ein Ausschnitt aus der Spitze des Apfelmännchens.
Bild 3. Ganz rechts, in Bild 2 nur als schwarzer Punkt zu sehen, tritt die Selbstähnlichkeit dieser Grafiken deutlich zu Tage.
Bild 4. In einem ganz anderen Bereich am Rand der Ausgangsform findet man spiralförmige Strukturen.
Bild 5. Ungefähr fünf Stunden Berechnungszeit sind keine Seltenheit. Probieren Sie doch mal die Werte 0.763; 0.768; 0.0999; 0.103 mit einer Tiefe von 254.
Bild 6. Farblich abgestimmt kann man die Bilder durchaus als Kunstwerke der Mathematik betrachten.
PROGRAMM : APFELROUTINEN  C800 CB1F
-----------------------------------
C800 : A2 40 A0 3F 4C D4 BB A9   80
C808 : 40 A0 3F 4C A2 BB 4C 89   3E
C810 : C8 4C FD C8 4C 41 C8 4C   21
C818 : AC CA 4C B5 CA 4C D5 CA   EF
C820 : 4C 27 C8 00 07 0A 02 A9   4E
C828 : 00 85 A4 A9 20 85 A5 A0   4F
C830 : 00 A9 00 91 A4 C8 D0 F9   FF
C838 : E6 A5 A9 40 C5 A5 D0 F1   14
C840 : 60 A9 00 8D 20 D0 AD 23   AC
C848 : C8 8D 21 D0 AD 24 C8 0A   6C
C850 : 0A 0A 0A 0D 25 C8 A2 00   A7
C858 : 86 A4 86 A6 A2 04 86 A5   56
C860 : A2 D8 86 A7 AE 12 D0 E0   85
C868 : 3A D0 F9 AE 11 D0 30 F4   A1
C870 : A0 00 A2 08 91 A4 48 AD   75
C878 : 26 C8 91 A6 68 C8 D0 F4   35
C880 : E6 A5 E6 A7 E4 A5 D0 EC   80
C888 : 60 AD 11 D0 09 20 8D 11   07
C890 : D0 AD 18 D0 09 08 8D 18   8E
C898 : D0 AD 16 D0 09 10 8D 16   52
C8A0 : D0 20 41 C8 60 AD 00 CF   FD
C8A8 : 29 F8 4A 4A AA BD EC CA   0B
C8B0 : 85 A4 E8 BD EC CA 85 A5   00
C8B8 : AD 00 CF 29 07 18 65 A4   8E
C8C0 : 85 A4 90 02 E6 A5 AD 01   50
C8C8 : CF 0A 0A 0A 90 02 E6 A5   60
C8D0 : 18 65 A4 85 A4 90 02 E6   19
C8D8 : A5 A0 00 AD 02 CF 91 A4   B1
C8E0 : 60 A5 6E 45 66 85 6F A5   F3
C8E8 : 61 60 A2 00 A0 01 98 9D   D2
C8F0 : 00 CE C8 C0 04 D0 02 A0   B2
C8F8 : 01 E8 D0 F2 60 AD 16 D0   6D
C900 : 29 EF 8D 16 D0 AD 11 D0   A7
C908 : 29 DF 8D 11 D0 AD 18 D0   23
C910 : 29 F7 8D 18 D0 A9 0C 8D   41
C918 : 21 D0 A9 0B 8D 20 D0 A9   DE
C920 : 93 20 D2 FF 60 78 20 EA   98
C928 : C8 A9 40 A0 3F 20 A2 BB   E0
C930 : A9 45 A0 3F 20 50 B8 20   34
C938 : 0C BC A0 9F 20 A2 B3 20   E4
C940 : E1 C8 20 12 BB A2 90 A0   24
C948 : CF 20 D4 BB A9 4A A0 3F   C2
C950 : 20 A2 BB A9 4F A0 3F 20   1D
C958 : 50 B8 20 0C BC A0 C7 20   BE
C960 : A2 B3 20 E1 C8 20 12 BB   6D
C968 : A2 30 A0 CF 20 D4 BB A0   1D
C970 : 04 B9 40 3F 99 40 CF B9   97
C978 : 4F 3F 99 60 CF 88 10 F1   3F
C980 : A9 00 8D 00 CF 8D 01 CF   9A
C988 : 8D 03 CF A9 00 8D 02 CF   D4
C990 : A9 00 8D 04 CF A0 04 99   62
C998 : 70 CF 99 80 CF 88 10 F7   D8
C9A0 : EE 04 CF AD 54 3F CD 04   B8
C9A8 : CF B0 05 A9 00 4C 37 CA   1B
C9B0 : A9 70 A0 CF 20 A2 BB A9   0D
C9B8 : 70 A0 CF 20 28 BA A2 57   02
C9C0 : A0 00 20 D4 BB A9 80 A0   4F
C9C8 : CF 20 A2 BB A9 80 A0 CF   88
C9D0 : 20 28 BA A2 F7 A0 00 20   CC
C9D8 : D4 BB A9 57 A0 00 20 67   38
C9E0 : B8 A5 61 C9 84 90 09 AE   4B
C9E8 : 04 CF BD 00 CE 4C 37 CA   05
C9F0 : A9 80 A0 CF 20 A2 BB A9   55
C9F8 : 70 A0 CF 20 28 BA A5 61   62
CA00 : F0 02 E6 61 A9 60 A0 CF   97
CA08 : 20 50 B8 20 B4 BF A2 80   57
CA10 : A0 CF 20 D4 BB A0 00 A9   4F
CA18 : F7 20 A2 BB A0 00 A9 57   9F
CA20 : 20 50 B8 A9 40 A0 CF 20   54
CA28 : 50 B8 20 B4 BF A2 70 A0   87
CA30 : CF 20 D4 BB 4C A0 C9 0E   C9
CA38 : 02 CF 0E 02 CF 0D 02 CF   F3
CA40 : 8D 02 CF A9 40 A0 CF 20   80
CA48 : A2 BB A9 90 A0 CF 20 67   1C
CA50 : B8 A2 40 A0 CF 20 D4 BB   46
CA58 : EE 03 CF AD 03 CF 29 03   CB
CA60 : F0 03 4C 90 C9 8D 03 CF   AC
CA68 : 20 A5 C8 EE 01 CF AD 01   B2
CA70 : CF C9 28 F0 03 4C 8B C9   A0
CA78 : A9 00 8D 01 CF A0 05 B9   2E
CA80 : 40 3F 99 40 CF 88 10 F7   40
CA88 : EE 00 CF AD 00 CF C9 C8   57
CA90 : F0 18 A9 30 A0 CF 20 A2   4B
CA98 : BB A9 60 A0 CF 20 50 B8   05
CAA0 : A2 60 A0 CF 20 D4 BB 4C   C5
CAA8 : 8B C9 58 60 20 89 C8 20   EC
CAB0 : 25 C9 4C FD C8 A2 08 20   8F
CAB8 : BA FF AD B0 CF A2 A0 A0   C9
CAC0 : CF 20 BD FF A9 00 85 A4   09
CAC8 : A9 20 85 A5 A9 A4 A2 56   8E
CAD0 : A0 3F 4C D8 FF A2 08 A0   B4
CAD8 : 01 20 BA FF AD B0 CF A2   7D
CAE0 : A0 A0 CF 20 BD FF A9 00   4B
CAE8 : 4C D5 FF 60 00 20 40 21   6F
CAF0 : 80 22 C0 23 00 25 40 26   8C
CAF8 : 80 27 C0 28 00 2A 40 2B   EA
CB00 : 80 2C C0 2D 00 2F 40 30   47
CB08 : 80 31 C0 32 00 34 40 35   A4
CB10 : 80 36 C0 37 00 39 40 3A   02
CB18 : 80 3B C0 3C 00 3E 09      02
Listing 1. Maschinenprogramm zu »Apfelmännchen«. Bitte mit dem MSE eingeben.
10 rem ********************************
15 rem *                              *
20 rem *        apfelmaennchen        *
30 rem *              by              *
40 rem *       gerhard  pehland       *
41 rem *                              *
43 rem *       markgrafenstr.64       *
44 rem *       8000 muenchen 82       *
46 rem *                              *
50 rem ********************************
60 poke53280,11:poke53281,12:printchr$(14)"{clr}{blk}{down}{down}{down}              Moment..."
70 ifa=0thena=1:load"apfelroutinen",8,1
90 poke 45,10:poke46,65:clr
100 c8=200:xi=64:xa=69:yi=74:ya=79:tm=84+3*4096+15*256:bn=49152+15*256+160
120 m1=51214:m0=m1+3:sc=m0+3:bg=sc+3:sa=bg+3:lo=sa+3:cl=lo+3
130 c0=cl+3:c1=c0+1:c2=c1+1:c3=c2+1
140 poke785,7:poke786,c8:rem usrvektor
150 vc=53248
151 poke 51208,xi:li=usr(0)
152 poke 51208,xa:re=usr(0)
153 poke 51208,yi:un=usr(0)
154 poke 51208,ya:ob=usr(0)
155 poke785,0
160 fori=832to894:readx:pokei,x:next
170 fori=896to958:readx:pokei,x:next
200 print"{clr}{down}{down}"tab(10)"**** MENUE ****"
220 print"{down}{down}"tab(10)"(1)  Neue Werte"
240 print"{down}"tab(10)"(2)  Ausschnitt"
260 print"{down}"tab(10)"(3)  Bild ansehen"
280 print"{down}"tab(10)"(4)  Speichern
300 print"{down}"tab(10)"(5)  Laden"
310 print"{down}"tab(10)"(6)  Directory
315 print"{down}"tab(10)"(7)  Effekt
320 print"{down}{down}{down}"tab(10)"Was darfs sein  ?"
340 get a$:if a$<"1" or a$>"7" then 340
360 on val(a$) gosub 1000,2000,3000,4000,5000,5500,7000
380 goto200
990 rem neue werte
1000 print"{clr}{down}*** NEUE{$a0}WERTE ***{down}"
1020 input"{down}Linker Rand  ";li
1040 input"{down}Rechter Rand ";re
1060 input"{down}Unterer Rand ";un
1080 input"{down}Oberer Rand  ";ob
1100 input"{down}{down}Maximale Tiefe ";tm%
1110 if tm%<5ortm%>254then1100
1120 print"{down}Fertiges Bild speichern ? ";
1130 get a$:if a$<>"j"and a$<>"n"and a$<>"_"then1130
1135 ifa$="_"thenreturn
1140 printa$:if a$="j"theninput"{down}Name des Bildes ";nb$
1141 syscl:poke51201,xi:us=usr(li)
1142 poke51201,xa:us=usr(re)
1143 poke51201,yi:us=usr(un)
1144 poke51201,ya:us=usr(ob)
1145 poketm,tm%
1150 sys bg
1160 if a$="j"then4020
1200 return
1990 rem ausschnitt
2000 print"{clr}{down}*** AUSSCHNITT ***"
2005 print"{down}Bewegung mit Cursortasten"
2010 print"{down}Markieren mit <SPACE>"
2015 print"{down}Zurueck mit '_'"
2017 print"{down}Weiter mit Taste"
2020 poke198,0:wait198,1:geta$
2030 dx=(re-li)/319:dy=(ob-un)/199
2040 sys m1:poke 2040,13:poke2041,14
2050 px=24:py=50
2060 poke vc,px:pokevc+1,py
2070 poke vc+39,1:pokevc+40,1
2080 pokevc+21,1:q$=""
2090 get a$:if a$=""then2090
2095 if a$=q$thensp=3
2100 if a$="_"thenpokevc+21,0:sysm0:return
2110 if a$="{down}"and py<249thenpy=py+sp:goto2160
2130 if a$="{up}"and py>50thenpy=py-sp:goto2160
2140 if a$="{rght}"and px<342thenpx=px+sp:goto2160
2150 if a$="{left}"and px>24thenpx=px-sp:goto2160
2155 ifa$=" "then2230
2160 ifpx<256thenpokevc,px:pokevc+16,0:goto2210
2200 pokevc,px-256:pokevc+16,1
2210 pokevc+1,py
2220 q$=a$:sp=1:ifpeek(198)=0thenq$=""
2225 goto2090
2230 ix=px:iy=py
2240 px=320:py=229:sp=1
2250 poke vc+2,px-256:pokevc+16,peek(vc+16)or2:pokevc+3,py:poke vc+21,3:q$=""
2280 get a$:if a$=""then2280
2285 if a$=q$thensp=3
2290 if a$="_"then pokevc+21,0:sysm0:return
2300 if a$="{down}"andpy<229thenpy=py+sp:goto2350
2310 if a$="{up}"and py>iy-18thenpy=py-sp:goto2350
2320 if a$="{rght}"and px<320thenpx=px+sp:goto2350
2330 if a$="{left}"and px>ix-20thenpx=px-sp:goto2350
2340 ifa$=" "then2440
2350 ifpx<256thenpokevc+2,px:pokevc+16,peek(vc+16)and1:goto2410
2400 pokevc+2,px-256:pokevc+16,peek(vc+16)or2
2410 pokevc+3,py
2415 q$=a$:sp=1:ifpeek(198)=0thenq$=""
2420 goto2280
2440 re=li+(px-1)*dx
2450 li=li+(ix-24)*dx
2460 un=ob-(py-30)*dy
2470 ob=ob-(iy-50)*dy
2520 pokevc+21,0:sysm0
2530 print"{clr}{down}*** AUSSCHNITT ***"
2540 print"{down}Linker Rand  :";li
2550 print"{down}Rechter Rand :";re
2560 print"{down}Unterer Rand :";un
2570 print"{down}Oberer Rand  :";ob
2580 goto1100
2990 rem ansehen
3000 print"{clr}{down}*** ANSEHEN ***"
3010 print"{down}Farben = Funktionstasten"
3020 print"{down}Zurueck mit '_'"
3023 print"{down}Weiter mit Taste"
3030 poke198,0:wait198,1:geta$
3040 sysm1
3050 get a$:if a$=""then3050
3055 if a$="_" then sys m0:return
3060 if a$="{f1}"thenpokec0,(peek(c0)+1)and15:sys sc
3070 if a$="{f3}"thenpokec1,(peek(c1)+1)and15:sys sc
3080 if a$="{f5}"thenpokec2,(peek(c2)+1)and15:sys sc
3090 if a$="{f7}"thenpokec3,(peek(c3)+1)and15:sys sc
3100 goto3050
3990 rem speichern
4000 print"{clr}{down}*** SPEICHERN ***"
4010 input"{down}Name des Bildes";nb$
4020 if len(nb$)>12thennb$=left$(nb$,12)
4030 nb$=nb$+".pic"
4040 fori=0tolen(nb$)-1
4050 pokebn+i,asc(mid$(nb$,i+1,1))
4060 next
4070 poke bn+16,len(nb$)
4080 sys sa
4090 open1,8,15:input#1,a,b$,c,d:close1
4100 print"{down}";a;b$
4110 wait198,1:poke198,0:return
4990 rem laden
5000 print"{clr}{down}*** LADEN ***"
5010 input"{down}Name des Bildes";nb$
5020 if len(nb$)>12thennb$=left$(nb$,12)
5030 nb$=nb$+".pic"
5040 fori=0tolen(nb$)-1
5050 pokebn+i,asc(mid$(nb$,i+1,1))
5060 next
5070 poke bn+16,len(nb$)
5080 sys lo
5090 open1,8,15:input#1,a,b$,c,d:close1
5100 print"{down}";a;b$
5110 poke 785,7
5120 poke 51208,xi:li=usr(0)
5130 print"{down}Linker Rand  :";li
5140 poke 51208,xa:re=usr(0)
5150 print"{down}Rechter Rand :";re
5160 poke 51208,yi:un=usr(0)
5170 print"{down}Unterer Rand :";un
5180 poke 51208,ya:ob=usr(0)
5190 print"{down}Oberer Rand  :";ob
5200 tm%=peek(tm)
5210 print"{down}Maximale Tiefe:";tm%
5220 poke198,0:wait198,1:poke198,0
5230 poke785,0:return
5490 rem directory
5500 print"{clr}{down}*** DIRECTORY ***{down}"
5510 poke198,0:open15,8,15,"i0":open10,8,2,"#"
5520 tt=18:ss=1
5530 print#15,"b-r";2;0;tt;ss
5540 print#15,"b-p";2;0
5550 get#10,x$:ifx$=""thenx$=chr$(0)
5560 tt=asc(x$)
5570 get#10,x$:ifx$=""thenx$=chr$(0)
5580 ss=asc(x$)
5590 forq1=0to7
5600 print#15,"b-p";2;q1*32+5
5610 f$=""
5620 forq2=0to15
5630 get#10,x$:ifx$=""thenx$=chr$(0)
5640 if asc(x$)=160thenq2=16:goto5660
5650 f$=f$+x$
5660 next
5670 ifright$(f$,4)=".pic"thenprintf$
5690 next
5700 iftt<>0then5530
5710 close15:close10
5720 wait198,1:poke198,0:return
6000 rem sprites
6010 data 255,255,255,192,0,0,192,0,0,192,0,0
6020 data192,0,0,192,0,0,192,0,0,192,0,0
6030 data192,0,0,192,0,0,192,0,0,192,0,0
6040 data192,0,0,192,0,0,192,0,0,192,0,0
6050 data192,0,0,192,0,0,192,0,0,192,0,0,192,0,0
6060 data0,0,3,0,0,3,0,0,3,0,0,3
6070 data0,0,3,0,0,3,0,0,3,0,0,3
6080 data0,0,3,0,0,3,0,0,3,0,0,3
6090 data0,0,3,0,0,3,0,0,3,0,0,3
6100 data0,0,3,0,0,3,0,0,3,0,0,3
6110 data 255,255,255
6990 rem effekt
7000 print"{clr}{down}*** EFFEKT ***"
7010 print"{down}Farben = Funktionstasten"
7020 print"{down}Zurueck mit '_'"
7023 print"{down}Weiter mit Taste"
7030 poke198,0:wait198,1:geta$
7040 sysm1
7050 ifa$="{f5}"then pokec2,(peek(c2)+1)and15
7060 cp=peek(c3):pokec3,peek(c2):pokec2,peek(c1):pokec1,cp
7070 geta$:ifa$="_"then7140
7080 ifa$="{f1}"then pokec0,(peek(c0)+1)and15
7090 ifa$="{f3}"then pokec1,(peek(c1)+1)and15
7100 ifa$="{f5}"then pokec2,(peek(c2)+1)and15
7110 ifa$="{f7}"then pokec3,(peek(c3)+1)and15
7120 sys sc
7130 goto7060
7140 sysm0:return
Listing 2. Den Basic-Teil geben Sie mit dem Checksummer ein. Beachten Sie dazu die Hinweise auf Seite 54.
        .OPT P1
 ;*** SYSTEMADRESSEN ***
VIC      =    53248   ;VIDEOCHIP
FAC      =    97      ;FLIESSKOMMA-AKKU
ARG      =    105     ;FLIESSKOMMA-AKKU #2
CHROUT   =    $FFD2   ;EIN ZEICHEN AUSGEBEN
DIV      =    $BB12   ;FAC=ARG/FAC
SUB      =    $B853   ;FAC=ARG-FAC
BYTENFAC =    $B3A2   ;BYTE IN Y NACH FAC
FACNARG  =    $BC0C   ;ARG=FAC
ZEIGSUB  =    $B850   ;FAC=(A/Y)-FAC
ZEIGADD  =    $B867   ;FAC=(A/Y)+FAC
ZEIGMULT =    $BA28   ;FAC=(A/Y)*FAC
KONNARG  =    $BA8C   ;ARG=(A/Y)
KONNFAC  =    $BBA2   ;FAC=(A/Y)
FACNKON  =    $BBD4   ;(X/Y)=FAC
CHSIGN   =    $BFB4   ;FAC=-FAC
FILEPAR  =    $FFBA   ;FILEPARAMETER SETZEN
FILENAM  =    $FFBD   ;FILENAME UEBERGEBEN
SAVE     =    $FFD8   ;SPEICHERN
LOAD     =    $FFD5   ;LADEN
 ;*** VARIABLE ***
ZEIG1    =    $A4     ;UNIVERSALZEIGER
ZEIG2    =    $A6
ZEILE    =    $CF00   ;AKTUELLE ZEILE
SPALTE   =    $CF01   ;AKTUELLE SPALTE
BYTE     =    $CF02   ;ENTHAELT IMMER 4 PUNKTE
POS      =    $CF03   ;ZAEHLER FUER 4 PUNKTE (0 BIS 3)
TIEFE    =    $CF04   ;AKTUELLE TIEFE
TIEFEMAX =    $3F54   ;MAXIMALE TIEFE
DX       =    $CF90   ;SCHRITTWEISE REALTEIL
DY       =    $CF30   ;SCHRITTWEISE IMAGINAERTEIL
CX       =    $CF40   ;REALTEIL AKTUELLER BILDSCHIRMPUNKT
CY       =    $CF60   ;DTO. IMAGINAER
XQUAD    =    87      ;XWERT*XWERT
YQUAD    =    247     ;YWERT*YWERT
XWERT    =    $CF70   ;MOMENTANER WERT DER FOLGE REALTEIL
YWERT    =    $CF80   ;DTO. IMAGINAER
XMAX     =    $3F45   ;RECHTER RAND
XMIN     =    $3F40   ;LINKER RAND
YMAX     =    $3F4F   ;OBERER RAND
YMIN     =    $3F4A   ;UNTERER RAND
FILENAME =    $CFA0   ;VON BASIC GEPOKED
FARBTAB  =    $CE00   ;TABELLE TIEFE MOD 3 +1
 ;
 ;*** PROGRAMM ***
         *=   $C800
USRIN    LDX  #XMIN
         JMP  FACNKON
USROUT   LDA  #XMIN
         JMP  KONNFAC
 ;SPRUNGTABELLE
         JMP  MULTION
         JMP  MULTIOFF
         JMP  SETCOL
         JMP  BEGIN
         JMP  SAVEPIC
         JMP  LOADPIC
         JMP  CLRSCR
COL0     .BYT 0       ;FARBEN
COL1     .BYT 7
COL2     .BYT 10
COL3     .BYT 2
CLRSCR   LDA  #0      ;GRAFIK LOESCHEN
         STA  ZEIG1
         LDA  #$20
         STA  ZEIG1+1
         LDY  #0
L1       LDA  #0
         STA  (ZEIG1),Y
         INY
         BNE  L1
         INC  ZEIG+1
         LDA  #$40
         CMP  ZEIG1+1
         BNE  L1
         RTS


SETCOL   LDA  #0      ;FARBEN SETZEN
         STA  53280
         LDA  COL0
         STA  53281
         LDA  COL1
         ASL  A
         ASL  A
         ASL  A
         ASL  A
         ORA  COL2
         LDX  #0
         STX  ZEIG1
         STX  ZEIG2
         LDX  #4
         STX  ZEIG1+1
         LDX  #$D8
         STX  ZEIG2+1
WAIT     LDX  VIC+18  ;WARTEN AUF STRAHLDURCHLAUF
         CPX  #58
         BNE  WAIT
         LDX  VIC+17
         BMI  WAIT
         LDY  #0
         LDX  #8
L2       STA  (ZEIG1),Y
         PHA
         LDA  COL3
         STA  (ZEIG2),Y
         PLA
         INY
         BNE  L2
         INC  ZEIG1+1
         INC  ZEIG2+1
         CPX  ZEIG1+1
         BNE  L2
         RTS


MULTION  LDA  VIC+17  ;MULTICOLOUR EIN
         ORA  #%00100000
         STA  VIC+17
         LDA  VIC+24
         ORA  #$00001000
         STA  VIC+24
         LDA  VIC+22
         ORA  #$00010000
         STA  VIC+22
         JSR  SETCOL
         RTS
SETBYTE  LDA  ZEILE   ;4 PUNKTE (=1 BYTE) SETZEN
         AND  #%11111000
         LSR  A
         LSR  A
         TAX
         LDA  ZEILTAB,X
         STA  ZEIG1
         INX
         LDA  ZEILTAB,X
         STA  ZEIG1+1
         LDA  ZEILE
         AND  #%00000111
         CLC
         ADC  ZEIG1
         STA  ZEIG1
         BCC  SETBYT1
         INC  ZEIG1+1
SETBYT1  LDA  SPALTE
         ASL  A
         ASL  A
         ASL  A
         BCC  SETBYT3
         INC  ZEIG1+1
SETBYT3  CLC
         ADC  ZEIG1
         STA  ZEIG1
         BCC  SETBYT2
         INC  ZEIG1+1
SETBYT2  LDY  #0
         LDA  BYTE
         STA  (ZEIG1),Y
         RTS

FACSARG  LDA  ARG+5;VORZEICHENVERGLEICH VON FAC UND ARG
         EOR  FAC+5
         STA  ARG+6
         LDA  FAC
         RTS


MAKETAB  LDX  #0      ;FARBTABELLE ANLEGEN
         LDY  #1
L40      TYA
         STA  FARBTAB,X
         INY
         CPY  #4
         BNE  MT1
         LDY  #1
MT1      INX
         BNE  L40
         RTS


MULTIOFF LDA  VIC+22  ;MULTICOLOUR AUS
         AND  #%11101111
         STA  VIC+22
         LDA  VIC+17
         AND  #%11011111
         STA  VIC+17
         LDA  VIC+24
         AND  #%11110111
         STA  VIC+24
         LDA  #12
         STA  53281
         LDA  #11
         STA  53280
         LDA  #147
         JSR  CHROUT
         RTS

APFEL    SEI          ;BERECHNUNG DER GRAFIK
         JSR  MAKETAB
         LDA  #XMIN
         JSR  KONNFAC
         LDA  #XMAX
         JSR  ZEIGSUB
         JSR  FACNARG
         LDY  #159
         JSR  BYTENFAC
         JSR  FACSARG
         JSR  DIV
         LDX  #DX
         JSR  FACNKON
         LDA  #YMIN
         JSR  KONNFAC
         LDA  #YMAX
         JSR  ZEIGSUB
         JSR  FACNARG
         LDY  #199
         JSR  BYTENFAC
         JSR  FACSARG
         JSR  DIV
         LDX  #DY
         JSR  FACNKON
         LDY  #4      ;CX=XMIN CY=YMAX
L13      LDA  XMIN,Y
         STA  CX,Y
         LDA  YMAX,Y
         STA  CY,Y
         DEY
         BPL  L13
         LDA  #0
         STA  ZEILE
         STA  SPALTE
         STA  POS
ITERAT   LDA  #0
         STA  BYTE
ITERAT1  LDA  #0
         STA  TIEFE
         LDY  #4
L15      STA  XWERT,Y
         STA  YWERT,Y
         DEY
         BPL  L15
ITER1    INC  TIEFE
         LDA  TIEFEMAX
         CMP  TIEFE   ;"MAXIMALE TIEFE ?
         BCS  ITER4
         LDA  #0      ;PUNKTFARBE
         JMP  PLOT
ITER4    LDA  #XWERT
         JSR  KONNFAC
         LDA  #WERT
         JSR  ZEIGMULT
         LDX  #XQUAD
         LDY  #0
         JSR  FACNKON
         LDA  #YWERT
         JSR  KONNFAC
         LDA  #YWERT
         JSR  ZEIGMULT
         LDX  #YQUAD
         LDY  #0
         JSR  FACNKON
         LDA  #XQUAD
         LDY  #0      ;SUMME XQUAD+YQUAD
         JSR  ZEIGADD
         LDA  FAC
         CMP  #$84    ;"SUMME GROESSER 8 ?
         BCC  ITER3
         LDX  TIEFE
         LDA  FARBTAB,X ;PUNKTFARBE
         JMP  PLOT
ITER3    LDA  #YWERT
         JSR  KONNFAC
         LDA  #XWERT
         JSR  ZEIGMULT
         LDA  FAC
         BEQ  ITER2
         INC  FAC
ITER2    LDA  #CY
         JSR  ZEIGSUB
         JSR  CHSIGN
         LDX  #YWERT
         JSR  FACNKON
         LDY  #0      ;XWERT=XQUAD-YQUAD-CX
         LDA  #YQUAD
         JSR  KONNFAC
         LDY  #0
         LDA  #XQUAD
         JSR  ZEIGSUB
         LDA  #CX
         JSR  ZEIGSUB
         JSR  CHSIGN
         LDX  #XWERT
         JSR  FACNKON
         JMP  ITER1
PLOT     ASL  BYTE
         ASL  BYTE
         ORA  BYTE
         STA  BYTE
         LDA  #CX
         JSR  KONNFAC
         LDA  #DX
         JSR  ZEIGADD
         LDX  #CX
         JSR  FACNKON
         INC  POS
         LDA  POS
         AND  #3
         BEQ  APFEL1
         JMP  ITERAT1
APFEL1   STA  POS
         JSR  SETBYTE
         INC  SPALTE
         LDA  SPALTE
         CMP  #40
         BEQ  APFEL2
         JMP  ITERAT
APFEL2   LDA  #0
         STA  SPALTE
         LDY  #5      ;CX=XMIN
L30      LDA  XMIN,Y
         STA  CX,Y
         DEY
         BPL  L30
         INC  ZEILE
         LDA  ZEILE
         CMP  #200
         BEQ  ENDAPFEL
         LDA  #DY
         JSR  KONNFAC
         LDA  #CY
         JSR  ZEIGSUB
         LDX  #CY
         JSR  FACNKON
         JMP  ITERAT
ENDAPFEL CLI
         RTS

BEGIN    JSR  MULTION
         JSR  APFEL
         JMP  MULTIOFF

SAVEPIC  LDX  #8      ;SPEICHERN
         JSR  FILEPAR
         LDA  FILENAME+16
         LDX  #FILENAME
         JSR  FILENAM
         LDA  #0
         STA  ZEIG1
         LDA  #$20
         STA  ZEIG1+1
         LDA  #ZEIG1
         LDX  #$56
         LDY  #$3F
         JMP  SAVE

LOADPIC  LDX  #8      ;LADEN
         LDY  #1
         JSR  FILEPAR
         LDA  FILENAME+16
         LDX  #FILENAME
         JSR  FILENAM
         LDA  #0
         JMP  LOAD
         RTS

 ;TABELLE DER ZEILENANFAENGE
ZEILTAB  .WOR 8192,8512,8832,9152,9472,9792
         .WOR 10112,10432,10752,11072,11392,11712
         .WOR 12032,12352,$3180,12992,13312,13632
         .WOR 13952,14272,14592,14912,15232,15552
         .WOR 15872
Listing 3. Das Source-Code-Listing des Apfelmännchens
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →