Showing posts with label ntxm. Show all posts
Showing posts with label ntxm. Show all posts

Tuesday, November 05, 2024

libntxm by asiekierka or libmx7 by sverx

For years and years, I've been post-poning the time where I could back-port my changes of the sound player library NTXM into the upstream github... And then in December 2023, I note that the library has been revived by one homebrew developer I'm following since March.

I asked whether they would be interested in a pull request for my effects system and she replied

PRs are always welcome! However, someone has already made merged pull requests to support more XM effects, so you might need to review their changes against your own.

Later on mastodon, she added

 I honestly recommend maxmod or libxm7 for gamedev use...

I know that other package released by Sverx quite a while ago. Since the time I was looking for a module player to replace mikmod, Sverx has decided to open-source it. I still have to code-study it. So no code exchange occured and nothing changed in my own dsgametools repository.

Early this month, she announced an interesting news: 
nrio-usb-disk, a tool to use the DS Linker Writer card to connect your Slot-1 cartridges to a PC as USB mass storage. This acts as an open-source replacement for the DS Linker "uDisk" tool, but this one supports any flashcart.

So she can use it to quick-cycle-develop and rebooted Nitro Tracker over USB (instead of uploading over WiFi as I do with runME). The PC is the USB host and the DS is device (via USB controller chip in Slot-2).

Given how fragile NDS development over WiFi has become with WiFi security ever increasing and the NDS hardware remaining unchanged, I might have to consider getting one such device myself and understand how it works for a safer future.

edit: the linker used isn't exactly new.

trivia: did you know Goodboy Galaxy programmer gecko contributed a few fixes to nitroustracker 0.4.9 ?

Saturday, March 02, 2024

Let's have more musics!

If you have tried the last demo, you most certainly noted that there are only 2 soundtracks for 3 rooms. And moreover, that there is a different set of sound effects depending on the room you're in. This is a drawback of the current sound engine, where everything is in one data file: main in-game tune, side tunes for menu and such, single-pattern for level clear, mini-patterns for 1-UPs and notable pick-ups, samples to play them all and samples to be used as standalone sound effects.

Bon, un des gros morceaux de programmation qu'il me reste à faire sur le moteur de jeu, c'est de faire en sorte qu'on puisse plus librement passer d'une musique à l'autre. Pas charger une autre musique en changeant de monde, ça c'est déjà fait. Non. Je veux dire décider que "string tracking" n'est pas la musique idéale pour la green zone et que "4U2" donnera mieux. Ou "little flower on the grass". Pour l'instant, ça pose un soucis parce que les fichiers musique contiennent aussi la palette sonore pour les différents personnages. Je voudrais donc pouvoir faire avec les samples et autres patterns ce que j'ai fait avec les images : charger un deuxième jeu de sons par-dessus la musique destinée au monde. ça fait un moment que ça me trotte en tête.

Et cette semaine, j'ai pu passer un premier cap: importer les samples. ça a l'air de marcher, mais ne nous leurrons pas: vu le type de programmation auquel on a affaire, il faudra rajouter quelques tests automatiques sous scruteur de mémoire pour garantir qu'on n'a pas ajouté une bombe à retardement dans le jeu. Et il y aura une repasse pour mettre ça au net avec des classes une fois que j'aurai validé le concept, parce que pour l'instant, ça part dans tous les sens, aucune des classes du moteur de jeu n'ayant été prévues pour ça.

So among the objectives I sketched in my 2024 notebook, there was some ideas to overlay .xm files the way I overlay .spr files... Or rather the other way'round. Here the generic "bilou.xm" containing mostly sound effects would see its samples and patterns imported over the world-specific song.

#ndsdev status last night: I could allow 2 instances of NTXM::Song to exist together.
#ndsdev status tonight: I can import instruments from one NTXM::Song so that different environment can share some sound effects.
little step for #gamedev, giant leap for game #MadeWithMyEngine.

I admit it might sound weird to add the common part over the world-custom part. After all video does the opposite. The reason here is that odds of adding common sounds over the course of the development feels higher than odds of adding new samples to an existing song. It shouldn't be too hard to tell my brother that patterns 50-60 should be kept free for sound effects, same for samples 50+, no matter what song we're using than to remap all samples of the per-world-songs to other slots because we've got one extra ooch-that-is-electric sample added in the shared bilou.xm

But yeah, I still make sure that bilou.xm is only loaded once, when the game initializes, and we don't pay extra wait time for overlaying it from the SD card. Instead, samples and patterns from the shared song got "borrowed" from the shared song and marked as such so that they aren't freed when we swap songs. Did I mention I read a bit about RUST programming language earlier this week ;) ?

edit: now also imports mini-pattern ^_^

edit: tried new songs ... some things worked, but some things look broken

edit: ow. turns out when you encounter pattern break on a mini-pattern, only the channel with the break command is discarded ^^". Seems like it was only a matter of luck that SchoolRush did work fine, and possibly explain why playing / leaving it idle long enough started producing super-fast trash sounds. Now, you'd have hard time dumping the ROM with that ... not as "easy" as with a runaway audio channel on a GBA.

edit: fixed

Tuesday, October 31, 2023

zik.more "bilou.xm"

Bon, après avoir peiné à permettre de mélanger deux jeux d'images dans la mémoire vidéo, il est probablement temps que je regarde à faire la même chose au niveau des sons. En particulier parce que pour l'instant ma démo "three rooms" est obligé de partager la même musique pour l'école et la pyramide. Et si CJ ou Piek me débarquait là tout de suite avec une musique plus pyramidale, je serais obligé d'aller copier-coller les samples et les pistes de 'bilousch16.it' par-dessus, sans quoi je risquerais d'avoir des effets bizarres.

La manière la plus simple de procéder serait de charger d'abord "pyramid.xm" puis d'aller piocher dans "bilou.xm" les pistes et les samples que je veux importer. ça a par contre l'inconvénient qu'à chaque fois que le jeu va charger un nouveau monde, il doit commencer par oublier tous les sons, charger les sons spécifiques au nouveau monde puis enfin remettre les sons communs par-dessus. Avouez que c'est un peu idiot.

Une alternative à creuser, ce serait de faire en sorte que les sons et pistes d'effets de Bilou.xm restent en mémoire, et que la musique "pour le monde en cours" sache y faire référence sans essayer d'en gérer directement le contenu. En somme, que ces samples aient un statut "d'invités" et que supprimer le morceau en cours n'ait aucun effet sur eux.

  • bonne nouvelle: XmTransport, la classe chargée d'ouvrir les fichiers XM, est déjà capable de travailler avec un NTXM::Song& donné.
  • [done] vérifier qu'il n'y a pas "d'effet Singleton" dans ::Song
  • [done] extraire le bilou.xm hors de la musique de SchoolRush

Saturday, December 18, 2021

Ludricous Speed

 There's another bug with my modified version of libntxm. It has been around since at least early School Rush prototypes and possibly even Apple Assault. If you let the player spin for too long, it suddenly starts to play things at ridiculous speed that makes the song barely recognizable.

I had the Dreams demo running with ARM7 debugger plugged in for another reason (undefined instruction) and it started speeding the song up so I dropped all my kitchen stuff and jumped on the CTRL+C to be able to dig that later. And later is now.

One symptom of the issue seems to be that the tick_ms variable is now way larger than the MsPerTick() property of the Song.

Every time the playTimeHandler() is invoked, it recomputes how many milliseconds elapsed since last call, and here I get the value of 1. It won't get out of the issue because there's nowhere we could read tick_ms = 0. Instead, the amount of time expected is substracted from the time elapsed so far, so that 'extra milliseconds' are deduced from the next 'tick'.But watching that tick_ms evolve, it is properly decreasing. It has not just been gone wild. It got corrupted from something else.

It doesn't tell me what goes wrong in the soft, unfortunately, but at least, it gives me a way to make sure players won't experience it. If I cap the tick_ms to 2*MsPerTick(), I shouldn't have issues.

Note how buggy tick_ms is close to last_ms ...

Note how unlikely it is that the player has been running for 43509 seconds. I wasn't even running it for one hour! And when it eventually occured again, lastms was 43494543, or something alike (decimal, not hexa).

Seeing some more code featuring 'compute over 100' now makes much more sense. 100 times higher than 43 million, we're quite at MAXINT for an unsigned. Plus, if you've got an unsigned, comparing -t to something might very well produce something that is compiler-dependent. Likely, there might be a switch to produce a warning for that.

Il y a un truc qui me chagrinait, avec School Rush: au bout d'un certain temps la musique partait en vrille. Le problème se posait uniquement au bout d'un temps assez long, du coup, je n'avais jamais eu l'occasion de prendre le temps de chercher le problème. Mais hier, j'avais un débuggeur ARM7 prêt à fonctionner, un émulateur branché dessus avec le code qui 'là-normalement-ça-devrait-marcher' pour un autre soucis et j'étais en cuisine ... donc ils ont tourné pendant longtemps sans intervention ... assez longtemps pour que le problème de School Rush se produise. J'ai bondi sur mon ordi pour interrompre tout ça et débugguer enfin cette histoire.

Au premier tour, tout ce que j'ai pu dire c'est que "bin c'est parce que tout d'un coup, on découvre qu'on est en retard de plus de 40 millions de microsecondes pour passer au 'tic' de musique suivant". J'avais espéré qu'il s'agissait d'une déviation ou quelque-chose de ce genre, j'avais mis quelques 'break if...' dans ddd mais quand le problème s'était finalement re-reproduit (bonne journée, ça), on était passé de quelques millisecondes de retard à plus de 43 millions, comme ça, sans-transition-à-vous-les-studios. J'en venais à me dire que 'tant pis, je vais juste mettre un patch qui limite artificiellement ce délai' puis je tombe sur l'implémentation de la lecture du temps à partir du hardware qui cache une division par 100 ... et 100 * 43 million, on approche du plus grand entier 32 bits. Là, ça pue le bug de conversions arithmétique dû à une soustraction mal calibrée... ça je pourrai corriger pour de bon.

Tuesday, December 14, 2021

PlaySFX vs. PlayInst

 

Je refais un peu d'explication-BD parce que là, c'est un brin compliqué. Le mécanisme que j'avais ajouté pour faire des effets-par-pattern, je l'ai poussé un peu trop loin.

Au départ, c'était bien vu: un ensemble de flags permettant de dire si on doit suivre la "partition" normale du module ou continuer à avancer dans la piste en cours jusqu'à trouver un effet 'pattern break'. Mais il y a un cas que je n'avais pas en tête à ce moment-là: les effets 'normaux' fait d'un p'tit sample tout seul. Eh oui.

Dans ce cas-là, la piste sur laquelle on met le sample n'a normalement pas de contenu. Depuis le nouveau code, elle est ignorée puisqu'au-dessus du nombre de pistes définies dans le fichier .xm. La seule exception à cette règle, c'est pour les pistes qu'on a attachées à un morceau de piste d'effet.

Disclaimer first: many of the things I'm now doing with libntxm are far beyond what it was designed to do, that is running a soundtracker on the NDS. When thigns go wild because I stop a song and replace it with another before the Player class on the ARM7 get any chance to run its every-millisecond handler routine, I'm worse than a TAS-speedrunner producing superhuman inputs on the software. Right ? Same when I feed the Player with two patterns simultaneously and going 'yeah, play pattern 9 on channels 1-12 while at the same time playing pattern 27 on channels 14-16, will you ?'. None of this was part of the original plan, and that's perfectly natural. It's up to me to make it work if I want it to work.

Ça, ça marche bien pour le moment 'lecture de la nouvelle cellule (note) dans la ligne'. Mais si on veut qu'un p'tit son puisse être joué, il faut qu'on continue à faire des calculs d'enveloppe, la gestion des registres de volume. C'était déjà un peu à ça que servait le flag channel_active. Il reprend du service.

Bon, là je me suis limité à un p'tit test tout bas, parce que ma fée est pas ultra-fan de StrTrk et que c'est l'heure de la p'tite série qu'elle aime bien à la télé.

So a few weeks ago, I fixed a crash in the ARM7 code with 'oh, I know: I'll give NTXM player a NULL song first, and then delete-and-create another one'. Not a bad idea in itself, but I missed a few things that the player has to do even when I change the song, like progressively muting the channels when there are no more notes to do. Obviously, I shouldn't prevent it from doing so even though we activated the NULL song.

I also finally implemented an if-block for the GobScript (it turned out quite simple thing to do) and tried to use that so that we'd use pattern-effects only when playing a tune with such patterns, and play plain-samples-effects otherwise. Nice try, but it turned out that no sample was playing at all. That was because of my previous changes again: when playing such lone samples, we're perfectly right to do so on channels that are not present in the song. (Actually, we should better do so). But the code from SchoolRush would only start playing a sample if there was a pattern Cell to back it up. Either a regular one, or one from a pattern-effect. I had to identify the tasks where that test was mandatory (e.g. when processing effects or advancing to the next row) and tasks where it shouldn't be used (process volume envelopes, start the sample, turn down the volume when done playing the sample, etc.)

Reste à espérer qu'avec les corrections de 'quelle musique jouer quand' et 'okay, on a plus de partitions, mais continue quand-même à baisser le volume', ça suffise pour que les musiques de la prochaine démo soit un peu plus sous contrôle.

Ah oui. Et au cas où, ces choses en forme de tentacules (Bob) sont des statues-registres.

Friday, November 26, 2021

Three tunes

Having three different visual environment for Bilou's Dreamland's first demo is one thing. I'd like to given them distinct musical background, too. That was last week-end's target, but unfortunately, it hasn't been very satisfying.

Sure, I could get 'school rush' theme played while being in the school room, and 'Apple Assault' theme while being in the green room (sic), but the loading time between them became quite excessive. Even if I expect this to happen only at 3 different time in the game, being completely silent and blank then is a no-go.

The second issue is with sound effects. Apple Assault used simple samples to play sound effects for e.g. jumps, stuns and the like. School Rush instead had mini-patterns with 3-4 tracks to produce the desired arpeggios and effects from ultra-basic sound palette. Of course the green zone tune did not featured any of this.


 The third and final(?) issue is an endless loop within the memory manager. Most likely, something's wrong within libNTXM memory management (or in my messed' up clone of it) which never showed up since I was playing the same module over the whole game's lifetime in previous installments.

Eh bin ... ça en a fait, des choses à fixer pour pouvoir passer d'une musique à l'autre au sein d'un même programme basé sur GEDS. Entre les makefiles, la bibliothèque NTXM elle-même, les p'tits soucis de parser et les modifications à apporter aux scripts, heureusement que TortoiseHg était là pour déméler tout ça au moment de faire enfin des commits.

C'est encore hautement perfectible, notamment au niveau des temps de chargements, mais si je veux avoir une première version jouable de Dreamland d'ici la fin des primaires de J.L.N., il va falloir que je me concentre d'abord sur le reste.

So I've been trying to see where I could have poorly managed memory ... something that would explain how the loop appeared, but given how shielded the memory management code already was in libntxm, I started doubting of my own deductions.

Then the emulator suddenly decided to give me addresses and register dumps! Huzzah!... but they were all for the ARM7 core.

It turned out that, no matter whether you invoked NTXM9->stop(), the timer interrupt keeps running and it keeps checking for the NTXM7->song pointer and dereference it. Simply, all channels are turned to mute, or something alike when you've stopped the playback on the ARM7. Note that background color for the top screen turns to weird orange when this occurs.

And of course, the ARM9 code would delete() that song before it sends the 'set song' command to the ARM7, meaning that the ARM7 core would start using recycled content to guide how it should work (including objects and VPTRs!) ... Pretty weird to see shared virtual tables between the two co-processor of a console, btw. Don't try to do that with the M68000/Z80 duo of Megadrive development.

  • step one: fix the .cmd so they use SFX that suit with the loaded level
  • step two: find a way to share revamped SFX through levels
  • step three: find a way to hide music loading latencies.

Don't start addressing step three before you get the 'three rooms' demo running and you're ready to encode levels.

Sunday, March 12, 2017

runMe truly resumed (hopefully)

All of sudden, runMe works as expected again. I have sound playback (missing since 1st of January) and I can use the GUI on the bottom screen while playing on the top screen. I'm relieved, but I can't really feel proud. This is the most silly fix I've done in years. For all that time, I've been linking runMe with the default ARM7 binary instead of using my own "ppp7.arm7" that integrates my modified version of libntxm. Some commands thus had no effect, and others had undefined effect (including likely crashing the ARM7, meaning that reading touchscreen no longer worked).

Tout à coup, runMe re-marche.Et je ne m'en sens même pas fier après cette descente dans les arcanes du système de la libnds. Voyez-vous, j'avais fini par suspecter un crash du processeur ARM7, celui qui se charge de lire la position du stylet dans les puces-esclaves de la DS pour en informer l'ARM9, le processeur principal. Mais aucune de mes théories ne semblait fonctionner. J'ajoute un p'tit embryon de widget succeptible de me dire en temps réel où on en est dans le fichier XM (la musique, pour ceux qui reviendrait de looongues vacances ou d'une rédaction de thèse), et il ne me donne aucune information pertinente ... je branche ddd sur le processeur 7, et il déclenche les break-points n'importe comment, comme si les fonctions s'enchaînaient les unes derrière les autres et ce avant même que main() ne soit appelé.

Jusqu'à ce que je me rende compte que la connexion ddd-arm7 marche sans problème avec SchoolTest et que je sois pris d'un très gros doute: est-ce que je compile bien ce que je crois ? est-ce que j'ai bien dit à l'outil qui rassemble le binaire pour ARM7 et le binaire pour ARM9 en un seul et même fichier (.nds) que je voulais utiliser mon binaire pour ARM7 et non celui par défaut de devkitpro ...
Eh bien non.

Donc si vous me le permettez, je sors chercher un miroir pour me lancer des noms d'oiseaux.

Tuesday, May 31, 2016

ChannelState.CurrentCell

Je replonge un peu dans le code de libntxm. L'idée, c'est d'ajouter à ChannelState une référence directe à l'emplacement dans le pattern.  La bonne nouvelle, c'est que comme les patterns sont stockés piste par piste (plutôt que ligne par ligne), il est assez facile d'avancer dans une de ces "pistes spéciales", l'idée étant bien sûr de les configurer pour qu'elle jouent le contenu d'un des "effets sonore sur pattern" de mon frère... pas de murs à défoncer pour cette-fois ci ... par contre, pour l'instant, on entend rien ^^"

Let's go for some more libntxm hacking. I added years ago a "ChannelState" structure to capture what effect processing code needs to know about the running player. What I want to have now is a way to "lock" some channels to a specific place in the tune indepently of where other channels are (that is, current position in song), so that I could have channels 1 and 2 of a sound effect playing temporarily on channels 14 and 15 of the NintendoDS. Well ... enough blogging, it's time to run ddd and figure out why I don't hear anything.

edit: oh, well. I guess with 'unmute()' function silently skipping action past the 12 official channels of the song, I'll have no hope to see it working :P

edit++done.


edit: according to my computation, this was the 1000th posted entry. Roughly 10 years after I decided to Bilou on Nintendo DS.

Thursday, May 19, 2016

Sound Effects.

La prochaine release aura des effets sonores supplémentaires. Mon frangin a enfin fait quelques prises avec BFXR et je me retrouve avec une nouvelle bande son qui propose deux ambiances (à l'aise pour l'encre ou non ?) et 8 nouveaux petits sons.

Niveau mémoire, ça semble passer, malgré la taille conséquente de 1Mo du fichier. Ça pourrait bien nous amener à une occupation de 50% de la mémoire totale pour la musique, puisque libntxm compense en software les limites du soundchip de la DS en créant des variantes des samples à l'octave, mais pour autant que j'aie pu en juger tout va bien.

Noël! My brother finally shipped me an updated soundtrack for Bilou : School Rush that features new sound effects for jumps, bounces, pick up, throw and other moves of the sound palette. The second good piece of news is that despite the fairly large 1MB for the soundtrack, it still fits in the memory budget (at least for the first level). Maybe I'll have to work a bit on the sub-sampling loader of NTXM, but it doesn't seem to be a priority.

La où ça va me demander d'avantage de travail, c'est que mon frère n'a pas mis des sons "tout simples" pour les effets. A la place, il propose des combinaisons du sample sur deux ou trois pistes simultanément, avec des notes différentes, voire des effets de portamento ou d'arpeggio comme on en aurait eu dans le module lui-même. Et ça, eh bien ... le moteur de jeu et la libntxm ne sont pas vraiment prêts à le faire.

Yet, there is a heavy chunk of coding ahead before I can use the sound effects as he designed them. The samples alone are not what I need to use: my brother designed the samples to be played at given pitch, combining 2 or 3 notes to get the desired effect. Sometimes I'll have to support arpeggios or portamentos, too. I'll need to figure a way to do that properly. I had plans for such things for quite a long time, but now it turned from [wish] to [need].

Saturday, October 26, 2013

G88 and the sound is gone!

For some reason, slide effect Gxx in music track wasn't played properly. Let me investigate ...

  • ::playRow() checks EFFECT_PORTA_NOTE. It will complain about instruments that change, then, capture the cell's note as "target note" and record the slidetune_speed from parameters. The playing note in the channel remains unchanged, although the "pattern cell" has the new one.
  • ::handleEffects() is for per-row effects. It also process some "volume column effects", but PORTA_NOTE is a "per-tick" effect.
  •  but I have checked that the PORTA_NOTE (effect #3) happens always on the 'regular' column.
  • xmtell.pl confirms there is a note on the cell that has PORTA_NOTE. Yet, when processing the row to setup channel state (including target note and slide speed), the cell mentions having EMPTY_NOTE ^^".
Reason ? The musical cells in an XM pattern may either be stored as is, or packed using a "magic bytes" that indicate which fields (effect, volume ...) are present and which are missing. For some reason, libntxm code was resetting the note to "EMPTY_NOTE" when the cell was stored in plain mode. I'd say there was no chance 0xt0b could debug that properly since he had no effects support -- thus likely only tested modules with no effects (where no cell can ever be "complete", obviously.


Pour éviter des bruits désagréables entre deux notes de la mélodie, mon frère a utilisé assez abondamment les effets de glissé pour enchaîner deux notes sans relancer le sample depuis le début. Mais dans la release d'origine, ces notes étaient curieusement silencieuses. Après pas mal de bourlinguage dans le code de la libNTXM d'0xtob, j'ai fini par me rendre compte que c'était lié avec la présence de "cellules pleines" (avec une note, un volume, un effet et ses paramètres). C'est maintenant réglé, ce qui veut dire que vous avez bien mérité une version révisée du niveau anniversaire.

Now, I have another issue with G00... parameter value 00 for an effect means "same value as the last effect" I used to do that on demand when processing per-tick effect, but for porta-to-note, I need to apply it earlier, when the finetune speed is defined.

So, enjoy g88 revision of the anniversary level.
  • camera control with UP and DOWN dpad directions;
  • improved spongebop bounces;
  • fixed music;
  • fixed crash/stall upon level reload.

Wednesday, October 23, 2013

Some bugfixes in progress

After a couple of days checking the stats, I opened the editors again. I wanted to experiment alternative collisions for Spongebop and improve the readability when falling down. I updated camera control so that UP/DOWN DPAD directions can be used to adapt camera (that was quite simple)

I think I tracked down an unpredictible crash on level loading. The crash only occured when reseting the level just after some droplets (the only object that turns into nil) gets deleted. Engine::delanim() should remove the object from the deleteme list in that case, not from the todo list. I also fixed another potential source of silent random crash linked to the lack of dedicated "you're dead / level clear" tracks :P .


Allez, quelques petites modif's avant d'aller au lit. Le nouveau comportement des collisions avec l'éponge, pour commencer, suivi d'une meilleure gestion de la caméra pendant les chutes (Morukutsu appréciera ;) puis la possibilité de regarder en haut et en bas quand on est à l'arrêt ... c'est toujours sympa, dans un jeu d'exploration.

J'ai du débugging sur la planche, aussi. Certains effets de glissés de la musique ne passent pas, les notes en questions restant du coup silencieuses et une sorte de condition de course logicielle pouvait planter la console si on avait le malheur de changer de niveau juste après qu'une goutte d'encre n'ait été retirée (à quoi ça tient, quand-même!)

I could also point out that the inconsistences in the music comes from module effects to be ignored. They should explicitly be supported! that's a task for ddd and --arm7gdb=7777 ... As soon as I got that sorted out and get the confirmation by early downloaders that the game can be launched, I'll post a fix.

All this reminds me, of course, of the "last minute panic" I got when I tried to enable throw-bladors-anytime (3 days before the release) and observed  curious effects: parsing the second level would then corrupt memory (most likely) and make the level loading impossible. On one of my machine, that made the std::map that holds BlockInfo to have an invalid pointer.
Hopefully, once that bug turned "stable", identifying the root cause was a mere "sherlock holmes game": list all the possible causes for one more state transition to corrupt memory, rule out those that are incompatible with the observed behaviour and you get pointed at a "owned" bitfield that has incoherent value (and still rules which transitions are deleted when).

Friday, November 26, 2010

#undef DSMI

La bonne nouvelle avec le passage au DKP-r32, c'est que du coup, j'ai les bonnes bibliothèques et outils pour compiler le projet NitroTracker d'0xtob ... et donc, que je suis potentiellement un peu plus proche d'un portage de mon support des effets de la libNTXM vers son projet d'origine ... On verra ça ;)

Il se pourrait bien, par contre, que les sources d'0xt0b soient autrement précieuses, puisque mon code ARM7 custom a du mal à passer à la vitesse supérieure, alors que le code d'0xt0b, lui, est déjà prêt à l'emploi. Finalement, il me resterait "juste" à lui ajouter le support de l'exécution d'un autre .nds pour revenir sur les bases nécessaires pour mes outils...

the good thing with the switch to "release 32" of the devkitpro is that I'm now able to compile the Nitro Tracker project -- the one where theNTXM sound library I use originates from. That brings me one step closer to backporting of my own NTXM extension to its seminate project, but also, it means that recycling the ARM7 code of 0xt0b could be more efficient than trying to upgrade my own custom ARM7 code, since Tobias has included support for the WiFi as well.

Tuesday, October 12, 2010

TrackSequence : public Animator

Ce coup-ci, c'est fait: j'ai enfin la possibilité de programmer des séquences d'actions en réutilisant la partition musicale comme "séquenceur". Ce n'est encore que moyennement utile vu le petit nombre d'actions disponibles dans le "dictionnaire" de guns.cxx, mais ça me permet par exemple de faire tourner une petite musique "Level Clear" avant de lancer le démarrage du niveau 2. A terme, je devrais pouvoir y insérer fade-in, fade-out, etc.

Cleared. I can now have a sequence of action performed timely with a musical pattern. The TrackSequence acts as a timeline on which you can insert new "guns" actions. I still have to populate the "dictionary of available actions" with more useful things for the effect to be any impressive, but it allows me to inform the player that he's done with one level (with a sub-tune) *before* I actually launch the loading of the next level. Fade-in/Fade out would come next, then remote control of remaining Gobs (esp. Bilou).

Btw, you'll find a new little poll on the blog, a companion for the 1.3 release of apple assault. Personnally, I think AA is barely a shareware demo for a not-yet-existing game, but we're now in the era of InstantFun(tm), downloadable content and casual gaming where you can buy iFart on the market. So by curiosity, how much do you think "Bilou : Apple Assault" is worth (per unit) if it was completed and available on such a store ?


Au passage : nouveau petit sondage sur le blog : combien selon vous vaut "Apple Assault" ? Perso, je le vois comme une démo un peu plus aboutie ... une sorte de "teaser shareware" pour un jeu complet qui n'est pas encore là, mais vous, là, qui téléchargez des oeufs de Zerg sur votre iPhone à la pièce, vous en donneriez combien, sur DSiWare ? (je parle d'une version achevée, bien sûr, avec les effets de transition terminés)

edit: résultats du poll.

Monday, September 20, 2010

Bxx : jump to order xx (dec).

A MODule (or .S3M, .XM or .IT) is made of individual patterns, short musical sentences (or loops) composed by the author. These are latter arranged into a song through the order table that indicates in which sequence patterns must be played.
A musician can decide to break the current pattern (Cxx) to skip to the next order (that is the pattern that comes next in the order table) but also to branch (Bxx) to any order (including a previous one). For apple assault (and most likely a lot of game music), this is especially interesting because it allows my brother to pack several musical themes into one file and have them self-looping until my program decide to switch (externally) to another theme. Well, just have an ear to his mp3 preview ... you'll know what I mean.


Un petit répit de quelques heures (tardives) entre un déliverable qui se prolonge et des répétitions à donner 1 ou 2 semaines plus tôt que je ne le pensais ... Je reprends mes petites notes sur la gestion de l'effet "pattern break" (Cxx) dans NTXM et je tente l'ajout de l'effet Bxx (order jump) qui permet à mon frangin CyborgJeff de me mettre plusieurs thèmes musicaux dans un seul fichier (menu, jeu, shuriken-rush, game over, etc. ... ah. Je sens que ça vous intéresse ;) J'ai un peu tâtonner (forcément, à écrire 4 lignes de code par semaine :P) mais dans un flash, j'ai trouvé juste avant de me mettre au lit ce qui manquait pour que ça marche. Permettez que je laisse la documentation dans la seule lange de Shakespeare (prononcez "Chakèspéare") et que je rattaque le boulot.

Now, programmatically speaking, both are global commands, that is they are not affecting a single channel (although they are present on a specific channel) but the song as a whole. Plus, they have deferred effect: they are read with other effects when the new row is parsed with parsing at Player::handleEffects, but only executed at Player::calcNextPos. There could be alternatives, such as pushing fake values in State::potpos and State::row and just have State::nextpos and State::nextrow altered by handleEffects ... I'm not sure that would be a good idea.

It will still need a few more lunchtime before it works properly, I'm afraid.
edit:
BonSangMaisCestBienSur if I never reset the newly introduced pattern_jump_requested state variable, I will end up doing weird things such as repeatedly playing the 1st row of the new pattern rather than letting the song flow. >_< * >_<* >_< *

done, and I also fixed the "zombie samples" problems that occured when switching to one tune to the other ^_^

Tuesday, September 14, 2010

on pattern(%%) do { ... } as x

One of the next challenge to handle for the GEDS engine will be the support for timed sequence. Such as "close the door, shake the ground, and now the boss can enter". Or more simply, "play the 'dead' animation, fade out, reload the level". As mentioned earlier, I could simply associate each of these individual actions to a row in a pattern of the soundtrack. That makes timing implicit, and it should ease the synchronisation between the two.

Beyond the syntax, the idea is to have TrackSequence as an external action that stores its own list of external actions and associate each of them with a row number. The TrackSequenceReader would then be an Animator that launches the individual actions appropriately. Well, my brother has partly "recovered" the improved soundtrack, and I have modified the NTXM player so that I could look at the current pattern/row position... things are getting in place for some tests.


S'il reste un aspect encore fort "amateur" de AppleAssault, c'est sans aucun doute la gestion des évènements genre "oups. t'es mort", "level clear" et autres "game over man". Didier les comparait même à des "crash windows" ... Avec mon système axé sur les machines d'état et tout ça, j'ai longtemps galéré pour trouver une approche, puis je me suis rendu compte que je pouvais tout simplement associer ça au suivi d'un pattern dans la musique. Il y a même moyen de procéder assez simplement en réutilisant les "iGun" déjà en place dans la machine d'état pour capturer les actions à effectuer dans un TrackSequenceGun qui lance leur exécution dans un Animator supplémentaire (lesquels me servent plus ou moins d'activités parallèles sur la DS).

Surprisingly, it seems that the most complicated part doesn't lie there, but in the management of the "shuriken rush" sub-tune that needs to be activated and de-activated depending on your "punch bar". "Surprising" in that the HUD logic -- and not the game logic -- is the place where it fits the best. Troublesome, isn't it ? And untidy, too.

edit: It's getting in place, but still buggy on many aspects.

todo: add Bxx support to NTXM so that we can loop sub-sections of the module.

Thursday, May 27, 2010

NitroTracker

Nitro-tracker, the homebrew soundtracker running on the Nintendo DS written by 0xtob and based on libntxm has been open-sourced a few monthes ago. Sounds like it is time for me to embrace the open-source spirit, grab the sources and port the improvement I made locally to a wider audience. That should be my "hobby-priority" once Apple Assault is released.

L'auteur de la libntxm a publié les sources de son NitroTracker il y a quelques mois. Ce serait justice que de m'assurer que la gestion des effets que j'ai ajoutée pour mes besoins personnels y soient également disponible ... et pourquoi pas en profiter pour ajouter un bouton "quit to runme" ? Allez, je boucle "Apple Assault" et je m'y mets.

Tuesday, May 25, 2010

Als de klok thuis tikt ...

Howdy. You've noticed the small bullet point on improper music replay on my latest "todo" post, haven't you ? That means more cscope-powered lunch times ahead, and I've just had one of them. I must add that, while I've been coding or hacking around players for tracked music for over 10 years now, I've got virtually no experience of the .MOD format itself and very little background on the .XM format. S3M and IT were what I worked with until I opted for 0xtob's libNTXM as the media player for GEDS. So my documentation of the current player state got stuck on question such as "Is there a 'volume column' at all in .MOD files ?" Screenshot from Wikipedia suggests it hasnt, and format 'specs' from wotsit confirms.

J'ai choisi la libNTXM d'0xtob pour sonoriser les aventures de Bilou, il y a bien 2 ans, maintenant. Pourtant mon expérience du fasttracker II est virtuellement nulle, et ma connaissance des .MOD (les fichiers produits par son précurseur) franchement aléatoire. Un exemple ? Hier, j'aurais été incapable de vous dire s'il y avait ou non une colonne dédiée au volume dans un .mod. Dans un .S3M, ça oui : c'est le format que mon "modplayer" en assembleur pour DOS prenait. Dans .IT aussi -- c'est le format que mon frère a utilisé le plus pour ses productions. Eh bien, il n'y en a pas en .MOD. Tout au plus un effet "set volume" (Cxx) et quelques variantes (portamento + vol slide, etc.

    _____byte 1_____  _byte2__  ______byte 3_______  _byte4_
/ / / /
0000 0000-00000000 0000 0000-00000000
| | | |
Upper four 12 bits for Lower four Effect command.
bits of sam- note period. bits of sam-
ple number. ple number.
LibNTXM code is not a maze, but it has to work around the glitchy sound hardware of the nintendoDS: NDS sound hardware doesn't allow us to alter the volume directly (if we do, it produce sound glitches), so we have to perform fading from the current volume value to the next one, requiring some actions to take place ahead of time. So you'll encounter things such as
 if(state.tick_ms >= song->getMsPerTick() - FADE_OUT_MS) {
// we are shortly before the next tick. (As long as a fade would take)


As a consequences, EFFECT_SET_VOLUME (Cxx), EFFECT_VOLUME_SLIDE (Axx) or EFFECT_E_NOTE_CUT (ECx) do not directly affect the channel volume, but record a request to set the volume in effstate.channel_setvol_requested, altering state.channel_fade_target_volume jointly. So what happens to the "volume column" of an S3M (yes, it had it when converted into an XM ?)


Pourquoi ce regain d'intérêt soudain pour libNTXM ? eh bien parce que le "mod" que je voudrais utiliser pour Apple Assault ne passe pas correctement sur DS. Je soupçonne fort "mon" player de ne pas tenir compte des changements de volume. Je creuse donc les sources, mais le code n'est pas d'une lisibilité exemplaire. En cause, le fait qu'il est nécessaire de baisser progressivement le volume d'un canal audio de la DS avant de changer le son en cours... faute de quoi, un "tic" se fait entendre. Le code de "EFFECT_SET_VOLUME", "EFFECT_VOLUME_SLIDE" et autre "NOTE_CUT" (que je connais sous leur 'nom' dans scream tracker, pour simplifier) va donc indiquer son "intention de modifier le volume" de sorte que le player puisse commencer le changement de volume suffisamment en avance ... De plus, le code de gestion des effets est découpé en 2 parties: ce qui s'exécute sur le premier "tic" d'une ligne et ce qui s'exécute sur tous les autres tics.
// Separate volume column effects from the volume column
// and put them into the effcts column instead


if((vol >= 0x10) && (vol <= 0x50)) {
u16 volume = (vol-16)*2;
if(volume>=MAX_VOLUME) volume = MAX_VOLUME;
ptn[chn][row].volume = volume;
} else if(vol==0) {
ptn[chn][row].volume = NO_VOLUME;
} else if(vol>=0x60) {

// It's an effect!
// decoded into ptn[chn][row].effect2
// and ptn[chn][row].effect2_param
// see XMTransport::load() for details.

}

Another thing I'll have to keep in mind while hacking around is that ProTracker effects (and i guess, their XM derivatives) are only supposed to be executed on non-row ticks. At least, that's the case for volume slide and portamento to note, and that explains many if (tick==0) return; in libmikmod's code. I blogged that a few years ago. That explains the separation between handleEffects() and handleTickEffects() in libntxm. Hence the name of this post: ticks are the ultimate measure of time in MOD-inspired formats. Final note for today: in .MOD and .XM, the same "Fxx" command is used to set speed (#of ticks per row, 0..31) and tempo (that is, BPM, 32..255)

next time: update of Player::playRow so that it affects volume in the same way as playNote(..., chn->cell.volume,...) does when note==EMPTY_NOTE. Stay tuneD.


Bref. Je vais devoir m'assurer que l'équivalent du code de "set_volume" existe lorsqu'une "cellule" contenant du volume mais pas de note (sinon playNote(...) aurait fait son boulot :P)

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.

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++ ;)

Thursday, July 17, 2008

fuuuusiooonn

hop. Je profite de mes p'tites vacances pour démarrer la branches "avec effets" du projet libntxm de 0xtob. Et à jouer avec les diff de GoogleCode, je me rends compte que j'ai changé bien plus de choses que je ne m'en souvenais. Je crois que je vais avoir droit à reprendre les fichiers un par un, passer les diff en revue pour voir ce que je dois garder et ce que je dois changer pour avoir une version "avec effets" qui soit la plus proche possible du code de base de 0xtob...

Since it's now holidays time, i start a branch in the libntxm's svn tree to bring in effects support ... Hm. And it seems i'll have full evening of diff'ing and patch'ing to keep my changes while remaining close to 0xtob's update (yeah, he did changes over what i used as a base too, now let's merge those changes ;)