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