Nous allons utiliser une bibliothèque qui permet une connexion DS à DS. Elle s'appelle la libLobby. Elle permet des connexions directes ou alors via des
rooms.
Normalement, vous l'avez sous forme de zip dans votre disque dur. Allez dans
devkitpro\Other libs\ et normalement vous avez un zip dont le nom commence par "liblobby". Ouvrez-le (au besoin, dézippez-le), allez dans le dossier "include" et copiez 802.11.h, lobby.h ainsi que MessageQueue.h.
Maintenant, nous allons modifier notre Makefile. Commentez
ARM7_SELECTED = ARM7_BASIC
et décommentez
#ARM7_SELECTED = ARM7_MP3_LIBLOBBY
.
Dans votre source, il faut inclure les trois headers :
Code : C | #include "MessageQueue.h"
#include "802.11.h"
#include "lobby.h"
|
Maintenant on va initialiser la libLobby avec :
Code : C | IPC_Init();
IPC_SetChannelCallback(0, &LWIFI_IPC_Callback);
LOBBY_Init();
|
Maintenant, il faut donner une fonction de réception à la libLobby. En fait, les communications sont non-bloquantes et il n'y a pas de fonction de réception. Vous devez la créer, puis la passer en argument à
void LOBBY_SetStreamHandler(unsigned short streamID, LOBBY_STREAMHANDLER_PROC callback);
pour indiquer à la libLobby que votre fonction doit être appelée à chaque réception.
Elle doit être de type
void et doit avoir trois arguments (dans l'ordre) :
- un pointeur de type unsigned char : c'est le message.
- une variable de type int : c'est la taille du message.
- une variable de type LPLOBBY_USER : c'est l'utilisateur qui a envoyé le message.
Voici donc un exemple de fonction de réception :
Code : C | void reception(unsigned char *message,int taille,LPLOBBY_USER from)
{
PA_OutputText(0,0,0,"Recu : %s",(char*)message);
}
|
Maintenant nous allons indiquer à la libLobby que la fonction
reception est la fonction de réception :
Code : C | LOBBY_SetStreamHandler(1,&reception);
|
Qu'est-ce que ce nombre avant le pointeur sur recepetion ?
Il s'agit de l'indentifiant d'un canal. D'après la source, ce nombre peut aller jusqu'à 32 768 mais le canal 32 767 est réservé.
Mais à quoi servent ces canaux ?
En fait, nous le verrons juste après, quand on fait un envoi, il faut préciser le canal. Ceci permet 32 767 fonctions de réceptions différentes. A vous de les gérer pour bien séparer les tâches.
A présent il faut connaître le nombre de joueurs connectés avec
unsigned short LOBBY_GetNumberOfKnownUsers(void);
.
Les fonctions sur les utilisateurs
On peut obtenir un utilisateur par son identifiant avec
LPLOBBY_USER LOBBY_GetUserByID(unsigned short id);
où
id est compris entre 0 et la valeur de retour de
LOBBY_GetNumberOfKnownUsers non inclus.
On peut aussi obtenir un utilisateur par son adresse MAC (à voir dans un jeu officiel) avec
LPLOBBY_USER LOBBY_GetUserByMAC(unsigned char *adresse);
.
Pour savoir si un utilisateur est déconnecté on utilise
int LOBBY_IsTimedOut(LPLOBBY_USER utilisateur);
. Cette fonction renvoie 1 s'il est déconnecté ou 0 dans le cas contraire.
Pour obtenir le nom d'un utilisateur on utilisera
const char *LOBBY_GetUserName(LPLOBBY_USER utilisateur);
.
Maintenant que nous connaissons beaucoup de fonctions concernant les utilisateurs, nous allons voir comment leur envoyer des messages.
Il existe la fonction
void LOBBY_SendToUser(LPLOBBY_USER user,unsigned short canal,unsigned char *message,int taille);
. C'est là qu'intervient la variable
canal. Supposons que vous créez un jeu de combat en temps réel multijoueur. Vous pouvez utiliser la variable
canal pour séparer les types d'envois. Par exemple le canal 1 peut servir d'envoi/réception d'infos concernant les autres joueurs connectés, et le canal 2 peut servir d'envoi/réception de messages du système de chat que vous avez récemment intégré au jeu

. Ca nous simplifie la vie, et comme nous avons quelques dizaines de milliers de canaux, on peut dire que vous n'avez pas de limite

.
Vous pouvez aussi envoyer un message à tous les utilisateurs connus avec
void LOBBY_SendToAll(unsigned short canal, unsigned char *message, int taille);
.
Les rooms
Il ne peut y avoir qu'une seule room par DS.
Les rooms sont caractérisées par leur nom, le nombre d'utilisateur maximal, l'identifiant du jeu et sa version.
A quoi servent l'identifiant du jeu et sa version ?
L'identifiant du jeu est un nombre qui indique le jeu utilisant la room. Sa version permet de connaître le fonctionnement du jeu. En fait, si les deux joueurs ont le même jeu, et si chez un joueur, l'identifiant est le même que chez un autre, on peut penser que le fonctionnement est le même (sauf si la version est différente).
Alors créons notre room avec
void LOBBY_CreateRoom(char *nom,int maxUsers,unsigned short gameCode,unsigned short version);
.
On peut définit la visibilité de la room avec
void LOBBY_SetRoomVisibility(int visible);
. Si
visible vaut 0 la room sera invisible. A l'inverse, si
visible vaut 1 la room sera visible. Seul le créateur de la room peut effectuer cette action.
Pour savoir combien il y a de rooms visibles, on fera appel à
unsigned short LOBBY_GetNumberOfKnownRooms(void);
.
Pour obtenir une room, on utilisera
LPLOBBY_ROOM LOBBY_GetRoomByID(unsigned long id);
Il ne faut pas confondre id avec gameCode (utilisé dans LOBBY_CreateRoom). En effet, id est le "numéro d'apparition" de la room. Par exemple, si c'est la première à avoir été détectée, il faut mettre 0.
Vous pouvez aussi obtenir une room à partir de l'adresse MAC de la DS du créateur de la room

en utilisant
LPLOBBY_ROOM LOBBY_GetRoomByMAC(unsigned char *mac);
.
Si vous voulez obtenir la room d'un utilisateur en particulier, il faudra appeler la fonction
LPLOBBY_ROOM LOBBY_GetRoomByUser(LPLOBBY_USER user);
.
De même, si vous voulez obtenir une room à partir de son
gameCode, il faudra appeler la fonction
LPLOBBY_ROOM LOBBY_GetRoomByGame(LPLOBBY_ROOM anchor, unsigned short gameCode);
. La variable
anchor sert à déterminer à partir de quelle room on lance la recherche. Si c'est 0 ce sera la première trouvée.
Pour savoir combien il y a d'utilisateurs dans une room, on va utiliser
unsigned short LOBBY_GetUsercountInRoom(LPLOBBY_ROOM room);
.
De même, pour obtenir le nombre maximal d'utilisateurs, on appellera
unsigned short LOBBY_GetMaxUsercountInRoom(LPLOBBY_ROOM room);
. Ces deux fonctions sont très importantes car elles permettent de trouver le nombre de places restantes dans une room.
Vous pouvez obtenir le nom d'une room avec
char* LOBBY_GetRoomName(LPLOBBY_ROOM room);
, son
gameCode avec
unsigned short LOBBY_GetRoomGameCode(LPLOBBY_ROOM room);
et sa version avec
unsigned short LOBBY_GetRoomGameVersion(LPLOBBY_ROOM room);
.
Avec les fonctions vues ci-dessus, vous pouvez choisir dans quelle room aller. Si vous voulez vous joindre à une room, il faudra utiliser
void LOBBY_JoinRoom(LPLOBBY_ROOM room);
. Si vous voulez la quitter, il faudra appeler
void LOBBY_LeaveRoom(void);
.
Vous pouvez envoyer des messages à tous les utilisateurs d'une room avec
void LOBBY_SendToRoom(LPLOBBY_ROOM room, unsigned short canal, unsigned char *message, int taille);
. Mais vous pouvez ne pas envoyer de message à tous. En fait, via l'argument
canal, vous pouvez faire le tri. Par exemple, si vous voulez envoyer des messages au créateur de la room sans que les autres utilisateurs ne les voient, il faut créer un canal chez le créateur qui n'est pas créé chez les autres. Ainsi, par le biais de ce canal, seul le créateur de la room pourra recevoir les messages...
Dans vos boucles, au même titre que
PA_WaitForVBL, il faudra systématiquement mettre :
Code : C | IPC_RcvCompleteCheck();
LOBBY_Update();
|
Sinon vous ne pourrez jamais ni détecter des utilisateurs et des rooms, ni envoyer ou recevoir de messages...
L'émulateur
J'ai une bonne nouvelle : l'émulateur No$GBA supporte très bien la liblobby ! Pour utiliser plus de Nintendo DS au sein de votre émulateur, faites F11 et rendez-vous dans la section "Number of Emulated Gameboys", et modifiez le nombre en mettant 2 à la place. Faites OK puis Options->Save Options. Fermez NO$GBA et lancez votre homebrew de nouveau. A présent, vous pouvez constater la résultat

.
Par contre, si vous voulez revenir à une seule Nintendo DS, il faut aller dans le dossier de NO$GBA et ouvrir NO$GBA.ini. Cherchez une ligne commençant par :
Citation : NO$GBA.iniNumber of Emulated Gameboys ==
Remplacez cette ligne
intégralement par :
Citation : NO$GBA.iniNumber of Emulated Gameboys == -One Machine
Et voilà

!