I. Introduction :

Maintenant que vous avez une toolchain proprement installée (voir Tutoriels - Installation Toolchain Linux), on va pouvoir commencer les choses sérieuses avec l'exemple classique en programmation : le fameux Hello World.

Dans ce tutoriel, vous apprendrez comment est structuré un programme C pour PSP. Nous verrons aussi comment écrire un Makefile pour la compilation de notre programme.

II. Structure d'un programme : 

Comme dans tous les programmes codés en C, il faut include des fichiers d'entêtes (headers .h) donnant accès à des fonctions plus ou moins basiques. Dans notre exemple, nous allons inclure 2 headers qui vont nous permettre d'initialiser notre programme et de pouvoir afficher un texte simple à l'écran.

Pour cela, il suffit de placer le code suivant au début de votre programme :

1
2
#include <pspkernel.h>
#include <pspdebug.h>

 

Ensuite, il faut renseigner quelques informations concernant notre application à l'aide de la macro PSP_MODULE_INFO. Le premier argument est une chaîne de caractère qui correspond au nom de notre application : Hello World. Le second argument est un entier qui représente le type d'application que l'on fait : User Mode, Kernel Mode ou VSH. Dans notre cas, nous faisons une application en User Mode, cet argument prendra la valeur 0. Les 2 derniers arguments sont des entiers représentant la version majeure et la version mineure de notre programme. Pour une application que l'on voudrait en version 0.1, la version majeure serait 0 et la version mineure 1.

Ce qui nous donne en code C :

1
PSP_MODULE_INFO("Hello World", 0, 0, 1);

 

Pour plus de simplicité dans la rédaction du code, nous allons "redéfinir" la fameuse fonction C printf. Le fichier pspdebug.h contient une fonction au comportement similaire à printf : pspDebugScreenPrintf. Pour cela, on définit une constante printf prenant la valeur pspDebugScreenPrintf à l'aide de la directive du préprocesseur #define :

1
#define printf pspDebugScreenPrintf

 

A chaque fois que aurez besoin de faire un affichage simple de texte à l'écran, vous pourrez appeler printf au lieu de taper pspDebugScreenPrintf.

III. Les fonctions indispensables : 

Afin que notre programme puisse fonctionner correctement, il nous faut rajouter quelques fonctions qui vont s'occuper de quitter notre programme proprement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
  done = 1;
  return 0;
}
 
/* Callback thread */
int CallbackThread(SceSize args, void *argp)
{
  int cbid;
 
  cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
  sceKernelRegisterExitCallback(cbid);
  sceKernelSleepThreadCB();
 
  return 0;
}
 
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
  int thid = 0;
 
  thid = sceKernelCreateThread("update_thread", CallbackThread,
             0x11, 0xFA0, 0, 0);
  if(thid >= 0)
  {
    sceKernelStartThread(thid, 0, 0);
  }
 
  return thid;
}

Ici, je vous donne le code complet de ces fonctions sans explications. En effet, il n'est pas indispensable de comprendre le fonctionnement exact de ce code pour faire fonctionner votre programme.

IV. Le programme principal main : 

Maintenant, il est temps de penser sur le cas de notre programme principal : la fonction main. Par défaut, on lui fait retourner un entier et elle ne prend aucun argument en entrée.

1
int main (void)

 

Les 2 premières lignes de notre main, doivent toujours contenir ces 2 fonctions : pspDebugScreenInit et SetupCallbacks. La première initialise l'écran en mode Debug : un mode similaire à un terminal (texte en blanc sur fond noir). La seconde se charge de lancer les callbacks d'arrêt de l'application que l'on a définies dans la section précédente.

1
2
pspDebugScreenInit();
SetupCallbacks();

 

Vient ensuite, le code de notre application à proprement parlé. Pour notre Hello World, il sufit d'appeler printf avec le texte souhaité :

1
printf("Hello World !\n");

V. Le fichier Makefile : 

Pour ceux qui débutent en programmation, le fichier Makefile contient tous les paramétrages permettant à make de compiler notre programme.

Pour commencer, nous allons définir les variables TARGET et OBJS. La première est un nom que l'on définit comme on veut et il ne doit pas contenir d'espace. La seconde variable contient le nom complet du ou des fichiers objets (.o) que make va générer pendant le processus de compilation. Le nom de ce fichier doit avoir le même nom que le fichier dans lequel vous avez la fonction main mais avec l'extension .o.

1
2
TARGET = hello-world
OBJS = hello-world.o

 

Dans notre cas, le fichier contenant la fonction main s'appelle hello-world.c. Si on veut l'appeler main.c, il faudra mettre main.o dans la variables OBJS. Nous verrons, certainement, dans d'autres tutoriels que l'on peut mettre plusieurs noms de fichiers dans cette variable et dans quels cas c'est intéressant de le faire.

Le groupe de 4 variables suivants concerne des paramétres pour gcc (le compilateur). La première variable du groupe est INCDIR et désigne un ou plusieurs répertoires contenant des fichiers headers en plus de ceux présents dans les dossiers par défaut et ne se trouvant pas dans les dossier par défaut : dans notre exemple elle est inutile, on la laissera vide. La seconde variable s'appelle CFLAGS : elle contient les paramètres que l'on passe au compilateur gcc comme on pourrait le faire si on l'appelait directement depuis un terminal. La troisième est CXXFLAGS qui est l'équivalent de CFLAGS mais à destination de g++ (le compilateur C++). Enfin, la dernière variable ASFLAGS se comporte comme les 2 précedentes mais elle est destinée au compilateur pour langage Assembleur. Si vous désirez plus d'explication sur les paramètres passés aux différents compilateurs vous pouvez toujours lire les pages manuels (man gcc, man g++,...).

1
2
3
4
INCDIR = 
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

 

Les 3 variables suivantes concernent les paramètres pour le linker ld : c'est lui qui génère l'executable ELF de l'application. La première variable est LIBDIR et c'est un equivalent de INCDIR pour ld. On ne l'utilise si l'on veut inclure des librairies qui ne se trouvent pas dans le dossier des librairies par défaut. La seconde LDFLAGS est un équivalent de CFLAGS : elle doit contenir les paramètres (de ligne de commandes) que l'on veut passer à ld l'éditeur de liens. La troisième est LIBS et elle doit contenir la liste des librairies non standard qu'il faut. Nous verrons, dans d'autres exemples, comment l'utiliser.

1
2
3
LIBDIR =
LDFLAGS =
LIBS =

 

La section que allons voir doit contenir toutes les variables de paramétrages pour notre application : elle va contenir le nom de l'application, le nom de l'icône ICON0 et des autres fichiers ressources, ainsi que le numéro de version minimum du firmware qu'il faut pour éxécuter l'application. Evidemment, on ne va spécifier que celle dont on a besoin : ici EXTRA_TARGETS, PSP_EBOOT_TITLE et PSP_FW_VERSION.

1
2
3
EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Hello World
PSP_FW_VERSION = 372

Ici, on spécifie que notre fichier de sortie sera EBOOT.PBP, que le nom de l'application qui s'affiche dans le XMB sera Hello World et qu'il faut un firmware 3.72 ou supérieur pour lancer l'application. Pour une liste complète des paramètres, vous pouvez vous reportez à la dernière section de ce tutoriel.

Enfin, la dernière section contient le paramétrage d'un variable nécessaire à l'inclusion d'un autre fichier contenant la paramétrage de l'environnement de développement : build.mak pour les applications EBOOT et build_prx.mak pour les plugins PRX.

1
2
PSPSDK = $(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

 

VI. Personnalisation de l'application : 

Il est possible de personnaliser son application en paramétrant plusieurs variables dans le Makefile. Toutes ces variable sont à placées avant la section de la variable PSPSDK.

PSP_EBOOT_TITLE permet de personnaliser le nom de l'application que l'on voit dans le XMB.

PSP_FW_VERSION permet de définir la version minimum du firmware pour éxecuter l'application. Par exemple, si l'on veut un application pour firmware 5.00 minimum on définira PSP_FW_VERSION = 500.

PSP_EBOOT_ICON permet de définir l'icône ICON0 du EBOOT. Par défaut, on lui attribut la valeur icon0.png et on place le fichier image dans le même dossier que le Makefile.

PSP_EBOOT_PIC1 permet de définir l'image de fond PIC1 du EBOOT. Par défaut, on lui attribut la valeur pic1.png et on place le fichier image dans le même dossier que le Makefile.

PSP_EBOOT_SND0 permet de définir la musique de fond SND0 du EBOOT. Par défaut, on lui attribut la valeur snd0.at3 et on place le fichier son dans le même dossier que le Makefile.

 

Il existe d'autres variables de personnalisation que nous rajouterons au fur et à mesure. En attendant, vous pouvez déjà commencer à faire des choses assez sympathique avec celles-ci.

 

VII. Le code source de l'exemple : 

Vous trouverez l'archive au format .tar.gz en fichier joint au tutoriel. Elle contient le fichier hello-world.c et le fichier Makefile.