:: PlayerAdvance.org ::  

Précédent   :: PlayerAdvance.org :: > :: Développement Amateur :: > Tutoriels

Publicité

Réponse
 
Outils de la discussion Modes d'affichage
Vieux 11/03/2007, 21h23   #1
Pitt
Membre confirmé
 
Date d'inscription: 16/08/2006
Localisation: ...
Messages: 578
Par défaut Programmer sur DS avec la libnds


Programmer sur DS avec la libnds
Version 20070427
par Pitt





## Partie A, Théorie


>> Sommaire

  • 0. Introduction
  • 1. Console, texte
  • 2. Le hardware de la DS
    • 2.1 Présentation
    • 2.2 Connexion sans fil
    • 2.3 Contrôles/sorties
    • 2.4 Mémoire
  • 3. Touches, pad et stylet
    • 3.1 Touches et pad
    • 3.2 Stylet
  • 4. Vidéo 2D
    • 4.1 "Power management"
  • 5. Vidéo 3D
  • 6. Direct Memory Access
  • 7. Timers
  • 8. Interruptions
    • 8.1 Interruptions hardwares
    • 8.2 Interruptions softwares
  • 9. Inter Processor Communication (IPC)
  • 10. Mots de la fin
    • 10.1 Remerciements
    • 10.2 Liens


0. Introduction

Ce tutoriel s'adresse à tous ceux qui souhaitent se lancer dans la programmation sur DS à l'aide, ou pas, de la libnds. Il vise plus à servir de référence qu'à initier, donc une expérience en programmation sur GBA, ou sur DS avec la PAlib constitue un atout non négligeable pour en débuter la lecture. J'essayerai d'être le plus court et concis possible, tout en restant relativement précis.

Comme son nom ne l'indique pas, ce tutoriel n'est pas destiné qu'à ceux qui veulent utiliser la libnds : j'essayerai d'ajouter le plus possible les adresses des registres et les différentes constantes et autres bits, pour permettre à ceux qui voudraient se débrouiller seuls ou seulement comprendre un peu mieux le hardware DS, d'avoir une documentation relativement précise et pas trop barbante ...

Pour le moment, ce tutoriel n'explique pas comment installer devkitpro et libnds, mais c'est tellement simple, et il y a suffisamment de bons tutoriels à ce sujet sur PA et sur le web pour que j'évite de le faire. Une fois ce document terminé, je le rajouterai peut-être, mais pas avant que j'aie mis toutes les choses utiles. Au cas où, vous avez les liens à la fin du tutoriel.

Bonne lecture !


N.B.: Sauf indication contraire, vous pouvez utiliser le template arm9 des exemples de la libnds pour tester les notions abordées dans ce tutoriel.


1. Console, texte

Avant d'entrer dans les détails techniques, il peut être sympathique d'aborder de façon simple le développement sur DS. Cette première partie montre donc brièvement comment afficher du texte grâce à une console par défaut, initialisée par la libnds.

Certaines notions peuvent vous être complètement inconnues, surtout si vous n'avez jamais programmé sur GBA. Mais le but de cette première partie est justement d'afficher un petit quelque chose, pour le plaisir de ceux qui débutent.
Vous pourrez donc revenir à cette partie plus tard, notamment après avoir lu la partie "Vidéo 2D" de ce tutoriel, pour mieux comprendre le pourquoi du comment.

Voici donc un petit Hello world commenté, qui vous permettra d'afficher du texte, même sans vraiment comprendre comment cela fonctionne réellement :

Code PHP:
#include <nds.h>
#include <stdio.h>

int main(void)
{
    
/**
     * Il n'est pas nécessaire de comprendre cette première partie,
     * sauf si vous avez déjà lu le tutoriel en son ensemble.
     * Donc débutant, passez directement à la case 7.
     */

    /* 1) Initialisation des interruptions */

    
irqInit();
    
irqSet(IRQ_VBLANK0);

    
/* 2) On initialise l'écran supérieur, mais pas
     * le tactile, étant donné qu'il nous est inutile. */

    
videoSetMode(0);
    
videoSetModeSub(MODE_0_2D DISPLAY_BG0_ACTIVE);

    
/* 3) On active la bonne banque de données sur notre écran */

    
vramSetBankC(VRAM_C_SUB_BG);

    
/* 4) On configure l'adresse de la carte de notre fond */

    
SUB_BG0_CR BG_MAP_BASE(31);

    
/* 5) La couleur du texte correspond à la couleur 255
     * de la palette ; on utilise la macro RGB() */

    
BG_PALETTE_SUB[255] = RGB15(313131);

    
/* 6) On initialise notre console */

    
consoleInitDefault((u16 *) SCREEN_BASE_BLOCK_SUB(31), (u16 *) CHAR_BASE_BLOCK_SUB(0), 16);

    
/* 7) On affiche du texte avec la fonction iprintf,
     * qui prend comme unique argument le texte à afficher */

    
iprintf("Hello world !\n");

    
/* 8) Une boucle infinie, pour éviter de freezer,
     * ça serait dommage ... */
    
while (1);

    return 
0;

Cette première partie n'est finalement qu'un aperçu pour les plus pressés, et elle n'apprend pas grand chose ... La troisième partie traite des différentes entrées basiques de la DS. Mais avant cela, il faut bien parler du hardware de la DS.


2. Le hardware de la DS

2.1 Présentation

La Nintendo Dual Screen, ou DS, est une console portable. Je précise au cas où vous ne seriez pas au courant ... Développée par Nintendo, elle est dotée de 2 processeurs, de la même famille, un ARM946E-S, cadencé à 67 MHz, et un ARM7TDMI, cadencé à 33 MHz. Pour le moment, nous n'utiliserons "que" l'ARM9, pour la simple et bonne raison que c'est celui qui nous permet d'utiliser les fonctions principales de la DS. Mais par la suite, nous utiliserons le second processeur.

2.2 Connexion sans fil

La DS gère la communication sans fil de 2 manières : en utilisant la norme IEEE 802.11 pour la connexion à internet, et un format propriétaire Nintendo, le NiFi, pour communiquer entre DS.
La première méthode peut être gérée via la libwifi, mais il n'y a encore aucune librairie fonctionnelle permettant d'utiliser le NiFi.

2.3 Contrôles/sorties

La DS est dotée de 2 écrans, dont un tactile. Ils ont tous les deux une résolution de 256x192 pixels, un pitch de 0,24 mm et ils gèrent 262 000 couleurs.
En plus de l'écran tactile, la DS possède de nombreux contrôles : une croix multidirectionnelle, et 8 boutons X, Y, A, B, L, R, Start et Select. Elle dispose également d'un micro intégré, en dessous de l'écran tactile pour les DS, et entre les deux écrans pour la DS Lite.
Enfin, elle dispose de 2 haut-parleurs stéréo.

2.4 Mémoire

La DS est dotée de 4 Mo de mémoire RAM. De plus, l'ARM7 peut accéder à une mémoire de 64 ko, et la console possède également une zone de mémoire partagée par l'ARM9 et l'ARM7, de 32 ko. Enfin, une mémoire de 656 ko est réservée à la vidéo, c'est-à-dire à l'unité graphique de la DS.
Le tableau suivant montre les types de données utilisés par la DS, et leurs equivalents utilisés par GCC :

NomTaille en bits
Types génériques
Nibble4
Octet (byte)8
Demi-mot (halfword ou hword)16
Mot (word)32
Double-mot (doubleword ou dword)64
Types utilisés par GCC
char8
short16
long32
long long64
float32
double64

Voici également un tableau des différents types déclarés par la libnds :

Non-signéSignéVolatile non-signéVolatile signéTaille en bitsAbbréviations
bool---8-
uint8int8vuint8vint88u8, s8, vu8, vs8
uint16int16vuint16vint1616u16, s16, vu16, vs16
uint32int32vuint32vint3232u32, s32, vu32, vs32
uint64int64vuint64vint6464u64, s64, vu64, vs64
-float32-vfloat3232-
-float64-vfloat6464-

De plus, la DS est Little Endian, donc les octets qui composent chaque mot sont inversés. Par exemple le double-mot 0xBADC0FEE sera stocké comme suit :

Octet3210
ValeurBADCOFEE



3. Touches, pad et stylet

La gestion des touches, du pad et du stylet est extrêmement simple sur DS. Cette troisième partie passe rapidement en revue les registres, et les fonctions de la libnds, servant à l'utilisation des entrées de la DS, du moins au niveau des doigts ...

3.1 Touches et pad

La DS stocke l'état actuel des différentes touches dans le registre REG_KEYINPUT, registre 16 bits situé à l'adresse 0x04000130.

Bit131211109876543210
NomKEY_LIDKEY_TOUCHKEY_YKEY_XKEY_LKEY_RKEY_DOWNKEY_UPKEY_LEFTKEY_RIGHTKEY_STARTKEY_SELECTKEY_BKEY_A
ProcesseurARM7ARM7ARM7ARM7Les 2Les 2Les 2Les 2Les 2Les 2Les 2Les 2Les 2Les 2
ReprésenteDiodeEcran tactileBouton YBouton XBouton LBouton RBasHautGaucheDroiteStartSelectBouton BBouton A

Il suffit donc de lire le contenu de ce registre, et d'utiliser des masques de bits pour détecter quelles touches sont pressées. Certains des bits ne sont actualisés que pour l'ARM7, mais cela importe peu quand on programme à l'aide de la libnds, car celle-ci fait passer le contenu de REG_KEYINPUT à l'ARM9 via l'IPC (voir plus loin).

La libnds propose plusieurs déclarations concernant la lecture des touches :
  • Une fonction permettant de récupérer le contenu du registre REG_KEYINPUT dans un buffer.
    Code PHP:
    void scanKeys(); 
  • 2 fonctions permettant de savoir, une fois le contenu de REG_KEYINPUT mis en buffer, quelles touches sont respectivement :
    - maintenues appuyées
    - pressées
    - relevées
    depuis le dernier appel à scanKeys().
    Code PHP:
    uint32 keysHeld(void);
    uint32 keysDown(void);
    uint32 keysUp(void); 
    /!\ Si le joueur reste appuyé sur un bouton, keysDown() renverra 0 pour ce bouton. C'est alors keysHeld() qui prendra le relais.
    il ne faut donc pas confondre ces 2 fonctions, et distinguer la différence entre une touche relevée, pressée ou maintenue.

  • 2 fonctions permettant respectivement de détecter la répétition d'un appui sur une touche, et de paramètrer la répétition des touches.
    Code PHP:
    uint32 keysDownRepeat(void);
    /**
     * setDelay est le nombre d'appels à scanKeys() avant que les touches commencent à se répéter.
     * setRepeat est le nombre d'appels à scanKeys() avant que les touches ne se répètent.
     */
    void keysSetRepeatu8 setDelayu8 setRepeat ); 
  • Une énumération représentant la valeur des différentes touches.
    Code PHP:
    typedef enum KEYPAD_BITS {
      
    /* Touches */
      
    KEY_A      BIT(0),
      
    KEY_B      BIT(1),
      
    KEY_SELECT BIT(2),
      
    KEY_START  BIT(3),
      
    KEY_RIGHT  BIT(4),
      
    KEY_LEFT   BIT(5),
      
    KEY_UP     BIT(6),
      
    KEY_DOWN   BIT(7),
      
    KEY_R      BIT(8),
      
    KEY_L      BIT(9),
      
    KEY_X      BIT(10),
      
    KEY_Y      BIT(11),
      
    /* Ecran tactile */
      
    KEY_TOUCH  BIT(12),
      
    /* Etat de la diode */
      
    KEY_LID    BIT(13)
    KEYPAD_BITS

Un usage fréquent de ces fonctions est présenté ci-dessous :
Code PHP:
scanKeys();
if (
keysDown() & KEY_A)
{
/* si le bouton A est pressé ...*/

3.2 Stylet

Pour savoir si le stylet est appuyé sur l'écran, il suffit d'effectuer un scanKeys(), puis de tester keysDown() avec le masque de bit KEY_TOUCH.
Pour connaitre l'endroit où le stylet est appuyé, il faut utiliser la fonction suivante, qui retourne une structure touchPosition. Cette structure contient 6 champs, qui sont expliqué plus bas.

Code PHP:
touchPosition touchReadXY(); 
Code PHP:
/* La structure touchPosition */
typedef struct touchPosition {
    
int16    x;    /* Coordonnée X de l'endroit où l'écran est touché */
    
int16    y;    /* Coordonnée Y de l'endroit où l'écran est touché */
    
int16    px;    /* Coordonnée X du pixel à l'endroit où l'écran est touché */
    
int16    py;    /* Coordonnée Y du pixel à l'endroit où l'écran est touché */
    
int16    z1;    /* FIXME : profondeur de l'appui ? */
    
int16    z2;    /* FIXME : profondeur de l'appui ? */
touchPosition
Cette structure est passée à l'ARM9 par l'ARM7 via une zone commune aux 2 processeurs, qui permet d'échanger des informations entre eux, l'IPC. Cette zone est expliquée plus en détail dans la partie 9, et ce sera par ailleurs l'occasion d'expliquer plus en détail les registres qui concernent la récupération des coordonnées du stylet, de la pression des touches X et Y, et de l'écran tactile.


4. Vidéo 2D

La DS est dotée d'un hardware relativement bien fourni concernant la 2D : il existe de multiples façons d'accéder aux écrans, et d'y afficher ce que l'on désire.
Il faudra bien comprendre dans cet partie la différence entre l'écran principal, généralement (mais pas tout le temps) utilisé en bas, et l'écran secondaire. Pourquoi cette distinction ? Parce qu'on peut échanger la place des 2 écrans, ce qui peut fausser toutes vos fonctions d'affichage si vous n'y pensez pas. De plus, la section suivante s'intéresse au hardware 3D, qui n'est utilisable QUE sur l'écran principal.


4.1 "Power management"

Tout d'abord, l'unité LCD est régie par un registre de gestion de l'alimentation, qui permet d'activer, ou non, les 2 écrans, mais aussi de déterminer quelles opérations sont activées.
C'est le registre 16bits REG_POWERCNT, situé à l'adresse 0x04000304.
Le tableau suivant récapitule les différents bits activables de REG_POWERCNT :

BitDefine de la libndsAction
0POWER_LCDActive les 2 écrans LCD
1POWER_2D_AActive la 2D sur l'écran principal
2POWER_MATRIXActive les matrices 3D
3POWER_3D_COREActive la 3D sur l'écran principal
9POWER_2D_BActive la 2D sur l'écran secondaire
15POWER_SWAP_LCDSEchange les 2 écrans

Afin de simplifier la vie des codeurs, la libnds contient 2 macros supplémentaires :
- POWER_ALL_2D, qui active toute la 2D (écrans, 2D sur chaque écran)
- POWER_ALL, qui active tout (écrans, 2D sur chaque écran, 3D)

La libnds fournit plusieurs fonctions concernant le "power management" :
  • Une fonction qui ajoute les paramètres qu'on lui donne

    Code PHP:
    static inline void powerON(int on); 
  • Une fonction qui n'active QUE les paramètres qu'on lui donne

    Code PHP:
    static inline void powerSET(int on); 
  • Une fonction qui désactive les paramètres qu'on lui donne

    Code PHP:
    static inline void powerOFF(int off); 
  • 3 fonctions de gestion de la position des écrans

    Code PHP:
    /* - Echange les 2 écrans */
    static inline void lcdSwap(void);
    /* - Mettre l'écran principal en haut */
    static inline void lcdMainOnTop(void);
    /* - Mettre l'écran principal en bas */
    static inline void lcdMainOnBottom(void); 

Deux utilisations typiques sont présentées ci-dessous :

Code PHP:
/* - utilisation de la 2D uniquement */
powerON(POWER_ALL_2D);
/* - utilisation de la 2D et de la 3D */
powerON(POWER_ALL); 

5. Vidéo 3D


6. Direct Memory Access

Pour transférer de manière rapide, on peut utiliser une technique spéciale, appelée Direct Memory Access, ou DMA. Comme son nom ne l'indique qu'à moitié, cette méthode demande au processeur de stopper l'exécution du programme et de transférer directement des données en mémoire. Cela peut avoir des avantages considérables, surtout lors de l'utilisation de modes graphiques bitmaps, ou encore pour transférer des sons vers les hauts-parleurs. Mais en contre partie, le DMA stoppe l'exécution du processeur, ce qui peut être vu comme un inconvénient.

La DS possède 4 canaux de transfert DMA, qui sont utilisables grâce aux registres DMA_CR(x), DMA_SRC(x) et DMA_DEST(x), où x est le numéro de canal compris entre 0 et 3. C'est 4 canaux ne diffèrent que par l'usage qu'on leur réserve généralement :
- canal 0 : le plus rapide, surtout utilisé pour les transferts critiques.
- canaux 1 et 2 : utilisés pour le transfert du son.
- canal 3 : les autres transferts.
Ces indications sont bien entendues théoriques ; le canal 0 peut très bien être utilisé pour transfèrer du son, et on peut très bien copier une structure avec le canal 1.

Le premier registre, DMA_CR(x), permet le contrôle du transfert DMA ; le tableau suivant récapitule les paramètres qui peuvent être utilisés pour le contrôle d'un transfert, via le registre DMA_CR(x) qui est un registre 32 bits situé à l'adresse :
- 0x040000B0 pour le canal 0.
- 0x040000BC pour le canal 1.
- 0x040000C8 pour le canal 2.
- 0x040000D4 pour le canal 3.

ParamètreBitProcesseurAction
Activation du transfert  
DMA_ENABLE31ARM7 & ARM9Active le transfert DMA sur ce canal.
DMA_IRQ_REQ30ARM7 & ARM9Active la génération d'une interruption à la fin du transfert.
DMA_START_NOW-ARM7 & ARM9Commence le transfert DMA immédiatement.
DMA_START_CARD-ARM7 & ARM9 
DMA_START_VBL27ARM7 & ARM9Commence le transfert DMA au prochain VBL.
DMA_START_HBL28ARM9Commence le transfert DMA au prochain HBL.
DMA_START_FIFO-ARM9 
DMA_DISP_FIFO-ARM9 
Tailles de transfert  
DMA_16_BIT-ARM7 & ARM9Transfert de demi-mots (halfwords = 16 bits).
DMA_32_BIT26ARM7 & ARM9Transfert de mots (words = 32 bits).
Types de transfert  
DMA_REPEAT25ARM7 & ARM9 
DMA_SRC_INC-ARM7 & ARM9Récupère les données à copier de manière ascendante.
DMA_SRC_DEC23ARM7 & ARM9Récupère les données à copier de manière descendante.
DMA_SRC_FIX24ARM7 & ARM9Copie toujours le même demi-mot/mot.
DMA_DST_INC-ARM7 & ARM9Copie les données de manière ascendante.
DMA_DST_DEC21ARM7 & ARM9Copie les données de manière descendante.
DMA_DST_FIX22ARM7 & ARM9Copie toujours au même endroit.
DMA_DST_RESET-ARM7 & ARM9 
Transferts prédéfinis  
DMA_COPY_WORDS-Transfert immédiat de mots. 
DMA_COPY_HALFWORDS-Transfert immédiat de demi-mots. 
DMA_FIFO-  

Le bit 31 (= DMA_BUSY) du registre DMA_CR(x) indique, une fois le transfert commencé, si le canal est occupé ou non. La libnds fournit également la fonction qui suit, et qui permet de savoir si le canal DMA choisi est libre, ou pas :

Code PHP:
static inline int dmaBusy(uint8 channel); 
Le second registre, DMA_SRC(x), contient l'adresse des données à copier.
C'est également un registre 32 bits, situé à l'adresse :
- 0x040000B4 pour le canal 0.
- 0x040000C0 pour le canal 1.
- 0x040000CC pour le canal 2.
- 0x040000D8 pour le canal 3.

Le troisième registre, DMA_DEST(x), contient l'adresse à laquelle les données seront transférées.
Celui-ci est encore une fois un registre 32 bits, situé à l'adresse :
- 0x040000B8 pour le canal 0.
- 0x040000C4 pour le canal 1.
- 0x040000D0 pour le canal 2.
- 0x040000DC pour le canal 3.

La libnds fournit plusieurs fonctions de transferts prédéfinies :
  • Transferts synchrones

    Code PHP:
    /* - de mots */
    static inline dmaCopyWords(uint8 channel, const voidsrcvoiddestuint32 size);
    /* - de demi-mots */
    static inline void dmaCopyHalfWords(uint8 channel, const voidsrcvoiddestuint32 size); 
  • Transferts Asynchrones

    Code PHP:
    /* - de mots */
    static inline void dmaCopyWordsAsynch(uint8 channel, const voidsrcvoiddestuint32 size);
    /* - de demi-mots */
    static inline void dmaCopyHalfWordsAsynch(uint8 channel, const voidsrcvoiddestuint32 size); 
  • Transferts "à la memcopy", utilisant le canal 3

    Code PHP:
    /* - synchrone */
    static inline void dmaCopy(const void sourcevoid destuint32 size);
    /* - asynchrone */
    static inline void dmaCopyAsynch(const void sourcevoid destuint32 size); 

Sinon, une utilisation typique du DMA se déroule comme suit :

Code PHP:
/* Version synchrone */
DMA_SRC(canal) = adresse_source;
DMA_DEST(canal) = adresse_destination;
DMA_CR(canal) = parametres taille;
while (
dmaBusy(canal));

/* Version asynchrone */
DMA_SRC(canal) = adresse_source;
DMA_DEST(canal) = adresse_destination;
DMA_CR(canal) = parametres taille

7. Timers

Un timer est un registre compteur, qui joue le rôle d'horloge. Il permet par exemple d'attendre un certain temps, ou d'effectuer une action à intervalles réguliers. La DS possède 4 timers, numérotés de 0 à 3, qui sont tous les quatre cadencés à 33.514 MHz. L'utilisation de ces derniers est très simple, et s'effectue grâce à 2 registres.

Le premier, TIMER_CR(x), où x est le numéro du timer, permet de gérer, comme pour les transferts DMA, la configuration et la mise en place du timer. Le tableau qui suit montre les différents paramètres que l'on peut sélectionner. Le registre TIMER_CR(x) est un registre 16 bits, qui se situe à l'adresse :
- 0x04000102 pour le timer 0.
- 0x04000106 pour le timer 1.
- 0x0400010A pour le timer 2.
- 0x0400010E pour le timer 3.

ParamètreBitAction
TIMER_ENABLE7Active le timer.
TIMER_IRQ_REQ6Active la génération d'une interruption lors du débordement du timer.
TIMER_CASCADE2Active la mise en cascade des timers, c'est-à-dire que le timer ne s'active que lorsque le timer précédent déborde. Ne peut être utilisé sur le timer 0.
TIMER_DIV_10-1Cadence le timer à 33.514 MHz.
TIMER_DIV_640-1Cadence le timer à (33.514 / 64) MHz.
TIMER_DIV_2560-1Cadence le timer à (33.514 / 256) MHz.
TIMER_DIV_10240-1Cadence le timer à (33.514 / 1024) MHz.

Le second registre, TIMER_DATA(x) possède un comportement un peu plus compliqué. En effet, il permet en écriture de sélectionner la fréquence du compteur, grâce aux macros présentées dans le tableau suivant, qui sont utilisées suivant la division de la cadence du timer. Mais en lecture, il renvoit la valeur actuelle du compteur.
Ce registre de 16 bits se situe à l'adresse :
- 0x04000100 pour le timer 0.
- 0x04000104 pour le timer 1.
- 0x04000108 pour le timer 2.
- 0x0400010C pour le timer 3.

Paramètre de division du timerMacro pour le choix de la fréquence x
TIMER_DIV_1TIMER_FREQ(x)
TIMER_DIV_64TIMER_FREQ_64(x)
TIMER_DIV_256TIMER_FREQ_256(x)
TIMER_DIV_1024TIMER_FREQ_1024(x)

La libnds ne fournit aucune fonction de gestion de timers, mais leur utilisation est très simple, et ce fait comme suit :

Code PHP:
/* En utilisant la bonne macro pour calculer la fréquence */
TIMER_CR(numero) = parametres;
TIMER_DATA(numero) = frequence

8. Interruptions

8.1 Interruptions hardwares

Le processeur ARM9 utilisé jusqu'ici, tout comme l'ARM 7 d'ailleurs, lit les instructions du programme courant les unes après les autres, et les exécute. Il est relié à différents périphériques, comme par exemple les touches ou les hauts-parleurs.
Pour échanger des informations entre les périphériques, on peut utiliser 2 méthodes :

- la première, appelée polling consiste à attendre dans une boucle infinie qu'une condition soit remplie, comme par exemple la pression du bouton R. Cette méthode a ses avantages, mais aussi ses inconvénients, vus qu'on ne peut pas vraiment effectuer de longues tâches pendant la période d'attente.

- la seconde consiste à utiliser un système d'interruptions. Une interruption, au sens électronique du terme, est un simple fil, qui relie un périphérique au processeur. Cet entrée conserve toujours la même valeur, soit 0 ou 1. Mais lorsque le périphérique a besoin d'informer le programme d'un évènement, il change la valeur de l'entrée. Le processeur interrompt alors l'exécution du programme, et exécute la routine vers laquelle il est configuré pour pointer lors de l'interruption. Une fois cette routine exécutée, l'entrée reprend sa valeur initiale, et l'exécution du programme continue là où elle s'était arrêtée.
Tout comme le polling, cette technique possède des avantages et des inconvénients, mais les interruptions possèdent un panel très varié : touches pressées, évènement Wifi, fin de transfert DMA ...

La DS possède 23 interruptions ; le tableau suivant les liste, indique le processeur qui y a accès, et donne une brève description de ces dernières.

NomBitProcesseurDescription
IRQ_VBLANK0ARM9 & ARM7Générée lors de la période de VBlank.
IRQ_HBLANK1ARM9 & ARM7Générée lors de la période de HBlank.
IRQ_VCOUNT2ARM9 & ARM7Générée lorsque la valeur du VCOUNT correspond à la valeur configurée dans DISPSTAT.
IRQ_TIMER03ARM9 & ARM7Générée lors du débordement du timer 0.
IRQ_TIMER14ARM9 & ARM7Générée lors du débordement du timer 1.
IRQ_TIMER25ARM9 & ARM7Générée lors du débordement du timer 2.
IRQ_TIMER36ARM9 & ARM7Générée lors du débordement du timer 3.
IRQ_NETWORK7ARM7 
IRQ_DMA08ARM9 & ARM7Générée lors de la fin d'un transfert DMA sur le canal 0.
IRQ_DMA19ARM9 & ARM7Générée lors de la fin d'un transfert DMA sur le canal 1.
IRQ_DMA210ARM9 & ARM7Générée lors de la fin d'un transfert DMA sur le canal 2.
IRQ_DMA311ARM9 & ARM7Générée lors de la fin d'un transfert DMA sur le canal 3.
IRQ_KEYS12ARM9 & ARM7Générée lorsque la valeur des touches pressées est égale à la valeur stockée dans REG_KEYCNT.
IRQ_CART13ARM9 & ARM7Générée par la cartouche GBA.
IRQ_IPC_SYNC16ARM9 & ARM7Générée lors de la synchronisation de l'IPC.
IRQ_FIFO_EMPTY17ARM9 & ARM7Générée lors de l'envoi d'un FIFO vide.
IRQ_FIFO_NOT_EMPTY18ARM9 & ARM7Générée lors de la réception d'un FIFO vide.
IRQ_CARD19ARM9 & ARM7Générée à la fin d'un transfert de données depuis la carte.
IRQ_CARD_LINE20ARM9 & ARM7 
IRQ_GEOMETRY_FIFO21ARM9Interruption géométrie FIFO.
IRQ_LID22ARM7 
IRQ_SPI23ARM7Interruption du bus SPI.
IRQ_WIFI24ARM7Générée lorsqu'un évènement Wifi se produit.
IRQ_ALL~0ARM9 & ARM7L'ensemble des interruptions.

On peut activer chaque interruption en activant le bit correspondant dans le registre REG_IE, registre 32 bits situé à l'adresse 0x04000210.
De plus, il peut être utile de désactiver momentanément toutes les interruptions. Pour cela, le bit 0 du registre REG_IME, registre 16 bits situé à l'adresse 0x04000208, permet de désactiver toutes les interruptions lorsqu'il est mis à 0, que le bit de l'interruption soit activé ou non dans le registre REG_IE.

La libnds propose plusieurs fonctions pour gérer les interruptions :
  • une fonction d'initialisation globale

    Code PHP:
    void irqInit(); 
  • 2 fonctions permettant respectivement d'associer une fonction à une interruption, ou de supprimer la fonction associée à cette interruption

    Code PHP:
    /* Associer : */
    void irqSet(IRQ_MASK irqVoidFunctionPointer handler);
    /* Effacer : */
    void irqClear(IRQ_MASK irq); 
  • 2 fonctions, permettant respectivement d'activer ou de désactiver une interruption

    Code PHP:
    /* Activer : */
    void irqEnable(IRQ_MASK irq);
    /* Désactiver : */
    void irqDisable(IRQ_MASK irq); 
  • une fonction permettant d'utiliser un "interrupt handler" différent de celui utilisé par la libnds

    Code PHP:
    void irqInitHandler(VoidFunctionPointer handler); 


8.2 Interruptions softwares

Dans la partie précédente, j'ai usé et abusé du terme d'interruption. en réalité, c'est un abus de langage, et les interruptions précédentes étaient en réalité des interruptions hardwares. Il existe un autre type d'interruptions, qui fonctionnent comme les interruptions hardware, mais qui sont déclenchées par le programme lui-même. On appelle ces interruptions interruptions softwares (abréviation : SWI, pour SoftWare Interrupt).

Pour utiliser une interruption software, il suffit d'utiliser l'instruction ARM swi. Même s'il est possible d'utiliser cette instruction en C via asm(), on préfèrera utiliser les fonctions libnds correspondantes, lorsqu'elles existent. La DS possède 25 interruptions softwares, que le tableau suivant récapitule, tout en leur associant les fonctions libnds qui leur correspondent.

ValeurProcesseurFonctionFonction libndsExplication des paramètres
00hARM9 & ARM7Effectue un reset software de la DS.void swiSoftReset(void);-
03hARM9 & ARM7Attends un certain temps.void swiDelay(uint32 duration);duration est la durée à attendre.
04hARM9 & ARM7Attends une interruption hardware.void swiIntrWait(int waitForSet, uint32 flags);Si waitForSet vaut 0, retourne si l'interruption a déjà eu lieu. Si waitForSet vaut 1, attend que l'interruption ait lieu. flags est l'interruption à attendre.
05hARM9 & ARM7Attends l'interruption VBL.void swiWaitForVBlank(void);-
06hARM9 & ARM7Stoppe le processeurvoid swiHalt(void);-
07hARM7Mise en veillevoid swiSleep(void);-
08hARM7change le registre SOUNDBIASvoid swiChangeSoundBias(int enabled, int delay);enabled est le niveau de BIAS, delay est le délai (ex.: 8 sur GBA).
09hARM9 & ARM7Division et modulo signéint swiDivide(int numerator, int divisor); numerator est le numérateur, et divisor le diviseur. Retourne le quotient.
IdemIdemIdemint swiRemainder(int numerator, int divisor); numerator est le numérateur, et divisor le diviseur. Retourne le modulo.
0BhARM9 & ARM7Copievoid swiCopy(const void * source, void * dest, int flags);Les bits 0-20 de flags correspondent à la taille du transfert, le bit 24 au type de transfert (COPY_MODE_COPY ou COPY_MODE_FILL, copie ou remplissage) et le bit 26 à la taille du transfert(COPY_MODE_HWORD ou COPY_MODE_WORD, demi-mot ou mot).
0ChARM9 & ARM7Copie rapidevoid swiFastCopy(const void * source, void * dest, int flags);Les bits 0-20 de flags correspondent à la taille du transfert et le bit 24 au type de transfert (COPY_MODE_COPY ou COPY_MODE_FILL, copie ou remplissage).
0DhARM9 & ARM7Racine carréeint swiSqrt(int value);value est le nombre dont on cherche la racine carrée.
0EhARM9 & ARM7Retourne le CRC-16uint16 swiCRC16(uint16 crc, void * data, uint32 size);crc est le CRC-16 initial, data est un pointeur vers les données, et size est la taille des données en octets.
0FhARM9 & ARM7Retourne 1 si le programmer tourne sur debuggeur hardware.int swiIsDebugger(void);-
10hARM9 & ARM7Récupère chaque bit d'un champ de bits dans un octet.void swiUnpackBits(uint8 * source, uint32 * destination, PUnpackStruct params);source est l'adresse du champ de bits, destination est l'adresse de récupération des bits en octet, et params est la structure de paramètres.
11hARM9 & ARM7 void swiDecompressLZSSWram(void * source, void * destination); 
12hARM9 & ARM7 int swiDecompressLZSSVram(void * source, void * destination, uint32 toGetSize, TDecompressionStream * stream);?
13hARM9 & ARM7 int swiDecompressHuffman(void * source, void * destination, uint32 toGetSize, TDecompressionStream * stream);?
14hARM9 & ARM7 void swiDecompressRLEWram(void * source, void * destination); 
15hARM9 & ARM7 int swiDecompressRLEVram(void * source, void * destination, uint32 toGetSize, TDecompressionStream * stream);?
16hARM9 extern void swiDecodeDelta8(void * source, void * destination); 
18hARM9 void swiDecodeDelta16(void * source, void * destination); 
1AhARM7Récupère un sinus.uint16 swiGetSineTable(int index);index est l'entier dont on souhaite calculer le sinus.
1BhARM7Récupère un pitch.uint16 swiGetPitchTable(int index);index est l'index du pitch recherché dans la table.
1ChARM7Récupère un volume dans la table des volumes.uint8 swiGetVolumeTable(int index);index est l'index du volume.
1DhARM9 & ARM7  
1FhARM9Ecriture dans le registre POSTFLG.--
1FhARM7Ecriture dans le registre HALTCNT.--

Pour utiliser les interruptions softwares qui ne sont pas gérées par la libnds, il faut utiliser du code ARM, mais cela dépasse les limites de ce tutoriel. Heureusement, ces quelques fonctions sont très peu utilisées.


9. Inter Processor Communication (IPC)


10. Mots de la fin

10.1 Remerciements

Je voudrais remercier :
  • Dr.Vince pour les modifications qu'il a apporté au système de BBCode, notamment sur les tableaux, et pour ses conseils.
  • Arcadia, pour ses news, toujours aussi amusantes, et qui font franchement plaisir !
  • Foxy, Noda et simonomis pour les corrections de coquilles
  • Ceux que j'ai dû oublier ...

10.2 Liens


## Partie B, Pratique : ShootMe


Cette seconde partie est un complément à la première, et consiste en une application des notions abordées dans la partie documentation en utilisant bien sûr le langage C. Elle vous montrera, par l'intermédiaire de la création d'un petit jeu, ShootMe, comment utiliser tout ce que je présente plus haut.
Comme son nom l'indique, cet homebrew sera un FPS, avec tout ce qui tourne autour, ce qui permettra d'aborder tout et n'importe quoi.

Attention : comme je ne rédige pas la partie théorique de façon linéaire, les exercices présents dans cette seconde partie sont dans un ordre qui ne suit pas l'ordre de la première partie. Il faut donc parcourir le tout, ou lire chaque passage au fur et à mesure que le besoin s'en fait. Pour ce faire, chaque exercice est numéroté, en rapport avec le passage auquel il se rapporte, et non de manière linéaire.

Bonne lecture, et bons tests !


Exercice 1.0 Une console pour notre jeu

Le but de ce premier exercice est très simple : initialiser une console sur l'écran secondaire, et échanger les 2 écrans, pour obtenir un espace de communication avec l'utilisateur pendant la phase d'initialisation. Tout ça dans une fonction qui nous servira de fonction d'initialisation :

Code PHP:
static inline void Initialize(void); 
Ensuite, il faudra ajouter un appel à cette fonction dans le main, et afficher le texte suivant : "ShootMe\n-------\n\n".

AIDE : pour échanger les 2 écrans et mettre l'écran principal en haut, il faut utiliser la fonction lcdMainOnTop() ; pour faire l'inverse, il faut utiliser la fonction lcdMainOnBottom(). Ceci est utile, car seul l'écran principal est capable d'afficher de la 3D, par exemple.


Correction 1.0 Une console pour notre jeu

Code PHP:
#include <nds.h>
#include <stdio.h>

static inline void Initialize(void);

int main(int argcchar argv[])
{
    
Initialize();

    
iprintf("ShootMe\n-------\n\n");

    while (
1)
    {
        
swiWaitForVBlank();
    }

    return 
0;
}

static 
inline void Initialize(void)
{
    
irqInit();
    
irqSet(IRQ_VBLANK0);

    
lcdMainOnTop();

    
videoSetMode(0);
    
videoSetModeSub(MODE_0_2D DISPLAY_BG0_ACTIVE);

    
vramSetBankC(VRAM_C_SUB_BG);

    
SUB_BG0_CR BG_MAP_BASE(31);

    
BG_PALETTE_SUB[255] = RGB15(313131);

    
consoleInitDefault((u16 *) SCREEN_BASE_BLOCK_SUB(31), (u16 *) CHAR_BASE_BLOCK_SUB(0), 16);

__________________
Utiliser la libnds ?
What's it ?

Dernière modification par Dr.Vince ; 01/05/2007 à 12h49.
Pitt est déconnecté   Réponse avec citation

Publicité

Vieux 11/03/2007, 21h33   #2
Arcadia
Modérateur saisonnier
 
Date d'inscription: 17/02/2006
Localisation: Compiègne
Messages: 2 942
Voir les codes amis Nintendo DS Voir les codes amis Wii
Par défaut

Bonne initiative ! Ça mérite une petite new ...


[EDIT] Et voili...

Au fait, il faudrait peut-être mettre les liens ou on peut toruver la lib non ? J'ai mis un site en page d'accueil mais je ne suis pas sûr que ce soit le bon, par manque de temps je ne peux pas trop vérifier...
__________________
.

Mes homebrews GBA : 1942 - Ghost'n Goblins




Mes autres passions, les flippers : Restauration d'un High Speed (Williams - 1985)

Dernière modification par Arcadia ; 11/03/2007 à 21h53.
Arcadia est déconnecté   Réponse avec citation
Vieux 11/03/2007, 21h55   #3
DJP
Bitchy Little Girl...
 
Date d'inscription: 29/10/2005
Messages: 3 201
Par défaut

Génial
Perso je n'utilise aussi que la libnds
__________________

>> On garde :: On améliore :: On kill <<
DJP est déconnecté   Réponse avec citation
Vieux 11/03/2007, 21h55   #4
Smealum
PsycoKid
 
Date d'inscription: 10/11/2005
Localisation: Là où il pleut
Messages: 1 141
Par défaut

Je sens que ça va aider des gens ça
Personnellement, je me suis mis à libnds il y a un bout de temps et la seule chose que je lui reproche, c'est son manque de documentation...c'est vraiment horrible : il n'existe qu'une doc, mais elle date de l'époque où libnds s'appelait ndslib (il y a très longtemps donc )
__________________

War. War never changes.
Smealum est déconnecté   Réponse avec citation
Vieux 11/03/2007, 22h00   #5
Foxy
Membre confirmé
 
Date d'inscription: 10/11/2005
Messages: 367
Par défaut

Juste un petit bémol, tu compares les fonction keysDown() et keysHeld(), elles ne font pas tout a fait la même chose !
Si l'on maintient une touche appuyée, KeysDown() ne la renverra que lors de l'appui et ensuite renverra zero, alors que keysHeld() renverra la valeur de la touche tant que celle ci sera appuyée.

(La précision est importante pour ceux qui n'ont pas forcément un niveau d'anglais suffisant).
__________________
Mes releases persos, etc...

Dernière modification par Foxy ; 11/03/2007 à 22h03.
Foxy est déconnecté   Réponse avec citation
Vieux 11/03/2007, 22h17   #6
Pitt
Membre confirmé
 
Date d'inscription: 16/08/2006
Localisation: ...
Messages: 578
Par défaut

Merci pour vos commentaires, c'est encourageant ! Et merci beaucoup pour la news, Arcadia, ça fait très plaisir !
Je vais rajouter le lien pour la lib, et modifier pour le keysDown() / keysHeld() (très juste, j'avais complètement oublié).
Surtout, corrigez-moi si j'ai écrit une annerie, je me suis relu, mais on n'est jamais à l'abri ... Pareil si vous avez besoin de précisions !
__________________
Utiliser la libnds ?
What's it ?
Pitt est déconnecté   Réponse avec citation
Vieux 11/03/2007, 22h36   #7
Dr.Vince
Administrateur
 
Date d'inscription: 10/11/2005
Messages: 4 965
Voir les codes amis Nintendo DS Voir les codes amis Wii
Par défaut

franchement bravo !!!!

ça fait un moment que je voulais faire ça mais j'ai jamais eu le temps de me pencher sur la libnds !!!
__________________
Projets Abandonnés: [Arcomage Advance] [Puzznic] [PA Card Games] [Blob Runner]
Projet en cours: [Ne plus abandonner de projet...]
Dr.Vince est déconnecté   Réponse avec citation
Vieux 11/03/2007, 22h37   #8
Doud_
Membre confirmé
 
Date d'inscription: 12/11/2005
Localisation: Cambrai
Messages: 327
Par défaut

Merci beaucoup Pitt!

Je regarde tout ça au plus vite

Bon courage pour la suite des tutos
__________________
Peace
Doud_ est déconnecté   Réponse avec citation
Vieux 11/03/2007, 22h42   #9
Pitt
Membre confirmé
 
Date d'inscription: 16/08/2006
Localisation: ...
Messages: 578
Par défaut

Merci !

@ Modos & admins >> Pour la suite du tuto, vous préférez que je crée d'autres topics, ou que je continue sur le même ?
__________________
Utiliser la libnds ?
What's it ?
Pitt est déconnecté   Réponse avec citation
Vieux 11/03/2007, 23h01   #10
Dr.Vince
Administrateur
 
Date d'inscription: 10/11/2005
Messages: 4 965
Voir les codes amis Nintendo DS Voir les codes amis Wii
Par défaut

hum.... continue sur le même ça nous évitera du boulot par la suite (CQP)

bah en fait y a que moi pour le CQP
__________________
Projets Abandonnés: [Arcomage Advance] [Puzznic] [PA Card Games] [Blob Runner]
Projet en cours: [Ne plus abandonner de projet...]
Dr.Vince est déconnecté   Réponse avec citation
Vieux 11/03/2007, 23h11   #11
DJP
Bitchy Little Girl...
 
Date d'inscription: 29/10/2005
Messages: 3 201
Par défaut

Citation:
Envoyé par Dr.Vince
hum.... continue sur le même ça nous évitera du boulot par la suite (CQP)

bah en fait y a que moi pour le CQP
Je pense pouvoir comprendre aussi mon petit gars ...
__________________

>> On garde :: On améliore :: On kill <<
DJP est déconnecté   Réponse avec citation
Vieux 11/03/2007, 23h13   #12
Pitt
Membre confirmé
 
Date d'inscription: 16/08/2006
Localisation: ...
Messages: 578
Par défaut

J'ai pas tout compris, même si j'ai quand même une petite idée sur la question ...
En tout cas, message reçu, la suite bientôt, au même endroit !
__________________
Utiliser la libnds ?
What's it ?
Pitt est déconnecté   Réponse avec citation
Vieux 11/03/2007, 23h23   #13
pmcc
Membre confirmé
 
Date d'inscription: 02/02/2007
Localisation: Ivry sur Seine (94)
Messages: 60
Par défaut

C'est clair qu'il manque une certaine documentation autour de la libnds. Je m'y suis mis il y a presque un mois et J'ai recherché plein d'infos la première semaine sur le hardware DS et la lib avant de réellement commencer à coder donc des tutos dessus sont toujours les bienvenues .
D'ailleurs je pense sortir mon premier homebrew avec le code source, ca peut toujours aider.
__________________
Projet DS en attente : Arkanoid 2
Devblog : www.gotrooted.net
pmcc est déconnecté   Réponse avec citation
Vieux 11/03/2007, 23h38   #14
mastertop101
Membre confirmé
 
Date d'inscription: 14/11/2005
Messages: 346
Par défaut

Merci !! Ça doit bien être le seul tutoriel francophone pour libnds ! (?)

Continue comme ça!
mastertop101 est déconnecté   Réponse avec citation
Vieux 11/03/2007, 23h58   #15
DJP
Bitchy Little Girl...
 
Date d'inscription: 29/10/2005
Messages: 3 201
Par défaut

Et encore, pour la libnds il y a beaucoup d'exemples, relativement bons...mais la libgba...
__________________

>> On garde :: On améliore :: On kill <<
DJP est déconnecté   Réponse avec citation
Vieux 12/03/2007, 12h20   #16
simonomis
Membre confirmé
 
Date d'inscription: 30/03/2006
Messages: 201
Par défaut

ca y est, tu m'a donné l'envie de me lancer dans le dev ds. En plus en ce moment j'ai un peu de temps devant moi, donc ca tombe bien
je t'en remercie

reste plus qu'à comprendre comment marche devkitpro maintenant

à bientot dans la section DEV
simonomis est déconnecté   Réponse avec citation
Vieux 12/03/2007, 17h54   #17
Pitt
Membre confirmé
 
Date d'inscription: 16/08/2006
Localisation: ...
Messages: 578
Par défaut

Citation:
Envoyé par DJP
Et encore, pour la libnds il y a beaucoup d'exemples, relativement bons...mais la libgba...
Ce qui sous-entend ... ?

Citation:
Envoyé par simonomis
ca y est, tu m'a donné l'envie de me lancer dans le dev ds. En plus en ce moment j'ai un peu de temps devant moi, donc ca tombe bien
je t'en remercie

reste plus qu'à comprendre comment marche devkitpro maintenant

à bientot dans la section DEV
Content d'avoir créé des vocations ! Devkitpro, c'est hyper simple, il n'y a (presque) rien à comprendre !

Je vais mettre en ligne un petit quelque chose ce soir, pas grand chose, j'ai un devoir de maths à faire ... Facile et long, il n'y a pas plus chiant ...

A part ça 'faudrait corriger le lien dans la new, il n'y a pas de site officiel à proprement parler pour la libnds.
__________________
Utiliser la libnds ?
What's it ?

Dernière modification par Pitt ; 12/03/2007 à 18h20.
Pitt est déconnecté   Réponse avec citation
Vieux 12/03/2007, 18h13   #18
barjo
Membre confirmé
 
Date d'inscription: 02/03/2006
Messages: 141
Par défaut

Merci beaucoup pour ce début de tuto ces simpa

Pourquoi les personnes qui utilise la libnds ne préfére pas la palib ?
Elle est pourtant beaucoup plus documenté avec de trés bonne explications sur le wiki.
__________________
visiter mon site
barjo est déconnecté   Réponse avec citation
Vieux 12/03/2007, 18h32   #19
Pitt
Membre confirmé
 
Date d'inscription: 16/08/2006
Localisation: ...
Messages: 578
Par défaut

La libnds permet de gérer le hardware DS. La PAlib est plutôt orientée simplicité, avec tout plein de fonctions d'abstraction du hardware.
En gros, la libnds, c'est plus pour les curieux, les puristes, etc.
__________________
Utiliser la libnds ?
What's it ?
Pitt est déconnecté   Réponse avec citation
Vieux 12/03/2007, 18h47   #20
Lazarus
Membre confirmé
 
Date d'inscription: 15/11/2006
Messages: 93
Par défaut

Citation:
Pourquoi les personnes qui utilise la libnds ne préfére pas la palib ?
Elle est pourtant beaucoup plus documenté avec de trés bonne explications sur le wiki.
Ben, déjà, la documentation ne fait pas non plus la lib

Sinon, on ne va pas refaire tout le débat, mais libnds est très orienté proche du hardware, avec un contrôle total sur la DS, mais du coup un peu plus de choses à comprendre avant de commencer et de maitriser la bête, alors que PAlib est orienté simplicité, donc a des fonctions toutes faites pour cacher pas mal de petites choses.

Au final, il en ressort que la PAlib est plus simple pour débuter (après, ca dépend pour qui, si tu maitrises déjà bien le C, ca va, si tu as dev sur GBA aussi, etc...), et que les codeurs 'avertis' préfèrent libnds pour la souplesse.

PAlib te permet de faire rapidement des choses sympas, mais libnds te permet à terme de mieux comprendre la DS en elle-même, ce qui est un but en soi pour certains.
Lazarus est déconnecté   Réponse avec citation
Vieux 12/03/2007, 19h24   #21
Smealum
PsycoKid
 
Date d'inscription: 10/11/2005
Localisation: Là où il pleut
Messages: 1 141
Par défaut

Et puis, PAlib et la 3D, c'est pas trop ça
__________________

War. War never changes.
Smealum est déconnecté   Réponse avec citation
Vieux 12/03/2007, 19h30   #22
barjo
Membre confirmé
 
Date d'inscription: 02/03/2006
Messages: 141
Par défaut

Ok merci pour les réponses
__________________
visiter mon site
barjo est déconnecté   Réponse avec citation
Vieux 12/03/2007, 19h42   #23
Lazarus
Membre confirmé
 
Date d'inscription: 15/11/2006
Messages: 93
Par défaut

Citation:
Et puis, PAlib et la 3D, c'est pas trop ça
Là, désolé, je suis pas d'accord. Je dirais que c'est pas du tout ça En gros, pour la 3d, c'est libnds, point barre. En pratique on peut utiliser PAlib pour la 2D et libnds pour la 3D dans un meme projet par contre
Lazarus est déconnecté   Réponse avec citation
Vieux 12/03/2007, 19h45   #24
Smealum
PsycoKid
 
Date d'inscription: 10/11/2005
Localisation: Là où il pleut
Messages: 1 141
Par défaut

Ca n'empêche qu'il existe existe des fonctions 3D dans PAlib et...ben voilà quoi
__________________

War. War never changes.
Smealum est déconnecté   Réponse avec citation
Vieux 12/03/2007, 19h48   #25
Lazarus
Membre confirmé
 
Date d'inscription: 15/11/2006
Messages: 93
Par défaut

Oui et non... Enfin, il y a bien des fonctions 3D, d'init par exemple, qui permettent d'utiliser sans aucun soucis libnds derriere.

Les autres fonctions plus 'avancées' ne sont pas à proprement parler de la 3D pure et dure, c'est juste une utilisation des textures pour faire des sprites, ce qui a ses avantages et ses inconvénients
Lazarus est déconnecté   Réponse avec citation
Réponse

Liens sociaux

Publicité



Utilisateurs regardant la discussion actuelle : 1 (0 membre(s) et 1 invité(s))
 
Outils de la discussion
Modes d'affichage

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 02h46.


Édité par : vBulletin® version 3.7.2
Copyright ©2000 - 2023, Jelsoft Enterprises Ltd. Tous droits réservés.
Version française #16 par l'association vBulletin francophone
Design par Ass-Itch, DJP et Dr.Vince