Tutoriaux / aides : Programmer sur dreamcast le how-to / Découverte du Développement sur Dreamcast avec KOS et SDL / des liens

  

 

        

 

 

Découverte du Développement sur Dreamcast avec KOS et SDL

Découverte du Développement sur Dreamcast avec KOS et SDL

par JMD // Mars 2003

 

Tout d'abord, au moment où je commence, je ne sais pas encore ce que va réellement devenir ce document. L'idée est de voir certains morceaux de codes utiles avec KOS 1.1.9 et SDL par des exemples concrets qui vont épater vos copines (en fait, je me fais pas d'illusions : je crois qu'elle s'en foutent ... mais bon, moi, ça m'amuse !). De plus, je ne suis pas un spécialiste mais quelqu'un qui apprend pour me faire plaisir et qui préfère les trucs concrets quitte à pas être super propre dans ma façon de coder .

Enfin, soyez indulgent car mes compétences en C et en dev sur console sont minimes au moment où je débute ce doc. De ce fait, une bonne partie des choix techniques que je vais faire seront sans doute discutables. D'un autre coté, mon but est d'avancer vite et de montrer qu'avec un peu de jujotte et de ténacité, on arrive à des trucs assez sympas assez facilement.

Note légale

 Bien sûr, ce document n'engage que moi et vous utilisez son contenu à vos risques et péril. Ce document est librement distribuable. Toutefois, si vous utilisez une partie  ou l'ensemble du document, merci de me le signaler et de ne pas oublier de me citer.  

 

1er chapitre – 1ere Partie : Afficher une image sur l'écran de la DC.

 

Notre programme doit faire :

                                                      - charger une image

                                                      - afficher à l'écran

La première chose à faire est de dessiner une image (ou prendre une photo) d'une taille inférieure à 640*480 et la mettre au format Bmp. Ensuite, on va écrire le début de notre programme en initialisant KOS et en déclarant un Romdisk dans lequel on pourra stocker l'image.

    // Declarations de KOS

    #define _arch_dreamcast

    #include <kos.h>

    // Declaration d'un objet externe : le Romdisk

    extern uint8 romdisk[];

     // Initialisation de KOS et du Romdisk

    KOS_INIT_FLAGS(INIT_DEFAULT | INIT_MALLOCSTATS);

    KOS_INIT_ROMDISK(romdisk);

    // là, ce sera notre code

    int main(int argc, char **argv)

    {                            return 0;

    }

 

En parallèle de ça, il faut penser à créer un romdisk avec genromf puis créer un objet linkeable avec bin2o et, enfin, le linker lors de la compilation. Je ne rentre pas dans le détail de ces opérations car elles dépendent beaucoup de l'environnement de dev. que vous utilisez et que je suis loin d'être un spécialiste là dedans. On trouve toutefois pas mal d'indications sur ce point dans les différents forums. Pour afficher l'image, on utilisera Sdl. Il faut donc faire la déclaration en ajoutant #include <SDL/SDL.h>  après l'include de KOS (ne pas oublier de rajouter le flag -SDL dans le makefile !).

Pour utiliser la librairie SDL, il faut l'initialiser suivant ce qu'on désire faire. Dans notre cas, on désire utiliser la partie graphique. On va donc initialiser cette partie là et on verra peut être plus tard  comment en initialiser d'autres. Pour ça, on va utiliser la fonction SDL_Init qui retourne une valeur inférieure à 0 en cas d'erreur.

On rajoutera donc dans la fonction main :

    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )

              {

              fprintf( stderr, "Couldn't initialize SDL: %s\n", SDL_GetError() ) ;

              }

         

La fonction SDL_GetError() donne des informations sur l'erreur rencontrée. Si une erreur est rencontrée, on écrit donc dans la console de DC-Tool le libellé de l'erreur.

 La partie graphique de SDL se base sur des surfaces. On peut en utiliser autant qu'on le désire, les empiler, les découper etc ... l'écran physique (zone d'affichage de la DC) est une surface au même titre qu'une image montée en mémoire mais pas affichée.

La première chose à faire est donc de créer une surface qui va représenter l'écran et de définir ses propriétés. Ceci se fait en 2 étapes : la déclaration (qui doit être une variable globale dans le cas de l'écran) puis l'initialisation (qui elle, est biens sûr dans le main()).

    SDL_Surface *MainScreen ;

    MainScreen = SDL_SetVideoMode(640, 480, 0, SDL_HWSURFACE|SDL_DOUBLEBUF);

                     

Les paramètres de  SetVideoMode sont les suivants : Nb pixels en largeur , Nb pixels en hauteur , Nb de bits par pixels , Infos sur la surface.

Pour plus de détails sur le dernier paramètre, je vous encourage à lire la doc de SDL car il y en a une tripotée. Dans notre cas, on a choisi l'utilisation de la mémoire video (et pas de la ram) pour stocker la surface et d'autoriser le double buffering (permet de zapper facilement entre 2 images). Il semble que ce soit ce qui soit conseillé.

Le 3eme paramètre est 0 et laisse donc, dans ce cas, à SDL le choix de la valeur la mieux adaptée.

La fonction SDL_SetVideoMode  retourne un pointeur vers la surface. Pour tester si tout s'est bien passé, il suffit donc de tester si le pointeur existe :

     if ( MainScreen == NULL )

              {

              fprintf("Unable to set 640x480 video: %s\n", SDL_GetError());

                   }

    

Maintenant que tout est OK, on va pouvoir charger en mémoire notre image. Pour stocker une image, on fait à nouveau appel à une surface. Il est très facile de charger une image Bmp grâce à la fonction  SDL_LoadBMP  auquel il suffit de passer le chemin vers le fichier et qui retourne un pointeur vers la surface. On rajoute donc les lignes suivantes :

    SDL_Surface *Image ;

    Image = SDL_LoadBMP("/rd/JMD.bmp");

          

Pour que KOS sache qu'il faut aller chercher le fichier dans le Romdisk, on rajoute /rd/ dans le path.

Maintenant que l'image est en mémoire, il faut l'écrire sur l'écran. Pour ça, SDL propose la fonction   SDL_BlitSurface qui écrit une surface source vers une surface destination. Comme nous avons choisi un mode avec double buffer, pour voir afficher quelque chose à l'écran, il faut intervertir l'écran et le buffer avec  SDL_Flip .

Pour utiliser  SDL_BlitSurface , il faut définir la surface source et la surface destination. SDL n'oblige pas à travailler sur l'ensemble de la surface mais permet de se limiter à une partie. De cette manière, on choisit un morceau (un rectangle) de la surface source (position et taille) et on le colle dans un morceau de la surface destination

Pour définir les 'morceaux', SDL utilise une structure de rectangle pour laquelle on peut définir taille et position. Dans notre cas, nous nous limiterons à définir la position du rectangle dans lequel on veut écrire l'image (bref, le rectangle destination).

On va donc créer une structure rectangle et en définir la position avec x et y :

    SDL_Rect dest;

    dest.x = 5;

    dest.y = 5;

        

Maintenant, on va écrire notre image dans le rectangle destination puis intervertir le buffer et l'écran :

    SDL_ShowCursor(0);

    SDL_BlitSurface(Image, NULL, MainScreen, &dest);

    SDL_Flip(MainScreen);

          

Comme on est perfectionniste, on utilise SDL_ShowCursor(0) qui permet de ne pas afficher de curseur car dans tous les cas (même si pas de souris), SDL affiche une flèche disgracieuse en haut à gauche.

Pour pouvoir admirer notre beau travail, on rajoute une boucle infinie et le tour est joué :

     int a=0;

              while(a==0)

              {

                        // boucle infinie

              }

      

Et voilà, notre programme est terminé. Il donne :

    #define _arch_dreamcast

    #include <kos.h>

    #include <SDL/SDL.h>

     

    extern uint8 romdisk[];

     

    KOS_INIT_FLAGS(INIT_DEFAULT | INIT_MALLOCSTATS);

    KOS_INIT_ROMDISK(romdisk);

    SDL_Surface *MainScreen ;

    int main(int argc, char **argv)

    {

         // Init SDL et test

         if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )

              {fprintf( stderr, "Couldn't initialize SDL: %s\n", SDL_GetError() );}

     

         // Init ecran principal et test

         MainScreen = SDL_SetVideoMode(640, 480, 0, SDL_HWSURFACE|SDL_DOUBLEBUF);

         if ( MainScreen == NULL )

              {fprintf("Unable to set 640x480 video: %s\n", SDL_GetError());}

     

         // charge l'image dans une nouvelle surface

         SDL_Surface *Image ;

         Image = SDL_LoadBMP("/rd/JMD.bmp");

     

         // creation d'un rectangle destination et definition de la position

         SDL_Rect dest;

         dest.x = 5;

         dest.y = 5;

     

         // affiche l'image

         SDL_ShowCursor(0);

         SDL_BlitSurface(Image, NULL, MainScreen, &dest);

         SDL_Flip(MainScreen);

     

         // on boucle à l'infinie pour montrer le spectacle

         int a=0;

         while(a==0)

         {  // boucle infinie

              }

         return 0;

    }