Tuesday, September 29, 2009

IRQ_VCOUNT

Voilà exactement le genre de technique de programmation que j'ai toujours admiré sur les consoles (et les ordinateurs Commodore, qui d'une certaine façon, sont des consoles avec un clavier et un lecteur de disquette). Mettons que je veuille modifier au milieu d'une image les paramètres de l'affichage, comme la palette de couleur, la priorité et la position de tel ou tel plan du jeu, etc.

Pour un jeu vidéo, ça me permettrait par exemple de garder une zone de score fixe dans un jeu à scrolling, ou (*ze* cas d'école) de virer la palette dans les bleus à la hauteur du plan d'eau. Dans mon éditeur de niveau, ça permettrait aux boutons de rester affichés correctement malgré les choix d'afficher ou de masquer les différents "calques".

Bien sûr, ça peut être approché aussi sur les cartes VGA etc. à condition de bien synchroniser le timer avec les débuts et fin de ligne à l'écran. Et c'est là toute l'élégance de la "solution console": il y a une ligne d'interruption dédiée directement à cette synchronisation (donc plus besoin de timers), et dans le cas de la DS, on a carrément le luxe d'un registre supplémentaire qui indique si la ligne courante correspond ou non à une ligne indiquée.
void vcountirq() {

if (REG_VCOUNT<192) {
BG_PALETTE[0]=RGB15(0,0,31);
REG_DISPSTAT = (REG_DISPSTAT&0xff)|(192<<8);
} else {
BG_PALETTE[0]=RGB15(0,0,0);
REG_DISPSTAT = (REG_DISPSTAT&0xff)|(160<<8);
}
The 'vertical count matched' interrupt is a perfect explanation of why I prefer underground console programming against overworld PC games. It is a very simple mechanism that lets code be run when the graphic controller is about to process line Y, and yet it enables a wide panel of special effects in games. The most common "showcase" is for sure implementing water: at a given horizontal position, you swap the palette and provide a "bluer" one so that bottom of the screen looks sunken.
The above code snippet does just that in a "raw" fashion where only backdrop color is changed. Don't let yourself scared by those bit masking, combining and shifting. It is just another facet of computing that is *very* handy when dealing with hardware registers. If you think of your process as an "electronic process" taking place on an array of bits, it just becomes natural.

Une petite fonction toute simple donc, qui sera appelée "sur la bonne ligne" et qui change les couleurs (ici, une seule, et entre deux valeurs pré-calculées, mais c'est juste pour la démo). Astuce, pour pouvoir être invoquée sur plusieurs lignes (plutôt que toujours sur la même) et donc remettre la couleur à sa valeur précédente, je change le numéro de la ligne où l'interruption doit se produire pour lui donner la valeur suivante dans l'interruption elle même (c'est le code avec REG_DISPSTAT).

Bon, okay, le code avec les & et les << fait un peu peur: c'est des manipulations de portions d'entiers pour modifier un byte qui se trouve en réalité dans la moitié d'un registre de 16 bits. La programmation DS est remplie de bidouille de ce genre. C'est de l'informatique d'avant XML, qui exploite pleinement la structure binaire des nombres.

Bien sûr, pour que ça fonctionne, je dois enregistrer la fonction vcountirq via la libnds (il ne suffit pas de lui donner le bon nom pour que ça se fasse tout seul. Vous rêvez, les gars!)
irqSet(IRQ_VCOUNT, vcountirq);

REG_DISPSTAT = REG_DISPSTAT|(160<<8);
irqEnable(IRQ_VCOUNT);
Vous remarquerez qu'on retrouve ici aussi les "manipulations bizarres" sur DISPSTAT, pour l'initialisation. Heureusement, le web est plein de gens qui passent leur temps à expliquer "X&FF = garder les 8 bits de poids faibles de X", etc.

Et pour désactiver l'effet,
irqDisable(IRQ_VCOUNT);
tout simplement.
J'aurais pu vous bricoler tout ça juste pour le fun ou parce que je prépare en secret un nouveau niveau de Bilou avec de l'eau. Malheureusement, je n'en suis pas encore là. Je suis dans une impasse avec mon éditeur de niveau, tout simplement: les boutons qui me permettent de décider si je veux voir ou non le fond, le plan principal, les sprites, etc. disparaissent ou deviennent illisibles par suite des manipulations pour changer la visibilité des plans. Résultat, rien de tel qu'un bon "virq" pour forcer l'affichage à "revenir" dans le bon état le temps de m'afficher la barre d'outils qui doit se trouver en bas de l'écran tactile...

Well, i wish i was posting this message because i'm working on an impressive water level. Not yet. I'm simply stuck with the UI of my level editor, where i need more layers than the console actually provide, so I'm doing a dynamic "horizontal split" when the user press "down" to access layer visibility setup. The hardest part is to integrate this properly in the GuiEngine (as usual with OOP >_<)

... Reste à intégrer ça dans le GuiEngine ...

edit: i managed to integrate and test on real hardware. It works, despite the amount of time taken by the operations confirms just "dma'ing" a new palette wouldn't work. The actual code for my 'vcount' handler is only 8 lines long (50 instructions, involving 8 stores to video registers), but it takes two scanlines to be fully processed. Plus, the first scanline shows a "flickering" area of some 24 pixels wide, suggesting that even the "companion code" that brings us from the interrupt to the "virtual void online" snippet is also too long. Maybe pushing it to ITCM would help ... and having the interrupt taking place one line in advance and forcing a busy loop until we encounter a HBLANK.

update: Pour la petite info, c'est maintenant intégré et testé sur la DS elle-même. Et ça marche, même si je suis surpris de voir 8 modifications de registres (les données sont constantes: ça se voit dans l'assembleur généré par le compilo) prendre quand même deux lignes d'affichage pour s'exécuter ! Je devrais peut-être essayer de mettre les routines concernées en ITCM, histoire de m'assurer qu'elles soient toujours en cache, ou qqch comme ça (sur du C++, ça va être coton, tiens!).

Thursday, September 24, 2009

Sur GBA

On est en janvier 2001. Le GBA commence tout doucement à prendre de l'ampleur et je rencontre dans le bus un gars qui s'est acheté une "cartouche programmable" pour y mettre plus de jeu. Je me renseigne un peu, entre 2 release de Clicker, et je trouve pas mal de documentation technique confuse, mais alléchantes, sur les capacités de la bête.

Ma petite BD de Bilou a le vent en poupe. Je fais 2 à 3 "mini-strips" par semaine, et je commence à envisager la possibilité de réimporter tous ces petits personnages dans un jeu ... sur GBA, justement. L'occasion de donner un coup de jeune aux mouvements possibles. La version BASIC était assez simpliste de ce point de vue-là : un bouton (ENTER) pour passer au pouvoir magique suivant, et un autre (SPACE) pour utiliser le pouvoir sélectionné. [L] et [R] pourrait bien jouer ce rôle ici, mais après quelques heures passées sur Megaman X, je me mets à chercher quelque-chose qui n'interromperait pas l'action à tout bout de champ.

A.D. 2001, I discover the Game Boy Advance and meet in a bus a guy who bought a strange cartridge with some 256MB of flash memory that can host games you upload from a PC. I dig the hardware specs that seems very interesting though still incompletely understood. By the same time, my little Bilou comic project is gaining speed, with 2 to 3 strips a week, and i'm starting to dream of re-importing those characters into a newer version of the video game ... on the GBA.

Finalement, la réponse de Nintendo concernant ma demande d'informations supplémentaire sur le hardware son de la GBA et la perspective de devoir gérer le mode thumb et les copies entre ROM et RAM de quelques Ko auront raison de l'aventure avant même que je n'aie installé une suite GCC pour ARM (que mon frère s'était quand-même empressé de télécharger chez Wan, avec tous les tutos disponibles à l'époque! Il y croyait dur comme fer! )

These drawings are a testimony of an attempt to re-think the controls of the game. After each level, Bilou recovers one of the "magic stones" that increases its abilities. Here, i tried to stick to two buttons and avoid interupting the action, while the BASIC version had a "select power" button (ENTER) and a "use power" button.

Despite my brother's efforts to make me start working on it, Nintendo's reply (we were asking for detailed information about how the sound worked on the device) and some awkward aspects of GBA programming (co-existence of thumb and normal instruction set and the need to manually move data between ROM and a fairly small SRAM area) burried down the project. Only the Nintendo DS that can potentially serve both as the game platform and the development platform revived the dream of a Bilou game on a true gaming console.


Tout ça parce que dans son commentaire sur "Summer Flight", mon frère mentionnait que le mod avait été remixé plus tard pour la version GBA de Bilou (qui, je le rappelle, ... ok, je sors)

Monday, September 21, 2009

curseur de copie pour LEDS


There isn't much to show (yet) about the new modifications of LEDS and its (disappeared) user interface. I'm still under the process of revising the GuiEngine's internals, adding a "transient window" flag here, a GUI_ANYKEY event there, analysing the codeflow so that i can intercept keystroke in the proper widget, etc.
But altogether, it slowly brings a revised level editor with "improved" features. The most interesting one being the (so) long awaited "block copy" mode. Note that it isn't quite the kind of "block copy" you might expect, but rather an adaptation of the "copy cursor" from CPC basic that Pierrick loved so much: you L-click on a tile from an object you want to copy, and then you click and draw from another location to reproduce the object at the source. Pretty useful.


Je progresse sur l'éditeur de niveau, même s'il n'y a pas encore grand-chose à montrer. C'est l'inconvénient de l'approche "interface utilisateur absente" où j'utilise au maximum les boutons de la DS comme contrôles. Pourtant, en interne, ça se transforme pas mal dans le code du GuiEngine, notamment pour introduire les fenêtres "temporaires" capables de disparaître dès qu'on relâche la touche qui les a invoquées, etc.
Mais la nouveauté de ce soir, c'est la copie de blocs sur la map, inspirée largement du "curseur de copie" du CPC qui plaisait tant à Pierrick.

vous voulez essayer ? téléchargez le petit 'pack' combinant la version actuelle de l'éditeur, le niveau 1 de Bilou et ses tiles tous prêts au travail...
  • L+dpad = move around the map
  • "draw mode" : L+click = grab tile, click = paint tile, dpad = select another block from the tileset
  • "copy mode" : L+click = define the source, click & move = copy from the initial click position the source image
  • select = toggle between bg and fg edition
  • B = toggle blocksize (8x8 or 16x16)
  • L = toggle between "draw mode" and "copy mode"
This is a debugging demo, so (unfortunately), you can't save your edits right now and you cannot edit anything else but the embedded map with the embedded tiles. A fully-featured application with external files selection from the map is of course planned as soon as those widgets update are done.

todo: allow tiletable as source for copies.

Tuesday, September 15, 2009

Révision du LevelEditor

C'est reparti, donc, pour un tour sur l'éditeur de niveaux. Et ça risque de prendre un moment, compte tenu du fait que je ne me souvenais même plus de l'architecture que j'avais choisie pour les classes "*Window". Avant de m'attaquer aux gros morceaux comme "copier-coller de blocs" ou "rogner la carte", je vais déjà un peu rationaliser l'espace de travail, histoire d'éviter qu'il soit bêtement saturé.

Pour ça, je compte sur le bouton "R" pour passer du mode "édition précise" au mode "brouillon" et sur un nouveau système de "pull down window", c.a.d. des fenêtres qui deviennent actives (et visible sur l'écran tactile) tant que le Dpad est maintenu dans une direction donnée. Ceux qui ont joué à Zelda: Phantom Hourglass voient de quoi je parle.

I'm resuming work on the level editor. It's been so long that i need to draw UML diagrams again to figure out the relationship between the classes, and so on. As you can see on the figure, there are quite a lot of things i want to alter on the UI, most of them relying on a newly introduced trick to have "pull" windows (that is, windows that only remain active on the touch screen as long as you hold the DPAD in the direction that invoked them.
  • [done] clean-up user-interaction
  • [done] layer visibility, "grid magnetism", etc.
  • [done] block-copy mode
  • [wish] pattern-fill mode
  • [todo] map cropping
  • [todo] tile-swapping tool.
  • [need] fix that dprint() macro !
  • [done] .cmd parsing and monsters edition
  • [wish] radar for moving around
  • [done] status report out of the playground.

Debugging sur DS

En règle générale, j'aime encore bien le débugging "à la dure" à grand coup de désassembleur et autres guru meditation, mais de temps en temps, ça ne suffit plus. Je ne suis pas contre le débugging "tea-time" avec une bonne tisane, un fluo et quelques listings, ceci dit ...

I usually enjoy the "guru meditation" kind of debugging, analyzing machine code and registers dump, with a good cup of tea, listings and a "swing" fluo pen. Yet, this time it wasn't enough, so i reused the kind of techniques i've mastered toying with my network processor, a few years ago. Since there are tons of tutos on using GDB in English, I'll focus on trying to give you the feeling of what's going on.
Mais cette fois-ci, c'est le module player NTXM qui tourne sur l'ARM7 qui posait problème, et sur l'ARM7, pas de moyen facile de sortir des messages d'erreur. J'avais bien bricolé un petit mécanisme de "rapport d'erreur" pour libntxm, qui restait désespérément muet. Bref, c'est un peu par chance que j'ai découvert que la version 0.7.3 de desmume (sous Linux, en tout cas) intègre un double "stub GDB". Du coup, moi:

desmume-cli gedsdemo.nds --arm7gdb=6667 --arm9gdb=6669
ln -s `which arm-eabi-gdb` gdb
ddd runme/arm7/runme.arm7.elf &
ddd gedsdemo.elf &
Ca mérite un mot d'explication. GDB est le débugguer intégré au compilateur gcc et g++ dans les systèmes Linux, les distributions cygwin, et le devkitpro. Dans la plupart des cas, on appellera directement le débuggueur avec le programme à corriger sur le système-cible, mais pour le développement embarqué, on sait rarement faire tourner le débuggueur complet sur le système-cible. Dans ce cas, on fait tourner une version minimale du debuggueur (le stub) avec le programme, sur le système-cible (ici, l'émulateur DS) et le front-end peut tourner sur un autre système (le PC linux, en l'occurence). Desmume intègre deux 'stubs', un pour chaque processeur de la DS, et on donne au démarrage le numéro de port à utiliser pour chacun d'eux.

desmume-cli gedsdemo.nds --arm7gdb=6667 --arm9gdb=6669
Gdb is the natural companion debugger in the GNU gcc/g++ compiler suite. It is a command-line debugger with a fairly crude (compared e.g. to Borland's debugger), but very complete and powerful interface. It is naturally available in the devkitpro toolchain as arm-eabi-gdb binary where it can disassemble and understand ARM7 and ARM9 machine code as long as they are in .ELF binaries. To get a fancy environment that lets me browse source and data structure, i use DDD (data display debugger) that acts as a front-end for a gdb session that it will launch and completely manage for you. And as crème de la crème, DDD also provides you a direct interface through the GDB session by means of a console at the bottom of its window, so if some magic button is missing for you to use the gdb tricks you know, just type it and you'll get it.
Ensuite, on démarre le débuggueur en lui donnant le fichier ELF à manipuler. Personnellement, j'utilise ddd (Data Display Debugger), qui permet l'affichage des données en graphe et le suivi de l'exécution dans les sources, en plus de toutes les fonctionnalités de gdb (breakpoints, inspection de la pile et des registres, etc.)
L'astuce est d'expliquer à ddd d'utiliser la version de gdb pour processeur ARM du devkitpro plutôt que la version pour intel propre à ma machine. Il suffit pour ça de créer un lien symbolique du nom de "gdb" pointant vers arm-eabi-gdb dans un des répertoires couverts par la variable $PATH. Dans mon cas, le répertoire courant fait l'affaire.

Reste à expliquer à chacun des gdb qu'il doit s'attacher à un stub existant plutôt que d'essayer de faire tourner lui-même le programme (par la commande run, qu'on aurait utilisé dans une session de débugging classique). Pour ça, j'utilise

target remote localhost:6667
dans la fenêtre qui fait tourner le code ARM7 et

target remote localhost:6669
dans la fenêtre qui fait tourner le code ARM9. Histoire de pouvoir suivre l'exécution des programmes, j'ai donné un "break main" dans chaque fenêtre, histoire d'interrompre le programme lors du début de son exécution en C.

Now, the system you want to debug is different from the system that runs the debugger. You may not be used to it, but remember that it is an über-common situation for people doing cross-compiling, kernel development and embedded systems. Debugging your NDS program with DDD and Desmume emulator just happens to be a specific instance of this problem. The debugged system will have to provide a (lightweight) stub for gdb, that is, a piece of code that blindly grab memory content, dumps registers, enforce breakpoints and stuff. On your debugging system, gdb has the guts to attach to this stub through the "target remote " command. Once attached, it all happens as if your debugged system had an extra process running gdb through a window of your desktop. Enjoy conditional breakpoints, data structure browsing and all ^_^.

Le reste dépend évidemment du problème qu'on cherche à résoudre. Ici, c'était une histoire de communication entre ARM7 et ARM9 (du moins, c'est ce que je croyais). Un breakpoint côté ARM9 sur l'envoi de commandes m'apprend que cette partie-là s'exécute bien sans problème, par contre mon breakpoint sur "calcNextPos" dans le module player n'est jamais appelé. Je passe en revue l'initialisation de l'ARM7 pas à pas et je me rends compte qu'il bloque au niveau de l'initialisation du Wifi ... logique, le code ARM9 pour la démo n'utilisait pas le Wifi. Faute d'un "ppp-nowifi.arm7", j'ajoute un "new Wifi(...); Wifi_Disable()" dans le code de ma démo pour pouvoir faire ma release "dans les temps" (avant le 9/9/2009 :)

PS: pour ceux que ça intéresse, je précise que QEMU (émulateur PC) intègre également un stub gdb, et que pour les autres programmes (p.ex. mes outils sur network processor), il suffit d'utiliser gdbserver qui supporte aussi bien les connexions TCP que le debugging sur cable null-modem.

Ca marche tellement bien que pour les tests que je veux faire sur mon LevelEditor, je vais carrément construire une "version light" (ledsdemo) qui tourne sous desmume et développer les nouveaux widgets, etc. dans cet environnement-là. Je le sens bien.

To conclude, 0xtob's library wasn't to blame if i got no sound: i made a slight mistake in my ARM7 initialisation code that prevented the module player from ever executing. Oh, and btw, yes, I am aware that a GDB stub running on bare DS hardware and accepting connections through WiFi is available. It just haven't been needed so far.

Just one last trick that is handy: ddd comes with tons of options to select the "inferior debugger", but i just prefer symlinking arm-eabi-gdb so that it is found under the name "gdb" when the $PATH is scanned, looking for the command to be run. Aliases won't work here.

Wednesday, September 09, 2009

Un Bilou tout neuf.

Wait a minute. Look at the date: the guy who posted a news on your forum hasn't dug this blog properly. You might be looking for a more recent demo
Level 2 is merely there to demonstrate we can now have multiple levels.
Voilà. Je vous livre mon travail de vacances: la forêt mystérieuse de Bilou, revue et corrigée. C'est une démo jouable de mon moteur de plate-forme toujours en cours de développement, où vous incarnez Bilou (la balle bleue) et récoltez les pommes pour progresser dans les niveaux. Nouveautés dans la release 0.999:

En cours de jeu, sautez avec X ou Y et dirrigez le personnage (la boule bleue, faut-il le répéter) avec le Dpad. Start passe le jeu en mode pause debugging, L+START revient au mode normal.

The sign points to the left: you haven't collected enough apples to access the second half of the level.
Here comes at last the new playable demonstration of my game engine on the Nintendo DS and a two-level game featuring Bilou, my blue and round mascot. Dodge angry applemans, avoid getting stomped by the funky funghis and collect enough apples to pass through the tree-with-a-sign (see picture on the left). You move Bilou (the blue hero) with the Dpad and jump with X or Y. Only yellow Woodworms can be stomped for now. In this new release:
  • sound & music by Pierrick H thanks to 0xtob's libntxm,
  • ease-of-use thanks to Noda's EFS
  • new monsters
  • improved controls
  • one extra (draft) level
  • 5 hitpoints per lives and unlimited lives
  • a few hidden places you needn't to find
  • some more gfx
  • parallax scrolling
yet, this is still work in progress. your comments are welcome on any aspects.

3, 2, 1 ... Release !


  • corriger la map du niveau 1
  • corriger la map du niveau 2
  • faire la vaisselle
  • dessiner une sortie pour le niveau 1
  • ajouter le haut des arbres
  • arranger le scrolling
  • bercer *deline
  • faire tourner la musique
  • empaqueter le tout.
  • uploader sur SourceForge
  • annoncer sur dev-fr

Tuesday, September 08, 2009

Compacting Tilesheet

'faut que je me méfie: j'atteinds de nouveau des taux d'occupation de ma tilesheet assez hauts. Il y a encore de la place (les bilous de la tilesheet peuvent être remplacés), mais j'aimerais autant éviter le genre de problème que j'ai eu dans le passé.

Et une solution pour ça consisterait à pouvoir réutiliser le même tile dans plusieurs blocs. C'est clairement un atout dans les blocs de terre, qui commencent à devenir fort nombreux. J'ai déjà des algorithmes pour ça sur le PC (en PERL), reste à voir si je parviendrais à les transposer en C++ sur la DS... Si c'est le cas, je descendrais de près de 1000 tiles à 666. Pas trop mal.

(PS: oui, je sais, c'est crapuleux de redimensionner une image comme ça. C'est pour ne pas gâcher la découverte des améliorations)

I'm done with the behaviour of appleman for now. It isn't perfect yet, and he can't be defeated, but it will do the trick for the next milestone. So i've started packaging all this into a new gedsdemo.nds, a job that has been greatly simplified with the addition of Noda's EFS library (when i don't forget to patch the .nds i produce :P) i still have to make sure the background music (and SFX) are properly loaded, and fix things here and there on the maps, but the last 5% shouldn't account for too much work.

Mais le "packaging" progresse bien. Du moins j'ai une première approximation pour faire des snapshots. Je la joue "ambitieux", mais je vais tenter d'ajouter le petit mod de Pierrick, cette foi-ci. Il y a encore du boulot pour arranger les maps et comme d'habitude, je me bagarre avec l'EFS de Noda. Je te parie que j'ai oublié de patcher le .nds, tiens.

Pour simplifier, j'oublie régulièrement un élément ici ou là, et je modifies les sources sans les mains pendant que je berce ma p'tite puce.

Friday, September 04, 2009

95% done.

J'ai repris ma petite todo-liste que j'avais fait après la release de ma dernière démo pour cocher les derniers développements. Bonne nouvelle: il ne reste rien à faire.
  • Techniquement, donc, le moteur de jeu est prêt pour la prochaine petite démo.
  • Artistiquement, je voudrais encore améliorer un peu le feuillage des arbres.
  • Niveau gameplay, je dois finir le comportement de l'appleman et rendre visible la sortie du niveau 1, histoire que vous puissiez essayer le niveau 2 ^_^
Ensuite, il sera franchement temps que je me remette au boulot sur l'éditeur de niveaux. Il est à la traine, le pauvre, avec des "fix" qui attendent depuis ... houu ... un an ?

Right after I released my the last demo, I came up with a little todo-list of things to be done before a new demo was worth to get out. Good news: they're all flagged as "done" right now. I still have non-technical things to finish, such as the trees' art or Appleman and BerryBat's behaviour. Then I'll have to ensure levels are playable and contain no "dead ends". It is just a matter of day before you see "grab-the-apples-and-find-the-exit-2.0-new-and-improved" (aka. gedsdemo). Some packaging will have to be done, as usual: i guess you don't want to bother with installing small files all over the place, or tap "B A R R Y L" to see the game starting so I actually build a separate binary that shares the game engine library.
The next goal: improve the level editor. The poor thing is waiting for an update for roughly one year now. It's getting too easy to screw up a level and too hard to fix the same level.


Bon, comme d'habitude, il y aura aussi un peu de "packaging" à faire: reprendre le moteur de jeu, les graphismes, la musique, tout ça, et l'intégrer dans un petit .nds prêt à la distribution. Avec l'EFS de Noda, ça devrait passer sans trop de problèmes.

Thursday, September 03, 2009

Sound Effects

Bon, il est temps de faire du bruit. Voilà le bout de code de la libntxm qui traite les nouvelles notes lors de la lecture du pattern. Le reste du temps, le player se contente d'ajuster le volume et de traiter les effets définis par une "cell" (une case du pattern).

Pour pouvoir faire des effets sonores, il faudra en quelques sortes que j'appelle ce même code à la demande depuis le processeur ARM9, probablement en réutilisant la technique d'IPC qui a servi à indiquer que le module devait être lancé ou arrêté (cf. NTXM7::updateCommands et le fichier command7.cpp)

It's been roughly 1 year that my game engine is waiting for sound effects. Let's see how to proceed, and add them to the ARM7 NTXM player that is the core of sound playback on the DS. This post is a sort of "exploration mission" to see how i'll proceed with programming them.
Primo, if i want to issue sound effects, the first thing to do is to ensure that I can invoke the "playNote" function (and surrounding code) on request from the game engine running on ARM9 . The most likely approach will be to mimmic the IPC approach 0xtob used to instruct the ARM7 to start or stop playing the whole song.
Funny enough, all the "commands handling code" always look the same. PLAY_SAMPLE and PLAY_INST commands already exist (i guess 0xtob needed them for the nitrotracker), but the actual stubs are missing. On the other hand, the "proxy" functions at the ARM9 are already present in command9.cpp ; they just lack an API in ntxm9.cpp ...

It should be running in a couple of evenings. It's really a shame it took me so0o long to check it out. It sounds that most of the effort will be to make GobExpression invoke ntxm9::playNote(), after all.

Tss. Même après l'an 2000, tous ces codes de "gestion des commandes" se ressemblent. PLAY_SAMPLE et PLAY_INST existent déjà, j'ai même déjà struct PlayInstCommand. Ils ne sont juste pas encore implémentés, mais Oxtob a bien préparé le terrain, pas de doute. Eh bien on va y remédier.
Cerise sur le gateau: CommandPlayInst et CommandStopInst sont déjà là dans command9.cpp ... Il reste juste à ajouter ça à NTXM9 et à faire en sorte que ce soit appelable depuis le GameScript et confrères.

edit: okay. Ca marche. Les pommes font "bzing!" quand on les prend. Il a fallu un peu plus de code que prévu du côté du game engine: c'est la première fois qu'une GobExpression du script appelle du code C++ ;)
this is the right place for quickstuff