PlanetSwitch Planet3DS PlanetVita PSP.de PlanetiPhone Classics Forum

PGN-ID:[?] (Nicht eingeloggt)
Login
Registrieren
PlanetDS PlanetGameboy N-Page.de

Einsteigertutorial 3: Joypad und DMA

zurück

Autor: hurik

Kategorie: devtut
Umfang: 1 Seiten

Seite   1  

Kommentare:

Kommentieren (-)

Game Boy Advance Artikel vom 29.04.2002












































Joypad und DMA (V1)
Inhaltsverzeichnis:
Einleitung
Header Dateien

Joypad
DMA
Ende
Einleitung
Hallo, liebe Leserschaft! Ich freue
mich, dass ihr bis zum dritten Teil meines und von LuckyGeorge Tutorials
vorgearbeitet habt. In dem Tut lernt ihr, wie ihr euer Programm über das
Joypad steuern könnt, und was DMA ist und was es euch bringt und was ihr
tolles damit machen könnt. Dieses Tutorial wird ziemlich kurz, aber es
ist trotzdem verdammt wichtig! Also viel Spaß und Erfolg!
Header Dateien

Hier ist die Header Datei,
die ich euch im vorigen Tutorial versprochen habe! Alle weiteren Tutorials
sind auf diese Headerdatei bezogen. Wer den MS VC++ Wizard (Wie im Tutorial
davor muss man Dovotos Libs wählen.) benutzt, kann dies tun, da die Libs
gleich aufgebaut sind, und alles gleich ist. Und hier könnt ihr das File
runterladen: href="http://andreas.abi-2005.org/devgba/gball.zip">gball.h downloaden
(Gepackt ist ein Zipfile!

Joypad

Bei einem Spiel ist die
Steuerung ein ganz wichtiger Punkt. Was wäre ein Spiel ohne Steuerung?
Und was wäre ein Spiel ohne GUTER Steuerung? Man darf die Steuerung in
einem Spiel nie hinten anstellen, also dies ist ein ganz wichtiger Punkt
hier, und er sollte genau studiert werden. Wobei, eigentlich ist es einfach!
Um Genau zu sein ist es sogar verdammt einfach. Also einfach mal anschauen
und verstehen! Als erstes hier noch das File mit den 2 Beispielprogrammen:
t3.zip

Das erste Beispiel, dass wir jetzt besprechen, ist die Datei "t3-1.cpp".
Die "make t3-1.bat" compiliert das ganze und spuckt das Programm
aus in die Rom "t3-1.gba". Nun startet mal die Rom und schaut
euch an, was das Programm kann. Also ihr seht dann das:


src="http://andreas.abi-2005.org/devgba/artikel/hurik/dt3/t3-1.jpg" width="240" height="160">


Drückt ihr nach rechts, dann kommt das:


src="http://andreas.abi-2005.org/devgba/artikel/hurik/dt3/t3-2.jpg" width="240" height="160">


Drückt ihr nach Links, kommt ihr wieder zum ersten, und
das die ganze Zeit! Toll, nicht? (Ich steh auf Selbstdarstellung! =) )
Na aber egal. In dem Beispiel benutzt ihr nur 2 Tasten, aber das reicht
vollkommen, da man die Tasten gleich anspricht, und wenn ihrs bei einer
Taste könnt, könnt ihr es bei allen! Aber hier, jetzt analysieren wir
den Quellcode Zeile für Zeile:


#include "gball.h"

Das ist meine Include Datei. Sie ist eigentlich Dovotos Headers zusammen
geworfen! Wobei ich sie leicht verbessert, andersweitig ergänzt habe,
und auch neuere Version genommen habe, die von anderen (z.B. Starmonkey)
verbessert wurden.


#include "hurik.h"

#include "slideshow.h"

Das sind die Bilddateien, die mit Dovotos pcx->gba Programm
in Header umgewandelt worden sind.


int main(void)

{

Start der Hauptschleife.


    SetMode(MODE_4
| BG2_ENABLE);

Setzt den Bildmodus auf Mode 4
und schaltet den Bachground Nummer 2 an.


    for(c =
0; c < 256; c++)

        BGPaletteMem[c] = hurikPalette[c];

Kopiert die Palette des des ERSTEN Bildes in den Speicher.
Da wir am Start, bevor man irgendwas drückt, das erste Bild sehen wollen.
Falls sich jemand fragt, woher die c Variable kommt, obwohl wir die gar
net deklariert haben, dem muss ich sagen, dass diese in der gball.h deklariert
wird. Ist einfach meine Countervariable, die man immer brauchen kann.


    for(c =
0; c < 19200; c++)

        VideoBuffer[c] = hurikData[c];

Kopiert die Bilddaten des ERSTEN Bildes in den Speicher.



    while(1)

    {

Das ist hier eine Endlosschleife, die das Programm am Leben
lässt, sodass es bis in die Ewigkeit läuft!


        if(!(*KEYS
& KEY_LEFT))

        {

Das ist eine ganz simple Abfrage, ob die eine Taste gedrükt
wurde (KEYS), und ob es die Linke war (KEY_LEFT). Wichtig ist nur, dass
das ganze "!(*KEYS & KEY_LEFT" in der Form dasteht! Und
das war schon das ganze Tastengeheimnis. Nach dem Programm gibts noch
ne Übersicht zu allen Tasten! Super einfach wie gesagt!


            for(c
= 0; c < 256; c++)

                BGPaletteMem[c]
= hurikPalette[c];

Kopiert die Palette des des ERSTEN Bildes in den Speicher.


            for(c
= 0; c < 19200; c++)

                VideoBuffer[c]
= hurikData[c];

Kopiert die Bilddaten des ERSTEN Bildes in den Speicher.


        }

Ende der Tastenifabfrage.


        if(!(*KEYS
& KEY_RIGHT))

        {

Siehe oben. Genau das Gleiche, nur halt passiert hier was bei
der rechten Taste.


            for(c
= 0; c < 256; c++)

                BGPaletteMem[c]
= slideshowPalette[c];

Kopiert die Palette des des ZWEITEN Bildes in den Speicher.


            for(c
= 0; c < 19200; c++)

                VideoBuffer[c]
= slideshowData[c];

Kopiert die Bilddaten des ZWEITEN Bildes in den Speicher.


        }


    }

}

Erste Klammer ist das Ende der Tastenschleife. Zweite Klammer
schliesst die Endlosschleife ab, die das Programm am Leben lässt. Die
letzte und dritte Klammer schliesst das Programm ab.



So jetzt noch eine Übersicht aller Tasten:

KEY_A

KEY_B

KEY_SELECT

KEY_START

KEY_RIGHT

KEY_LEFT

KEY_UP

KEY_DOWN

KEY_R

KEY_L

So, ich denke, dass alles Selbsterklärend ist.


Also das wars schon! Also viel Spass mit eurem Wissen und
macht jetzt schön mit dem 2 Teil des Tuts weiter, mit DMA. Viel Spass!

DMA
Das Programm oben ist ja
ganz nett, doch es macht igendwelche nicht schönen Grafikfehler beim aufbau
des nächsten Bildes. Hier ein Beispiel:

src="http://andreas.abi-2005.org/devgba/artikel/hurik/dt3/t3-3.jpg" width="240" height="160">


Hier sieht man gut, dass die Pallete kopiert wurde, aber
nur die halben Bilddaten. Einfach nicht schön. Und was machen wir jetzt?
Nein, wir benutzten nicht einen Bildmodus mit Backbuffer! Warum? Das wäre
zu einfach! Ausserdem will ich das ihr DMA lernt. Also dann startet mal
die Rom "t3-2.gba", und schaut euch das an, und ihr werdet sehen,
dass hier das Programm genau gleich ist, bis auf das, dass keine Grafikfehler
entstehen. Aber bevor wir das Programm auseinandernehmen, ein paar Informationen
zu DMA. DMA heist DirectMemoryAcces. Und mit DMA können wir Daten von
A nach B kopieren und das noch schnell, um genau zu sein verdammt schnell,
und schneller geht es nicht (Auf dem GBA.)! Also was mit DMA zu kopieren
ist der schnellste Weg. Und das brauchen wir hier. Denn der andere Weg
war zu langsam. Es gibt 4 verscheidene DMA Modi.



bordercolor="#000000">















DMA 0 DMA 0 ist der DMA Modus
der die höchste Priorität hat. Er wird nicht von anderen Prozessen
unterbrochen und ist für Zeitkritische Aufgaben da.
DMA 1 width="437">Das sind die Modi die nur für Soundsachen benutz werden
also im moment für uns uninterresant.
height="12">DMA 2
DMA 3 Das ist der Modus, den
man halt für so standart Datenkopieren benutzen sollte, und den
wir auch benutzten.

Und jetzt schauen wir und das Programm mal an damit wir
es verstehen. (Die Make und Source ist genau so wie bei Joypad, nur
halt ner 2 statt der 1.)



#include "gball.h"


#include "hurik.h"

#include "slideshow.h"


int main(void)

{

    SetMode(MODE_4 | BG2_ENABLE);


Bis hier ist alles wie oben! Aber nun was ist das das unten? Sieht seltsam
aus! Das schauen uns wir mal genauer an!


    REG_DMA3SAD
= (u32)hurikPalette;

    REG_DMA3DAD = (u32)BGPaletteMem;

    REG_DMA3CNT = 256 | DMA_16NOW;

Was ist den das für ein Gebilde? Da kopieren wir Daten mit
DMA. Und jezt erkläre ich das hier mal genauer.

REG_DMA3SAD ist eine Speicheradresse. Ihr seht das DMA3, dass sagt, dass
wir DMA 3 Modus benutzen. SAD steht für "Sourceadress" und,
das heist übersetzt "Quelladresse". Und das ist hier die Quelle,
woher wir die Daten kopieren. So einfach.

REG_DMA3DAD ist auch eine Speicheradresse, wer häts gedacht =) ! Die ist
genau so wie die da oben, bis auf dass statt dem S ein D da ist. Und das
DAD steht für "Destinationadress", und das heisst "Zieladresse".
Also das ist die Adresse, wo wir die Daten hinkopieren. Einfach oder?

REG_DMA3CNT ist auch eine Adresse, nur hier kommen jetzt Daten rein. Diese
Speicher Adresse ist etwas komplexer. Hier ein kleines Bild, das die Adresse
einfach mal ein bischen besser darstellt:



bordercolor="#000000">










































Bit
31
30
29
28
27
26
25
24
23
22
21
20 - 16 15 - 1
Aufgabe
Enable IRQ Timing
- 16/32 Repeate Quelle
Ziel
- Counter
Unsere Wete 1 0 00
  0 0 00
00
  256

Wir schreiben den Wert 256 in die Speicheradresse in die
Bits 1 - 15. Damit sagen wir, dass der DMA 256 16 Bit Werte kopieren
soll. Das DMA_16NOW schreibt die Werte 0 in 21 - 22, 23 - 24, 25, 26,
28 - 29, 30 und den Wert 1 in 31. Ok, jetzt erzähle ich mal, was die
Werte genau machen:




cellspacing="0" width="500" bordercolor="#000000">












































Bit Erklärung
31 Schaltet DMA an. Einfach eine 1 reinschreiben.
30 Schaltet den DNA Interupt an. Da wir
den nicht brauchen, schreiben wir eine 0 rein.
29 - 28 Das Timing, wann das Kopieren gestartet
werden soll. 00 bedeutet sofort starten. 01 starte im Vblank. 10
starte im Hblank. 11 kann nur im DMA Mode 3 benutzt werden. Der
Kopiervorgang wird gestartet, wenn die erste Zeile gezeichnet wird.
So kann man Flickerfrei Sachen kopieren in Modus 3.
27 Unbenutzt.
26 Kann man zwischen 16 Bit und 32 Bit umschalten.
Also wie man kopieren will. 0 steht für 16, 1 für 32.
25 Repeat Bit. Bei 0 wird nix wiederholt.
Bei 1 wird der Vorgang immer bei Hblank oder Vblank wiederholt.
24 - 23 Bei 00 wird der Quellzeiger immer um
1 Byte erhöht. 01 wie bei 00 nur der Quellzeiger wird es verkleinert.
10 bleibt der Zeiger gleich. 11 ist unbenutzt.
22 - 21 Das Gleiche, wie bei den Bits 24 -23,
nur alle auf den Zielzeiger bezogen.
20 - 16 Unbenutzt.
15 - 1 Wieviel kopiert werden soll. Bei uns
256.




Ok, das wars schon. Wie gesagt echt einfach! Schaut mal in die gball.h
bei DMA. Da stehen ein paar Definitionen, wie ihr einfach die Werte setzen
könnt. Das wars schon. Echt einfach, oder? Ihr müsst ja nicht alle Hintergründe
wissen, so lange ihr könnts reicht das fürs erste. Aber es gibt noch eine
kleine Falle! Schaut euch das mal an.


    REG_DMA3SAD
= (u32)hurikData;

    REG_DMA3DAD = (u32)VideoBuffer;

    REG_DMA3CNT = 192000 | DMA_16NOW;

Hier kopieren wir die Bilddaten in den Speicher. Nur irgendwie
stimmt hier was nicht! Und was? Eigentlich müssten wir 38400 Bytes kopieren,
weil ja 240 * 160 = 38400. Aber jetzt werden die Bilddaten in 8 Bit Werten
gespeichert, aber wir kopieren 16 Bit Werte. Also müssen wir nur halb
so viel hinschreiben. Das wärs schon, und diesmal endgültig alles. Einfach
oder? Der Rest des Codes müsste selbsterklärend sein.


    while(1)

    {

        if(!(*KEYS & KEY_LEFT))

        {

            REG_DMA3SAD
= (u32)hurikPalette;

            REG_DMA3DAD
= (u32)BGPaletteMem;

            REG_DMA3CNT
= 256 | DMA_16NOW;


            REG_DMA3SAD
= (u32)hurikData;

            REG_DMA3DAD
= (u32)VideoBuffer;

            REG_DMA3CNT
= 192000 | DMA_16NOW;

        }

        if(!(*KEYS & KEY_RIGHT))

        {

            REG_DMA3SAD
= (u32)slideshowPalette;

            REG_DMA3DAD
= (u32)BGPaletteMem;

            REG_DMA3CNT
= 256 | DMA_16NOW;


            REG_DMA3SAD
= (u32)slideshowData;

            REG_DMA3DAD
= (u32)VideoBuffer;

            REG_DMA3CNT
= 192000 | DMA_16NOW;

        }

    }

}

Ende
Ok, das wars schon. War doch einfach,
oder? Im nächsten Tutorials geht es um Sprites, und das wird schon ein
bischen schwerer. Aber keine Angst, es hält sich alles in Grenzen. Also
ich werde mich dann mal ans nächste machen und hoffe ihr seit schön am
üben. Bei Fragen, Anregungen und Verbesserungsvorschlägen fragt einfach
im href="http://andreas.abi-2005.org/pgforum/board.php?boardid=11"
target="_blank">Forum. Viel Spaß!

Dank geht an locke (Christian Locklair), da er meine Rechtschreibfehler
verbessert hat, und das ist genau so schwer, wie das Tut hier zu schreiben!
=)

style="text-align:center">(c) by hurik ( href="mailto:webmaster@hurik.de">Andreas Giemza)

< vorige Seite Seite   1   nächste Seite >