Hallo Bit Byter,

warum einen Kurs über das geheimnisvolle Demoprogrammieren werden sich einige Mitglieder jetzt 
fragen. Nun die kreativste Arbeit am XL ist das Programmieren (finde ich zumindest). Ich bin ein 
leidenschaftlicher Demo-Sammler und finde es interessant, wie sich die Demos in den vergangenen 
Jahren verändert haben. Auch ich erlag dem Trugschluß  so was  nicht programmieren zu können. 
Ich dachte, irgendwie ist es  ein wenig Zauberei und ich kann das nie. Auch benötigt man 
Assembler-Kenntnisse, die über das  Normale  hinausgehen. So fing ich an im Jahre 1990 meine 
ersten Grafik-Demos zu schreiben und zwar in Assembler.  

Was sind Demos eigentlich?

Demos haben eigentlich keinen Sinn, sie sollen den Betrachter durch nie (?) dagewesene Effekte 
beeindrucken. Sie sind eigentlich kleine Kunstwerke, wie Videoclips. Daneben kann der 
Programmierer sein  Können  unter Beweiß stellen. Wir werden sehen, daß es meistens nichts mit 
 Können  an sich zu tun hat, sondern einfach mit Cleverness. 

Welche Arten von Demos kann man unterschieden?

Wie in jeder Szene gibts es gewisse Fachbegriffe, die für bestimmte Effekte benutzt werden. Doch 
unterscheidet man auch die Arten der Demos, d.h. wie sind sie aufgebaut sind  in ihrer 
Grundstruktur. Hier folgt nun meine Einteilung der Demos, die nicht umbedingt vollständig ist:

-Screen: Mit Screen bezeichnet man einen kompletten Bildschirmaufbau mit allen Effekten. 
Nach Beendigung durch den Betrachter, meistens per SHIFT oder START kehrt das 
Demo wieder ins DOS zurück oder macht einen Warmstart.
         Bsp. meistens die Titelbilder auf den Magazin-Disketten.

-Intro:  Intro werden oft kurze Demos-Screens oder Demos genannt. Wie der Name schon sagt, 
dienen sie als Einführung in den Hauptteil. Sie sind meistens nicht so aufwendig und 
wurden meistens in kurzer Zeit geschrieben. Dienen oft nur zum Installieren des 
Entpackers, der Laderoutine, der Ausgabe des Titels und einer  Please wait 
loading... -Mitteilung.

-Outro:  Gegenteil von Intro. Viele Demoprogrammierer und Gruppen verwenden ein Outro. Es 
ist als kleines Demo zum Schluß gedacht, vielleicht mit Credits (s.u.). Sonst gilt das 
gleiche wie führ Intro. Danach wird entweder ein Kaltstart oder zumindest ein Reset 
ausgeführt.

-Mainpart:  Hauptteil. Oft eingekreist durch ein Intro und Outro. Aber häufig fehlt das Outro. Hier 
werden alle Effekte gezeigt, die der Programmierer dem Betrachter offenbaren möchte.
 
-Mega-Demo: Viele Demogruppen schreiben nicht nur einen Effekt. Und da der Hauptspeicher 
des Computers begrenzt ist, lagert man die Effekte auf Diskette aus. Fast immer 
wird mindestens eine Diskettenseite belegt. Solche Demos müssen gebootet 
werden. Ein Mega-Demo besteht aus mehreren Screens oder Parts. Nach dem 
Beenden durch den Betrachter wird der nächste Teil der Demo von Diskette 
geladen.
            Bei den 16-Bittern hat eine Mega-Demo meistens ein Menu, durch welches man 
die verschiedenen Parts auswählen kann. Kommt aber bei XL-Demos sehr selten 
vor. Die Reihenfolge der einzelnen Teildemos ist meistens vorgegeben.

-Menü:   Es gibt verschieden Arten von Menüs. Die ersten Menüs waren aufgebaut wie das Dos 
2.5 Menü. Durch A wurde Part 1 geladen, durch B Part 2 usw.
Solche Menüs sind praktisch, aber langweilig. Die Demogruppen wollten den Betrachter 
mehr in die Demo einbeziehen und mehr Spaß vermitteln. So kamen die  Game -Menüs 
auf. Per Joystick oder Cursortasten steuert der Betrachter wie in einem Videospiel eine 
Figur durch ein Labyrinth und führt es zu Türen oder Höhlen, hinter denen sich die 
einzelnen Demos befinden. Somit waren der Gestaltung von Menüs keine Grenzen mehr 
gesetzt. Ein solches Menü habe ich aber bis heute nicht auf dem XL gesehen!

-Multipart: Multiparts kamen auf den 16-Bittern (Amiga, Atari ST) in Mode. Multipart heißt ja 
eigentlich übersetzt, daß das Demo mehrere Effekte bzw. Screens hat. Was unterscheidet 
dann ein Multipart-Demo von einer Mega-Demo? Meistens ist ein Multipart keine 
Bootdiskette, sondern ein einzelnes File, das entweder vom Dos aus oder von einem 
Gamedos-Lader geladen wird. Ein Multipart ist also ein File, das mehrere Effekte 
enthält, die nacheinander gezeigt werden. Sie stehen komplett im Speicher und in der 
Regel wird nichts mehr nachgeladen. Auch hat der Betrachter oft keine Möglichkeit zum 
nächsten Effekt zu  springen  , sei es durch einen beherzten Druck auf Space, Shift oder 
Start. Multiparts sind auf jedenfall schwerer zu programmieren, da ja der komplette 
Speicher als Grenze dient, der Programmcode länger ist und damit mehr Speicher 
benötigt. Der Programmierer muß genau wissen, wo er welchen Effekt im Speicher hat. 
Je mehr Effekte er unterbringen kann, umso effektiver hat er den Speicher genutzt und 
letztendlich abwechslungsreicher ist es.
Ein Grund für das Aufkommen von Multiparts könnte gewesen sein, daß die Computer 
vermehrt mit Festplatte ausgestattet sind und wie soll man eine Bootdiskette (egal ob 
Amiga, ST oder PC), die noch für das jeweilige Dos unleserlich ist (wie auf dem XL,ST, 
Amiga), auf Festplatte installieren bzw. wie soll ein solche Mega-Demo dann auf 
Festplatte laufen?

Beispiele auf dem XL:

Intros oder einzelne Demos:   Titelbilder vom Abbuc-Magazin
Megademos:  Das Halle-Projekt, HARD-Megademo, Slight-Megademo,    The Top 3, Sweet 
Illusions von den Shadows

Multiparts:    The Top 1+2, Shake-Demo, Just-Fancy-Demo

Oft werden Multioparts und Megademos kombiniert z.B. bei Shadows-Megademo. Der  Effekt 
1 -Part enthält ja mehrere Effekte, obwohl das Demo eine Megademo ist.

Aus welchen Mitgliedern besteht eine Demo-Gruppe?

Diese Frage ist schwer zu beantworten, da jede Demogruppe ihren eigenen individuellen Aufbau hat. 
Folgende Bezeichnungen haben sich eingebürgert:

-Coder:  Sind Programmierer, die eigentliche Denkzentrale einer Demogruppe. Sie 
programmieren nächtelang an neuen Effekten und Routinen.

-Grafiker:  Grafiker haben meistens keine Ahnung vom Programmieren, sind aber für Logos, 
Grafiken, Zeichensätze usw. verantwortlich.

-Musiker:   Sie schreiben den Demo-Screens passende Musik auf den Leib. Wie in einem guten 
Film, sollte die Musik zur Action passen, d.h. z.B. langsame Musik bei einem schnellen 
Grafikdemo hat wohl wenig Sinn. Kommt aber auf den Geschmack an und was für eine 
Stimmung erzeugt werden soll.

-Swapper:   Sie sind für die Verbreitung der Demo zuständig. In den Zeiten der Raubkopiererei, als 
Demos eigentlich nur von den Raupkopierern geschrieben wurden, um Intros für ihre 
 Cracks   zu haben, hatten Swapper die Aufgabe, die Kontakte zu den Tauschpartnern zu 
pflegen. Heute aber so gut wie nicht mehr vorhanden, da die Demo-Szene sich von der 
Raupkopiererszene, Gott sei Dank, gelöst hat. There is no coding like demo coding!

Natürlich können mehrere Aufgaben in einer Person vereint sein. Sollte man allein Programmieren 
(so wie ich), stellt sich oft die Frage, wo bekomme ich z.B. Musikstücke oder Grafiken her. Haben 
sich mehrere Leute zusammengeschloßen, die unterschiedliche Aufgaben wahrnehmen, so wird die 
Demoprogrammierung auf jeden Fall einfacher und weniger zeitaufwendiger, die Demos sehen 
proffessioneller aus.

Die einzelnen Begriffbestimmungen für die jeweiligen Effekte spare ich mir hier im Moment noch 
auf. Sie sind meistens aus dem Englischen abgeleitet und bezeichnen die Art des Effektes, das 
Aussehen oder die Programmierung (z.B. Plasma-Effekt soll eben Plasma darstellen). Dabei sind der 
Phantasie keine Grenzen gesetzt.

Kommen wir nun endlich zum eigentlichen Thema, dem Demoprogrammieren. Folgende Tools 
sollte man haben: Einen Assembler, von dem man die Start-Adresse weiß oder zumindest resetfest 
ist. Turbo-Basic, mit dem man seine Tabellen berechnet bzw. Routinen zuerst testen kann. Es ist 
einfacher erst einen Algorithmus in Basic zu schreiben und diesen dann in Assembler umzusetzen. 
Mehr benötigt man eigentlich nicht. Ein Malprogramm wie z.B. Rambrandt XL wäre von Vorteil. 
Einen Zeichensatzeditor für eigene Fonts. Was man aber unbedingt benötigt, ist eine genaue 
Beschreibung der XL Hardware, vor allem des Antics und des GTIAs. Ich benutze bzw. kann 
folgendes Buch schon auswendig, nämlich von Data Becker "Atari intern". Und ganz wichtig ist 
Kreativität. Grundkenntnisse in Assembler sollten vorhanden sein. Ein Demo besteht meistens nicht 
mehr als aus LDAs und STAs !!! (In Basic: Peeks und Pokes)

Wie geht man nun an ein neues Demo heran. Man könnte sich auf ein Blatt Papier eine Skizze 
machen, welchen Effekt man darstellen möchte. So habe ich das Titel-Demo für das Magazin 42 
entwickelt. Die Idee dazu  entstand in einer Vorlesung. Ich wollte, fasziniert durch die 
Pixel-Routinen anderer Demos, auch eine schnelle Plot-Routine schreiben. Wie geht man aber an die 
Sache heran. In Assembler habe ich ja keine Hilfsbefehle wie in Basic, so scheidet also ein 
Plot-Befehl aus, genauso wie umfangreiche Berechnungen. Die Idee war, das vom oberen 
Bildschirmrand Pixel herunterfallen sollten. Ich stand nun vor zwei Problemen: Die Pixelroutine 
sollte schnell sein, damit kein Geflackere auftritt und die Pixel sollten wie Gummibälle realistisch 
nach unten anhand einer physikalischen Formel fallen. Da man in Assembler keine  Funktionen  an 
sich hat, gab ich die Idee vorerst auf.
Doch man könnte in Turbo-Basic eine Tabelle berechnen, die die Y-Koordinaten anhand einer 
physikalischen Formel berechnet und im RAM ablegt. Meine Pixel-Routine mußte also nur die 
Werte aus dem Ram holen und die Pixel setzten. Das war eigentlich das ganze Geheimnis.
Diese Tabelle war schnell berechnet, nun folgte das eigentliche Problem, nämlich eine schnelle 
Pixelroutine zu schreiben.

Meine Pixel-Routine entstand zu erst im Kopf.  Ich hatte schon im Jahre 1990 (glaube ich) eine 
Routine geschrieben. Ich war richtig stolz,  sie war zwar in Assembler entwickelt worden,  was nicht  
heisst dass sie schnell war.  Ich hantierte mit LSR und ASL,  was auch nicht gerade zur 
Geschwindigkeit beitrug.  Dann kam mir aber die  Idee, die  ganzen  Berechnungen  schon  vorher  
für  jede  Y-Koordinate durchzuführen  und in einer Tabelle zu speichern.  So konnte  ich einfach  die 
Y-Koordinate als Offset fuer eine Tabelle  benutzen, die  den  Wert  für  den  Bildschirmspeicher  
enthielt.   Die  X-Koordinate wurde als Offset für die Bildschirmadresse benutzt. So mussten auch 
keine Bildschirm-Adressen-Berechnungen stattfinden.
Als Grafikstufe wähle ich Gr.8. Die Auflösung beträgt 256 x 128 Pixel. Diese Werte passen 
hervoragend zum Konzept (256 passt genau in ein Register).

Hier nochmal genauere Überlegungen, wie ich ein Pixel setze:

Eine  Bildschirmzeile  in Gr.8 besteht aus  40  Bytes. Da ich aber nur 256 Pixel in X-Richtung 
darstellen wollte, mußte ich den Screen verkleinern.  Dabei hilft der Antic. Durch ein simplen LDA 
#33,  STA $d400 schalte ich auf 256 Pixel-Darstellung um. In Basic läßt sich das durch POKE 
559,33 testen. Das Bild ist auch in der Mitte vom Schirm mit einem etwas größeren Rand rechts und 
links.  Eine Zeile besteht  jetzt aus 32 Bytes.
Um  ein Pixel zu setzen, muss man zuerst wissen in  welchem  Byte das  Pixel zu setzen ist.  In Gr.  8 
besteht ein Byte aus 8  Pixel,  d.h. jedes Bit repräsentiert ein sichtbares Pixel.
Folglich erhält man das Byte,  indem man die X-Koordinate durch 8 teilt. (Kommastellen 
vernachlässigen!) Man multipliziert diesen Wert nun wieder mit 8.  Nun zieht man von der 
X-Koordinate diesem Wert  ab und  erhält die Nr.  des zu setzenden Pixels.  Anhand  von  einer 
Tabelle  ermittelt  man den Wert,  den man in  das  Bildschirmram schreiben muss. Die 
Bildschirmzeile erhält man, indem man die Y-Koordinate mit der Zeilenlänge multipliziert (hier mit 
32, da eine Zeile 32 Bytes hat). Wer will kann dies anhand des Taschenrechners mal ausprobieren, 
hier ein kleines Beispiel:
Die Routine soll ein Pixel an der x-Koordinate 83 und an der y-Koordinate 50 setzen. Gehen wir nun 
anhand der obigen Ausführungen vor. 83 geteilt durch 8 ergibt 10,375.  Wir vernachlässigen die 
Nachkommastellen, d.h. wir erhalten den Wert 10. Jetzt wissen wir, daß wir in das 10. Byte in der 
noch zu ermittelnden Bildschirmzeile einen Wert schreiben müssen. Jetzt aber welchen Wert? Wir 
multiplizieren 10 wieder mit 8 und erhalten 80. Dieser Wert stellt die x-Koordinate des 10. Bytes dar, 
da 1 Byte 8 Bit bzw. hier Pixel hat. Jetzt ziehen wir 83 von 80 ab und erhalten als Ergebnis 3. Diese 3 
sagt uns, wir müssen das 3. Bit von links setzen. Welchen Wert haben aber die einzelnen Bits? 
Anhand einer Tabelle ermitteln wir nun den Wert, den wir in das Bildschirm-Ram schreiben müssen. 
Die Tabelle lautet 128,64,32,16,8,4,2,1. Der 3. Wert von links ist folglich 32. Jetzt haben wir den 
Wert, aber uns fehlt noch die richtige Bildschirmzeile. Deren Adresse wird in unserem Beispiel 
ermittelt, indem wir y-Koordinate 50 mit 32 multiplizieren, da eine Bildschirmzeile 32 Bytes breit 
ist (32*8 Pixel=256 Pixel pro Bildzeile). 50*32 ergibt 1600, d.h. wir müssen 1600 Bytes zu der 
Anfangsadresse des Bildschirm-Rams dazuaddieren. Zu dieser Adresse, die ja die Anfangsadresse 
der 50. Zeile ist, zählen wir noch die oben ermittelten 10 dazu und haben die gesuchte Adresse. In 
diese Adresse schreiben wir den Wert 32 und sofort erscheint unser Pixel an der Koordinate 83,50. 
Da aber Multiplikationen in Assembler recht langsam und kompliziert sind, könnte man doch schon 
vorher die Anfangsadressen jeder Bildschirmzeile in einer Tabelle ablegen, getrennt nach Low- und 
Hi-Byte (hier scrtabl,h).

Nun die alte Routine aus dem Jahre 1990:

CLC            ;2 Carry-Bit löschen wegen LSR+ASL
LDA XPOS    ;3 X-Koordinate
LSR            ;/2   ;2 durch 8 teilen (LSR)
LSR            ;/2   ;2 
LSR            ;/2   ;2
STA BYTE    ;MERKEN  ;3 jetzt hat man das gesuchte Byte
ASL            ;*2   ;2 im Screen-Ram. Dieses wird wieder
ASL            ;*2   ;2 mit 8 multipliziert (ASL)
ASL            ;*2   ;2
STA MERK    ;MERKEN  ;3
SEC            ;2 Carry-Bit setzten wegen SBC
LDA XPOS    ;3 Xpos-Byte=Nr. des Pixels
SBC MERK    ;3
TAX               ;2 Nr. ins X-Register als Offset 
LDA PIXTAB,X      ;4 Wert aus der Tabelle holen
STA PIXEL      ;3
LDX YPOS ;Y-KOORDINATE  ;3
LDA SCRTABL,X  ;BILDSCHIRMADRESSE AUS TABELLE   ;4
STA V0         ;3
LDA SCRTABH,X  ;4
STA V0+1       ;3
LDY BYTE ;OFFSET FÜR ZEILE ;3
LDA (V0),Y  ;WERT AUS BILDSCHIRM-RAM HOLEN;5
ORA PIXEL   ;UND MIT PIXEL VERKNÜPFEN  ;3
STA (V0),Y  ;WIEDER INS RAM ZURÜCK  ;6
RTS            ;6
            SUMME TAKTZYKLEN  ;80

PIXTAB DFB $80,$40,$20,$10,$08,$04,$02,$01

Zur Erinnerung: Ein Byte hat 8 Bit (kein Scherz!!!):
Jedes Bit representiert ein sichtbares Pixel.

Dual        Hexadezimal

%00000000   ;$00
%10000000   ;$80
%00010000   ;$10
%10000001   ;$81

Pixtab enthält also die Werte, die in den Bildschirm geschrieben werden müssen, damit bestimmte 
Pixel gesetzt werden.

Kurz nochmal der Aufbau des Bildschirmrams in Gr.8:

Anfangsadressen der Bildschirmzeilen werden in einer Tabelle abgelegt 

y-Wert:        <--------- x-Wert --------> (32 Bytes=256 Pixel)

1. Zeile:$3000 00 00 00 00 00 00 00 00 00 00 00 00 00 ...
2. Zeile:$3020
3. Zeile:$3040
4. Zeile:$3060
...
Man könnte nun statt jedesmal diese arithmetischen Operationen (asl+lsr) und die Pixelermittlung 
neu zu berechnen, diese schon vorab in einer Tabelle für jede mögliche x-Koordinate durchführen 
und in Tabellen ablegen. Es genügt somit anhand der x-Koordinate den jeweiligen Wert für den 
Zeilenoffset und das Pixel aus den Tabellen zu holen. Dies kostet zwar Speicherplatz, aber es läßt 
sich einiges an Rechenzeit einspaaren.

So sieht die neue Routine '95 aus:

init  jsr tabinit ;vorher natürlich die Tabellen berechnen
...
plot  ldx xpos    ;Koordinaten stehen in xpos,ypos ;3
      lda bytetab,x     ;in welches Byte muß Pixel       ;4
      sta byte          ;merken           ;3
      lda pixtab,x      ;welches Pixel setzen         ;4
      sta pixel         ;merken           ;3
      ldx ypos                ;3
      lda scrtabl,x     ;Screenadresse aus tabelle       ;4
      sta v0            ;low-byte            ;3
      lda scrtabh,x              ;4
      sta v0+1          ;hi-byte          ;3
      ldy byte                ;3
      lda (v0),y              ;5
      ora pixel                  ;3
      sta (v0),y  ;ab damit ins screen-ram         ;6
      rts                  ;das war's           ;6

            SUMME  TAKTZYKLEN ;57

tabinit  ldx #0   ;Hier werden die Tabellen vorbereitet
      lda #0   ;  aus Sicherheitsgründen alles auf
l2   sta scrtabl,x   ;0 setzen (Ich trau dem Entpacker nicht)
      sta scrtabh,x
      sta bytetab,x
      sta pixtab,x
      inx      ;256 mal
      bne l2

      lda #scradr.l     ;Screen-adresse für
      sta v0            ;jede Zeile in die
      lda #scradr.h     ;Tabelle scrtabl,h
      sta v0+1          ;speichern, damit
      ldx #0            ;der Plot schneller
l3    lda v0            ;ist.
      sta scrtabl,x  ;In dieser Tabelle stehen die
      sta v0+1    ;Anfangsadressen der Bildschirmzeilen
      sta scrtabh,x  ;getrennt in Low- und Hibyte
      clc
      lda v0
      adc #32           ;Zeilen-Offset (32 Bytes pro Zeile)
      sta v0
      lda v0+1
      adc #0
      sta v0+1
      inx      ;für 256 Zeilen, (dargestellt werden nur 128)
      bne l3

      ldx #0            ;Byte Tabelle vorbereiten
l4    txa               ;für jede x-position.
      clc               ;Carry-Bit löschen
      lsr a             ;Xpos/8 ergibt
      lsr a             ;Spalten-offset
      lsr a             ;--> 3 mal nach rechts schieben
      sta bytetab,x   ;In welchem Byte Pixel zu setzen ist
      inx               ;bis xpos=255
      bne l4

      ldx #0            ;Pixel-Werte vorbereiten
l5    lda bytetab,x  ;diese werden direkt (später durch Plot)
      clc               ;in den Bildschirm geschrieben
      asl a             ;*2   Bytewert*8
      asl a             ;*2
      asl a             ;*2
      sta byte
      sec               ;Subtraktion
      txa               ;Xpos-Bytepos=Pixelnr.
      sbc byte
      tay               ;merken in y-register
      lda pixwert,y     ;Pixel-Wert
      sta pixtab,x      ;in Tabelle
      inx
      bne l5
      rts

pixwert DFB 128,64,32,16,8,4,2,1

Wie man aus der Summe der Taktzyklen erkennen kann, ist die zweite Routine schneller, was zur 
Folge hat, daß mehr Pixel pro VBL dargestellt werden können, ca. 35% mehr. Es lassen sich weitere 
Geschwindigkeitsoptimierungen vornehmen, wie z.B. statt STA (V0),y könnte man die Werte direkt 
in den Code statt in V0 schreiben.

Diese Routine setzt jetzt Pixels an jeder beliebigen Koordinate. Eine Tabelle mit den fallenden 
Y-Werten wurde auch schon berechnet.

Ablaufen soll der Effekt folgendermaßen:
 
Zufällig wird ein Pixel in der ersten Zeile gesetzt. Danach wird die Y-Positionen jede 1/50 Sekunde 
verändert, indem die Routine den neuen Y-Wert aus der Tabelle holt. Das alte Pixel wird gelöscht. 
Das Löschen kann durch die gleiche Routine erreicht werden, man verwendet statt "ora pixel" eben 
"and pixel" und eine andere Tabelle für die Pixelwerte. Sie enthält die Werte zum Ausmaskieren von 
Bits.
Die Plot-Routine soll erstmal mit einem Pixel laufen, wenn dies klappt wird sie ausgedehnt auf max. 
255 Pixel. Im Demo steigt die Zahl der fallenden Pixel auf 96 kontinuierlich.

Hier die kleine Routine für ein Pixel:


;fallende Pixel Entwicklungstext
;(c) 02.05.95 

phase = Variable, die angibt, was mit dem Pixel gerade geschieht.

Phase = 0 : Zufällige X-Position ermitteln (0-255) mit 'LDA 53770'

Phase = 1 : Zähler auf 0 setzen, Phase auf 2 setzen

Phase = 2 : Zähler ist Offset für die Tabelle mit den Y-Werten
In dieser Phase wird das Pixel jeden VBL bewegt bis Pixel aus dem Bildschirm 
"fällt". Zähler wird jeden VBL um 1 erhöht.
                     ...
                     lda #0
                     sta zaehler
                     lda 53770      ;Zufallszahl holen
                     sta xpos
loop        ldx zaehler
                     lda ypostab,x  ;Werte aus Tabelle holen
         sta ypos       ;xpos ist bereits gesetzt
                     jsr plot       ;Punkt setzen
                     inc zaehler ;Zähler erhöhen
                     lda zaehler
                     beq exit       ;zaehler=0 (=255)?
                     ...
               exit  lda #0
                     sta phase      ;neue Phase
                     rts

Diese kleine Routine gilt nur für 1 Pixel. Erweiterbar ist sie auf max. 256,indem man eine Zähl-, 
Xpos- und Phasentabelle einführt (für jedes Pixel). Statt "lda zaehler" nun "lda zaehltab,x" usw.

Jetzt hat man den Grundstock für eine Demo. Auf der Magazindiskette ist ein Beispiel-Source-Code, 
bei dem zufällig die Pixel herunterfallen.

HeAvEn, 10.06.96

published in Abbuc Magazine #42

nadkar@fh-pforzheim.de