A S S E M B L E R - K U R S (c) Jeff Kandle 1990 10.Teil... So, was wollten wir machen...achja das Schwingende Logo...mmmh, da habt ihr euch aber was vorgenommen. Es ist ganz im gegentum zu den anderen sache superleicht zu verstehen, allerdings mit der realisation ist es so eine sache, wir werden dazu Mininum 5 - 6 voellig neue Befehle, mit bisher noch nie dagewesener Funktion. Naemlich die Logischen Verknuepfungen, mit And und Oder, Not und Eor. Alles boemische Doerfer fuer euch, ich will ich allerdings jetzt noch nichts davon erzaehlen, denn ich will es so wie bisjetzt halten das ich den Neuen Befehl erst Benutze und dann erklaere was ich mit ihm gemacht habe. So versteht man sehr schnell. Oder versteht ihr jetzt schon was `Ausmaskieren des Oberen Kontrollwortes` heisst, seht ihr ! Also, los gehts !!! Ein teil des Problems koennen wir schon anhand des Kinoscrollers erklaeren. Man verstellt die Pointer beim Kinoteil immer um eine Zeile. Beim Titschenden Logo stellen wir die Pointer immer um die kleinste einheit die ein Wort betraegt, nach links oder rechts. Das in feinen abstaenden wird sogenanntes Hardscrolling ergeben. Das aller ding saehe mit verlaub `ein bisschen Scheisse` aus, deshalb benutzen wir ein wahrhaft fantastisches register..naemlich BPLCON1 = $DFF102. Ihr erinnert euch..mit BPLCON0 konnte man schon eine menge machen. Dieses register beherbergt neben anderen tollen sachen auch noch die Scrollwerte fuer die geraden und die ungerade planes, und mit diesen scrollwerten koennen wir die Planes 0 bis 15 Pixel nach rechts schieben, ist doch toll. So koennen wir durch geschicktes Kombinieren von Hard- und Softscrolling jede Position auf dem Bildschirm vom logo einnehmen lassen. Vergegenwaertigen wir uns mal wie das errechnen der hard- und softscrollwerte von statten gehen muesste. ...Wir schauen uns erstmal die Position an, an der das Teil Stehen soll. Dann versuchen wir mit hardscrolling so nah wie moeglich ranzukommen. So nah wie moeglich heisst, innerhalb der naechsten 15 Pixel. Dann stellen wir den rest noch mit den Scrollwerten fuer das Softscrolling ein. So einfach ist das. Mal konkret...Wir haben ein Normales Playfield wie wir es dauernd benutzen, mit den Massen 320*256. Die 256 wollen wir mal jetzt weglassen, wir gehen mal von einem Einzeilenlogo aus, welches genau ein Wort breit ist. Der Bildschirm hat 320 position, das entspricht 20 woertern a 16 Pixel. Wir wollen unser `Logo` an der position 78 darstellen. Jetzt kommt der Vorzug der hexdezimalen schriebweise. Bei dezimal muss man jetzt erst grossartig durch divideren herausfinden wieviel mal die 16 darin ist, dammit man die Hardscrollposition heraus findet, dann muesste mann das nochmal machen damit man den Genauen rest, zum einstellen des Softscrollings ermitteln. In Hexadezimaler darstellung heisst 78 aber $4e, und da haben wir alle beide positionen schon fertig. Man muss nur noch die 4 nehmen muss und als Hardscrollzeiger nehmen. Die softscrollpositioen habe wir automatisch in dem rest stehen, diese E bytes koennen wir direkt in das BPLCON1 register schreiben wo wir ja die Soften werte einstellen. So koennen wir relativ einfach eine bewegung erzeugen. Schrieben wir nun eine Routine, die Anhand dieses `Steuerwertes` die Position fuer das Logo errechnet. Der plane begin ist $40000, die Breite wie gehabt 320, das logo ist ein wort breit. Damit wir ohne groessere Multiplikationen auskommen muessen, benutzen wir einige neue Befehle. Fangen wir mal an ich erklaeren jetzt mal jeden einzelnen schritt. Der kontroll wert ist am anfang der Routine schon in D0....und es ist eben diese $4e von eben, so kann ich beschreiben was nach jedem Schritt passiert mit dem Kontrollwort. Move.w d0,d7 ; Erstmal sichern da zwei aktionen mit ; mit dem Kontrollwert gemacht werden. Divs #16,d0 ; Dividiert durch 16 ergibt 4, somit habe ; ich den wert fuer das Hardscrollregister. ; Da Hexadezimal alles abgerundet wird, ; weil es keine kommastellen gibt. Add.w d0,d0 ; Wert verdoppeln, da eine Position also ; ein wort ja Zwei Bytes in der Plane ; bedeuten. Move.l #$00040000,d1 ; Grundadresse der Bitplane setzen. Add.w d0,d1 ; Errechnete Position in der Bitplane ; zu der Grundadresse dazu addieren. So ; erhaelt man die endgueltige Position ! Move.l d1,Bpl1pt ; Und ab in den Bitplanepointer. So jetzt kommt der Teil mit dem Softscrolling... Move.w d7,d0 ; Wert neu nach D0 schreiben. Da wir die $4 vor dem E nicht brauchen koennen, muessen wir sie irgendwie loswerden. In unserem ganz speziellen fall koennten wir natuerlich -$40 schreiben, aber wenn andere wert auf kreuzen kommen wir nich an das gewuenschte Ziel oder wir schiessen in den Minus Bereich. Das wollen wir ja nicht. Also setzen wir dem Prozessor eine Augenklappe auf. Das ist natuerlich nur sinnbildlich zuverstehen. Aber es ist in der tat so das wir dem Prozessor die Bits Markieren die er sehen kann. Nach dem Prinzip koennten wir einfach dieses Kontroll wort nehmen, und dem Prozessor sagen das er nur die letzten 4 bits sehen kann. Denn die sind ja im endeffekt nur noch interresant fuer uns. Also wollen wir sehen wie man das macht. And.w #%0000000000001111,d0 Merke: Dieses And hat nichts mit der Addition von Zahlen zu tun, sondern es ist wie ein Filter. Das funktioniert so... Der Prozessor nimmt beide werte, und verknuepft sie miteinander. Das ergebnis haengt von der Funktion ab..Bei And ist das Ergebnis-Bit gesetzt wenn auch das Quell-Bit `UND` das Ziel Bit gesetzt sind. Bei unserem Beispiel koennen das nur die ersten 4 Bits sein. Jetzt mal Bildlich Quelle %0000000001001110 = $4e And %0000000000001111 = $0f ------------------------------------- Ziel %0000000000001110 = $0e Tolle sache ne.. Man koennte das And wort auch so sehen... And %------------```` Wobei - sperrt, und ` durchlaesst. Jetzt haben wir in D0 nur noch die SoftPosition stehen, und die koennen wir direkt ind das BPLCON1 register setzen.. Move.l d0,BPLCON1 Rts So, das war die Routine, sehr ausfuehrlich beschrieben oder ? Diese Routine koennte die Steuerung fuer dieses Einwort Logo uebernehmen. Allerdings nimmt man fuer Logo halt immer groessere Objekte. Und damit man die nicht jedesmal soo ein riesiges Paket Daten kopieren muss. Setzen wir einfach das Logo schon auf das Bild, Und verschieben nur noch das ganze bild. Ich will jetzt aber nicht wieder ein Listing hiereinpumpen sondern wir werden Horizontal und VertikalScrolling erstmal ruhen lassen um uns etwas anderem Widmen, naemlich... 13.Der Vertikal Blanking Interrupt Bevor ich mit den Groesseren Demoreifen sachen Anfangen solltet ihr diesen doch sehr Wichtigen teil des Amigas kennenlernen. Ich habe euch doch schon von dem Vertikal Blanking bereich erzaehlt. Das war doch der bereich der so gut fuer manipulationen an dem Bildschirm und an der Copperliste ist weil dort vom Amiga noch nichts gemacht wird und noch keine Copperliste Aktiv ist. Dieser VB bereich liegt zwischen 0 und $3f. Wir haben ihn bisjetzt ja immer mit unserer einfachen Warteschleife Wait: Cmpi.b #$00,VHposr Bne.s Wait abgefragt. Das ist Theoretisch richtig, aber der Computer macht dann alles Zweimal pro bildschirm aufbau. Denn die 0 tritt zweimal auf einmal bei $00 und einmal bei $100, denn die $1 vor den Nullen testen wir ja nicht, also passiert alles zweimal pro durchlauf. Verhindern koennten wir dies indem wir diese 1 auch noch abfragen. Die Routine dafuer lautet... Wait: move.l $dff004,d0 ; Rasterpos holen and.l #$1ff00,d0 ; alles unwichtige ausmaskieren cmp.l #$1000,d0 ; Zeile 16 ($10) erreicht ? bne.s Wait ; noe... Das waere die Abfrage fuer die Wirkliche Position $10. Allerdings ist das mit den Abfragen so eine Sache. Man kann ohne ihren Rythmus zu beeinflussen nicht allzuviel dazwischen setzen, und das ist bei manchen sache ja noetig. Stellen wir uns nur mal vor ihr bastelt ein Musik demo zusammen. Ihr habt 10 musikstuecke a 30 KB, und ihr habt eine normale Soundtrackerroutine. Diese muss in regelmaessigen Abstaenden, und zwar alle 50 stel Sekunde, aufgerufen werden. Der Bildschirm wird alle 50 stel sekunde aufgebaut, und den Anfang fragen wir ja ab. Wenn wir dann aber noch einbauen das er, damit es schnell geht, immer wenn die gewuenschte position noch nicht erreicht ist, mal schnell die tasten F1 bis F10 fuer die einzelnen musikstuecke abfragen, und falls eine gedrueckt war wird das Flag fuer die neue Musik gesetzt. So falls der Prozessor ganz knapp vor der Gewueschten Zeile abfragt kriegt er ja nur gesagt das sie es noch nicht ist. Er fragt dann wieder alles ab...Und solche sachen Koennen mitunter sehr lange dauern. Und dann faengt es an zu Flackern, dieses Flackern sieht man bei schlecht programmierten Intros und Demos. Und weil wir das nicht wollen, muessen wir uns etwas ausdenken oder etwas benutzen was ganz bestimmt diese Sachen die Flackern koennten zu einem ganz bestimmten Zeitpunkt durchfuehrt egal was passiert. Dazu muessen wir aber nichts neues programmieren sondern etwas vom Amiga benutzen, denn er hat die selben schwierigkeiten wie wir. Er behilft sich mit einem Interrupt, naemlich dem VBI, Vertikal Blanking Interrupt. Erst muss ich erklaeren was ueberhaupt ein Interrupt ist. Interrupt heisst abbrechen, wie bei Coitus Interruptus, was viele ja schon kennen duerften. Beim Computer ist es aber mehr eine Unterbrechung da die arbeit nach der unterbrechung wieder aufgenommen wird. Es ist ungefaehr wie wenn ihr jetzt diese Saetze lest und das Teflon bimmelt, ihr nehmt ab, Quatscht kurz oder lang, legt wieder auf, denkt nach wo ihr dran wart, und lest weiter. Nicht anderes macht ein Computer, sobald er das Signal `IRQ` kriegt macht er einen Generalinterrupt. Zuerst rettet er alle Arbeitsregisterinhalte D0-D7 und A0-A7, auf den Stack. Dann analysiert er was fuer ein Interrupt das war, das steht in einem ganz bestimmten register, dann springt er indirekt je nach Interruptart ueber einen ganz bestimmten Zeiger zum Programm das im Falle eines Interrupts ausgefuehrt werden soll. Es gibt alle moeglichen Interrupts, uns interresiert aber im Moment nur einer, halt der VBI, der Vertikal Blanking Interrupt. Er wird ausgeloest wenn der Computer beim Bildschirm aufbau auf diesen Bereich trifft. Nachdem der Prozessor weiss das es der VBI war, springt er in die Adresse die in $0000006c steht, und fuehrt das Programm aus was dort steht. Da liegt unsere Chance auf einen wirklich regelmaessigen Zeitpunkt zum ausfuehren unserer Routinen zu kommen. Wir muessen nur die alte adresse nehmen und irgend wo sichern, und dann unsere eigene hinschreiben. So einfach ist das. Natuerlich muessen wir vor verlassen des Intros oder der Routine den Alten VBI wieder aktivieren. Und ganz wichtig ist halt das wir den VBI nicht mit all dem anderen Interrupts ausschalten, dazu kommen wir noch. Wenn ich eine Ganz bestimmte Tabelle hier finde werde ich euch ein paar befehle geben die man nur waehrend eines Interrupts benutzen kann, warum ? ...Es gibt zwei modi in denen der Prozessor betrieben werden kann 1.User Modus 2.Supervisor Modus Wir arbeiteten jetzt immer nur im User modus, das wird auch im grossen und ganzen so bleiben, aber erstmal die erklaerung. Im Supervisor modus ist es als wenn ein Zweiter Prozessor arbeiten koennte, das ist noetig damit z.b Fehler noch fuer die Guru meldung analysiert werden kann. Sobald eine Exception (ausnahmesituation) auftritt, der Interupt gehoert auch dazu, wechselt der Prozessor in den Supervisor Modus. Dies ist auch gleichzeitig die Einzige moeglichkeit in diesen Zustand zu gelangen. Wir wollen aber nur wissen was das ist und deshalb werden wir auch nur indirekt in diesem Modus arbeiten. Wiegesagt es kommen ein paar befehle dazu, aber alle alten sind noch vorhanden. Sobald der Prozessor dann auf den Rueckkehr-befehl trifft, holt er die alten Daten vom Stapel und macht weiter als waere nichts geschehen. Dieser Rueckkehr Befehl heisst `RTE` Return from Exception. Der Vorteil liegt klar auf der Hand..wir initialisieren einmal diesen Interrupt, und koennen ein Endlosschleife gemuetlich auf alle moeglichen sachen warten lassen. Wir koennen Tausende Tasten abfragen, neue Flags fuer die Musiken setzen, der Prozessor unterbricht uns dann zwar immer, aber das ist ja das was wir wollen, das die Routine die Zeitkritisch sind immer zu einem Ganz bestimmten Zeitpunkt abgearbeitet wird. Verloren geht uns auch nichts, weil ja alle sachen die wichtig sind vor der eigentlichen Routine gerettet werden. ein kleines Beispiel fuer die Noetigen sachen fuer den VBI....Die ernsthafte anwendung folgt spaeter. Zuerst alle Interrupts loeschen. Move.w #$7fff,intena Dann alten interupt wert an einer bestimmten stelle im Source retten... Move.l #$006c.w,Oldirq Und nun den neuen wert schrieben.. Move.l #Newirq,$006c.w Nun koennen wir den VBI anschalten.. Move.w #$c020,Intena und unser programm irgendwas machen lassen...Wichtig ist nur das das Programm mit dem Label `Newirq` steht, es wird direkt beim naechsten VBI abgearbeitet. Newirq: blabla #55,97 Blablabla soundso und am enden der Routine muss dann dieses Rte stehen damit der Prozessor wieder an unserem normalen programm arbeiten kann. So einfach ist das. Arbeiten werden wir allerdings erst ein bisschen spaeter damit. Da ich jetzt erstmal ein paar Effekte Programmieren muss, damit ich die euch praesentieren kann, es koennte also drei vier Tage dauern bis ich mich wieder melden. Vergesst mich nicht Jeff Kandle