Aller au contenu

[TUTO HOMEBREW] Faire son premier homebrew, et surtout le comprendre


Wolfi

Messages recommandés

Salut, venant de comprendre une bonne partie du lancement/fermeture de programme pour la ps3, je vous fais un petit tuto, pour que d'autres qui ne connaissent pas très bien openGL puissent démarrer concretement plus rapidement.

 

Le but de ce tuto sera d'initialiser le contexte graphique, d'executer une boucle interruptible par le bouton PS/quitter le jeu, puis de répondre à l'interruption en revenant proprement sur le XMB.

 

Ce tutorial est utile aux personnes connaissant le C et l'OpenGL, et je développe une petite librairie en C++ pour abstraire tout ce qui pourrait l'être (polygones, brush, manette, affichage de chaines de charactères, reseau, etc).

 

Tout d'abord, petite introduction, inspirée de diverses présentations trouvables sur les sites officiels de Sony: comment la PS3 dessine-t-elle à l'écran.

 

Il y a deux librairies disponibles pour les développeurs: GCM et PSGL, GCM étant le pendant bas-niveau de PSGL. J'ai décidé d'utiliser PSGL car on n'a pas vraiment besoin d'un plus bas niveau pour développer des petits homebrew, mais sachez que le développeur anonyme de l'open backup manager utilise GCM, ce qui rend son code difficile à comprendre et trop complexe pour ce qu'il fait en réalité (ce qui est peut-être fait expres).

 

PSGL est une implémentation made in Sony d'OpenGL ES, une version simplifiée d'OpenGL (110 primitives au lieu de 400) mais qui d'après eux reste aussi puissante. Nous nous contenterons ici de parler des mecanisme d'initialisation et de fermeture, car l'utilisation d'OpenGL n'est pas propre à la PS3 et il existe déja des centaines de cours bien construits.

 

Enfin, il faut savoir qu'il n'existe aucun autre moyen que ces librairies graphiques pour afficher quelque chose à l'écran, donc pas de sortie standard, pas de printf etc.

 

Mon tutorial sera sous la forme d'un code commenté pour chaque étape.

 

Première partie - initialiser la PS3 -

 

// On demande 1 spu pour PSGL sur les 6 disponibles

sys_spu_initialize(6, 1);

 

// Met en pause la PS3 tant que la sortie HDMI n'est pas prête.

CellVideoOutState videoState;

do {

cellVideoOutGetState(CELL_VIDEO_OUT_PRIMARY, 0, &videoState);

} while(videoState.state != CELL_VIDEO_OUT_OUTPUT_STATE_ENABLED );

 

// On enregistre nos option d'initialisation.

PSGLinitOptions initOpts;

initOpts.enable = PSGL_INIT_MAX_SPUS | PSGL_INIT_INITIALIZE_SPUS;

initOpts.maxSPUs = 1;

initOpts.initializeSPUs = false;

initOpts.persistentMemorySize = 0;

initOpts.transientMemorySize = 0;

initOpts.errorConsole = 0;

initOpts.fifoSize = 0;

initOpts.hostMemorySize = 128 * 1024 * 1024; // 128 mb

 

psglInit(&initOpts);

 

// Tableau des résolution désirées, par ordre de priorité.

const unsigned int resolutions[][3] = {

{CELL_VIDEO_OUT_RESOLUTION_1080, 1920, 1080},

{CELL_VIDEO_OUT_RESOLUTION_720, 1280, 720},

{CELL_VIDEO_OUT_RESOLUTION_576, 720, 576},

{CELL_VIDEO_OUT_RESOLUTION_480, 720, 480}

};

// On choisi la résolution disponible et on enregistre son index dans le

// tableau précédent.

int chosenResolutionIndex = -1;

for (int i = 0; i < 4 && chosenResolutionIndex == -1; i++) {

if(cellVideoOutGetResolutionAvailability(CELL_VIDEO_OUT_PRIMARY,

resolutions[0],

CELL_VIDEO_OUT_ASPECT_AUTO,

0)) {

chosenResolutionIndex = i;

}

}

 

// On peut maintenant passer à l'initialisation de PSGL

if (chosenResolutionIndex != -1) {

// On cherche à obtenir les information de largeur et longueur de la

// résolution choisie.

unsigned int width = resolutions[chosenResolutionIndex][1];

unsigned int height = resolutions[chosenResolutionIndex][2];

 

// On crée une sortie PSGL paramétrée avec nos dimensions.

PSGLdeviceParameters params;

// On choisi les parametres a faire prendre en compte par createDevice

params.enable = PSGL_DEVICE_PARAMETERS_COLOR_FORMAT

| PSGL_DEVICE_PARAMETERS_DEPTH_FORMAT

| PSGL_DEVICE_PARAMETERS_MULTISAMPLING_MODE

| PSGL_DEVICE_PARAMETERS_WIDTH_HEIGHT;

// 4 composantes disponibles pr les vertex

params.colorFormat = GL_ARGB_SCE;

// 24 bits dispo pour les couleurs

params.depthFormat = GL_DEPTH_COMPONENT24;

params.multisamplingMode = GL_MULTISAMPLING_NONE_SCE;

params.width = width;

params.height = height;

 

device = psglCreateDeviceExtended(&params);

 

context = psglCreateContext();

psglMakeCurrent(context, device);

psglResetCurrentContext();

 

// On initialise le Viewport - Partie OpenGL indispensable

 

// On cherche à obtenir les dimensions effectives de dessin.

GLuint renderWidth, renderHeight;

psglGetRenderBufferDimensions(device, &renderWidth, &renderHeight);

 

// On fixe la taille du Viewport

glViewport(0, 0, renderWidth, renderHeight);

 

// On met en place la projection orthogonale.

GLfloat aspectRatio = psglGetDeviceAspectRatio(device);

float l=aspectRatio, r=-l, b=-1, t=1;

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrthof(l,r,b,t,0,1);

 

glClearColor(0.f, 0.f, 0.f, 1.f);

glDisable(GL_CULL_FACE);

 

// Il faut effacer au moins une fois l'ecran.

glClear(GL_COLOR_BUFFER_BIT

| GL_DEPTH_BUFFER_BIT

| GL_STENCIL_BUFFER_BIT);

psglSwap();

 

// On enregistre l'event handler sur le slot 0.

cellSysutilRegisterCallback(0, systemCallback, NULL);

}

La dernière ligne prépare la prochaine étape: l'execution de la boucle principale.

En effet comme dans toute application OpenGL, on doit nous même boucler pour que le programme de s'arrête pas. Cependant il existe un cas ou nous aimerions que le programme s'arrête: quand l'utilisateur éteind la ps3 ou demande au programme de s'arreter via sa manette. Pour cela, on utilise un gestionnaire d'evenement (event handler) qui appelera a chaque evenement une fonction "réponse" (callback) qu'il faut enregistrer au préalable grace à l'appel cellSysutilRegisterCallback.

 

Le premier argument de cette fonction est le "slot", il y en a 4 disponibles, de 0 à 3. Le dernier argument est un pointeur vers un buffer contenant diverse information utiles au callback, mais je n'en ai pas vraiment besoin, je le met donc à NULL. Enfin, le deuxieme argument est une fonction à executer quand un évènement aura eu lieu.

 

Deuxieme Etape - Execution de la boucle principale

 

Juste apres l'initialisation du contexte, on doit executer une boucle interruptible comme cela:

while(!systemExited) {

cellSysutilCheckCallback(); // On vérifie les interruptions

// ... On execute des instructions de dessin

}

Si un evenement a lieu, une fonction enregistrée comme callback sera appelée, en voici un exemple:

 

void systemCallback(const uint64_t status, const uint64_t param,

void *userdata) {

(void)userdata; // Pour supprimer les warnings

(void)param;

switch (status) {

case CELL_SYSUTIL_REQUEST_EXITGAME: systemExited = true;

break;

case CELL_SYSUTIL_DRAWING_BEGIN:

case CELL_SYSUTIL_DRAWING_END:

default: break;

}

}

Le prototype doit être exactement identique (3 arguments, renvoie void).

L'arguement status est le code d'interruption, on cherche donc lequel c'est grace à un branchement conditionnel, et si c'est une requête de sortie de programme, on modifie la valeur de systemExited, qui lui meme permettra d'arréter la boucle.

 

Une fois la boucle interrompue, on doit fermer le contexte OpenGL pour eviter que la PS3 bug completement et retourne plutot calmement au XMB:

 

glFinish();

psglDestroyContext(context);

psglDestroyDevice(device);

psglExit();

Ces primitives parlent d'elles-même. A noter que pour compiler vous aurez besoin des header <psgl/psgl.h> <cell/sysmodule.h> et <sys/spu_initialize.h>.

 

Si ce tuto vous a plu, n'hésitez pas à m'en demander d'autre, comme la création d'un Makefile efficace, je prépare aussi la gestion complete de la manette.

 

Si vous avez le sentiment que mon code pourrait être simplifié/amélioré dites-le moi aussi :)

Lien vers le commentaire
Partager sur d’autres sites

Je lirais ça tête reposée, ça a l'air très intéressant :)

 

Ca l'est! Je suis en train de terminer l'abstraction des manettes, je pense poster dans pas trop longtemps un petit programme complet, basé sur un exemple du sdk qui fait tourner une grille colorée, mais en permettant de la faire tourner dans l'autre sens quand on appuie sur une touche et de la stopper quand on appuie sur start :D Et avec un peu de chance, de meme faire vibrer la manette quand on fait reprendre la rotation, ca permettra de voir comment fonctionne la manette et la librairie que je fais sera ultra facile à utiliser puisque toute en objet, contrairement à ce que j'ai pu voir des autres homebrew qui font tout en impératif.

Lien vers le commentaire
Partager sur d’autres sites

Je suis d'accord, j'ai cherché partout des mini tuto pr démarrer, mais tous les gars qui savent partagent pas, ceux qui partagent ont un code flou, mal commenté, avec parfois des trucs clairement cachés (la fonction "syscall36" de l'open backup manager est pas trop débutant-friendly xD).

 

Donc j'ai eu envie, au cas incroyable ou d'autres seraient dans mon cas (savent coder en C/C++/OpenGL mais pas assez pr piger direct la doc du SDK).

 

Et puis même pr les gros gros débutants (savent coder un peu, mais l'openGL c'est du chinois) ca peut être marrant de voir et d'avoir le sentiment de comprendre un petit bout du codage de homebrew, qui pour une fois est plutôt facile.

 

En tout cas j'ai pigé la manette, je poste un mini tuto tres bientot :)

Lien vers le commentaire
Partager sur d’autres sites

Comme promis, voila un deuxième tuto pour comprendre le fonctionnement de la librairie libpad, gérant la manette de la PS3.

 

Première partie - Initialiser la librairie

 

Comme pour toutes les librairie (qui sont des prx chargés automatiquement au lancement d'un programme linké statiquement avec une librairie stub) il faut l'initialiser:

 

if (cellPadInit(7) == CELL_OK){

padInitialized = true;

}

Cette fois-ci, c'est très simple, il suffit d'appeler cette fonction, avec en argument le nombre maximal de pad que l'on veut gérer (entre 1 et 7).

 

Deuxieme partie - Obtention des informations de la manette

 

Il y a plusieurs choses à savoir pour utiliser la manette. Déja, plusieurs types de

manettes sont disponibles, la sixaxis simple, la dualshock 3 et meme des manette sans pression analogique des boutons (type PS1, soit c'est appuyé, soit ça ne l'est pas, impossible de savoir à quel point).

 

Ensuite, ou et quand demander les informations: dans la boucle principale, avant ou après le dessin, et a chaque passage dans la boucle il faudra mettre à jour ces informations.

 

Passons au code, que j'ai simplifié pour la bonne compréhension:

CellPadData padData;

cellPadGetData (0, &padData);

cellPadGetData a comme premier argument le numéro de la manette que l'on veut observer, ici 0, et comme second argument une structure à deux champs, len et buttons, et cette structure sera remplie pendant l'appel de la fonction avec les informations de la manette.

 

Le champ len est très important, il permet de savoir exactement à quel type de manette on a affaire, au lieu d'utiliser les methodes spécialisées pour cela, même si ce n'est pas le but premier. len donne en fait la taille du tableau buttons, qui selon sa taille contient des information de pression des boutons, de degré de pression, puis de mouvement du pad. Ce qui va nous interesser ici, c'est de savoir si le bouton "CROIX" est appuyé: on doit donc tester si len est supérieur à 0 (sinon la manette n'est pas encore disponible), et ensuite verifier si le troisième élément du tableau peut être masqué par la valeur du bouton CROIX:

 

if(padData.len > 0) { //Longueur inf ou égale à zero -> manette déconnectée

if (padData.buttons[3] & CELL_PAD_CTRL_CROSS) { // On teste avec le masque du bouton croix, les masques étant toujours: CELL_PAD_CTRL_*nom du bouton*

// Le bouton croix a été appuyé, on réagit en conséquence.

}

}

Troisieme partie - Fermer la librairie

 

Pour fermer la librairie, après la boucle principale il suffit d'executer:

 

cellPadEnd();

Voila, c'est tout pour le polling de manette, qui est plutot simple, et il est bien possible que la gestion du clavier et de la souris le soit tout autant.

 

Enfin, pour completer avec un exemple concret, pour ceux qui voudrait voir comment on peut coder ça en C++ et pas en impératif basique (avec aussi un superbe Makefile très inspiré de celui de l'open backup manager, qui la a bien géré) je vous joint un petit programme à compiler vous-meme (puisque distribuer des pkg semble interdit), c'est une grille moche qui tourne (exemple du SDK) à laquelle j'ai ajouté la possibilité de stopper avec START et faire changer de direction de rotation avec les fleches gauche et droite, le tout refait en vrai C++ . Petite note pour la compilation, je n'ai pas réussi a desactiver la levée d'exception dans la STL donc vous aurez à commenter la ligne qui rejette une erreur dans l'header de l'objet list de la STL du SDK (si quelqu'un a une idée à ce propos ...)

 

http://rapidshare.com/files/424639848/PS3Library.zip

Modifié par Wolfi
Lien vers le commentaire
Partager sur d’autres sites

Bonsoir,

 

Je sais que je t'ai déjà posé certaines questions et je te remercie de tes réponses.

 

J'ai cru comprendre également que tu n'avais pas beaucoup de temps mais accepterais-tu de nous faire un post sur la mise en place d'un environnement de développement ?

 

Je pense (mais je peux me tromper) que plusieurs personnes seraient intéressées.

 

Merci d'avance de toutes réponses (positives ou négatives) que tu pourrais nous fournir.

 

Sph@x

Lien vers le commentaire
Partager sur d’autres sites

Pour l'environnement, perso j'utilise eclipse. Tout est déja fait, faut juste savoir utiliser les makefile avec eclipse, ce qui est décrit dans beaucoup de bien meilleurs tuto que ce que je pourrais faire moi-même. Donc c'est pas vraiment un problème.

 

Si tu parles de la toolchain, sony file un pdf avec tout expliqué, et de toute on a pas vrt le droit d'en parler :D

 

Bonsoir,

 

Je sais que je t'ai déjà posé certaines questions et je te remercie de tes réponses.

 

J'ai cru comprendre également que tu n'avais pas beaucoup de temps mais accepterais-tu de nous faire un post sur la mise en place d'un environnement de développement ?

 

Je pense (mais je peux me tromper) que plusieurs personnes seraient intéressées.

 

Merci d'avance de toutes réponses (positives ou négatives) que tu pourrais nous fournir.

 

Sph@x

Lien vers le commentaire
Partager sur d’autres sites

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
  • Contenu similaire

    • Par wesker0404
      Bonjour,
       
      Je possède une copie de mon iso original de RE2 sur psone sur multiman que je lance sans problème sur ma ps3.
       
      J'aimerai savoir si il serait possible d'y inclure des codes action replay dessus ?
      ou inclure directement les codes AR directement sur l'iso ?
       
      Merci.
    • Par bad wolf
      Coucou les gens,
       
      Je vends une PS3 Slim 250Go, Très bon état (quelques rayures sur le dessus de la console).
      Elle possède le dernier FW, n'a jamais été downgradé ou autre.
       
      Le HDD était un 160 à l'origine et a été changé pour un 250Go (je n'ai plus les caracs en tête mais je peux les retrouver)
       
      Le lecteur BR est tombé en panne et a été changé par un officiel Sony.
       
      Elle est vendue dans sa boite d'origine avec :
       
      câbles HDMI et RGB,
       

      câble USB pour recharger les manettes)
      2 SixAxis noires officielles et 1 DualShock 3 (avec vibration) blanche (qui tire un peu sur le jaune ) officielle
      1 oreillette/micro Bluetooth officielle
      19 jeux sur Bluray en excellent état :



      Motorstorm
      Motorstorm 2
      Resistance
      Resistance 2
      Top Spin 3
      Fifa 08
      Ratchet & Clank 1
      God of War 3
      Genji
      Haze
      Unreal Tournament
      Dark Sector
      Littlebig Planet
      GTA 4
      Price of Persia
      Killzone 2
      Dead Space
      Metal Gear Solid 4 (édition limitée)
      Demon's Souls (édition deluxe -- en VO !!)




       
      Disponible en MP sur Nantes et périphérie.
      Possibilité d'envoie par la poste à vos frais.
       
      Prix de vente : 250€ négociable dans la mesure du raisonnable
      Pas de vente séparée.
       
      Merci, bonne journée.
    • Par Manau47
      Bonjours à tous, j'ai récupérer il y a peu de temps, deux ps3 fat (model 40 et 80 go) qui on des problème.
       
      la 80go démarre je vois le message de mise en garde pour l'épilepsie, les ventilos tourne à fond et la console se coupe, elle a eu la pate thermique sur les processeur de changer et son ancien propriétaire ma dit quelle à déjà vécu un yold.
       
      la 40go refuse d'afficher autre chose que le menu recovery, quand je l'allume normalement, j'entend le lecteur et le disque dur s'allumer puis une minute ou deux après le console s'éteint (pas de led jaune, pas d'image, ni de son), j'ai tente à peu près toute les option du menu recovery mais rien à faire elle me retourne un message d'erreur ou un ecrant noir (suivie de l'arret de la console) à chaque fois (et elle na jamais eu de yold).
       
      Pensez vous qu'il y est un moyen de récuper au moins une des console ? (je penche plutôt pour la 40go au vue de diffèrent forum déjà visiter) et si oui comment je doit procéder.
    • Par thegameg
      PS3 Slim 160 GB CFW 4.46
       
      Très peu utilisée. Très bon état.
       
      - 160 GB
       
      - CECH-2503A
       
      - CFW 4.46 Rogero
      - Pas de ban PSN.
       
      - 1 manette originale
      - 1 manette non-originale (fonctionnelle)
       
      - Cable alimentation, HDMI, USB pour manette.
       
      - Jeu UFC 2009
       
      - Pas de boite.
       
      Produit disponible sur Paris ou en région parisienne.
       
      Prix: 160€.
    • Par snake00331
      Salut à tous,
       
      je vends pour la PS3 2 jeux et leurs accessoires :
       


      Guitar Hero World Tour + Guitar
      DJ Hero + Platine

       
      Le tout pour 30 € sur Paris.
  • Statistiques des membres

    23 028
    Total des membres
    1 033
    Maximum en ligne
    Subaru
    Membre le plus récent
    Subaru
    Inscription
  • Statistiques des forums

    128,1 k
    Total des sujets
    1,7 M
    Total des messages
×
×
  • Créer...