home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / assembler-kurs / lektionen / lektion3.txt < prev    next >
Text File  |  1977-12-31  |  26KB  |  542 lines

  1.  
  2.  ASSEMBLERKURS - LEKTION 3
  3.  
  4. Nun fahren wir mit der Praxis fort, ich rate euch vorher  aber,  68000.TXT
  5. in  einen  Textbuffer  zu  laden,  es  ist  eine  Art  Zusammenfassung von
  6. Lektion2. Diese wird euch nützlich sein, wenn  ihr  eine  Adressierungsart
  7. vergessen habt oder mit einem Befehl nichts mehr anzufangen wißt, da diese
  8. Lektion eine gewisse Vertrautheit mit ihnen voraussetzt.  In  diesem  Text
  9. sind alle Adressierungen erklärt, auch jene, die nur sehr selten verwendet
  10. werden, deswegen lest ihn aber sorgt euch nicht,  wenn  ihr  einige  Dinge
  11. nicht versteht, wie z.B. die Adressierung mit INDEX, denn in Lektion3 wird
  12. sie noch nicht verwendet!
  13.  
  14. In  diesem  Kapitel  beginnen  wir  damit,  etwas   auf   dem   Bildschirm
  15. darzustellen: um  das  zu erreichen, müssen wir eine COPPERLIST schreiben,
  16. das ist ein Programm für  den  COPPER-Chip,  dem  Typen,  der  dir  Grafik
  17. steuert, wir haben ihn bereits verwendet, um die Bildschirmfarbe zu ändern
  18. ($dff180 ist ein Register des Copper, das COLOR0 heißt).  Bis  jetzt  aber
  19. haben  wir die Register nur direkt mittels Prozessor angesprochen, und wie
  20. ihr beim Debuggen der  Listings  bemerkt  haben  werdet,  sind  nur  kurze
  21. "Lichtblitze"  in  der  Farbe aufgetreten, die wir hineinschrieben, sofort
  22. aber ersetzte die Farbe des  Betriebssystemes,  oder  des  ASMONE,  unsere
  23. eigene.  Nur  in einer Schleife, bei der dauernd eine Zahl in das Register
  24. geschieben wurde, schafften wir es, den ganzen Bildschirm zu färben, aber,
  25. kaum  aus  dem Programm ausgestieben, kehrt erbarmungslos der alte Zustand
  26. zurück. Das  ist  darauf  zurückzuführen,  daß  alles,  was  wir  auf  dem
  27. Bildschirm  sehen  -  Fenster,  Schriften  und der Rest - ist das Ergebnis
  28. einer  COPPERLIST,  genauer  einer  SYSTEM-COPPERLIST.  Diese  ist  nichts
  29. anderes als eine Art:
  30.  
  31.     MOVE.W    #$123,dff180    ; COLOR0 - Beschreibe Farbe 0
  32.     MOVE.W    #$456,dff182    ; COLOR1 - Beschreibe Farbe 1
  33.     etc....
  34.  
  35. Diese wird dauernd ausgeführt, und hier liegt auch  die  Erklärung,  warum
  36. die  System-Farbe  sofort  zurückkehrt,  wenn nur mit dem Prozessor in die
  37. Register schreiben: weil die Copperlist jede 1/50 Sekunde alle Farben  neu
  38. definiert!!! Nun werdet ihr ahnen, daß es schier unmöglich sein wird, eine
  39. Figur in Ruhe und Frieden auf den Bildschirm zu bringen, wenn man  dauernd
  40. mit  der Copperlist des Betriebssystemes zu kämpfen hat, die dauernd alles
  41. umdefiniert. Wir müßten unsere eigene Copperlist erstellen und sie mit der
  42. des   Systemes   ersetzen...  NICHTS  LEICHTER  ALS  DAS!  Wie  ich  schon
  43. prophezeiht habe, ist die Copperlist nichts anderes als eine Schlange  von
  44. MOVE,   die   Werte   in   die   Register   des  Copper  geben,  also  den
  45. $dffxxx-Registern. Diese Move aber werden nicht vom Prozessor, sondern vom
  46. Copper  selbst  gemacht,  der  unabhängig  vom Prozessor läuft und den für
  47. andere Sachen freihält... das ist einer der Gründe, wieso sie auf PC nicht
  48. LIONHEART oder PROJECT X des Amiga haben. Wir müssen ihm also wirklich ein
  49. Listing schreiben, wie wir es vom  68000er  her  kennen,  und  danach  den
  50. Copper  darüber  informieren, wo es sich befindet und es ihn an Stelle der
  51. Workbench-Copperlist ausführen lassen. Der Copper besitzt nur  3  Befehle,
  52. wovon in der Praxis nur zwei verwendet werden: diese sind ein MOVE und ein
  53. WAIT; derjenige, den niemand verwendet, ist das SKIP,  deswegen  behandeln
  54. wir es nur, wenn wir ein Listing damit finden.
  55.  
  56. Das MOVE ist kinderleicht: könnt ihr euch an das erinnern ? :
  57.  
  58.     MOVE.W    #$123,dff180    ; Gib die Farbe RGB in COLOR0
  59.  
  60. Gut, in Copperlist schaut das so aus:
  61.  
  62.     dc.w    $180,$123    ; die Zahlen werden direkt mit dc.w
  63.                 ; in den Speicher gegeben, aber wir 
  64.                 ; müssen ja nur zwei Befehle lernen!!
  65.  
  66. Das heißt, man muß zuerst die Adresse angeben, in die der Wert kommt (ohne
  67. dem $dff, so wie wir es schon gesehen haben wenn wir in a0 $dff180 gegeben
  68. haben: $180(a0). Genauso haben  die  Entwickler  daran  gedacht,  uns  das
  69. dauernde  $dff zu ersparen, und so reicht es, wenn wir $180 oder $182 oder
  70. was auch immer, schreiben. Hauptsache, wir beschreiben nur Copperregister,
  71. denn  nur  Register  des  COPPER  können  mit  der  COPPERLIST angesteuert
  72. werden!! Weiters darf nur auf  GERADE  Adressen  zugegriffen  werden,  wie
  73. $180,  $182  ...,  NIE  $181,  $179 etc, weiters können nur WORD verwendet
  74. werden. Wie ihr seht, wird  die  COPPERLIST  nicht  auf  die  gleiche  Art
  75. assembliert  wie  die  Instruktionen des 68000, bei denen aus Befehlen wie
  76. RTS, MOVE... $4e75 usw. wird,  sondern  es müssen  die  BYTES  so  in  den
  77. Speicher gelegt werden, wie sie der Coprozessor Copper lesen kann. Deshalb
  78. verwenden wir das DC, um Byte für Byte die Befehle hineinzuschreiben, aber
  79. es ist sehr einfach! Z.B. um die ersten vier Farben zu definieren:
  80.  
  81. COPPERLIST:
  82.     dc.w    $180,$000    ; COLOR0 = SCHWARZ
  83.     dc.w    $182,$f00    ; COLOR1 = ROT
  84.     dc.w    $184,$0f0    ; COLOR2 = GRÜN
  85.     dc.w    $186,$00f    ; COLOR3 = BLAU
  86.  
  87. Erinnert ihr euchm wie das Farbformat aussieht? RGB = RED ,  GREEN,  BLUE.
  88. Um  einen  Kommentar  über  die  $dffxxx - Register zu erhalten, könnt ihr
  89. jederzeit "=C" schreiben, oder, speziell Z.B. für $dff180  "=C  180",  und
  90. ihr  werdet  eine  Zusammenfassung in englisch bekommen. Probiert z.B. "=C
  91. 006" und ihr werdet Namen und Erklärung über dieses Register bekommen, das
  92. ihr  verwendet  habt,  um  den  Bildschirm zum Blinken zu bringen. Um alle
  93. Register zu sehen, "=C".
  94.  
  95. Das WAIT hingegen dient dazu, eine bestimmte Zeile  abzuwarten,  wenn  man
  96. z.B.  die  Hintergrundfarbe  (COLOR0)  bis  zur  Hälfte  des  Bildschirmes
  97. schwarz, und von da ab blau machen möchte, dann sieht das so aus:
  98.  
  99.     dc.w    $180,0        ; COLOR0 Schwarz
  100.  
  101. gefolgt von einem WAIT, das die Mitte des Bildschirmes abwartet, und dann
  102.  
  103.     dc.w    $180,$00F    ; COLOR0 Blau
  104.  
  105. Mit dieser Strategie kann man die ganze Palette (die Farbliste)  in  jeder
  106. Bildschrirmzeile  verändern, von so was können die PC mit VGA nur träumen,
  107. denn in der Tat haben die meisten Amiga-Spiele nur Screens mit 32  Farben,
  108. aber durch ändern der Farbpalette hie und da, z.B. wenn das Spielfeld nach
  109. unten scrollt, kann man mehr Farben erzeugen als eine VGA mit 256  Farben.
  110. Vor  allem  wenn  man  in  Betrachtung zieht, daß man einen Farbverlauf im
  111. Hintergrund erzeugen kann,  indem  man  bei  jeder  Bildschirmzeile  Farbe
  112. wechselt,  und  das wird unser erstes Programm in dieser Lektion sein. Der
  113. WAIT-Befehl präsentiert sich so:
  114.  
  115.     dc.w    $1007,$FFFE    ; WAIT Koordinate X = $10, Y = $07
  116.  
  117. Dieser Befehl bedeutet: WARTE DIE HORIZONTALE LINIE $10 AB, SPALTE 7 (also
  118. der  siebte  Punkt  von  links,  diese "Punkte" werden Pixel genannt). Das
  119. $FFFE steht für WAIT, es muß immer gesetzt werden, während das erste  Byte
  120. die horizontale Linie (x) ist, die es abzuwarten gilt, und das zweite Byte
  121. die Vertikale (y). Der Bildschirm besteht aus vielen kleinen Punkten,  die
  122. alle  aneinander  gereiht sind, wie ein Blatt Papier mit kleinen Kästchen,
  123. Millimeterpapier  in  etwa.  Um  den  Punkt  (Pixel)  an   Position   16,7
  124. anzupeilen,  also der 16. Punkt vom oberen Rand und der 7. vom linken Rand
  125. nach rechts, werden wir $1007 ($10  =  16!)  schreiben.  Wie  bei  Schiffe
  126. versenken!  Normalerweise  gibt  man  nur  die  horizontale Linie an ihrem
  127. Anfang an, der ist $07 statt $01, weil der Rest über dem linken  Rand  des
  128. Monitors  liegt.  Der  WAIT-Befehl  wird auch dazu verwendet, das Ende der
  129. Copperlist zu kennzeichnen. Am Ende der COP setzt man ein
  130.  
  131.     dc.w    $FFFF,$FFFE    ; Ende Copperlist
  132.  
  133. Dies  interpretiert  der  Copper  per  Definition  als  Ende, auch weil es
  134. bedeuten würde, eine Linie abzuwarten, die es nicht gibt!  Die  Copperlist
  135. startet  dann  von  vorne. Es hat sich auch rumgesprochen, daß bei einigen
  136. älteren Amigamodellen zwei abschließende Instruktionen nötig  seien,  aber
  137. es  scheint  eine  Art  von Massenpsychose zu sein, da niemand jemals zwei
  138. verwendet hat und alles immer funktionierte.
  139.  
  140. Um unsere Copperlist zu schreiben, die am Anfang  noch  ohne  Bilder  sein
  141. wird,   lediglich  mit  einigen  Farbverläufen,  müssen wir  die  BITPLANE
  142. abschalten, also die  aus  Bits  bestehenden  "Ebenen",  die  übereinander
  143. gelegt  die  Bilder erzeugen. Um da zu erreichen, setzen wir am Anfang ein
  144. DC.W $100,$200 ein, wir geben also den Wert $200 ins Register $dff200, das
  145. das Kontrollregister der Bitplane ist.
  146.  
  147. NUN  SIND WIR IMSTANDE, EINE VOLLSTÄNDIGE COPPERLIST ZU SCHREIBEN, DIE BIS
  148. MITTE BILDSCHIRM GEHT UND DANN FARBE WECHSELT!
  149.  
  150. Copperlist:
  151.     dc.w    $100,$200    ; BPLCON0  Keine Bilder, nur Hintergrund
  152.     dc.w    $180,0        ; COLOR0 Schwarz (Hintergrund)
  153.     dc.w    $7f07,$FFFE    ; WAIT - warte Linie $7f ab (127)
  154.     dc.w    $180,$00f    ; COLOR0 Blau
  155.     dc.w    $FFFF,$FFFE    ; ENDE DER COPPERLIST
  156.  
  157. Wenn man bedenkt, daß  ihr  die  Funktionstüchtigkeit  eurer  Copperlisten
  158. überprüfen  wollen  werdet,  hier eine TABELLE ZUM NACHSCHLAGEN DER FARBEN
  159. DES COPPER:
  160.  
  161. Der Amiga besitzt 32 Register  für  dementsprechend  vielen  verschiedenen
  162. Farben:
  163.  
  164.     $dff180    ; COLOR0 (Hintergrund)
  165.     $dff182    ; COLOR1
  166.     $dff184    ; COLOR2
  167.     $dff186    ; COLOR3
  168.     ...
  169.     $dff1be    ; COLOR31
  170.  
  171. In jedes dieser Register kann eine der 4096 möglichen Farben  kommen,  die
  172. durch  Mischen  der  drei  Grundfarben  Rot, Grün und Blau zustande kommen
  173. können. Jede dieser Farben kann eine Intensität von 0 bis 15  haben,  also
  174. 16  "Helligkeitsstufen".  Nachgerechnet  ergibt  sich  aus allen möglichen
  175. Kombinationen, 16*16*16=4096, eben die Anzahl der darstellbaren Farben (16
  176. Farbtöne  Rot,  16  von Grün und 16 von Blau). Den Wert der Farbe kann man
  177. entweder mit dem Prozessor oder mit dem Copper eingeben:
  178.  
  179.     move.w    #$000,$dff180    ; Farbe SCHWARZ in COLOR0
  180.  
  181.     dc.w    $180,$FFF    ; Farbe WEIß in COLOR0
  182.  
  183. In diesem Beispiel haben wir die zwei Extremwerte  gesehen:  $FFF,  gleich
  184. Weiß,  und $000, Schwarz. Um die Farbe zu wählen muß man bedenken, daß das
  185. WORD der Farbe so aufgebaut ist:
  186.  
  187.     dc.w    $0RGB
  188.  
  189.     wobei die vierte 0 (ganz links) nicht verwendet wird, und gilt:
  190.  
  191.     R = ROT -Komponente der Farbe (RED)
  192.     G = GRÜN-Komponente der Farbe (GREEN)
  193.     B = BLAU-Komponente der Farbe (BLUE)
  194.  
  195. Die  Bit  vom  15  bis  zum  12 sind nicht verwendet, die Bit von 11 bis 8
  196. stellen den Rotanteil dar, Bit 7 bis Bit 4 den Grünanteil und  Bit  4  bis
  197. Bit 0 den Blauanteil.
  198.  
  199. Jede  RGB-Farbe kann einen Wert von 0 bis 15 haben, also von $0 bis $15 in
  200. Hexadezimal, es ist also leicht eine Farbe auszuwählen:
  201.  
  202.     $FFF = Weiß
  203.     $D00 = Ziegelrot
  204.     $F00 = Rot
  205.     $F80 = Rot-Orange
  206.     $F90 = Orange
  207.     $fb0 = Goldgelb
  208.     $fd0 = Cadmiumgelb
  209.     $FF0 = Zitrone
  210.     $8e0 = Hellgrün
  211.     $0f0 = Grün
  212.     $2c0 = Dunkelgrün
  213.     $0b1 = Baumgrün
  214.     $0db = Wasser
  215.     $1fb = Wasser Hell
  216.     $6fe = Himmelblau
  217.     $6ce = Helles Blau
  218.     $00f = Blau
  219.     $61f = Brillantes Blau
  220.     $06d = Dunkelblau
  221.     $c1f = Violett
  222.     $fac = Rosa
  223.     $db9 = Beige
  224.     $c80 = Braun
  225.     $a87 = Dunkelbraun
  226.     $999 = Mittelgrau
  227.     $000 = Schwarz
  228.  
  229. Nun ist das einzige Problem, den Copper dazu zu zwingen, unsere Copperlist
  230. auszuführen und die der Workbench bei Seite zu lassen. Aber da gibt´s noch
  231. ein  anderes Problem: wenn wir unsere eigene ausführen lssen, wie schaffen
  232. wir es dann, den Orginalzustand wiederherzustellen? Antwort: Man  muß  auf
  233. ein  Zettelchen  aufschreiben, wo sie war!!! Oder anders: Wir schreiben in
  234. ein bestimmtes Longword die Adresse, an der sie zu finden ist. Wir  werden
  235. dieses  Longword  OLDCOP  nennen,  also ALTE COPPERLIST, die des Systemes.
  236. Aber wen müssen wir fragen, um  zu  wissen,  wo sich  die  Copperlist  des
  237. Systemes  befindet?  Das  Betriebssystem natürlich!!! Um es das zu fragen,
  238. müssen wir eine Routine aus dem CHIP des Kickstart ausführen!  Um  das  zu
  239. tun, müssen  wir  immer  als  Bezug  die Adresse nehmen, die in Adresse $4
  240. steht. Diese wird vom Kickstart geschrieben und enthält  die  Adresse,  ab
  241. der wir unsere AdressierungsDistanzen (Offsetes) machen müssen. Diese sind
  242. vordefiniert, wir werden später darüber plaudern. Um das Long der  Adresse
  243. $4 aufzusammeln, reicht ein:
  244.  
  245.     MOVE.L    $4,a6    ; In a6 haben wir nun die ExecBase
  246.  
  247. Oder besser:
  248.  
  249.     MOVE.L    4.w,a6  ; 4 ist eine kleine Zahl, deswegen kann 4.w
  250.             ; geschrieben werden, was Platz spart.
  251.             ; Es wird also $0004 statt $00000004 geschrieben,
  252.             ; bei dem die ersten vier Nullen nicht gebraucht
  253.             ; werden. VERSCHOBEN WIRD ABER IMMER EIN LONGWORD!
  254.             ; Also das Long, das in Adresse 4, 5, 6 und 7
  255.             ; enthalten ist.
  256.  
  257. Ist einmal die Adresse, die in $4 enthalten war, in a6 kopiert, können wir
  258. darangehen,  die Routinen des Kickis auszuführen, indem wir JSR verwenden,
  259. kombiniert mit der richtigen Distanz (Offset),  denn  es  existieren  ganz
  260. exakte  Distanzen,  die gewissen Routinen entsprechen. Nun wissen wir, daß
  261. z.B. mit einem JSR -$78(a6) das Multitasking abgeschalten wird!!! Es  wird
  262. also  nur  unser  Programm  ausgeführt,  nix anderes! Sofort testen! Ladet
  263. Listing3a.s in einen Buffer und startet es. Aber  die  Exec  kümmert  sich
  264. nicht  um  alles: der Kickstart, 256kB lang, wenn es sich um die Versionen
  265. 1.2 oder 1.3 handelt, oder 512k  bei  V2.0  und  V3.0,  ist  in  Libraries
  266. aufgeteilt,  eine  Art  "Sammlung" von Routinen, die schon fertig sind und
  267. aufgerufen werden können. Und da jeder Kickstart anders  ist,  ja  richtig
  268. hardwaremäßig,  im Sinne daß die Routine, die das Multitasking abschaltet,
  269. im Kick 1.3 z.B. auf  Adresse  $fc1000  liegen  könnte,  während  sie  bei
  270. anderen  Versionen  irgendwo  anders  im  Speicher  sein könnte, haben die
  271. lieben Erbauer des Amiga  eine  ihrer  wunderbaren  Geistesblitze  gehabt:
  272. "WARUM  GEBEN  WIR  IN SPEICHERZELLE 4 NICHT EINE ADRESSE, VON DER AUS MAN
  273. IMMER DIE GLEICHEN ROUTINEN AUSFÜHREN KANN, WENN MAN MIT EINEM  JSR  EINEN
  274. BESTIMMTEN  OFFSET ANSPRINGT?" (P.S. JSR ist das gleiche wie BSR, nur kann
  275. ein JSR Routinen im gesamten Speicher  anspringen,  während  das  BSR  nur
  276. innherhalb 32768 Bytes nach vorne oder hinten operieren kann).
  277.  
  278. Und  das  haben  sie  getan!  Um  z.B.  das Disable, also das Multitasking
  279. killen, auszuführen, wird auf jedem Kickstart folgendes getan:
  280.  
  281.     move.l    4.w,a6        ; Adresse der Exec in a6
  282.     jsr    -$78(a6)    ; Disable - blockiert Multitasking
  283.     bsr.w    MeinProgramm
  284.     jsr    -$7e(a6)    ; Enabel -schaltet Multitasking wieder ein
  285.  
  286. In jedem Kickstart liegt die Routine auf einer anderen Adresse,  aber  mit
  287. dieser Methode sind wir sicher, daß wir immer diese ausführen. Man muß nur
  288. alle Offsets der verschiedenen Routinen kennen, und das Spiel ist gemacht.
  289. Uns   interessiert   aber   nur,   die   Copperlist  des  Betriebssystemes
  290. abzuspeichern, und um das zu schaffen, müssen wir und an eine Routine  des
  291. Kick  wenden,  die  Graphics.library  heißt.  Es ist die, die sich mit der
  292. Graphic befaßt, aber nur unter dem Betriebssystem, das sei klar, nicht auf
  293. Hardwareebene.  Um  auf  diese  Bibliothek  (Library) zugreifen zu können,
  294. müssen wir sie zuerst öffnen:
  295.  
  296.     move.l  4.w,a6        ; ExecBase in a6 schreiben
  297.     lea    GfxName,a1    ; Adresse des Namens der Library, die
  298.                 ; es zu öffnen gilt, in a1
  299.     JSR    -$198(a6)    ; OpenLibrary, Routine der Exec, die
  300.                 ; eine Bibliothek öffnet, und als Resultat
  301.                 ; die Basisadresse dieser zurückliefert 
  302.                 ; (in d0), ab
  303.                 ; welcher wir die Offsets ansetzen müssen.
  304.     move.l  d0,GfxBase    ; Speichere die Basisadresse der Gfx in
  305.     ...            ; GfxBase
  306.     ...
  307.  
  308. GfxBase:
  309.     dc.b    "graphics.library",0,0    ; BEMERKUNG: Um Charakter, also
  310.                     ; Buchstaben, in den Speicher zu
  311.                     ; geben, verwenden wir immer das
  312.                     ; dc.b und setzen sie unter ""oder´´
  313. GfxBase:
  314.     dc.l    0
  315.  
  316. In diesem Fall haben wir die Routine der Exec verwendet, die  Bibliotheken
  317. öffnet,  die  "OpenLibrary". Sie verlangt, daß in a1 die Adresse steht, an
  318. der der Text mit dem Name der zu öffnenden  Library  zu  finden  ist.  Wir
  319. hätten  z.B. auch die "dos.library" öffnen können, um mit Files umzugehen,
  320. oder "intuition.library" für die Fenster, Screens etc. Einmal  ausgeführt,
  321. liefert  OpenLibrary  in d0 die Basisadresse der gefragten Bibliothek., um
  322. uns zu verstehen, eine Adresse wie GfxBase, ab der wir dann mit JSR unsere
  323. Offsets  machen, um die verschiedensten Routinen anzuspringen, die mit der
  324. Grafik zu tun haben. Außer den JSR wissen wir auch noch, daß  die  Adresse
  325. der  aktuellen  COPPERLIST  des  Systemes auf $26 nach GfxBase leigt, also
  326. fahren wir mit unserem Programm fort, indem wir diese Adresse in ein Label
  327. (OLDCOP) abspeichern:
  328.  
  329.     move.l  4.w,a6        ; ExecBase in a6 schreiben
  330.     lea    GfxName,a1    ; Adresse des Namens der Library, die
  331.                 ; es zu öffnen gilt, in a1
  332.     JSR    -$198(a6)    ; OpenLibrary, Routine der Exec, die
  333.                 ; eine Bibliothek öffnet, und als Resultat
  334.                 ; die Basisadresse dieser in d0 zurückliefert,
  335.                 ; ab welcher wir die Offsets ansetzen müssen.
  336.     move.l  d0,GfxBase    ; Speichere die Basisadresse der Gfx in
  337.                 ; GfxBase
  338.  
  339.     move.l  d0,a6
  340.     move.l  $26(a6),OldCop  ; Nun speichern wir die Adresse der z.Z
  341.                 ; aktuellen System-Copper in OLDCOP ab
  342.     ....
  343.  
  344. GfxName:
  345.     dc.b    "graphics.library",0,0    ; BEMERKUNG: Um Charakter, also
  346.                     ; Buchstaben, in den Speicher zu
  347.                     ; geben, verwenden wir immer das
  348.                     ; dc.b und setzen sie unter ""oder´´
  349. GfxBase:
  350.     dc.l    0
  351.  
  352. OldCop:
  353.     dc.l    0 
  354.  
  355. Nun können wir unsere eigene Copperlist ansteuern, ein WaitMouse dazufügen
  356. und dann wieder den alten Zustand herstellen; mit ansteuern meine ich, daß
  357. wir die Adresse unserer Copperlist ins Register COP1LC geben, das ist  das
  358. $dff080,  das  der  Zeiger  auf  die  sie  ist,  d.h. der Copper führt die
  359. Copperlist aus, deren Adresse sich im  Register  $dff080  befindet.  Also,
  360. einmal  die  Adresse  unserer  Copperlist in  $dff080, müssen wir sie noch
  361. "starten", indem wir ins Register $dff088 (COPJMP1) irgend  einen  Nonsens
  362. schreiben, egal, ob wir hineinschreiben oder was rauslesen, denn da es ein
  363. sog.  STROBE-Register  ist,  reicht  irgend  eine  Änderung,  um   es   zu
  364. aktivieren.  Die  Strobe-Register  sind  wie eine Art Knopf, der grade mal
  365. berührt werden muß, um ausgelöst zu werden.  Verwendet  aber  nicht  CLR.W
  366. $dff088, das gibt komischerweise Probleme. Nun wird unsere Liste bei jedem
  367. Fotogramm ausgeführt, solange, bis in $dff080  nicht  wieder  eine  andere
  368. kommt  (oder  besser, deren Adresse...!). Ein Problem ist, daß $dff080 ein
  369. NUR-SCHREIBE-REGISTER ist, probiert ein "=c 080"  und  ihr  werdet  das  W
  370. bemerken  (WRITE).  Um  die alte Copperlist - die, die der Asmone oder die
  371. Workbench verwendet- wieder an  ihren  Platz  zu  setzen, müssen  wir  das
  372. Betriebssystem  fragen, welche Adresse in $dff080 enthalten ist, da dieses
  373. Register selbst ja nicht ausgelesen werden kann. Und dafür  verwenden  wir
  374. die  Routine  des  Kickstart.  Wenn wir dann diese Adresse erhalten haben,
  375. speichern wir sie in ein LONGWORD unseres Programmes, danach  starten  wir
  376. unsere  einene  Copperlist,  und  am  Ende  des  Programmes  geben wir die
  377. gespeicherte Adresse wieder in COP1LC ($dff080).
  378.  
  379.  
  380.     move.l    4.w,a6        ; ExecBase in a6 schreiben
  381.     JSR    -78(a6)        ; Disable - schaltet Multitasking aus
  382.     lea    GfxName,a1    ; Adresse des Namens der Library, die
  383.                 ; es zu öffnen gilt, in a1
  384.     JSR    -$198(a6)    ; OpenLibrary, Routine der Exec, die
  385.                 ; eine Bibliothek öffnet, und als Resultat
  386.                 ; die Basisadresse dieser in d0 zurückliefert,
  387.                 ; ab welcher wir die Offsets ansetzen müssen.
  388.     move.l    d0,GfxBase    ; Speichere die Basisadresse der Gfx in
  389.                 ; GfxBase
  390.  
  391.     move.l    d0,a6
  392.     move.l    $26(a6),OldCop    ; Nun speichern wir die Adresse der z.Z
  393.                 ; aktuellen System-Copper in OLDCOP ab
  394.  
  395.     move.l    #COPPERLIST,$dff080    ; COP1LC-Wir zeigen auf unsere COP
  396.     move.w    d0,$dff088        ; COPJMP1-Wir starten unsere COP,
  397.                     ; indem wir etwas hineinschreiben,
  398.                     ; z.B. d0
  399. mouse:
  400.     btst    #6,$bfe001
  401.     bne.s    mouse
  402.  
  403.     move.l    OldCop(PC),$dff080    ; COP1LC - Wir zeigen auf die alte
  404.                     ; System-Copperlist
  405.     move.w    d0,$dff088        ; COPJMP1 - und starten sie
  406.  
  407.     move.l    4.w,a6
  408.     jsr    -$7e(a6)    ; Enable - schaltet Multitasking wieder ein
  409.     move.l    GfxBase(PC),a1    ; Base der zu schließenden Bibliothek
  410.                 ; (Bibliotheken werden IMMER geschloßen!!!)
  411.     jsr    -$19e(a6)    ; Closelibrary - Schließt die graphics lib
  412.     rts
  413.  
  414.  
  415. GfxName:
  416.     dc.b    "graphics.library",0,0    ; BEMERKUNG: Um Charakter, also
  417.                     ; Buchstaben, in den Speicher zu
  418.                     ; geben, verwenden wir immer das
  419.                     ; dc.b und setzen sie unter ""oder´´
  420. GfxBase:
  421.     dc.l    0
  422.  
  423. OldCop:
  424.     dc.l    0      
  425.  
  426. COPPERLIST:
  427.     dc.w    $100,$200    ; BPLCON0 - Keine Bilder, nur Hintergrund
  428.     dc.w    $180,0        ; COLOR0 SCHWARZ
  429.     dc.w    $7f07,$FFFE    ; WAIT - Warte auf Zeile $7f (127)
  430.     dc.w    $180,$00F    ; COLOR0 BLAU
  431.     dc.w    $FFFF,$FFFE    ; ENDE DER COPPERLIST
  432.  
  433. Ihr  werdet  dieses Beispiel mit Vorschlägen und Änderungen in Listing3b.s
  434. finden. Holt es in den Buffer mit F2 oder einem x-beliebigen  anderen  und
  435. bestaunt  das  erste  Programm  aus  dem  Kurs, das den Chips des Amiga so
  436. richtig "Power unterm Hintern" macht.
  437.  
  438. Habt ihr eure Experimente mit der Copperlist gemacht? Gut,  nun  versuchen
  439. wir,  einige  bewegte Effekte zu erzeugen. Bevor wir aber anfangen muß ich
  440. euch mitteilen, daß um irgend eine Bewegung zu machen, diese Routinen  mit
  441. dem   Elektronenstrahl,   der   das   Bild   auf   dem  Monitor  zeichnet,
  442. synchronisiert werden müssen. Für die,  die  es  noch  nicht  wissen,  der
  443. Bildschirm wird 50 Mal pro Sekunde neu gezeichnet, und die Bewegungen, die
  444. uns flüssig erscheinen,z.B. die der besser programmierten Spiele, sind auf
  445. diese  fünfzigstel  Sekunde angepaßt. Wir haben das Register $dff006 schon
  446. verwende, das bekanntlich dauernd seinen Inhalt ändert. Aus  gutem  Grund,
  447. es  beinhaltet ja die Position des Elektronenstrahles auf dem Monitor, und
  448. der düst mit 50 Seiten pro Sekunde durch die Gegend... Er startet  bei  0,
  449. also dem höchten Teil des Monitors, ganz oben, und durchläuft ihn bis ganz
  450. unten. Wenn wir nun eine Routine schreiben, die Bewegungen auf den  Schirm
  451. bringt,  ohne  sie  zu zeitlich anzupassen, ohne Timing, dann wird sie mit
  452. der Geschwindigkeit des Prozessors laufen, also viel zu schnell  um  etwas
  453. zu sehen. Um eine gewisse Zeile des Bildschirmes abzuwarten müssen wir nur
  454. das erste Byte von $dff006 auslesen. In ihm  steht  die  gerade  erreichte
  455. Zeile, also die vertikale Position (gleich dem WAIT des COPPER):
  456.  
  457. WaitZeile:
  458.     CMPI.B    #$f0,$dff006    ; VHPOSR - Sind wir auf Zeile $f0 ? (240)
  459.     bne.s    WaitZeile    ; wenn nicht, kontrolliere nochmal
  460.     ...
  461.  
  462. Dieser Zyklus wartet die Zeile 240 ab, und erst dann fährt er mit den
  463. folgenden Befehlen fort, wie etwa die Routine, die auf einen Mausdruck
  464. wartet. Fügen wir auch diesen Teil ein:
  465.  
  466. mouse:
  467.     CMPI.B    #$f0,$dff006    ; VHPOSR - Sind wir auf Zeile $f0 ? (240)
  468.     bne.s    mouse        ; wenn nicht, kontrolliere nochmal
  469.  
  470.     BSR.s    RoutineMitTiming ; Diese Routine wird nur einmal
  471.                  ; pro Fotogramm ausgeführt
  472.     
  473.     bsr.s    MuoviCopper    ; Die erste Bewegung am Bildschirm!!!!!
  474.     btst    #6,$bfe001    ; linke Maustaste gedrückt?
  475.     bne.s    mouse        ; wenn nicht, zurück zu mouse:
  476.     rts  
  477.  
  478. Jetzt haben wir eine Routine, die 1 Mal  pro  FRAME  -  oder  Fotogramm  -
  479. ausgeführt  wird,  also  1 Mal alle 50stel Sekunden, und um genau zu sein,
  480. wird sie jedesmal ausgeführt, wenn wir bei Zeile 240 angekommen sind,  und
  481. dann  wird  sie  ruhen,  bis  wir erneut Zeile 240 erreichen, dem nächstem
  482. FRAME.
  483.  
  484. Bemerkung: Die Bilder werden mit der RASTER-Technik  gezeichnet,  die  mit
  485. einem  "ElektronenPinsel"  links  oben  beginnt, nach rechts geht, bis zum
  486. Ende der Zeile, dann wieder ganz links, Zeile 2, usw. bis er am  Ende  des
  487. Bildschirms  angekommen ist. Es ist mit dem Lesen vergleichbar: jede Zeile
  488. von links nahc rechts, angefangen bei der ersten ganz oben bis runter  zur
  489. letzten  auf  der Seite, und DANN startet man wieder von vorne, so, als ob
  490. wir vergessen hätten, Seite zu wechseln. Denn der Monitor ist ja auch  nur
  491. einer, und er muß nur auf dem einen Schirm schreiben, der Elektronenpinsel
  492. malt ja nicht auf die Wand.
  493.  
  494. Ladet das Beispiel Listing3c.s in einen anderen Textbuffer und probiert es
  495. aus.  Dieses bewegt ein WAIT nach unten und somit die folgende Farbe, wenn
  496. ihr die Maustaste drückt. Linke Taste zum Aussteigen.
  497.  
  498. Listing3c.s verstanden?  Dann  lassen  wir  es  ein  bißchen  schwiereiger
  499. werden!  Ladet Listing3c2.s in einen Buffer und studiert es, ich habe eine
  500. Zeilenkontrolle eingefügt, um den Scroll zu stoppen.
  501.  
  502. Alles klar in Listing3c2.s?? Gut, dann geht´s weiter  mit  der  Praxis  in
  503. Listing  3c3.s, in der ein Balken mit 10 WAIT verschoben wird, anstatt nur
  504. ein Wait alleine. Immer schwieriger!!!
  505.  
  506. Lebt ihr noch nach  Listing3c3.s?  Dann  massakriert  euer  Hirn  mit  dem
  507. nächsten Listing, dem Listing3c4.s, in der wir von 10 Label BALKEN auf ein
  508. einziges umsteigen, und die Adressierungsdistanz verwenden.
  509.  
  510. Nun, es war ja nicht recht schwer, oder? Das Schwierige  konne  jetzt  mit
  511. Listing  3d.s, in dem der Balken rauf und runter geht, und wir werden auch
  512. die Geschwindigkeit ändern.
  513.  
  514. Habt ihr Listing3d.s verstanden? Ja? Glaub ich nicht! Euch kommt nur  vor,
  515. ihr   hättet  verstanden...  ich  würde  noch  mal  nachsehen,  bevor  ich
  516. weitergehen würde...na, noch mal angeschaut?  Tja...dann  holt  euch  eine
  517. Variante zum Thema rein mit Listing 3d2.s.
  518.  
  519. Nun  seid  ihr  bereit,  Listing3e.s  in Angriff zu nehmen, in der erklärt
  520. wird, wie man ein RASTERBAR herzaubert, also  ein  wiederholendes  Fließen
  521. der Farben.
  522.  
  523. Ein  anderer Spezialfall: Wie erreiche ich die PAL-Zone (nach $FF) mit den
  524. Wait des Copper. Soviel in Listing3f.s.
  525.  
  526. Um Lektion3.TXT abzuschließen, schaut euch Listing3g.s und Listing3h.s an,
  527. bei  dem  ein  Verlauf  von  Links  nach  Rechts statt von oben nach unten
  528. erzielt wird. Danach seid ihr  bereit,  Lektion4.TXT  durchzuackern.  Dort
  529. wird  die  Verwaltung  von  farbigen Bildern und die möglichen Effekte auf
  530. ihnen behandelt!
  531.  
  532. Bemerkung: Die Beispiele  4x.s  der  Lektion4.TXT  befinden  sich  in  der
  533. Directory  Listings2,  darum müßt ihr ein "V df0:Listings2" tippen, um die
  534. Bilder in dieser Directory laden zu können. Danach ladet  Lektion4.TXT  in
  535. diesen oder einen anderen Buffer (mit "r").
  536.  
  537. *  Komplimente,  daß  ihr  bis  hier  her  gekommen  seid!  Das Größte ist
  538. geschafft! Nun werden wir mit Leichtigkeit  weitergehen,  da  wir  in  die
  539. Logik der Assemblerprogrammierung eingestiegen sind!
  540.  
  541.  
  542.