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:
- Neue Werte: Hier können Sie die Grenzen für Realteil (linker/rechter Rand) und Imaginärteil (oberer/unterer Rand) der Zahlen (siehe Bild 1) eingeben, die Sie darstellen wollen. Das Ausgangsbild aller Apfelmännchen finden Sie mit den Parametern: linker Rand —0.7, rechter Rand 2.1, unterer Rand —1, oberer Rand 1. Die maximale Tiefe bestimmt, nach wievielen Iterationen (Wiederholungen) abgebrochen wird. Es sind Werte von 5 bis 254 zugelassen. Je größer die Tiefe, desto mehr Details treten am Rand der Figur zutage. Beachten Sie aber, daß eine große Tiefe auch eine lange Rechenzeit bedeutet. Nach Eingabe der Tiefe werden Sie gefragt, ob die fertige Grafik auf Diskette gespeichert werden soll — zum Beispiel, wenn Sie den Computer über Nacht rechnen lassen. Falls Ihnen die Werte nicht gefallen sollten, können Sie jetzt noch mit dem Linkspfeil ins Menü zurück. Wenn Sie die Grafik speichern lassen, muß ein File-Namen eingegeben werden. Nach der letzten Eingabe beginnt der Aufbau des Bildes. Das Programm kann dann nur noch durch RUN/STOP-RESTORE abgebrochen werden. Natürlich kann eine abgebrochene Berechnung nach einem RUN gespeichert werden, zum Beispiel um später einen Ausschnitt zu berechnen. Denn statt die Grenzen als Zahlen einzugeben, können Sie auch einen Ausschnitt aus einem bereits bestehenden Bild berechnen lassen.
- Ausschnitt: Am linken oberen Rand erscheint ein weißes Eck, mit dem Sie die linke obere Ecke des neuen Bildes markieren. Gesteuert wird es mit den Cursortasten, und fixiert mit der Space-Taste. Mit dem rechten unteren Eck wird genauso verfahren. Der Ausschnitt sollte ungefähr die Form des Bildschirms haben, da sonst die Grafik stark verzerrt wird. Mit der Eingabe der maximalen Tiefe geht es dann weiter wie bei der Eingabe von neuen Werten.
- Bild ansehen: Unter diesem Menüpunkt können Sie sich eine fertige Grafik ansehen. Mit den Funktionstasten können Sie die Farben verändern. Zurück ins Menü geht es mit dem Linkspfeil.
- Speichern: Ein fertiges Bild kann auf Diskette gespeichert werden. Dabei wird an den Filenamen die Endung ».pic« angehängt. Zusätzlich werden die Parameter des Bildes mit auf Diskette abgelegt.
- Laden: Bilder von Diskette können unter Angabe des Namens von Diskette geladen werden. Die Endung ».pic« ist dabei nicht mitanzugeben. Nach Beendigung des Ladevorgangs werden die dem Ausschnitt entsprechenden Parameter angezeigt.
- Directory: Nach Aufruf dieser Funktion wird ein Verzeichnis aller Bilder, die mit ».pic« enden, auf dem Bildschirm gelistet. Effekt: Durch zyklisches Vertauschen der Farbwerte entsteht der Eindruck eines bewegten Bildes. Auch hier können Sie die Farben mit den Funktionstasten verändern. Ins Menü zurück kommt man wieder mit dem Linkspfeil.
Programmbeschreibung
Die wesentlichen Routinen sind im Maschinenprogramm enthalten, das den Bereich von $C800 bis $CBlE belegt. Es gibt folgende Einsprungadressen:
Adresse | Variable | Routine | Funktion der Routine |
51200 | USRIN | übergibt Werte an Maschinenprogramm | |
51207 | USROUT | übergibt Werte an Basic | |
51214 | M1 | MULTION | Grafik einschalten |
51217 | MO | MULTIOFF | Grafik ausschalten |
51220 | SC | SETCOL | Farben setzen |
51223 | BG | BEGIN | Berechnen der Grafik |
51226 | SA | SAVEPIC | Bild speichern |
51229 | L0 | LOADPIC | Bild laden |
51232 | CL | CLRSCR | Grafikbildschirm 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:

Ab Zeile | Funktion |
1000 | Eingabe neuer Werte |
2000 | Ausschnitt |
3000 | Grafik ansehen |
4000 | Bild speichern |
5000 | Bild laden |
5500 | Directory |
7000 | Bewegungseffekt |
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.
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.






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