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

  1.  
  2.  ASSEMBLERKURS - LEKTION 6
  3.  
  4. In dieser Lektion werden  wir  lernen,  Texte  am  Bildschirm  anzuzeigen,
  5. screens hin- und herzuscrollen, die größer sind als der Bildschirm und wie
  6. man Tabellen mit vordefinierten Werten verwendet, um "Hüpfbewegungen"  und
  7. Wellen zu simulieren.
  8.  
  9. Zu  lernen, Schriften am Bildschirm anzuzeigen ist extrem wichtig, denn es
  10. gibt kein Spiel oder  Grafikdemo,  das  ohne  auskommt:  ob  wir  nun  den
  11. Punktestand  anzeigen  wollen,  oder die Leben von Player1, eine Botschaft
  12. zwischen einem Level und dem anderen, ein Gruß an die Freunde,  usw...  Es
  13. leuchtet  hoffentlich  ein, daß da nicht jedesmal Bilder im Format 320x256
  14. angezeigt werden, die die vorgefertigten Schriften beinhalten! Stellt euch
  15. vor,  ihr  wollt 5 Seiten Text als Intro von eurem Spiel hinmalen: "Es war
  16. einmal ein Ritter, vor langer, langer Zeit, der sich auf  die  Suche  nach
  17. dem  heiligen  Graal  machten,...", ihr habt schon verstanden. Nun gut, es
  18. gibt zwei Möglichkeiten: entweder ihr zeichnet euch mit einem  Malprogramm
  19. fünf  Bilder mit dem Text darauf, und in diesem Fall haben wir 5 Bilder zu
  20. 40*245 = 51200 Bytes verwendet,  die  uns  Platz  auf  Disk  und  Speicher
  21. fressen,  oder wir erledigen alles mit 1kB Fonts und einigen Bytes Routine
  22. und erreichen das Gleiche. Nur 50kB weniger Speicher haben wir verschenkt.
  23. Habt  ihr  die  Charakter-FONTS  des  Betriebssystemes  vor  Augen, TOPAZ,
  24. DIAMOND und all die anderen?
  25. Sehr gut, aber die interessieren uns überhaupt nicht. Tut mir  leid.  Aber
  26. wir  werden eigene verwenden!! Klar, wir können auch diese verwenden, aber
  27. die sind begrenzt, aber wenn wir uns selbst  was  zusammenbasteln,  können
  28. wir  anzeigenm  was  wir  wollen,  keine  Größe  kann  uns aufhalten, kein
  29. arabischer Zeichensatz. Auch Farben, kein  Problem,  dann  müßt  ihr  halt
  30. einen  Font in Farbe zeichnen und die richtige Routine dazuschreiben. Wenn
  31. man einmal das PRINT-System verstanden hat, also jenes, das die Buchstaben
  32. auf  den Monitor bringt, dann sind Variationen kein Thema mehr. Zum Anfang
  33. lernen wir mal, wie wir einen kleinen Font anzeigen, 8 mal 8  Pixel  groß,
  34. in einer Farbe.
  35. Zuerst brauchen wir einmal ein BITPLANE, auf  dem  wir  unsere  Buchstaben
  36. "drucken"   können,   und  einem  CHARAKTERFONT,  indem  diese  Buchstaben
  37. gespeichert sind. Bim Bitplane gibt´s keine Probleme, da  braucht  man  ja
  38. nur  ein  Stück  Speicher  mit Nullen aufzufüllen, das den Dimensionen des
  39. Bitplane entspricht, und es dann anpointen, es also  anzeigen.  Um  dieses
  40. Stück leeren Speicher zu schaffen können wir das DCB.B 40*256,0 verwenden,
  41. das ein richtiges Stück mit NULL füllt und uns zu Verfügung  stellt.  Aber
  42. es  gibt  eine  spezielle  SECTION  für  die  leeren  "BUFFERS": die BSS -
  43. Section. In ihr kann man die Anweisungen DS.B / DS.W / DS.L verwenden, die
  44. angeben,  wieviele  Bytes,  Words oder Longwords man auf NULL setzen will.
  45. Der Vorteil liegt in der Gesamtlänge des ausführbaren Files: wenn wir  mit
  46. einem "Bitplane: dcb.b 40*256,0" aufwarten, dann werden die 10240 Bytes in
  47. der Länge eingebaut, hingegen mit der Section BSS:
  48.  
  49.     SECTION EinBitplaneHier,BSS_C    ; _C bedeutet, daß sie in CHIP RAM
  50.                     ; kommen muß, ansonsten könnte das
  51.                     ; Betriebssystem auf die Idee
  52.                     ; kommen, sie in FAST zu lagern.
  53.                     ; Und Bitplanes müssen IMMER in 
  54.                     ; CHIP RAM!!!
  55. BITPLANE:
  56.     ds.b    40*256      ; 10240 Bytes auf 0
  57.  
  58. Am Ende des File wird dann ein HUNK angehängt, der im  Moment  des  Ladens
  59. soviel bedeuten wird wie 40*256 Bytes, im File selbst aber nur einige Byte
  60. belegen wird.
  61. Es ist, als ob man einen Sack voller 10 Pfennig-Münzen  haben  würde,  und
  62. mit  dem  "ds.b 40*256" einen Schein zu 100 DM. Das Resultat ist immer das
  63. gleiche, aber der 100 DM-Schein ist etwas leichter. Das Gleiche  gilt  für
  64. den File, er ist "magerer".
  65.  
  66. Zu  Bemerken,  daß  das  "ds.b 40*256" nicht von "0" gefolgt ist, wie etwa
  67. beim DCB.B der Fall, denn "DS" bedeutet immer NULL. DCB hingegen kann auch
  68. was anderes sein.
  69.  
  70. Nun haben wir das  "Stück  Papier",  worauf  wir  unseren  Text  schreiben
  71. können. Jetzt fehlt noch der Font und die Druckroutine.
  72. Schauen wir uns mal an was ein Font eigentlich ist und  wie  er  aufgebaut
  73. ist.  Ein  Font  ist  ein  File, der die Anweisungen und Daten enthält, um
  74. etwas zu schreiben. Er kann in verschiedenen Formaten  vorliegen.  Er  ist
  75. eigentlich  nichts  anderes als eine Serie von Charaktern, einem unter dem
  76. anderen, um Präzise zu sein sind sie alle in  einer  Reihe:"ABCDEFGHI...".
  77. Einige Fonts sind in .IFF gezeichnet, also ein Screen aus Charaktern:
  78.  
  79.      ------------
  80.     |ABCDEFGHIJKL|
  81.     |MNOPQRSTUVWX|
  82.     |YZ1234567890|
  83.     |         |
  84.     |         |
  85.      ------------
  86.     
  87. Dieses  Bild  wir  dann in RAW umgewandelt, und die Buchstaben werden dann
  88. aus diesem Bild herausgenommen und an die  richtige  Stelle  ins  Bitplane
  89. kopiert:  wenn  ein  "A"  erscheinen  soll,  dann  wird  die Stelle im RAW
  90. herauskopiert und kommt mit einigen Move ins Bitplane. Wenn wir  also  ein
  91. "A" brauchen, wissen wir jedesmal, wo wir es zu suchen haben. Idem mit den
  92. anderen Lettern.
  93. Sprechen wir über das System, das wir in diesem  Kurs  mit  dem  8x8  Font
  94. anwenden werden: die Buchstaben brauchen 8 Pixel*8 Pixel, sie sind also so
  95. groß wie die Font des Kickstart. Eigentlich sind sie  etwas  schmaler,  da
  96. sie ja auch noch einen kleinen Abstand enthalten müssen, sonst würden sie,
  97. einmal aneinandergeschrieben, alle aufeinander kleben. Die Buchstaben sind
  98. dann   alle   in   der  "richtigen"  Reihenfolge  aufgestellt,  also  nach
  99. ASCII-Norm, das sieht so aus:
  100.  
  101.     dc.b    $1f,' !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO'
  102.     dc.b    'PQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~',$7F
  103.  
  104. Das $1f am Anfang und das $7f am Ende bedeuten, daß der  erste  Charakter,
  105. das  LEERZEICHEN, das nach dem $1f ist, also $20, gefolgt von dem "!", das
  106. den Wert $21 einnimmt, usw, bis zu den letzten Lettern, die dann  bei  $7F
  107. ankommen.  Das  grade  mal  um  euch  eine  Idee  von  der Ausrichtung der
  108. AsciiTabelle zu geben. Wir haben  schon  einmal  darüber  gesprochen,  daß
  109. Ziffern  auch  ASCII-Zeiche (Buchstaben) sein können, probiert ein "?$21".
  110. Das Ergebnis wird in Hex($), Dezimal, Binär und  ASCII  "...!"  angezeigt.
  111. Überzeugt? Wir haben auch gesehen, daß ein:
  112.  
  113.     dc.b    "hund"
  114.  
  115. äquivalent zu einem
  116.  
  117.     dc.b    $68,$75,$6e,$64
  118.  
  119. ist. Denn "h" ist im  Speicher  ein  $68,  ein  "u"  ein  $75  etc.  Jeder
  120. Charakter  besetzt  im Speicher ein Byte, also hat ein Text, der 5000 Byte
  121. lang ist, 5000 Zeichen.
  122. Kommen wir zu unserem Font zurück. Stellt euch ein Bild  vor,  das  nur  8
  123. Pixel  breit  ist,  aber  lang  genug,  um alle Buchstaben einen unter dem
  124. anderen zu enthalten:
  125.  
  126. !
  127. "
  128. #
  129. $
  130. %
  131. &
  132. '
  133. (
  134. )
  135. *
  136. +
  137. ,
  138. -
  139. .
  140. /
  141. 0
  142. 1
  143. 2
  144. 3
  145. 4
  146. 5
  147. 6
  148. 7
  149. 8
  150. 9
  151. :
  152. ;
  153. <
  154. =
  155. >
  156. ?
  157. @
  158. A
  159. B
  160. C
  161. D
  162. E
  163. F
  164. G
  165. H
  166. I
  167. J
  168. K
  169. L
  170. M
  171. N
  172. O
  173.     
  174. Und so weiter...
  175.  
  176. Den  Font,  den  wir  in unserem Kurs verwenden ist nichts anderes als ein
  177. Bild in RAW, das so aussieht. In Wirklichkeit wird ein  solcher  Font  mit
  178. speziellen  EDITOREN  entworfen, Programmen, dies eigens für Fonts gedacht
  179. wurden. Für Fonts, die größer sind ist es aber vorteilhaft, sie  in  einem
  180. Bild   zu  malen,  normalerweise  320x256,  und  eine  eigene  Routine  zu
  181. verwenden, um sie "auszuschneiden".
  182. Aber zum Anfang sehen wir uns den einfachsten Font an und wie er  auf  den
  183. Schrim  kommt:  zu  erst  muß einmal der String (Zeichenkette) vorbereitet
  184. werden, in dem steht, was dann angezeigt werden soll, z.B.:
  185.  
  186.     dc.b    "Erste Schrift!"    ; Bemerke: es können die ´´oder""
  187.                     ; verwendet werden.
  188.  
  189.     EVEN                ; oder: gleiche alles an GERADE
  190.                     ; Adressen an
  191.  
  192. Der Befehl EVEN dient dazu, ungerade Adressen zu vermeiden, die unter  dem
  193. dc.b entstehen können. Die Text-Strings bestehen aus einzelnen Buchstaben,
  194. und es kann passieren, daß eine  ungerade  Anzahl  dabei  rausspringt.  In
  195. diesem  Fall  wäre das Label darunter auf einer ungeraden Adresse, und das
  196. kann Fehler beim Assemblieren verursachen: beim 68000er müssen die Befehle
  197. immer  auf  geraden  Adressen liegen, wenn man nicht einen GURU MEDITATION
  198. verursachen will.  Ein  Move.L  oder  Move.W  auf  eine  ungerade  Adresse
  199. verursacht Crashes, GURUS und Explosionen.
  200. Also erinnert euch, immer ein Even am Ende eines  Textstrings  zu  setzen,
  201. oder versichert euch, daß die Anzahl gerade ist. Dafür könnt ihr auch eine
  202. 0 am Ende anhängen, und somit die Rechnung aufgehen  lassen.  Bei  GFXName
  203. habe isch das so gemacht:
  204.  
  205. GfxName:
  206.     dc.b    "graphics.library",0,0
  207.  
  208. Könnte man auch so schreiben:
  209.  
  210. GfxName:
  211.     dc.b    "graphics.library",0
  212.     even
  213.  
  214. Es reicht eine NULL am Ende, die andere setzt das Even. Gut, wenn wir also
  215. festgelegt  haben,  was  wir  anzeigen  wollen,  müssen  wir nur noch eine
  216. Routine schreiben, die das Richtige an den richtigen Ort gibt.
  217. Ich stelle euch schon die Routine vor, die einen Buchstaben druckt:
  218.  
  219. PRINT:
  220.     LEA    TEXT(PC),A0    ; Adresse des zu schreibenden Textes in a0
  221.     LEA    BITPLANE,A3    ; Adresse des Ziel-Bitplanes in a3
  222.     MOVEQ    #0,D2        ; Lösche d2
  223.     MOVE.B    (A0),D2        ; Nächster Charakter in d2
  224.     SUB.B    #$20,D2        ; ZÄHLE 32 VOM ASCII-WERT DES BUCHSTABEN WEG,
  225.                 ; SOMIT VERWANDELN WIR Z.B. DAS LEERZEICHEN
  226.                 ; (Das $20 entspricht), IN $00, DAS
  227.                 ; MALZEICHEN ($21) IN $01...
  228.     MULU.W    #8,D2        ; MULTIPLIZIERE DIE ERHALTENE ZAHL MIT 8,
  229.                 ; da die Charakter ja 8 Pixel hoch sind
  230.     MOVE.L    D2,A2
  231.     ADD.L    #FONT,A2    ; FINDE DEN GEWÜNSCHTEN BUCHSTEBEN IM FONT
  232.  
  233.                 ; DRUCKE DEN BUCHSTABEN ZEILE FÜR ZEILE
  234.     MOVE.B    (A2)+,(A3)    ; Drucke Zeile 1 des Buchstaben
  235.     MOVE.B    (A2)+,40(A3)    ; Drucke Zeile 2  "    "
  236.     MOVE.B    (A2)+,40*2(A3)  ; Drucke Zeile 3  "    "
  237.     MOVE.B    (A2)+,40*3(A3)  ; Drucke Zeile 4  "    "
  238.     MOVE.B    (A2)+,40*4(A3)  ; Drucke Zeile 5  "    "
  239.     MOVE.B    (A2)+,40*5(A3)  ; Drucke Zeile 6  "    "
  240.     MOVE.B    (A2)+,40*6(A3)  ; Drucke Zeile 7  "    "
  241.     MOVE.B    (A2)+,40*7(A3)  ; Drucke Zeile 8  "    "
  242.  
  243.     RTS
  244.   
  245. Habt ihr´s schon verstanden??? 
  246. Analysieren wir sie Schritt für Schritt:
  247.  
  248.     LEA    TEXT(PC),A0    ; Adresse des zu schreibenden Textes in a0
  249.     LEA    BITPLANE,A3    ; Adresse des Ziel-Bitplanes in a3
  250.     MOVEQ    #0,D2        ; Lösche d2
  251.     MOVE.B    (A0),D2        ; Nächster Charakter in d2
  252.   
  253. Bis hierher keine Probleme,, wir haben in d2 den Wert des Buchstaben, wenn
  254. es ein "A" wäre, dann wäre dieser Wert $41.
  255.  
  256.     SUB.B    #$20,D2        ; ZÄHLE 32 VOM ASCII-WERT DES BUCHSTABEN WEG,
  257.                 ; SOMIT VERWANDELN WIR Z.B. DAS LEERZEICHEN
  258.                 ; (Das $20 entspricht), IN $00, DAS
  259.                 ; MALZEICHEN "*" ($21) IN $01...
  260.   
  261. Auch was hier passiert müßte klar sein, schauen wir mal, wieso wir 32($20)
  262. abziehen:
  263.  
  264.     MULU.W    #8,D2        ; MULTIPLIZIERE DIE ERHALTENE ZAHL MIT 8,
  265.                 ; da die Charakter ja 8 Pixel hoch sind
  266.     MOVE.L    D2,A2
  267.     ADD.L    #FONT,A2    ; FINDE DEN GEWÜNSCHTEN BUCHSTABEN IM FONT
  268.   
  269. Diese  Operation gibt uns als Ergebnis in A2 die Adresse des Buchstaben im
  270. Font, also die Adresse, von der wir den Charakter auschneiden  müssen,  um
  271. ihn dann in unser Bitplane einzufügen.
  272. Was ist passiert? Erinnert ihr euch, daß die  Charakter  im  Font  in  der
  273. gleichen Reihenfolge eingesetzt wurden wie im ASCII-Standart? Wenn wir nun
  274. diesen ASCII-Wert kennen, können wir auch unser hypotetisches "A" im  Font
  275. ausfindig  machen. Wenn jeder Buchstabe 8 Pixel mal 8 Pixel groß ist, dann
  276. bedeutet das, daß er 8 Bit lang ist, also 1 Byte pro Zeile, mit  8  Zeilen
  277. ergibt sich daraus dann 8 Bytes.
  278. Also befindet sich das Leerzeichen (erstes Zeiuchen im Font) am Anfang des
  279. Fonts,  und  das nächste Zeichen beginnt 8 Byte später (Rufezeichen), usw.
  280. Durch das Abziehen von $20 vom Wert erhält das Leerzeichen  nun  den  Wert
  281. $00,  das  Rufezeichen  $01, ... , das "A" bekommt $21, das "B" $22 und so
  282. fort. Wir brauchen also nur noch diese Ziffer mit 8 zu multiplizieren, und
  283. wir  haben  die  richtige  Distanz  vom  Anfang  des  Fonts  weg!  Nochmal
  284. wiederholt:
  285.  
  286.     SUB.B    #$20,D2        ; ZÄHLE 32 VOM ASCII-WERT DES BUCHSTABEN WEG,
  287.                 ; SOMIT VERWANDELN WIR Z.B. DAS LEERZEICHEN
  288.                 ; (Das $20 entspricht), IN $00, DAS MALZEICHEN
  289.                 ; ($21) IN $01...
  290.     MULU.W    #8,D2        ; MULTIPLIZIERE DIE ERHALTENE ZAHL MIT 8,
  291.                 ; da die Charakter ja 8 Pixel hoch sind
  292.  
  293. Nun haben wir in  D2  die  Distanz  (Offset)  zum  Anfang  des  bestimmten
  294. Buchstaben  vom  Anfang  des  Fonts  weg  gerechnet!  Um nun die effektive
  295. Adresse im Speicher zu finden, zählen  zu  diesem  "Offset  innerhalb  des
  296. Fonts" noch die Adresse des Fonts selbst dazu:
  297.  
  298.     MOVE.L    D2,A2
  299.     ADD.L    #FONT,A2    ; FINDE DEN GEWÜNSCHTEN BUCHSTEBEN IM FONT...
  300.   
  301. Nun ahben wir in A2 die  Adresse,  wo  sich  unser  auserwählte  Buchstabe
  302. befindet, z.B. das "A". Nun noch von FONT auf den Bildschirm, also auf das
  303. Bitplane von 320x256, in dem jede Zeile 40 Byte lang ist:
  304.  
  305.                 ; DRUCKE DEN BUCHSTABEN ZEILE FÜR ZEILE
  306.     MOVE.B    (A2)+,(A3)    ; Drucke Zeile 1 des Buchstaben
  307.     MOVE.B    (A2)+,40(A3)    ; Drucke Zeile 2  "    "
  308.     MOVE.B    (A2)+,40*2(A3)  ; Drucke Zeile 3  "    "
  309.     MOVE.B    (A2)+,40*3(A3)  ; Drucke Zeile 4  "    "
  310.     MOVE.B    (A2)+,40*4(A3)  ; Drucke Zeile 5  "    "
  311.     MOVE.B    (A2)+,40*5(A3)  ; Drucke Zeile 6  "    "
  312.     MOVE.B    (A2)+,40*6(A3)  ; Drucke Zeile 7  "    "
  313.     MOVE.B    (A2)+,40*7(A3)  ; Drucke Zeile 8  "    "
  314.   
  315. Die Kopie erfolgt Zeile für Zeile, der Charakter ist 8  Zeilen  hoch,  und
  316. jede besteht aus 8 Bit (1 Byte):
  317.  
  318.     12345678
  319.  
  320.     ...###.. Zeile  1 - 8 bit, 1 byte
  321.     ..#...#. 2
  322.     ..#...#. 3
  323.     ..#####. 4
  324.     ..#...#. 5
  325.     ..#...#. 6
  326.     ..#...#. 7
  327.     ........ 8
  328.  
  329. Also  um  eine  Zeile  pro  Durchgang  zu kopieren müssen wir ein Byte pro
  330. Durchgang kopieren. Aber der ZielScreen ist 40 Byte pro Zeile  breit,  wir
  331. müssen bedenken, daß jede Zeile unter die andere kommen muß, wenn wir also
  332. nicht jedesmal 40 Byte überspringen würden, dann sähe alles so aus:
  333.  
  334.     ...###....#...#...#...#...#####...#...#...#...#...#...#.........
  335.  
  336. Wir  müssen  aber  ein  Byte  kopieren,  ZEILE WECHSELN, indem wir 40 Byte
  337. weiterspringen, und dann das nächste Byte kopieren:
  338.  
  339.  
  340.     MOVE.B  (A2)+,(A3)    ; Drucke Zeile 1 des Buchstaben
  341.  
  342. Auf dem Monitor:
  343.  
  344.     ...###..
  345.  
  346.     MOVE.B  (A2)+,40(A3)    ; Drucke Zeile 2  (40 Bytes weiter)
  347.  
  348.  
  349. Auf dem Monitor:
  350.     
  351.     ...###..
  352.     ..#...#.
  353.  
  354.     
  355.     MOVE.B  (A2)+,40*2(A3)  ; Drucke Zeile 3  (80 Bytes weiter)
  356.  
  357. Auf dem Monitor:
  358.  
  359.     ...###..
  360.     ..#...#.
  361.     ..#...#.
  362.  
  363.  
  364. Und  so  weiter. Für einen Screen, der 8 Byte breit ist (640x256 in HIRES)
  365. müßte die Routine nur so abgeändert werden:
  366.  
  367.     MOVE.B    (A2)+,(A3)    ; Drucke Zeile 1 des Buchstaben
  368.     MOVE.B    (A2)+,80(A3)    ; Drucke Zeile 2  "    "
  369.     MOVE.B    (A2)+,80*2(A3)    ; Drucke Zeile 3  "    "
  370.     MOVE.B    (A2)+,80*3(A3)    ; Drucke Zeile 4  "    "
  371.     MOVE.B    (A2)+,80*4(A3)    ; Drucke Zeile 5  "    "
  372.     MOVE.B    (A2)+,80*5(A3)    ; Drucke Zeile 6  "    "
  373.     MOVE.B    (A2)+,80*6(A3)    ; Drucke Zeile 7  "    "
  374.     MOVE.B    (A2)+,80*7(A3)    ; Drucke Zeile 8  "    "
  375.  
  376. Sehen wir uns in der Praxis an, wie dieses "A" auf unser  Bitplane  kommt.
  377. Listing6a.s, wenn ich bitten darf.
  378.  
  379. In Listing6b.s gehen wir zu einer ganzen Zeile über.
  380.  
  381. Und zum Schluß drucken wir soviele Zeilen, wie wir wollen. Dafür seht euch
  382. Listing6c.s an. Diese Routine ist  die  ENDGÜLTIGE,  die  ihr  immer  dann
  383. verwenden könnt, wenn ihr etwas auf den Bildschirm schreiben wollt.
  384.  
  385. Warum  nicht  den  eigenen  Font zeichnen? In Listing6c2.s ist der Font in
  386. dc.b-Format, so wie dieses Beispiel:
  387.  
  388. ; "B"
  389.     dc.b    %01111110
  390.     dc.b    %01100011
  391.     dc.b    %01100011
  392.     dc.b    %01111110
  393.     dc.b    %01100011
  394.     dc.b    %01100011
  395.     dc.b    %01111110
  396.     dc.b    %00000000
  397.  
  398. Die Buchstaben sind mit vielen dc.b % in den Speicher gegeben (binär). Ihr
  399. könnt jeden einzelnen Charakter so abändern, wie ihr wollt. Wenn ihr einen
  400. eigenen  Font  herstellt,  speichert ihr auf eine andere Diskette oder auf
  401. Hard Disk!
  402.  
  403. Nun versuchen wir etwas, was  wir  noch  nie  versucht  haben:  auf  einem
  404. einzigen  Screen  lassen  wir gleichzeitig ein Bild in LowRes und eines in
  405. HiRes zusammenleben!  Der  Amiga  kann  gleichzeitig  mehrere  Auflösungen
  406. anzeigen  (was  mir  auf  den  PC´s  nicht bekannt wäre), einfach ein Wait
  407. setzen und darunter mit einem BPLCON0 eine  andere  Auflösung  einstellen,
  408. genau so, als ob wir nur die Farben umdefinieren würden!
  409. Z.B. könnten wir von der ersten Zeile bis zu Zeile $50 ein Bild in HAM  zu
  410. 4096  Farben  LowRes  anzeigen,  darunter  eines  in  HiRes mit 16 Farben,
  411. nochmal darunter ein weiteres in LowRes zu 32 Farben, und  so  weiter.  In
  412. einigen  Spielen  ist z.B. das Spielfeld, in dem sich die Figur bewegt, in
  413. LowRes gehalten, und das Bedienfeld darunter in HiRes (siehe AGONY).
  414.  
  415. Versuchen wir es sofort. In Listing6d.s haben wir ein Bild in LowRes  über
  416. einem anderen in HiRes.
  417.  
  418. Kommen  wir  nun  zu  einem "Trick", der uns einen "Relief-Effekt" bei den
  419. Worten hervorruft, die wir auf den Schirm malen: in Listing6e.s aktivieren
  420. wir  2  Bitplanes  statt  nur  einem,  und  wir  uberlagern den ersten dem
  421. zweiten, nur um eine Zeile nach unten verrutscht. Was passiert,  wenn  wir
  422. zwei  gleiche  Bilder übereinanderlegen, die durchsichtig erscheinen, aber
  423. ein bißchen verschoben? Sie "verdoppeln" sich! Und was passiert, wenn  wir
  424. das  "obere",  verdoppelte  Bitplane  dunkler  machen  als  das untere? Es
  425. passiert, daß ihr verstanden habt, wie Listing6e.s funktioniert.
  426.  
  427. Übrigens, weil wir gerade von Überlagerungen sprechen; wieso nicht einfach
  428. über  einem  Bild ein anderes Bitplane legen und darauf schreiben?? So was
  429. wird in Listing6f.s gemacht.
  430.  
  431. In Listing6g.s sehen wir den  "Transparenz"-Effekt.  Eine  Schrift  bewegt
  432. sich über einem Bild.
  433.  
  434. In  Listing6h.s sehen wir eine Methode, um Texte in 3 Farben zu schreiben,
  435. indem wir zwei Texte auf zwei Bitplanes überlappen lassen.
  436.  
  437. In Listing6i.s lassen wir einen der der Farben des Textes  blinken,  indem
  438. wir  eine  vorgefertigte  TABELLE  mit Werten benutzen. Wir haben schon in
  439. LEKTION1 von Tabellen gesprochen, jetzt seht ihr in der Praxis, wie so was
  440. geht.
  441.  
  442. In Listing6l.s seht ihr eine Variation der Routine, die eine TAB liest, um
  443. die Farben zu ändern; die Änderung liegt darin, daß statt die Tabelle  von
  444. Anfang bis zum Ende zu lesen, und dann von vorne zu beginnen, sie hier bis
  445. zum Ende gelesen wird, und dann wird von hinten nach vorne gegangen.
  446.  
  447. Die Tabellen können für viele Zwecke nützlich bis unentbehrlich sein.  Zum
  448. Beispiel,  um  Feder- und Sprungeffekte zu erzeugen. Sehen wir den Vorteil
  449. einer Tabelle gegenüber einem simplen Sub und Add, wenn es  um  Bewegungen
  450. geht. Ich verweise auf Listing6m.s...
  451.  
  452. Weil wir gerade von Bewegung sprechen: wir haben für den Horizontal-Scroll
  453. bislang nur das $dff102 verwendet, das uns aber maximal 16 Pixel  in  eine
  454. Richtung  erlaubte.  Aber wie können wir dann den Bildschirm beliebeig hin
  455. und herscrollen, und soviel wir wollen? Die Antwort ist  relativ  einfach:
  456. wir verwenden auch die Bitplanepointers!
  457. Wir haben schon gesehen, daß mit ihnen ein  Scroll  nach  Oben  und  Unten
  458. möglich ist, wir brauchen nur eine/mehrere Zeilen dazu- oder wegzählen (40
  459. in LowRes, 80 in HiRes). Aber wir können  auch  vor-  und  zurückscrollen,
  460. aber  nur  in  Schritten zu 8 Pixel (1 Byte). Wie? Zu den Bitplanepointers
  461. ein Byte dazuzählen oder abziehen, jenachdem, in welche Richtung wir gehen
  462. wollen. Somit ergibt sich ein Scroll von einem Byte, eben 8 Pixel.
  463. Wenn wir mit den Bitplanepointers 8 Pixel scrollen  können,  und  mit  dem
  464. $dff102 jeweils 1 Pixel, dann können wir "fließende" Bewegungen eigentlich
  465. ganz leicht herstellen: mit dem $dff102 in eine Richtung,  bis  maximal  8
  466. Pixel,  und  dann  mit  dem  BPLPointer einen großen "Schritt" von 8 Pixel
  467. machen, und zugleich das BPLCON1 ($dff102)  auf  NULL  setzen.  Der  große
  468. Schritt könnte so aussehen:
  469.  
  470.     subq.l    #1,BITPLANEPOINTER
  471.  
  472. Somit  sind wir auf das neunte Pixel gekommen. Dann wieder Pixel für Pixel
  473. mit dem BPLCON1, und bei 8 angekommen, auf NULL setzen  und  einen  großen
  474. Schritt.  In  den Beispielen aber lasse ich den großen Schritt nur alle 16
  475. Pixel machen, da das BPLCON1 ja 16 Pixel verträgt. Für 16 Pixel muß dann 2
  476. zu  den  BitplanePointers addiert oder subtrahiert werden (Da 1 ja das PIC
  477. um 8 Pixel bewegte). Ich bewege das Bild also um 1 einzelnes Pixel mit dem
  478. $dff102,  und  verwende  seine  maximale  "Spannweite",  von  $00 bis $FF,
  479. insgesamt 16 Positionen, danach mache ich eine Sprung zu 16 Pixel mit  dem
  480. Bitplanepointers, etwa mit ADDQ oder SUBQ #2,BITPLANEPOINTERS.
  481. Hier eine Routine, die ein  Bild  soweit  nach  rechts  scrollt,  wie  wir
  482. wollen,  in  Schritten  zu 1 Pixel. Betrachtet MEINBPCON1 als das Byte des
  483. $dff102.
  484.  
  485. Rechts:
  486.     CMP.B    #$ff,MEINBPCON1    ; sind wir bei maxim. Scroll angekommen (15)?
  487.     BNE.s    CON1ADDA    ; wenn noch nicht, geh noch eines weiter,
  488.                 ; verwende das BPLCON1
  489.  
  490. ; Liest die Adresse des Bitplane
  491.  
  492.     LEA    BPLPOINTERS,A1    ; Mit diesen 4 Operationen holen wir aus der
  493.     move.w    2(a1),d0    ; Copperlist die Adresse, wo das $dff0e0 gerade
  494.     swap    d0        ; hinpointet und geben es in d0
  495.     move.w    6(a1),d0
  496.  
  497. ; Scrollt nach Rechts um 16 Pixel, mit dem Bitplanepointer
  498.  
  499.     subq.l    #2,d0        ; Pointet 16 Bit weiter nach hinten (die PIC
  500.                 ; scrollt um 16 Pixel weiter nach Rechts)
  501.  
  502. ; Läßt das BPLCON1 wieder bei 0 starten
  503.  
  504.     clr.b    MEINBPCON1    ; löscht den Hardware-Scroll BPLCON1 ($dff102)
  505.                 ; wir sind ja 16 Pixel mit dem Bitplanepointer
  506.                 ; gesprungen, nun müssen wir wieder bei NULL
  507.                 ; starten, um mit dem $dff102 Pixel für
  508.                 ; Pixel nach Rechts zu scrollen
  509.  
  510.     move.w    d0,6(a1)   ; Kopiert das niederw. Word der Adresse des Plane
  511.     swap    d0       ; vertauscht die 2 Word
  512.     move.w    d0,2(a1)   ; Kopiert das hochwertige Word der Adresse des Plane
  513.     rts           ; Steige aus der Routine aus
  514.  
  515. CON1ADDA:
  516.     add.b    #$11,MEINBPCON1    ; scrolle das Bild um 1 Pixel nach Rechts
  517.     rts            ; Raus aus der Routine
  518.  
  519.  
  520. Die Routine erhöht das BPLCON1 ($dff102) jeweils um eins, es läßt es  alle
  521. möglichen Positionen durchlaufen:
  522. 00,11,22,33,44,55,66,77,88,99,aa,bb,cc,dd,ee,ff, dann springt es zum Pixel
  523. ff+1, indem es zwei Operationen durchführt:
  524.  
  525. 1) 2 Bytes (1 Word, 16 Bits) im Bitplanepointer zurückpointen, um das Bild
  526.    um 16  Pixel nach  rechts  scrollen  zu lassen  (also 1 Pixel  nach der
  527.    Position $FF, also 15, die im vorigen Frame erreicht wurde.
  528.  
  529. 2) Das $dff102 auf NULL setzen, da  wir  ja  16  Pixel  in  einem  Schritt
  530.    gemacht  haben. Ansonsten würden sich die 16 Pixel des Bitplanepointers 
  531.    zu den 15 ($ff) des  $dff102 summieren. Aber durch  Löschen des BPLCON1 
  532.    starten wir  wieder bei $00 + 16 = sechzehntes  Pixel, danach gehen wir 
  533.    weiter bis zum 15ten  mit dem BPLCON1, und  lassen die Bitplanepointers 
  534.    unverändert.
  535.  
  536. Wenn das noch nicht klar sein sollte, folgt diesem Schema,  das  #  stellt
  537. das Bild dar, das sich nach rechts bewegt:
  538.  
  539.                 ; WERT BPLCON1  - BYTE VON BPLPOINT. ABGEZOGEN
  540.  
  541. #                ;    $00    -    0    - tot. pixel:
  542.  #                ;    $11    -    0    -    1
  543.   #                ;    $22    -    0    -    2
  544.    #                ;    $33    -    0    -    3
  545.     #                ;    $44    -    0    -    4
  546.      #                ;    $55    -    0    -    5
  547.       #                ;    $66    -    0    -    6
  548.        #            ;    $77    -    0    -    7
  549.     #            ;    $88    -    0    -    8
  550.      #            ;    $99    -    0    -    9
  551.       #            ;    $aa    -    0    -    10
  552.        #            ;    $bb    -    0    -    11
  553.         #            ;    $cc    -    0    -    12
  554.          #            ;    $dd    -    0    -    13
  555.           #            ;    $ee    -    0    -    14
  556.            #        ;    $ff    -    0    -    15
  557.         #        ;    $00    -    2    -    16
  558.          #        ;    $11    -    2    -    17
  559.           #        ;    $22    -    2    -    18
  560.            #        ;    $33    -    2    -    19
  561.             #        ;    $44    -    2    -    20
  562.              #        ;    $55    -    2    -    21
  563.               #        ;    $66    -    2    -    22
  564.                #    ;    $77    -    2    -    23
  565.  
  566. Und so weiter...
  567.  
  568. Dieses Schema spricht für sich: wenn wir z.B. 22 Pixel nach rechts wollen,
  569. dann  müssen  wir  2  von  den  Bitplanepointers  abziehen und das BPLCON1
  570. ($dff102) aus $66 setzen.
  571.  
  572. Möchten wir nach links, müßten  wir  alle  16  Pixel  2  zu  den  Pointers
  573. dazuzählen, und mit dem $dff102 rückwärts gehen: $ff, $ee, $dd...
  574.  
  575. Sehen  wir in Listing6n.s die Routine im Härtetest. Ihr bemerkt sicher die
  576. Störung am linken Rand des Screens; das ist kein Fehler  in  der  Routine,
  577. aber  eine  Charakteristik  der  Hardware  des Amiga, um sie zu beseitigen
  578. reicht eine kleine Ausbesserung. Sie ist im Listing selbst erklärt.
  579.  
  580. Da wir ja nun ein Bitplane in jede Richtung scrollen können,  wieweit  wir
  581. wollen,  wieso  bewegen  wir  dann nicht ein Bild, das größer ist, als der
  582. Bildschirm selbst?? In Listing6o.s tun wir´s : ein  Bild,  das  640  Pixel
  583. breit  ist, rollt in einem normalem LowRes - Screen von 320x256 nach links
  584. und rechts.
  585.  
  586. Wir haben schon bei den Tabellen die Verwendung eines Longword als Pointer
  587. auf eine Adresse gesehen:
  588.  
  589. POINTER:
  590.     DC.l    TABELLE
  591.  
  592. Im Longword "POINTER" wird die  Adresse  von  Tabelle  assembliert,  somit
  593. können  wir  festhalten, wohin wir in der Tabelle gekommen sind, indem wir
  594. die Länge eines Elementes dazuzählen oder wegzählen.
  595. Wir müssen jedesmal abspeichern, wohin wir gerade gekommen  sind,  da  die
  596. Routine  nur  einmal pro Fotogramm ausgeführt wird, und nicht durchgehend.
  597. Es ist also möglich, daß andere Routinen in  der  Zwischenzeit  aufgerufen
  598. werden,  und  unsere  Werte  "verwischen".  Wenn diese Routine also wieder
  599. aufgerufen  wird,  dann  muß  sie   dort   fortfahren,   wo   sie   vorhin
  600. stehengeblieben ist. Sie kann das durch ein simples
  601.  
  602.     MOVE.L  POINTER(PC),d0    ; In d0 ist die  Adresse,  wohin wir
  603.                 ; das letzte Mal gekommen sind.
  604.  
  605. tun.  Vor  dem  Aussteigen  aus  der Routine muß nur die aktuelle Position
  606. abgespeichert werden. Diese Systematik  kann  vielfach  verwendet  werden,
  607. z.B.  um  nur  bei  jedem Fotogramm einen Buchstaben auf den Bildschirm zu
  608. bringen, anstatt den ganzen Text auf einmal hinaufzuklatschen.  Dafür  muß
  609. nur die PRINT: - Routine etwas modifiziert werden und zwei Pointer erzeugt
  610. werden: einer, der auf den letzten gedruckten Buchstaben zeigt, und einer,
  611. der auf die letzte Adresse zeigt, wo wir in unserem Bitplane gewesen sind.
  612. So ist es, als würden wir einen Buchstaben schreiben, die Routine für  die
  613. Dauer eines Frames einfriefen, und sie danach weiterlaufen lassen. Aber in
  614. Wirklichkeit frieren wir sie nicht ein,  wir  führen  sie  aus,  um  einen
  615. Buchstaben  zu schreiben, speichern den erreichten Stand der Dinge ab, und
  616. fahren später fort. Das Listing, das diese Theorien in die Praxis umsetzt,
  617. heißt Listing6p.s
  618.  
  619. In  einem  Bitplane  können  wir -außer Text drucken- auch Zeichnungen wie
  620. Schachbretter, Webmuster oder Balken hineinmalen.  Einfach  die  richtigen
  621. Bits auf 1 setzten!!! In Listing6q.s befinden sich einige Beispiele.
  622.  
  623. Wir  sind  am  Ende von LEKTION6 angekommen, nun bleibt uns nichts anderes
  624. übrig,  als  einige   Listings   zusammenzusetzen,   verbunden   mit   den
  625. "Neuigkeiten"   dieses   Kapitels,   und   so  ergibt  sich  das  gewohnte
  626. "Letzte_Mega_Listing", mit allem Drum und Dran, auch Musik: Listing6r.s
  627.  
  628. Nun gehen wir zum Studium der Sprites  über.  Ihr  müßt  nur  LEKTION7.TXT
  629. laden  und  dann den Path mit "V df0:LISTINGS3" wechseln. Die Listings für
  630. dieses Kapitel befinden sich in dieser Directory auf Disk1.
  631.  
  632.