home *** CD-ROM | disk | FTP | other *** search
- A S S E M B L E R - K U R S (c) Jeff Kandle 1991
-
- 32.Teil...
-
- Mahlzeit, Leuts...
- Wollen wir mal die in den letzten paar Teilen vorgekommenen
- Programmierkniffe anwenden, und eine in einem fruehere Kursteil vorgekommene
- Routine ansehen, und verstehen.
- Es handelt sich um eine Punkt Setz/Loesch-routine, die den Punkt anhand der
- X und Y Koordinate, und der Playfieldbase setzt.
- Ich habe die Routine damals einfach so reingesetzt, ohne ihr besonders viel
- beachtung zu schenken. Das hat sich aber jetzt etwas geaendert. Ich habe
- die letzten paar Tage an einem Dots(Punkte) Demo gearbeitet und da ist mir
- diese Routine wieder eingefallen die ich damals mal irgendwo abgetippt
- hatte.
- Frueher war sehr viel noetig um ein Bit zu setzen, ich meine frueher auf
- dem 64er. Naja, viel auch nicht, aber mit dem 68000 ist halt alles
- einfacher, und der Bset oder Bclr-befehl nimmt uns mehrere Logische
- Operationen ab.
- Also, ueberlegen wir uns mal was alles fuer das setzen eines Punktes mit
- uebergabe der X und Y Koordinate noetig ist.
-
- Als erstes kommt da erstmal die X-Koordinate. Wir muessen dort erstmal die
- Anzahl der Bytes errechnen die wir ueberbruecken koennen. Mit Words waere
- das natuerlich einfacher, aber der Bset/clr Befehl kann im normalen
- Speicher nur Bytemaessig setzen und loeschen, also rechnen wir das aus.
- Normalerweise, wuerde man jetzt den Divs oder Divu-Befehl benutzen, weil er
- halt einfach teilt. Die letzten Teile des Kurses haben aber genau davon
- abgeraten, weil er ja so langsam ist. Also, shiften wir das Wort in D0
- dreimal nach rechts, was ja /8 entspricht. So, jetzt haben wir ja die
- Anzahl der Bytes, vom Linken Rand des Ausgabe Fensters, die wir einfach zur
- Byteanzahl die sich aus
- Y-Koordinate * (Bytes pro Zeile) + Playfieldbase
- errechnet.
- Dann haben wir das genaue Byte in den die Aktion stattfinden soll.
- Aber, wie kommen wir an das zu setzende Bit in dem Byte.
- Wieder durch 8 Teilen ?. Solange 8 abziehen bis ein wert >8 rauskommt. Das
- dauert viel zu lange. Man benutzt einfach am anfang den Divu befehl, denn
- er teilt und gibt das ergebnis und den Rest aus. Der rest steht dann im
- oberen Wort des Ergebnisses. Da der Rest aber die anzahl der Bits vom
- linken Byterand angeben wuerde, und der Bset/Bclr Befehl aber die anzahl
- der Bytes von rechten Byterand braucht, muessen wir das ergebnis noch von
- -1 abziehen, und wir haben das zusetzende Bit ausgerechnet.
- Damit haben wir dann auch die Nummer des Bits errechnet. Zusammen mit der
- Playfield_Base und den zu addierenden Werte aus X und Y Koordinate koennen
- wir den Punkt setzen/loeschen.
-
- Die fertige Routine hat allerdings noch ein kleines Schmankerl, wie es nur
- von sehr wenigen Programmierern genutzt wird, naemlich selbstmodifikation
- des Programms. Was nichts anderes heisst als wie das sich das Programm
- selber umschreiben kann. Im Programm wird das so genutzt, das wenn es von
- Anfang an ab dem Label `Clear` gestartet wird, es nur den Bset Befehl am
- ende des Programmes in eine Bclr Befehl umwandelt, die berechnung bleibt
- dieselbe. Am Ende des Programms wir der Bclr-befehl dann wieder in Bset
- umgewandelt. Beim Aufruf ab `Set` wird einfach alles beim alten gelassen.
-
- Hier mal die Routine, aber Dokumentiert...
-
- Clear: Move.b #$B5,Label+1 ; Aendert Bset in Bclr
- Set: Divu #8,D0 ; Teilt durch 8, um Byteanzanzahl zu
- ; erhalten - Rest im oberen Word
- Mulu #40,D1 ; Y-Koordinate * Bytes pro zeile
- Add.w D0,D1 ; Bytes fuer X plus Y Bytes
- Swap D0 ; holt oberes Wort nach vorne,
- Moveq #-1,D2 ; um es von -1 in D2 abzuziehen
- Sub.b D0,D2
- Label: Bset D2,(A5,D1) ; Zu setzendes Bit in D2 vermerkt, setzt
- ; Bit in Adresse die sich aus Playfieldbase
- ; in A5 und +(Bytes) in D1 zusammensetzt
- Move.b #$F5,Label+1 ; setzt eventl. veraenderung durch die
- ; selbstmodifikation zurueck
- Rts
-
- Natuerlich sollte, wenn die Routine fuer einen Dots-Effekt benutzt wird,
- der Teil fuer die Selbstmodifaktion geloescht werden, da man den Bildschirm
- ja sowieso mit dem Blitter loescht. Desweiteren, sollte man die Mulu
- Funktion durch eine Tabelle ersetzen, aus der man die Werte die fuer eine
- bestimmt Y-Position uebernehmen kann, ersetzt werden. Den Divu befehl
- sollte man lassen, da das ersetzen durch schnellere Befehle nichts bringt,
- im gegentum, es ist die schnellste loesung die mir im moment einfaellt.
-
- Ich schaetze das es sehr viel schneller nicht mehr geht so etwas zu
- berechnen. Schneller kann man nur noch werden, wenn man den Gedanken mit
- der X und Y Koordinate fallen laesst, und fuer den Y Wert schon die
- Komplette Byteanzahl in der tabelle hat, und somit das ausrechnen durch
- Mulu, oder das auslesen der Tabelle von der ich sprach wegfaellt.
-
- Mit dieser Routine, wie sie dort steht schafft man ohne Double-Buffering
- (dazu Spaeter mehr) knapp 400 Punkte mit Bewegung und Loeschen durch den
- Blitter. Dabei sollte das Rotieren der Koordinaten und das loeschen des
- Bildschirmausschnitts im VBI gestartet werden. Die Punktsetz-Routine sollte
- dann sofort unter dem VBI beginnen, wobei man daran denken muss, das sich
- darstellung und bearbeitung nicht ueberschneiden, sonst bekomt man nicht so
- gute ergebnisse.
- Die 400 Punkte koennen natuerlich auch nicht auf dem ganzen Bildschirm
- verteilt sein, mit einem 64 * 64 Feld kann man auch schon ganz schoene
- Effekte erzielen. Alles was groesser wird geht auf kosten der Dots anzahl
- pro Zentimeter auf dem Bildschirm. Natuerlich sieht ein 64*64 Sinus mit 3
- Punkten pro Zentimeter besser aus als einen mit nur 1. Grosse Sinuskurven,
- sind mit 3 Dots/cm gar nicht realisierbar, jedenfalls nicht mit unseren
- mitteln, aber sind sehen auch bei 1Dot/cm, noch sehr gut aus.
-
- Also, macht euch ein kleine Sinustabelle, und lasst die Routine drueber
- laufen, und durch veraenderung einige Parameter im auslesen lassen sich
- schoene Effekte erzielen.
-
- Allerdings ist die Zeit die man fuer die Punkte braucht bei der selben
- anzahl Punkte immer dieselbe, so das man auch groessere Sinen ablaufen
- lassen kann. Tja, da gibt es aber ein Problem, naemlich die Zeit.
- Wenn ich einen 64*64 Sinus als Kreis auf den Bildschirm bringe, und durch
- Rotation der Tabelle einen Effekt zaubere, dann darf ich in dem Bereich wo
- die Punkte sind nichts machen. Ich darf den Blitter nicht loeschen lassen,
- ich darf die Punktesetzroutine nicht laufen lassen und das Rotieren der
- Tabelle geht auch nicht, da alles sichtbar waere, weil die veraenderungen
- ja sofort auf dem Bildschirm zu sehen waeren.
- Also kommen wir zum oben erwaehnten Doublebuffering.
- Die Technik ist folgende: Das erste Bild wird vor dem Start der
- Endlosroutine ausgerechnet. Es liegt z.B. bei $30000 Der Rasterstrahl baut
- dieses Bild auf. Gleichzeitig arbeitet der Prozessor und der Blitter an dem
- zweiten Bild, welches bei z.B $40000 liegt. Sobald der Amiga mit der
- darstellung des ersten Bildes fertig ist, setzt man die Bitplanepointer
- fuer den naechsten durchlauf auf die Plane bei $40000. Wenn diese
- dargestellt wir koennen wir die alte bei $30000 loeschen, und die neuen
- Punkte setzen. Dann geht wieder alles von vorne los. Somit haben wir den
- Kompletten Bildschirm zeit fuer den Aufbau des Bildschirm, und muessen
- nicht auf ueberschneidungen mit dem Rasterstrahl achten. Das laeuft ganz
- gut, solange man nicht den ganzen Bildschirm fuer Dots benutzt. Sobald das
- aber gemacht wird, muessen wir diese Technik noch eine Stufe weitertreiben.
- Treblebuffering - Waehrend Bild A angezeigt wird, instruiert der Prozessor
- den Blitter Bild B zu loeschen und baut Bild C, waehrend der Blitter
- arbeitet, auf.
- Ich schaetze ihr koennt das selber realisieren, und werde deshalb dazu kein
- Programm liefern. Allerdings ein kleine Dots Routine werde ich mal
- dabeipacken. An ihr koennt ihr dann schon mal sehen, wie ich die Routine
- eingebaut habe, und wie man Zeit spart. Ich habe die einzelen Aktionen
- farblich auf dem Bildschirm gekennzeichnet.
-
- Rot - Blitter loescht altes Bild
- Gruen- Prozessor baut neues Bild auf
- Gelb - Tabelle wird rotiert
-
- Baut mal die von mir angeprochenen verbesserungen ein, und versucht die
- Zeit auf ein Minimun zu reduzieren.
-
- Start:
- Execbase= 4
- Openlibrary= -408
- Vhposr= $dff006
- Forbid= -30-102
- Permit= -30-108
- Dmacon= $dff096
- Intena= $dff09a
- Dmaconr= $dff002
- Bltdmod= $dff066
- Bltafwm= $dff044
- Bltcon0= $dff040
- Bltcon1= $dff042
- Bltdpt= $dff054
- Bltapt= $dff050
- Bltsize= $dff058
-
-
- Move.w #$0020,dmacon
- Move.w #$4000,intena
- Move.l execbase,a6
- Jsr forbid(a6)
- Bsr.l makecl
- Bsr.l clearscreen
- Bsr.l kreis
- Wait: Cmpi.b #$72,$dff006
- Bne.s wait
- Move.w #$0400,$dff180
- Bsr.l blitclear
- Move.w #$0040,$dff180
- Bsr.l kreis
- Move.w #$0440,$dff180
- Bsr.l rotate
- Move.w #$0000,$dff180
- Maus: Btst #6,$bfe001
- Bne wait
- Move.l execbase,a6
- Jsr permit(a6)
- Lea gfxname(pc),a1
- Jsr openlibrary(a6)
- Move.l d0,a6
- Move.w #$83e0,dmacon
- Move.w #$c000,intena
- Move.l 38(a6),$dff080
- Moveq #0,d0
- Rts
- Makecl:
- Lea $07f000,a0
- Move.l a0,$dff080
- Move.l #$008e3081,(a0)+
- Move.l #$009030c1,(a0)+
- Move.l #$00920038,(a0)+
- Move.l #$009400d0,(a0)+
- Move.l #$01001200,(a0)+
- Move.l #$00e00003,(a0)+
- Move.l #$00e20000,(a0)+
- Move.l #$01080000,(a0)+
- Move.l #$01800000,(a0)+
- Move.l #$01820fb0,(a0)+
- Move.l #$fffffffe,(a0)+
- Rts
- Set:
- Divu #8,d0
- Mulu #40,d1
- Add.w d0,d1
- Swap d0
- Move.b #-1,d2
- Sub.b d0,d2
- Bset d2,(a5,d1)
- Rts
- Kreis:
- Move.w #238,d3
- Lea sinus,a0
- Lea sinus+120,a1
- Lea $3000e,a5
- Move.w (a0)+,d0
- Addq #6,a0
- Move.w (a1)+,d1
- Addq #4,a1
- Bsr.s set
- Moveq #0,d0
- Moveq #0,d1
- Dbf d3,loop
- Rts
- Rotate:
- Lea Sinus,a0
- Move.l a0,a1
- Add.l #8,a1
- Move.w #476,d0
- Move.l (a0),a2
- Move.l 4(a0),a3
- Roloop:
- Move.l (a1)+,(a0)+
- Dbf d0,roloop
- Move.l a2,(a0)
- Move.l a3,4(a0)
- Rts
- Sinus:
- Dc.w $0020,$0020,$0021,$0022,$0023,$0023,$0024,$0025
- Dc.w $0026,$0027,$0027,$0028,$0029,$002A,$002A,$002B
- Dc.w $002C,$002C,$002D,$002E,$002F,$002F,$0030,$0031
- Dc.w $0031,$0032,$0033,$0033,$0034,$0034,$0035,$0036
- Dc.w $0036,$0037,$0037,$0038,$0038,$0039,$0039,$003A
- Dc.w $003A,$003B,$003B,$003B,$003C,$003C,$003C,$003D
- Dc.w $003D,$003D,$003E,$003E,$003E,$003E,$003F,$003F
- Dc.w $003F,$003F,$003F,$003F,$003F,$003F,$003F,$003F
- Dc.w $003F,$003F,$003F,$003E,$003E,$003E,$003E,$003D
- Dc.w $003D,$003D,$003C,$003C,$003C,$003B,$003B,$003A
- Dc.w $003A,$003A,$0039,$0039,$0038,$0038,$0037,$0037
- Dc.w $0036,$0035,$0035,$0034,$0034,$0033,$0032,$0032
- Dc.w $0031,$0030,$0030,$002F,$002E,$002E,$002D,$002C
- Dc.w $002C,$002B,$002A,$0029,$0029,$0028,$0027,$0026
- Dc.w $0026,$0025,$0024,$0023,$0022,$0022,$0021,$0020
- Dc.w $0020,$0020,$001F,$001E,$001D,$001C,$001C,$001B
- Dc.w $001A,$0019,$0019,$0018,$0017,$0016,$0016,$0015
- Dc.w $0014,$0013,$0013,$0012,$0011,$0011,$0010,$000F
- Dc.w $000F,$000E,$000D,$000D,$000C,$000B,$000B,$000A
- Dc.w $000A,$0009,$0009,$0008,$0008,$0007,$0007,$0006
- Dc.w $0006,$0005,$0005,$0005,$0004,$0004,$0003,$0003
- Dc.w $0003,$0003,$0002,$0002,$0002,$0002,$0001,$0001
- Dc.w $0001,$0001,$0001,$0001,$0001,$0001,$0001,$0001
- Dc.w $0001,$0001,$0002,$0002,$0002,$0002,$0002,$0003
- Dc.w $0003,$0003,$0004,$0004,$0004,$0005,$0005,$0006
- Dc.w $0006,$0007,$0007,$0007,$0008,$0008,$0009,$000A
- Dc.w $000A,$000B,$000B,$000C,$000C,$000D,$000E,$000E
- Dc.w $000F,$0010,$0010,$0011,$0012,$0012,$0013,$0014
- Dc.w $0015,$0015,$0016,$0017,$0018,$0018,$0019,$001A
- Dc.w $001B,$001B,$001C,$001D,$001E,$001F,$001F,$0020
- Dc.w $0020,$0021,$0021,$0022,$0023,$0024,$0025,$0025
- Dc.w $0026,$0027,$0028,$0028,$0029,$002A,$002B,$002B
- Dc.w $002C,$002D,$002E,$002E,$002F,$0030,$0030,$0031
- Dc.w $0032,$0032,$0033,$0034,$0034,$0035,$0035,$0036
- Dc.w $0036,$0037,$0038,$0038,$0039,$0039,$0039,$003A
- Dc.w $003A,$003B,$003B,$003C,$003C,$003C,$003D,$003D
- Dc.w $003D,$003E,$003E,$003E,$003E,$003E,$003F,$003F
- Dc.w $003F,$003F,$003F,$003F,$003F,$003F,$003F,$003F
- Dc.w $003F,$003F,$003E,$003E,$003E,$003E,$003D,$003D
- Dc.w $003D,$003D,$003C,$003C,$003B,$003B,$003B,$003A
- Dc.w $003A,$0039,$0039,$0038,$0038,$0037,$0037,$0036
- Dc.w $0036,$0035,$0035,$0034,$0033,$0033,$0032,$0031
- Dc.w $0031,$0030,$002F,$002F,$002E,$002D,$002D,$002C
- Dc.w $002B,$002A,$002A,$0029,$0028,$0027,$0027,$0026
- Dc.w $0025,$0024,$0024,$0023,$0022,$0021,$0020,$0020
- Dc.w $0020,$001F,$001E,$001E,$001D,$001C,$001B,$001A
- Dc.w $001A,$0019,$0018,$0017,$0017,$0016,$0015,$0014
- Dc.w $0014,$0013,$0012,$0012,$0011,$0010,$0010,$000F
- Dc.w $000E,$000E,$000D,$000C,$000C,$000B,$000B,$000A
- Dc.w $0009,$0009,$0008,$0008,$0007,$0007,$0006,$0006
- Dc.w $0006,$0005,$0005,$0004,$0004,$0004,$0003,$0003
- Dc.w $0003,$0002,$0002,$0002,$0002,$0001,$0001,$0001
- Dc.w $0001,$0001,$0001,$0001,$0001,$0001,$0001,$0001
- Dc.w $0001,$0001,$0002,$0002,$0002,$0002,$0003,$0003
- Dc.w $0003,$0004,$0004,$0004,$0005,$0005,$0005,$0006
- Dc.w $0006,$0007,$0007,$0008,$0008,$0009,$0009,$000A
- Dc.w $000A,$000B,$000C,$000C,$000D,$000D,$000E,$000F
- Dc.w $000F,$0010,$0011,$0011,$0012,$0013,$0014,$0014
- Dc.w $0015,$0016,$0016,$0017,$0018,$0019,$0019,$001A
- Dc.w $001B,$001C,$001D,$001D,$001E,$001F,$0020,$0020
- Dc.w $0020,$0020,$0021,$0022,$0023,$0023,$0024,$0025
- Dc.w $0026,$0027,$0027,$0028,$0029,$002A,$002A,$002B
- Dc.w $002C,$002C,$002D,$002E,$002F,$002F,$0030,$0031
- Dc.w $0031,$0032,$0033,$0033,$0034,$0034,$0035,$0036
- Dc.w $0036,$0037,$0037,$0038,$0038,$0039,$0039,$003A
- Dc.w $003A,$003B,$003B,$003B,$003C,$003C,$003C,$003D
- Dc.w $003D,$003D,$003E,$003E,$003E,$003E,$003F,$003F
- Dc.w $003F,$003F,$003F,$003F,$003F,$003F,$003F,$003F
- Dc.w $003F,$003F,$003F,$003E,$003E,$003E,$003E,$003D
- Dc.w $003D,$003D,$003C,$003C,$003C,$003B,$003B,$003A
- Dc.w $003A,$003A,$0039,$0039,$0038,$0038,$0037,$0037
- Dc.w $0036,$0035,$0035,$0034,$0034,$0033,$0032,$0032
- Dc.w $0031,$0030,$0030,$002F,$002E,$002E,$002D,$002C
- Dc.w $002C,$002B,$002A,$0029,$0029,$0028,$0027,$0026
- Dc.w $0026,$0025,$0024,$0023,$0022,$0022,$0021,$0020
- Dc.w $0020,$0020,$001F,$001E,$001D,$001C,$001C,$001B
- Dc.w $001A,$0019,$0019,$0018,$0017,$0016,$0016,$0015
- Dc.w $0014,$0013,$0013,$0012,$0011,$0011,$0010,$000F
- Dc.w $000F,$000E,$000D,$000D,$000C,$000B,$000B,$000A
- Dc.w $000A,$0009,$0009,$0008,$0008,$0007,$0007,$0006
- Dc.w $0006,$0005,$0005,$0005,$0004,$0004,$0003,$0003
- Dc.w $0003,$0003,$0002,$0002,$0002,$0002,$0001,$0001
- Dc.w $0001,$0001,$0001,$0001,$0001,$0001,$0001,$0001
- Dc.w $0001,$0001,$0002,$0002,$0002,$0002,$0002,$0003
- Dc.w $0003,$0003,$0004,$0004,$0004,$0005,$0005,$0006
- Dc.w $0006,$0007,$0007,$0007,$0008,$0008,$0009,$000A
- Dc.w $000A,$000B,$000B,$000C,$000C,$000D,$000E,$000E
- Dc.w $000F,$0010,$0010,$0011,$0012,$0012,$0013,$0014
- Dc.w $0015,$0015,$0016,$0017,$0018,$0018,$0019,$001A
- Dc.w $001B,$001B,$001C,$001D,$001E,$001F,$001F,$0020
- Dc.w $0020,$0021,$0021,$0022,$0023,$0024,$0025,$0025
- Dc.w $0026,$0027,$0028,$0028,$0029,$002A,$002B,$002B
- Dc.w $002C,$002D,$002E,$002E,$002F,$0030,$0030,$0031
- Dc.w $0032,$0032,$0033,$0034,$0034,$0035,$0035,$0036
- Dc.w $0036,$0037,$0038,$0038,$0039,$0039,$0039,$003A
- Dc.w $003A,$003B,$003B,$003C,$003C,$003C,$003D,$003D
- Dc.w $003D,$003E,$003E,$003E,$003E,$003E,$003F,$003F
- Dc.w $003F,$003F,$003F,$003F,$003F,$003F,$003F,$003F
- Dc.w $003F,$003F,$003E,$003E,$003E,$003E,$003D,$003D
- Dc.w $003D,$003D,$003C,$003C,$003B,$003B,$003B,$003A
- Dc.w $003A,$0039,$0039,$0038,$0038,$0037,$0037,$0036
- Dc.w $0036,$0035,$0035,$0034,$0033,$0033,$0032,$0031
- Dc.w $0031,$0030,$002F,$002F,$002E,$002D,$002D,$002C
- Dc.w $002B,$002A,$002A,$0029,$0028,$0027,$0027,$0026
- Dc.w $0025,$0024,$0024,$0023,$0022,$0021,$0020,$0020
- Dc.w $0020,$001F,$001E,$001E,$001D,$001C,$001B,$001A
- Dc.w $001A,$0019,$0018,$0017,$0017,$0016,$0015,$0014
- Dc.w $0014,$0013,$0012,$0012,$0011,$0010,$0010,$000F
- Dc.w $000E,$000E,$000D,$000C,$000C,$000B,$000B,$000A
- Dc.w $0009,$0009,$0008,$0008,$0007,$0007,$0006,$0006
- Dc.w $0006,$0005,$0005,$0004,$0004,$0004,$0003,$0003
- Dc.w $0003,$0002,$0002,$0002,$0002,$0001,$0001,$0001
- Dc.w $0001,$0001,$0001,$0001,$0001,$0001,$0001,$0001
- Dc.w $0001,$0001,$0002,$0002,$0002,$0002,$0003,$0003
- Dc.w $0003,$0004,$0004,$0004,$0005,$0005,$0005,$0006
- Dc.w $0006,$0007,$0007,$0008,$0008,$0009,$0009,$000A
- Dc.w $000A,$000B,$000C,$000C,$000D,$000D,$000E,$000F
- Dc.w $000F,$0010,$0011,$0011,$0012,$0013,$0014,$0014
- Dc.w $0015,$0016,$0016,$0017,$0018,$0019,$0019,$001A
- Dc.w $001B,$001C,$001D,$001D,$001E,$001F,$0020,$0020
- Dc.w $20,$20,$20,$20,$20,$20,$20,$20
-
- Clearscreen:
- Move.w #10239/2,d0
- Lea $30000,a0
- Clloop:
- Clr.w (a0)+
- Dbf d0,clloop
- Rts
- Blitclear:
- Move.w #%0000000100000000,bltcon0
- Move.w #32,bltdmod
- Move.l #$3000e,bltdpt
- Move.w #$40*64+4,bltsize
- Blwait:
- Btst #14,Dmaconr
- Bne.s blwait
- Rts
-
- Gfxname: dc.b "graphics.library",0
-
- So, das war mal wieder genug fuer Heute...Wieder viel zu viel Source drin,
- aber das ist halt etwas handfestes..
-
- Jeff Kandle
-