Ce billet est une tentative de FAQ reprenant une partie de mes discussions ou de réaction aux commentaires récents de nouveaux arrivants qui ne m'ont pas vu gribouiller des p'tits Bilous dans tous les coins depuis des années.
An English translation of this FAQ is available here.
Qui est Bilou ?
Un personnage imaginaire -- une balle bleue avec de grands yeux, des pieds et des mains "en orbite" -- servant de héros à mes jeux vidéos, que je tiens initialement de Pierrick, et autour duquel s'est construit tout un petit monde "cartoon" où l'on retrouve des influences de Lewis Carol et des premiers dessins animés, mélangées à du Commander Keen et du SuperMario.
Pourquoi sur DS ?
Parce que la DS est la plate-forme dont je rêve depuis que j'ai un C64. Mixage son en hardware, graphisme multi-couche et support des sprites en hardware. Elle combine un écran tactile assez précis pour des applications graphiques et des contrôle de jeu à la SNES idéaux. Elle a des possibilités d'interconnexion avec le reste du monde et du stockage local pour peu qu'on se donne la peine de les faire fonctionner. Elle est un peu restreinte en resources (33+66Mhz et 4Mo de RAM), ce qui oblige le dévelopeur à chercher des solutions plutôt que de coder comme un bourrin, mais elle a quand-même assez de puissance pour ne pas nécessiter que _tous_ les aspects ne nécessitent une micro-optimisation pour pouvoir faire quelque-chose d'intéressant comme une SNES ou une Genesis. Ses possibilités 3D ne sont pas extraordinaires, mais si jamais je veux m'en servir, elles sont mieux documentées que les nvidias.
Enfin, elle existe. Si je devais coder mes jeux ailleurs, il y a de fortes chances que je commencerais par me donner l'équivalent de la DS en machine virtuelle.
Quel genre de jeu ?
J'ai un faible pour les jeux de plate-forme, donc ce sera un jeu de plate-forme. Ceci dit, j'ai encore des hésitations sur le type de gameplay. Course rapide à la Sonic ? Puzzle à la Fury ? Arcade à la Johny Biscuit ? Exploration à la Commander Keen ? Avec une composante RPG comme dans Cave Story ? Il y a de fortes chances pour que je touche un peu à tout avec des petits groupes de niveaux d'une sorte ou de l'autre, sans chercher à intégrer le tout au départ. Ca permet aussi de continuer à avancer et à proposer du fun aux joueurs.
Peut-on l'essayer ?
Oui. Les démos sont annoncées au fur et à mesure dans la section "downloads". Il s'agit de travaux en cours : je n'ai pas une équipe de béta-testeurs très étendue, et un regard neuf est toujours apprécié, même si certaines propositions ne seront pas adoptées telles quelles.
Pour les faire tourner, il vous suffit d'une DS "homebrew-ready" ou d'un émulateur.
Homebrew ?
Le développement officiel sur console Nintendo est très fermé. Ca va plus loin qu'un simple SDK coûteux ou qu'un droit de regard sur ce qui est publié et ce qui ne l'est pas. Sans une structure commerciale pré-existante et bien reconnue, c'est l'impasse. Heureusement, il existe des outils permettant malgré tout de programmer la console sans passer par le kit officiel. On dit que les jeux et programmes faits de cette façon sont "fait-maison" ("home-brew" a un petit côté "je distille mon alcool de framboise en effilant les tubes de verre moi-même" qui colle assez bien au résultat comparé au développement sur d'autres plate-formes plus ouvertes). Si vous savez ajouter des jeux sur votre DS via une carte-mémoire type SD ou micro-SD à l'aide d'un gadget acheté à un ami ou sur Internet, vous avez ce qu'il faut pour faire tourner les jeux homebrew. Bravo. ^_^
Où sont les vidéos ?
Je ne fais que rarement des photos d'écran et encore moins souvent des vidéos. Celà demande un investissement en temps colossal pour avoir quelque-chose de correct à montrer. Si vous mettez en ligne des photos ou vidéos de mes productions, je vous invite à l'annoncer à tous via un commentaire sur la démo en question.
Comment est-il programmé ?
Le moteur de jeu est en C++, de même que le modplayer responsable de la musique, le tout dans l'environnement libre "devkitpro" sous Linux. Le côté "PC" de certains outils est généralement bricolé en PERL parce que je le vaux bien. Je tente de garder au maximum la logique de jeu séparée via un langage de script spécifique, dans la veine du micro-basic d'Eric Chahi (Another World) ou de SCUMM (Maniac Mansion et successeurs). Tout ce qui doit être invoqué en permanence (moteur de collision, déplacement des sprites, lecture des touches, etc.) est gardé en C++ de sorte que les scripts n'interviennent que lors d'évènements (changement d'état d'un personnage, collision, fin d'une animation, etc.)
Verra-t-on Bilou dans les magasins ?
C'est très peu probable, et ce n'est pas mon but. La politique commerciale de Nintendo laisse très peu de place aux petits développeurs indépendants. C'est un autre monde où un jeu doit être rentable et disponible dans les bacs à Noël. Je m'appuie sur l'expérience de Cave Story et de Qwak. Je cherche à faire un jeu amusant, et il sera prêt ... quand il sera prêt. L'aventure a commencé il y a 15 ans. L'expérience de Qwak, ce jeu GBA homebrew produit en série limitée et vendu sur Internet, ouvre aussi des perspectives intéressante pour passer du stade "petites démos" à un "produit fini". On verra en temps utile.
En 3D sur PC / Wii / Xbox ... ?
C'est très peu probable également. Je n'ai jamais été séduit par le contrôle d'un personnage dans un environnement 3D. Celà demande également des techniques de programmation, d'animation et de développement très différentes de ce que le "développement-dans-le-grenier" permet. J'ai exploré cette piste pendant une bonne 10aine d'années sans réel succès, et l'arrivée des nouvelles consoles ne change pas fondamentalement la donne.
Intégrer des éléments 3D dans le jeu pique ma curiosité, mais pas au point de quitter l'approche "pixel art" que j'ai choisie.
Open Source ?
Le moteur de jeu et les outils que je développe dans le cadre du projet "Bilou sur DS" sont disponibles dans le projet sourceforge "dsgametools". Mon ambition est de m'approcher autant que possible d'un système de "game maker" entièrement présent sur DS: édition des niveaux, des graphismes, du comportement des personnages, etc. Vous pourrez donc les réutiliser pour créer votre projet complet.
En revanche, je conserve la propriété intellectuelle intégrale sur l'univers et les graphismes de Bilou. Je ne souhaite pas que X fasse une "suite" au jeu, ni que Y réutilise tel ou tel élément dans son jeu. Pour cette raison, les démos disponibles et à venir sont distribués comme un .nds "tout-en-un". Je vous demande de respecter ce choix. Si vous êtes fan de mon travail au point de vouloir proposer un "level pack", les "dsgametools" vous permettront de "schématiser" vos idées et de produire un prototype sur lequel on discuterait d'une collaboration.
Le vrai fan comprendra et respectera ce choix.
Tuesday, June 16, 2009
Bilou sur DS
Monday, November 03, 2008
Hacking gspca for Logitech QuickCam E1000 support.
Hop, je fais le saut: j'achète une webcam. Pas chère (25 francs) avec oreillette inclue "für skype" ... Mon choix s'est arrêté sur la QuickCam E1000 de Logitech, dans un rayon qui semble comporter une douzaine d'autres webcam qui se ressemblent toutes, en ce qui me concerne, hormis peut-être leur prix.
Je branche ça sur mon portable linux ... et évidemment ça ne marche pas tout seul. Le CD ne comporte que des drivers pour windows, ce qui n'est pas une surprise non-plus. Haa... on a pas encore fini de changer le monde.
Bref. Un petit tour de google, et je tombe là-dessus : http://doc.kubuntu-fr.org/spca5xx "installer gspca sous ubuntu, la version facile" ... je prends. je suis les instructions à la lettre, le module (comprenez "le driveur" pour les windoziens) s'installe. c'est bien. Sauf que point de webcam.
I just blindly bought the Logitech QuickCam E1000 this week-end (since it was the cheapest webcam around) and of course realised that it did not came with any Linux driver (not that it's surprising in any way) nor does it seems to be supported by any "out-of-the-box" driver for Ubuntu gutsy (unless i'm proved wrong). Hacking around, checking lsusb and reading the sources of the gspca driver, i figured out that it was yet-another-generic-driver that has a "white list" of supported devices. I thus added the product-id to that white list and now proudly have a working webcam. See compiled driver (which might no longer work with Labtec Webcam Pro, because i've really been *hacking* instead of *patching*) and modified sources down the page.
Un petit "lsusb" me donne au moins la référence "technique" du produit : Bus 001 Device 012: ID 046d:08af Logitech, Inc.
Ces deux numéros magiques (vendor-id=046d et product-id=08af) me permettent de voir (dans les sources du driver, en bas à gauche de l'image) que si pas mal d'autres webcam logitech sont supportées, par contre, la mienne n'est visiblement pas là. Comme le "gspca" est un driver "générique" (à savoir qu'il est en fait valide avec toutes les webcams 'standard'), j'ai 9 chances sur 10 pour que le code puisse effectivement faire fonctionner la webcam si j'arrive à expliquer au driver que "si, si, je t'assure, tu la connais aussi, celle-là". Un peu comme si votre clé-télécommande devait reconnaître la plaque minéralogique de votre voiture pour pouvoir la faire démarrer.
Bref. Premier jeu, donc, ajouter dans gspca_core.c l'identité de notre caméra. Perso, je parasite n'importe quelle entrée dans device_table[], mais il serait plus propre d'y ajouter {USB_DEVICE(0x046d, 0x08af)}, /* Logitech QuickCam E1000*/ et d'éditer en conséquence clist[] et l'énumération des caméras.
Avec ça, le driver peut dire au noyau que la webcam est pour lui, mais ça ne suffit pas. La fonction spcaDetectCamera() est appelée chaque fois qu'une nouvelle webcam est branchée, histoire de lui souhaiter la bienvenue, de prendre un verre avec les autres périphériques USB ... euh ... ou pas. C'est là que l'on va retrouver un gros "switch" qui va règler les options de notre driver générique pour chaque modèle de caméra (peut-être pas si générique que ça, donc, en fait :P) Je fais bêtement le pari que ma caméra "8af" sera probablement juste une réédition de la "8ae" (QuickCam for Notebooks), et donc :
case 0x08ae:
case 0x08af: // uber-experimental.
spca50x->desc = QuickCamNB;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HDCS2020;
break;
Et hop! ça marche!
J'adore linux!
le module recompilé pour gutsy : gspca_e1000.ko le fichier gspca_core modifié pour la QuickCam E1000 : gspca_core_e1000.c (soyons open-source jusqu'au bout ;)
Et pour ceux qui trouvent que "Aarhgh! Skype, c'est le mal", je propose la lecture de l'édifiant "Castle in the Skype" de Fabrice DESCLAUX, puis je leur dirai que MSN, c'est pas forcément mieux ;)
edit: cette manipulation est valable sur Gutsy uniquement. Sous Hardy Heron (et probablement les versions ultérieures), les drivers pré-compilés supportent directement la caméra.
Saturday, January 05, 2008
Le dernier temple.
Voilà. Je vous poste un petit message pendant que le forgeron de la mer du nord-ouest me prépare l'épée spectrale qui permettra (enfin) d'aller botter le train à tous ces spectres qui squattent le temple de Papy-Roi-des-Mers.
L'occasion de faire le point sur ce jeu très sympa mais qui ne détrônera pas "Link's Awakening" au panthéon de mon jeu de Zelda préféré. Okay, il y a eu des éléments très sympas dans ces derniers donjons (il n'y a pas d'ordre particulier pour affronter les deux derniers, notez), en particulier les 1001 utilisations du grappin (enfin un grapin pratique à utiliser! notez bien ça), mais 'juste' 6 temples (contre 11 au moins dans Zelda 3 et 8 dans Link's Awakening), je trouve que ça reste un peu court. Enfin, il y a le temple du roi des mers qui est d'une profondeur (sic) à nulle autre pareille. Et finalement, le coup du temps limité est une trouvaille de génie. (Lors de mes deux dernières visites, j'ai trouvé ma carte marine à l'arrachée et à grand coup de potions magiques pour me redonner des coeurs).
Mais que manque-t-il donc à Phantom Hourglass ?
Probablement pas le "monde en terre ferme". L'océan est sympa, plein d'îles mystérieuses absentes des cartes, mais que vous pourrez rajouter en croisant au large, par hasard.
La chaîne de l'échange, peut-être ? Ca devenait un peu éculé, mais je trouve qu'elle nous impliquait plus émotionellement dans l'aventure et dans des relations avec les petits personnages de l'île.
Les miniboss ? sûrement. Le seul temple que j'ai du reprendre à plusieurs coup, c'est celui où un "lapin-glouton" devait être vaincu. Dommage, après l'avoir affronté une fois, j'avais déjà accès à un "raccourci" pour y être en 5 secondes depuis l'entrée du temple :-/ Dans Link's Awakening, chaque donjon possédait un "miniboss" et un "téléporteur qui ramène au milieu du chateau". A la place, les temples de Phantom Hourglass ont des téléporteurs juste avant le boss final (je ne pense pas m'en être souvent servi, mais c'est ridiculement trop simple, si vous me demandez) et un de ces "raccourcis" qui font qu'à mi-parcours, vous avez réouvert l'accès à l'entrée.
Et les dialogues avec les Boss ? où sont-ils passés ? Vous croyez que je vais me satisfaire de voir le monstre onduler la tête en hurlant avant le combat ? "Héhé ! tu ne m'auras pas tant que j'aurai ma jarre" ... "Quoi ? tu as cassé ma jarre ? Là, je suis Furax!".
Bon, ils n'étaient pas tous aussi inspirés, mais bizarrement, le fait d'avoir "causé" avec le monstre lui donne plus d'ampleur. Il n'est pas juste fait de muscles, il y a une intelligence démoniaque derrière qui dirrige toute ça haine contre votre petit bouclier dans chacune des attaques.
Je vous invite à jeter un coup d'oeil au donjon 5 de "Link's Awakening", en guise de comparaison. Un des plus énigmatiques par ce que parsemé de salles "vides" au premier passage dans lesquelles vous affronterez le même miniboss (le squelette à l'épée) dans un ordre subrepticement caché. Autre truc vicelard, les passages souterrains (en side-scrolling, à la Mario) qui vous transportent un peu n'importe où dans le donjon, de sorte que vous êtes obligé de mémoriser bien mieux par où vous passez. Dans PH, tout est quasiment 'transparent' et il "suffit" de retourner voir la carte du niveau au-dessus (ou en-dessous) pour savoir comment atteindre un point donné.
J'ai remarqué beaucoup moins de "respawning" des monstres dans les temples de PH, aussi.
Enfin. J'étais tout jeune, à l'époque de LA. Maintenant, j'ai des années de Zelda d'expérience, et je n'hésite plus sur ce qu'il convient de faire quand je vois un oeil dans un mur ...
Ah oui. Il y avait ces bêtes puzzles, aussi. Les petits chevaux à lancer jusqu'à ce qu'ils soient debout tous les deux, les pingouins-carte-à-jouer, etc.
note: les maps vers lesquelles je vous envoies font partie du projet vgmaps. Si vous tombez sur une image-fourre-tout au lieu de la map en question, essayez en passant par leur répertoire.
edit: note pour plus tard: dans le combat contre bellum, penser à donner des coups d'estoc plutôt que des coups de taille.
Tags: featured, game, rpg, translate me
Friday, September 21, 2007
libmikmod deep test
I turned down the volume of my PC yesterday and let the DS be the music center, using a couple of updates on my "file server" (mostly truncating filenames and ungzipping on the fly submitted files). That was a fun time, but it revealed several oddities in the playback, so i have decided to delve deeper in the mikmod player library this lunch time to see whether i could improve playback.
The whole story is atm. only detailed in french, but to put it shortly, i mnaged to play a couple of .IT files from my brother thanks to a small patch (skip rendering in the first few ticks). I wish i could have opted for hardware playback, too, but this one seems completely buggy atm (understand: it completely locks down the system :P)
Hier, j'ai baissé le son de mon PC: c'est la DS qui a pris le relai, moyennant deux ou trois petits ajouts au programme servant de "serveur" côté PC (notamment, décompression à la volée et troncage approprié des noms de fichiers).
C'était sympa, mais le player a méchamment tendance à bugger, notamment au démarrage. J'ai essayé d'y voir un peu plus clair dans le code de mikmod (cf le post plus long). Il y a pas mal de positifs (j'arrive à jouer "Prehis2.it" de mon frère, par exemple ou la "pipe zone"), mais je crains que le player software ne devienne vite trop gourmand. Et le player hardware ? bin il crashe tout. oui, ma bonne dame.
note that while the job of hardware driver's update is straightforward, the software driver will actually try to fill the playout buffer at each step.
Software Mixing 
Bon, le mixage hardware plante tout. comme ça au moins, c'est réglé. Dommage: le mixage software va être beaucoup plus tordu. Ici, le fonctionnement du mixeur est guidé par le playout buffer, une zone de mémoire dans lequel notre processeur principal construit un "wav" que le processeur secondaire (ARM7 et les circuits de la DS) transmettent vers nos oreilles.
Tout ce joue à l'aide de deux indicateurs de position (les "curseurs" dixit la bibliothèque mikmod) qui repère où en est l'écriture et où en est la lecture dans ce qu'il est commun d'appeler un buffer circulaire. Notre driver software va donc, à chaque appel de sa méthode Update(), calculer le nombre de bytes libres dans ce buffer et faire appel au virtual channel qui est chargé d'avancer dans le pattern et de produire des bytes.
il y avait dans Player_HandleTick() ce curieux bout de code avec comme commentaire "don't handle the very first ticks, this allows the other hardware to
#if 0
if (isfirst) {
isfirst--;
return;
}
#endif
settle down so we don't loose any starting notes". En clair, le "#if 0" désactive le bloc en question, qui avait pour effet de ne pas générer de données sur les "isfirst" premiers appels à HandleTick(). Comme quasiment tous mes mods démarraient de travers, je l'ai simplement réactivé, et je ne suis pas mécontent du résultat.
Mikmod_Update()
Bion. Donc chaque appel à MikMod_Update(), pour la version "software mixing", le player va estimer combien de bytes du buffer ont déjà été joués et les remplacera par des nouveaux. Reste à quelle fréquence on va appeler cette fonction (plus elle sera appelée souvent, plus son temps d'exécution sera court, du coup).
while(1) {
ge.handle();
MikMod_Update();
ge.animate();
}
La méthode la plus directe (et utilisée dans Tetris Attack) consiste à la placer après le traitement d'une nouvelle image.
Dans cette approche, le programme va alterner les tâches suivantes:
A première vue, c'est sous-optimal: on voudrait avoir le rendu du son comme tâche de fond, p.ex. pendant que l'on attend le rafraichissement d'écran (tant qu'à attendre, ...)
Wednesday, September 05, 2007
.: easy :: normal :: hard :.

Suite au commentaire de CJ sur "armageddon machine", j'ai cherché davantage de niveaux de Commander Keen 4 & 5. Je suis tombé sur une véritable mine d'or: les niveaux tels qu'ils seraient vus dans TEDEDIT 5, l'outil d'édition de niveaux de Apogee/ID Software, réalisés par "pleinair123". Le layout même de ces niveaux suggérait que pleinair123 avait accès pas uniquement à des screenshots réassemblés, mais bien à une reproduction de ce que donnerait un éditeur. J'en veux pour preuve les flèches transparentes, qui servent de guide aux plateformes mobiles et surtout, ces curieux blocs gris avec un B que vous voyez à gauche de l'image et qui, selont la légende, servent de "frontière" pour les objets qui rebondissent (étoiles à pointes, passerelles, etc.)
Intéressant de constater que, bien que les éléments du jeu soient nettement plus sophistiqués que ce qu'il y avait dans le GameMaker, ce simple "plan" supplémentaire contenant les ennemis et ce genre d'objets de contrôle invisible permet des fonctionnements bien plus riches en se prenant nettement moins la tête.
1. Commander Keen est toujours la propriété intellectuelle d'ID software
2. Son inventeur serait ravi de refaire des Keens s'il récupérait cette propriété intellectuelle
3. Tout utilisation non-privée des infos dans "mobydoc.txt" (comme un homebrew) constituerait une violation des droits d'auteurs de Apogee
4. Il resterait quand même le plus costaud: reconstruire le comportement de tous les monstres, la physique du jeu, etc.
Bref. Je pense que ça n'intéresserait pas grand monde un keen sur DS qui avance mal, qui saute de travers et où les robots roses ne montent pas aux barres. Donc, je vais rester sur mon Bilou et ses éditeurs de niveau (non, la structure des niveaux de Commander Keen - même si elle est source d'inspiration - n'est pas géniale au point de vouloir utiliser TED pour Bilou :P)
Oh, et pour ce qui est du titre, je prends le niveau "security" de Armageddon Machine (le 2eme du jeu), au pif.
Mode easy: 6 Sparky, 3 Ampton et 2 SliceStars.
Mode normal: 13 Sparky, 5 Ampton et 5 SliceStars
Mode hard: on rajoute 4 Sparky, 1 ampton et une SliceStar qui se balade horizontalement au milieu des écrans bleus ...
Idem pour le niveau final. Ce que j'ai dit à propos des ennemis rebondissant dans un espace limité ne tient évidemment que s'il y en a (et il n'y en a aucun en mode easy dans cette partie du jeu). Le Shikadi Master est lui aussi réservé au mode "normal", et seule une rangée de lasers est activée, ce qui laisse au joueur le soin de passer à l'aide du pogo du côté d'où les lasers viennent sans être inquiété...
Donc, non, frérot: si t'as pas re-terminé les Commander Keen au moins en mode "normal", t'as jamais essayé plus que la "grande foire au bonus" réservée aux moins de 14 ans. Désolé.
edit: oh, et on ne sauvegarde pas au milieu d'un stage, hein ?
Tags: difficulty, featured, game, keen, level editor, nostalgy, platforms, tiled
Friday, August 31, 2007
Guru Meditation
Okay. Il y a les jours avec et les jours sans. Et quand il s'agit d'un "guru meditation", on préfère généralement les jours sans :P
Mais 10 ans de programmation d'OS m'ont au moins appris une chose: quand vous tenez un bug, ne le lâchez surtout pas avant d'avoir trouvé d'où il vient. A ce moment alors, et à ce moment seulement, modifiez votre code pour l'éliminer. Ouais, je sais, c'est plus facile à dire qu'à faire. C'est un peu comme jouer à Mario sans s'autoriser à faire marche arrière, ou offrir sa glace à la vanille pour manger un yaourt nature.
Alors si vous n'êtes pas particulièrement porté sur le développement sur DS, vous risquez de trouver tout ceci complètement imbuvable. Auquel cas, je vous propose d'aller voir ma gallerie de geek à la place ... Voilà. Vous êtes prévenus.
If you've ended up here, I bet there are chances your homebrew (or someone else's) threw a "guru meditation" screen at you, which you can basically compare to window's blue-screen-of-death with a smiley reference to Amiga micro-computers. What you see on screen is hexadecimal dump of the DS' internal state: registers and stack. From these, the programmer can try and identify the root cause of the bug. So if the software isn't yours, the best you can do is shooting a screenshot of what's on screen, ensure it is readable and hand that to your favourite homebrew developer with a jar of coffee
Bon, d'abord, j'ai placé un defaultExceptionHandler() le plus tôt possible dans mon programme. Si quelque-chose tourne mal, au moins, j'aurais droit à l'équivalent d'un écran-bleu-windows, mais en rouge. Sans celà, la console se bloque purement et simplement, et on est bon pour débugger à coup de "print toto".
Ensuite, je suis passé faire un petit tour dans le code de gurumeditation.c de la libnds et j'ai trouvé ceci:
//----------------------------
static void defaultHandler() {
//----------------------------
videoSetMode(0);
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
vramSetBankC(VRAM_C_SUB_BG);
SUB_BG0_CR = BG_MAP_BASE(31);
BG_PALETTE_SUB[0] = RGB15(31,0,0);
BG_PALETTE_SUB[255] = RGB15(31,31,31);
consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);
En clair, dès qu'un pépin est détecté, la DS va tenter de gérer l'exception et commence par retourner aux modes vidéo par défaut. C'est sympa d'y avoir pensé, mais la ligne en rouge est particulièrement agaçante: elle nous masque complètement l'écran du haut. J'aime autant la commenter: puisque c'est généralement là que se trouve ma console pleine de messages inutiles, j'aurais en vis-à-vis le programme planté et les infos sur où il s'est planté.
Maintenant, l'avantage que l'on a ici sur un écran bleu, c'est qu'on a le code du programme sous la main, de quoi interpréter tous ces chiffres cabalistiques. Voyons un peu.In order to figure out what went wrong, it may be useful to tweak the code that generate that error report so that it doesn't "kill" your console log (what you've printed with printf). This is shown on the snippet above, which shows the start of defaultHandler, and where I suggest you remove the red line to keep one screen of the DS untouched. Note, too, that in order to have this report ever generated, you'll need
defaultExceptionHandler() invoked by your main function -- the soonest possible, the best.La première chose, c'est de savoir où le programme s'est crashé. la valeur qui suit "pc:" correspond à l'adresse fautive dans notre programme. Le plus souvent, ce qui gène le CPU, c'est un accès vers une zone mémoire non-définie (le "data abort"), et l'adresse de cette zone-mémoire est indiquée après "addr:".
La technique la plus rapide consiste à appeler arm-eabi-addr2line -e mybrew.arm9.elf 0x2001156 (merci Thoduv). Quand ça ne suffit pas, j'ajoute "-C" pour le code en C++, ou je reprends mes vieux fichiers .map et je désassemble le code pour y voir plus clair (cf la suite).
Histoire de progresser un peu, je vais passer faire un tour dans le fichier arm9/build/.map qui a été généré automatiquement lors de la compilation de mon programme et qui indique où se trouve quelle fonction/objet pour le CPU.
Petite recherche sur "2001156". Pas de résultat. Evidemment. Par contre, en cherchant juste "2001", je tombe rapidement sur les infos suivantes:
0x02000bb8 _ZN10SpriteAnimC2Ej
.text 0x02000d00 0x970 SpriteSet.o
0x02000d10 _ZN9SpriteSet6setOAMEtP12sSpriteEntry
0x02000fe4 _ZN9SpriteSet17createDefaultPageEv
0x02000e34 _ZN9SpriteSet8SaveBackEv
0x0200107c _ZN9SpriteSet6unpackEPhj
0x020012c0 _ZN9SpriteSet4LoadEPc
0x020015f8 _ZN9SpriteSet15createEmptyPageEv
0x02000f60 _ZN9SpriteSet7getdataEPht
.text 0x02001670 0x1e8 Wifindows.o
0x02001788 _ZN4Wifi17create_wfc_windowEP6Wind
- Notre erreur se trouve quelque part dans le fichier SpriteSet.o (vu qu'il démarre à une adresse inférieure au crash, et que l'unité suivante Wifindows.o commence elle trop loin).
- la fonction SpriteSet::unpack est la seule qui pourrait contenir l'adresse fautive.
Pourquoi s'être acharné jusqu'ici, me demanderez-vous ? parce qu'avec ce code désassemblé, on va pouvoir tenter de retrouver le rôle de chaque registre au moment du crash. Lors d'un appel (à memcpy ou à iprintf, par exemple), les arguments seront placés dans r0,r1,r2 ... Je me sers évidemment aussi un peu de ce que je sais des données ... il y a 22 couleurs dans ma palettes, je retrouve "r6: 0x16", ça colle : le registre r6 contient le nombre de couleurs dans la palette avant le crash, et aurait dû être passé comme argument à iprintf un peu plus tard.memcpy(palette_target,fptr,pal_hdr.ncols*sizeof(u16));
fptr+=pal_hdr.ncols*sizeof(u16);
iprintf("%i colors loaded\n",pal_hdr.ncols);
44e: 0074 lsls r4, r6, #1 ;; Log. Shift Left Short (r4:=r6*2)
450: 4651 mov r1, sl ;; r1:=r10 -- 'this' (sl='stack limit')
452: 9003 str r0, [sp, #12]
454: 1c22 adds r2, r4, #0 ;; r2==0x2c==22*2
456: 6848 ldr r0, [r1, #4]
458: 1c29 adds r1, r5, #0
45a: f7ff fffe bl 0
45a: R_ARM_THM_CALL memcpy
45e: 1c31 adds r1, r6, #0
460: 484f ldr r0, [pc, #316] (5a0 <.text+0x5a0>) 462: 192f adds r7, r5, r4
464: f7ff fffe bl 0
Evidemment, c'est le genre de petit jeu qui demande pas mal de connaissance de la machine. Et pour le processeur ARM, j'ai encore pas mal de lacunes ... Mais c'est le genre de trucs que j'adore apprendre, alors dès que j'aurais un peu de papier devant moi, j'irai m'imprimer un le jeu d'instructions du processeur, histoire d'être mieux ARMé pour la suite (ouarf.) et je crois que je vais quand-même refaire quelques "print toto" par-ci par-là pour y voir plus clair ^_^.
oh, pour info, le registre "lr" contient généralement l'instruction ayant fait appel à la fonction en cours ... des fois qu'une erreur dans une bibliothèque vous laisserait dans le vague...
edit: Une petite discussion bien utile avec Bamba, François et Gaël m'a permis de me rendre compte que tout ça, c'était la faute à un pointeur 'this' (r10) non-initialisé avant l'appel de ma fonction SpriteSet::unpack(). Comme quoi, j'ai encore du boulot à faire avant d'être fiable en C++ :P
Read more!
Tags: featured, guru meditation, mybrew, translate me, tutoriel


Vote for your favourite post

