Showing posts with label modplayer. Show all posts
Showing posts with label modplayer. Show all posts

Sunday, March 23, 2025

PENMENU.S3M

Vous pouvez l'écouter sur modarchive, vous pouvez le dédicacer sur Nectarine ... ce n'est pas le meilleur module de mon frangin, loin de là. C'est le thème envisagé pour le menu d'accueil de Pengo's Adventure, notre premier jeu sur RSD Game-Maker.

Mais c'est surtout en 1996 qu'il est devenu inoubliable pour moi, et associé à un écran tout bleu (avec un raster-effect un peu raté), preuve que ma routine d'interruption continuait bien à progresser dans les patterns et à mixer les 6 pistes pour les mettre dans le buffer transmis en continu par DMA à ma Master Boomer ...

If you've ever written your own .mod player routine (or any other tracked music format), there's a chance that you've had a very-first-tune-that-worked on that player. In my case, that was a tune my brother wrote, that should have replaced the menu music in our very first RSD Game-Maker title: Pengo. Sure my brother wrote plenty of much better tunes afterwards ... he already had some better ones at the time, including a title for the "Maya Zone" of a puzzle-platformer, which I was eager to start working on...

But since "penmenu.s3m" used no effects, it was possible to get it running earlier. It still reminds me of that blue raster showing up while playing -- like everyone else doing low-level programming at the time, I was hacking the background color to give me hints about where in the code I was. There would still be work to do before it could be featured in a game, but my 8-track player had turned from dream ... to reality.

Bon, bien sûr j'aurais préféré que ça soit la musique de Nono dans la Maya Zone ... mais pour ça il aurait fallu aussi le support des effets (dont l'arpeggio) alors que PENMENU, avec juste la colonne de volume, c'est réglé.

Thursday, April 18, 2024

32-bit

Bion, jusqu'ici mon laptop tient bon, mais il a un truc un peu spécial qu'il vaut mieux que je documente pour mon moi-du-futur: il continue de faire tourner certains programmes en 32-bit alors que c'est un ubuntu 64-bit. Lors de mes premiers pas dans l'espace d'adressage gigantesque d'AMéDée64, le double support 32/64, c'était la règle, mais ça fait quelques années déjà qu'on y est plus.

Or, mon environnement de tests automatiques pour libgeds s'efforce de faire croire au code qu'il est sur une DS en ajoutant de la mémoire valide ici où là pour que les écritures dans les registres n'échouent pas. Ruse qui ne marche qu'avec un système 32-bit pour une raison qu'il faudra que je demande à mon moi-du-passé de me documenter.

When AMD64 support had been introduced in Ubuntu systems, the default was to ensure the system could run both 32-bit and 64-bit executables. That means 2 copies of the standard libraries, 2 copies of many libraries, etc. Nowadays, your default Linux distributor has dropped 32-bit distros and the 64-bit distros have been updated so that they only feature 64-bit binaries. So the CPU can still run 32-bit thing, the kernel can still run 32-bit processes, but the support libraries are missing. That means when I e.g. try to use 2009-old SchismTracker to export a .xm of a soundtrack, I get a puzzling error message.

En plus de ça, l'outil que j'utilise pour éditer les musiques du jeu (SchismTracker) a laissé tomber le support des fichiers .XM pour ne plus produire que des .IT ... alors que je m'en sers essentiellement pour convertir les .IT du frangin en .XMs :P ... Je promène donc avec moi un répertoire de binaires 32-bits lui permettant de continuer de tourner mais il faut pour celà que l'OS lui-même ait quand-même quelques outils et configurations sous la main pour exécuter du 32 bits. Faute de quoi, le shell persistera à nous dire

-bash: /home/grizzly/bin32/schismTracker: no such file or directory

alors qu'il est bel et bien là (ouais, pas terrible, les codes d'erreur pour le coup).

Comme linaro vient de me faire le coup, je profite que je suis pas à pas un petit howto sur stackoverflow pour me laisser un topo de voyageur temporel...

Of course, the binary alone is not enough: I have noah-arch-ived a few mandatory libraries that the application will use, like libXxf86misc.so, but these are not the "support" libraries. When I mean by that is C and C++ runtime, ia32 elf loading libraries (yup, your kernel typically doesn't know how to do that alone and needs a shared library to load executables into memory ^^"). So for future self and geeks-in-training reading this, here are the commands I typically use


sudo dpkg --add-architecture i386 # there is more than x86_64, you know
sudo apt-get update
# accidentally did an apt-get upgrade...
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
# that was enough for me.
# sudo apt-get install multiarch-support # might be needed otherwise...
sudo apt-get install libz1g:i386 # was needed later on for linaro building newlib

edit: does it sound convoluted to use 2 different versions of SchismTracker when you could just use some XM-targetting software to create the music in first place ? Well, you should ask Nina Kalinina to tell you how *she* makes music ready for GBA playback ;-)

Friday, November 16, 2018

rez x-factor 2

Let this be my official "I love (idea I have of) the demoscene" post. (better late than sorry)

back in '96, demoscener REZ wrote a stunning .mod track featuring about 1'30" of chiptune within 3x64 lines of 5-track (amiga-compatible?) patterns ... He did so by pushing the use of loop commands to an extreme. I love that spirit of taking something that was meant to work within some constraints and pushing it far out of its limits.

He also used very pleasing waveforms (reminding me of Namco's wavetables), of 16 to 64 bytes plus a few larger (300 and 700 bytes) drums. The result is a stunning 8.8K chiptune. Of course, by now, we have 4K compos with songs twice the lenght, but REZ did it without requiring a custom player. Chapeau.

Je l'avoue: j'aime la démoscène. Cet esprit de faire-plus-avec-moins qui a conduit en '96 REZ à faire un morceau entier en 3 patterns, usant et abusant des commandes 'boucle-moi-ça', utilisant des sons de 16 à 64 bytes tenant plus de la WaveTable façon Namco que du véritable sample. Le tout pour une taille record (à l'époque) de 8.8Ko.


Monday, October 23, 2017

out'm'up

The inscene'99 visit had been quite as success, especially regading the 100K game competition. My brother and I then tried to figure out what we would do on the next instance - obviously, our chance of making a good game were higher than making a big demo like the one envisioned for "samedi, tous in my home".

A comment by my peer "Gedeon" about how it was a shame that crazy brix was only using boxes for collisions pushed me towards the implementation of some pixel-perfect collision routines. I remember I wanted to do some pinball game, but after all, it was decided to go for a shoot-em-up. Our secret "games to do" folder had a long list aborted shmups, from the "Polycosmos" conversion of "space Mission", the failed "cosmowars" on RSD Game-Maker, and the aborted "Bilou sky quest" ... Nothing getting any close to our childhood golden award "Warhawk". So I picked the "Tyrian" palette and started to pixel some ships.

Retournons au passage à l'an 2000. La Inscene '99 avait plutôt été un succès en particulier pour mon jeu 100K, Crazy Brix. Deux choses étaient claires: 1) on y retourne l'an prochain et 2) on a plus de chances de parvenir à refaire un p'tit jeu en 1 an que d'aligner une mégadémo sur le thème "Samedi tous in my home"... Gédéon m'avait motivé à dépasser le simple test de boîtes de collisions pour le prochain titre. ça pourrait convenir pour un pinball ou un shoot-em-up. 

Des shoot'em'up abandonés, j'en ai déjà une belle liste derrière moi, à l'époque: le Space Mission pour C64, la BD impliquant le polycosmos, le "Bilou Sky Quest" annulé par un verre de Franta et le Cosmowars foireux sous Game-Maker. Pourtant j'aime ça quand c'est bien fait. Que ce soit Warhawk ou Tyrian si il y a des étoiles et des barres de vies, je suis partant. Et comme j'avais la palette de couleurs de Tyrian sous la main, justement, je me suis lancé.

The assembly code for crazy Brix was quite horrible, and I remember taking care of increasing the quality of the organisation for out'm'up. Especially, frames-to-aminations, level layout, and to some extent the sprites behaviour were described in a "data-oriented" macros system that looked a bit like game script, but converted straight into binary pointers and values -- something that was apparently common in MegaDrive games development.

The second key development was to support a dynamic list of sprites, allowing fancy explosions, lots of shots and even powerups where crazybrix couldn't even accomodate for anything but a ball and a paddle. Two lists, in fact. This engine was the first time I decided to split objects in two separate casts to reduce the amount of collision checks required.

While the level design wasn't very inspired, the game received a brilliant soundtrack, a classic but good-looking starfield effect and Out'm'Up won the first place - although mostly due to the lack of significant competition.

Même s'il a disposé de 3 fois moins de temps que Crazy Brix, Out'm'Up a eu droit au niveau programmation à tout ce qui faisait défaut à son prédécesseur: des effets d'explosions, des power-ups, des sprites ennemis, des niveaux programmables.

J'avais même une structure 'scriptable' pour permettre à mon frangin de passer au level design une fois le travail sur le son terminé, mais il n'y a jamais montré beaucoup d'intérêt. L'aventure s'arrêtera donc une fois la première place de la Inscene y2k empochée. Ce sera mon dernier projet en VGA + S3M. mon dernier projet MS-DOS.

Thursday, March 10, 2011

Life-changing books (2/3)

When I turned 17, it became clear that I couldn't realise all my projects with BASIC alone. I opted for physics/chemics labs rather than computer labs, unfortunately, and the teacher wouldn't let me get a copy of the Turbo Pascal she was using for her courses. "It wouldn't make any sense to me without her teaching" or something alike.

A friend of mine (later known as Parmy in PPP Team) had a copy of A86 -- a 16-bit assembler for dos -- left over a floppy, and a book "Easy Assembly" he never really made sense of. Being from the 8-bit era, "Assembly" meant to me "the language of gods" and "blazing fast execution speed", so I immediately accepted the offer and started studying Intel's instruction set.


Vers 16 ans, je commençais a avoir fait le tour de ce qui peut se faire en BASIC. J'avais (mal?)heureusement préféré les cours de labo physique/chimie l'année précédente, et la prof d'informatique ne voulait pas me faire une copie du Turbo Pascal sous prétexte que je serais incapable de m'en servir sans suivre ses cours. Grmbl. En allant expliquer à un de nos nouveaux amis (que l'on connaîtra plus tard dans PPP Team sous le nom de Parmy) mes techniques graphiques en BASIC, je tombe dans sa bibliothèque sur un bouquin "L'assembleur facile" et une diskette 5'1/4 estampillée "A86". "Je ne m'y suis jamais vraiment mis", me confie-t'il. Pour un enfant de la génération 8-bit comme moi, l'assembleur, c'est comme le langage des dieux. J'emprunte sans hésiter le bouquin et je me mets à potasser le jeu d'instruction des processeurs Intel.


After I showed my uncle my first assembly program (iirc, a password-prompting tool to prevent my sister to mess up with "our" computer), he brought me a box full of low-level C64 stuff, including a copy of "programming the 6502" book, a disassembled and commented dump of the C64 kernal rom, an EEPROM programmer (with no EEPROM provided) and other similar books. SYS 49152 was no longer a mystery to me -- although POKEing machine instructions from a BASIC program wasn't a very sexy way to proceed. It took me time to wrap my brain around the LIFO stack concept ...
I never really "programmed" the 6502 at assembly level, as it was already a decade-old machine, but I must admit the beauty of 6502's instruction set simplicity has been inspiring to many regards... more about that in part 3.

At last, mastering assembly and the Ms-DOS service interrupts allow direct manipulation of any file format, opening up countless possibilities.


Voyant mon premier programme assembleur, mon oncle me propose de reprendre une caisse de documentation technique sur le commodore, dont une copie d'un livre d'introduction à la programmation du 6502 en assembleur -- le processeur du commodore 64. La caisse contient un programmateur d'EEPROM pour faire "de véritables cartouches" façon Rick Dangerous. Je bave. Je prends. Il n'en sortira pas grand-chose, cependant, hormis une meilleure compréhension de cette machine de rêve définitivement désuète et une admiration sans borne pour la simplicité de ces LAY et LAX. Mais n'anticipons pas.

Knowing the assembly language, however, wouldn't be of much use without knowing the hardware that sits around the CPU. A "PC" was still fairly simple by that time: everyone had a VGA-clone video card (super-VGA was only slowly starting to be adopted, and not by game vendors) and a Sound Blaster clone. Both and more were discussed in the "Bible of PC System Programming", a fairly huge book that I borrowed to another friend -- later known as Nowan -- before I got myself a copy of my own. He also let me grab another Sound-blaster related book (ISBN 978-2742901951) from the same editor, which was describing "how to build a 4-track modplayer from scratch -- in Pascal".

Bien sûr, l'assembleur tout seul ne servirait pas à grand-chose sans une meilleure compréhension du hardware du PC. Fort opportunément, c'est approximativement à ce moment qu'un autre ami (connu plus tard sous le pseudo de Nowan) va me préter coup sur coup la bible du PC et le supergrand livre de la SoundBlaster. Me voilà plongé de plus belle dans les documentations techniques, et armé jusqu'aux dents pour attaquer la conception 100% assembleur d'un modplayer -- pardon un S3Mplayer -- qui devra être le coeur de l'Ultimate Game Maker. J'aurai bien un petit jeu réalisé (Crazy Brix) fin '97, qui sera amélioré plus tard pour la Inscene '99, mais UGM restera un tas de papier attendant la réalisation de mon propre OS -- Clicker, une idée de Nowan, à l'origine -- le Windows 95 ne pouvant définitivement pas convenir pour nos projets.

I still had no Pascal compiler by that time, and I was sufficiently confident that, with that knowledge and the S3MINFO.TXT file shipped with my brother's Scream Tracker III, I would be able to run a 8-track Stereo S3M player instead, with 2 tracks dedicated to sound effects and 6 tracks dedicated to background music. I started copying every meaningful bit of information into a smaller draftbook, easier to carry around and not to be returned to a friend by the end of the month ^_^

According to my brother's archive, it took me another 6 month to convert that idea into something capable of replaying some simple modules. I never made it "the corner stone of the ultimate game maker" as I initially intended, but it was the core of Crazy Brix and Out'm'Up, the two awards-winning 100K game at Inscene'99 and Inscene'Y2K, respectively.

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.

Wednesday, June 02, 2010

BRIX.TXT

Amusant, ce qu'on retrouve dans les fonds de tiroir ... voilà le fichier "readme" de mon premier jeu en Assembleur pour MS-DOS: Crazy Brix, qui (2 ans plus tard), remporta la compétion "100K games" à la Inscene'99 ... A défaut d'Internet, à cette époque, je tentais de voir mes jeux paraître sur le CD du magazine PC-Fun ... sans grand succès, malheureusement.

Well, I dug a README.TXT file for my first A86 game : Crazy Brix, as submitted to the French magazine Pc-Fun. It wouldn't make much sense to translate that to you, right ? it mostly has some nostalgic value. What I find amusing is how it built up : from a proof-of-concept QuickBas game (hardly playable, but conceptually correct), i retro-fitted the "algorithms" into my growing assembly-written .S3M player for the Sound Blaster Pro. Somehow, "importing" the S3M player into a fresh game project didn't work. Debugging such a program was a nightmare ...
I had no idea of the existence of GPL or free-software by that time (neither did I have any free software at hand, which more or less explain the use of assembly), so I was trying to trade my code against something else I could have a use for. Funny.


- - - 8< - - - 8< - - -

Salut à tous !
Bien le bonjour à vous, futurs joueurs de CrAzY BRIX.
Je me permets de me présenter: je suis Sylvain
( alias PYPEIN ), programmeur de BRIX. Vous allez sans tarder découvrir la version 1.9 du nouveau XAM-WARE de PPP TEAM SOFTWARE.

(XAM-WARE comme produit pendant les examens.)

Les Versions.
1.0: Développement de l'algorithme de jeu en BASIC ("appelle moi pour jouer",dit Vivien)
1.1: Première implémentation en Assembleur: MODPLAY+ chargement des images (ricanement de Piet)
1.2: Réalisation des routines graphiques
1.3: On peut commencer à jouer, mais c'est plein de bugs.
1.4: premiers essais de transparence ("C'est quoi, cette horreur?" dit Piet " C'était encore mieux en BASIC!")
1.5: décors de fond retravaillés
1.6: ajout des patterns "GAME OVER" et "NEXT LEVEL"
1.7: on peut changer la vitesse de la balle.
1.8: Ajout des samples pour les bruitages ("Je te laisse débugger, Pype, je reviens à 12h00")
1.9: image d'intro en POVRAY
1.A: "ajout d'animations"

Note aux programmeurs
Mon module player n'est pas encore au point, néanmoins, si l'un d'entre vous veut en faire un en assembleur, je lui conseille d'abord de lire 'Le SuperLivre de la SoundBlaster' paru chez Micro Application. Je peux aussi vous passer une partie des sources (les fonctions de la S.B.) mais ne me demandez pas les sources complètes du player: le code est pas encore optimisé (PENTIUM minimum). Je vous le passerai seulement contre d'autres trucs (un player pour un autre format, des truc de balaises sur le mode protégé, un jeu que vous avez fait et qui est mieux que le mien...)

- - - >8 - - - >8 - - -

(tout ça, c'était avant que je ne découvre la GPL, NDLR)
D'une certaine manière, Crazy Brix reflète assez bien ce qu'était PPP Team : en apparence un projet solo, ce jeu n'aurait jamais vu le jour sans le bouquin de Nowan sur la soundblaster ni sans l'assembleur A86 de Parmy. Il n'aurait pas été fun sans les Bilou/Badman de Pierrick, ni sans le personnage "tentacle bob" de Tbob, ni sans les mods de mon frère. Il n'aurait pas gagné la 100k sans les routines de compression de Kris, ni sans la voiture de Gino. Il n'aurait pas eu de sens si Pierrick n'avait pas lâché à Romu "tu te rends compte qu'il a fait ça en 100% assembleur !?"

download and play in DosBOX

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)

Saturday, May 22, 2010

Apple Assault : 90% done ?

Okay, code is done and working on real hardware. You can stomp and bounce on applemen, you can "shoot something" when you've bounced enough. And applemen can be respawned, and their number can be dynamically defined. We're definitely getting closer to a "AppleAssault" release.

Oh yeah, I know. You've been hearing that since the start of the month. That's quite typical from a hobby project.

Why ain't I not releasing, then, might you think... Data, that is it. I need a few more things do be done:

Ca se rapproche, ça se rapproche. Ma petite démo ressemble de plus en plus au gameplay prévu pour Apple Assault. Au niveau du code du moteur de jeu, on y est, en fait. Reste une animation par-ci, par-là (coup de poing de Bilou, Appleman projeté ... Twinbee et Bonkers ont accepté de poser pour un résultat plus réaliste). Ensuite, il faudra que je m'attaque à quelques "arènes" pour ces moments épiques.

Note that the level editor is still in a "broken" state (that is, it won't be able to add monsters to a map in its current shape), so I hope this will not prevent me from doing arenas anyway.

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

Tuesday, March 25, 2008

-funroll-sample-loops

Bon, j'avais un peu mis le développement de libntxm en berne ces derniers jours, notamment par ce que je ne comprenais pas ce qui faisait sonner faux tous mes chiptunes. je soupçonnais quelque-chose du côté des ajustements de notes (vous savez,le truc calibré à 8636Hz pour un DO, et qu'il faut ajuster à la main quand on importe un nouveau son dans un mod), mais non. C'est 0xtob qui a mis le doigt dessus : la DS gère les loops en hardware, mais uniquement quand la longueur des loops est un multiple de 4 ...

Aucun soucis si on a un son "ordinaire" que l'on essaie de faire tourner en boucle (au pire, il y aura des petites déformations dans le son). Mais s'il s'agit d'une onde pour un chiptune (souvent faite à la main, et dont la taille a tout juste la longueur d'onde du son), c'est tout différent. Retirez-lui un ou deux samples, et vous vous retrouvez avec une autre longueur d'onde (et donc une autre note de référence). Bref, c'est l'horreur.
Heureusement, la solution est plus simple que le problème: répéter (au plus 4 fois) la boucle de sorte que sa longueur devienne un multiple de 4 (si ça c'est pas bête et sot :P)

Well, coding on libntxm has been a bit slowed down these last days, maybe because i couldn't figure out why all those chiptunes i've got sounded de-tuned. My guess was that i missed something in the "instrument fine-tuning" mechanism, but Oxtob pointed out that there was actually something going wrong with loops.
You typically use looped in two cases. Case 1 is that you want something like a "strings" instrument that can keep playing (the same) as long as you let it flow. These are the loops the DS prefers to play. Case 2 is that you're doing a chiptune and hand-crafted a waveform that you want to loop to create your bare sample. In that case the loop is typically very small (as small as 32 bytes for some musicians), and this is where DS sound hardware gets in your way.

What happens is that the DS hardware wants loops to have lengths expressed in 32 bits quantities (yep, even with 8 and 16-bit samples :P ), but hand-crafted loops may not conform to this requirement. And given that the loop length is the wavelength (which define the note's height), a single byte skipped by the hardware may doom your module's playback.
Hopefully enough, the cure is simpler than the illness here. You need a multiple-of-four amount of samples in your loop and you have an odd (or just even) amount ? well, just copy-paste the loop as many times as it takes to have 4xN samples. Period. Since loops are small, it doens't hurt.

Voilà. J'attends les nouveaux .xm de Pierrick, et je vais aller ranger un peu parce que mon beau-père vient m'aider à travailler dans la salle de bain cet après-midi ... le plus dur, ça va être de débrancher la DS de la chaine Hi-Fi qui est occupée à me rejouer la musique du niveau 1 de SMB3 en boucle depuis 10 minutes ^_^

Get it on sourceforge : code and binary (runme)

Tuesday, March 11, 2008

It surely ~vibes~!

Well, after three days working on my paper for that PRESTO workshop and visiting the "batibouw" (kitchen, showers, solar boilers ...) i was hardly needing a coding intermission. So after a nice cooking-time this evening, i picked up DS, laptop and headphones and gave vibratos a try... The hardest time was to get rid of a bug that prevented some instruments to get played, and i may not have found the exact multipliers, but dudes, let me tell you one thing: it surely ~vibes~ here.

There is only support for sine waveform atm (which is the most used anyway), and it looks like i'll have a hard time adding support for the "volume-column effects", which many trackers have been using instead of ProTracker combo effects.

Salut les poteaux. Bon, après trois jours sur mon article pour PRESTO et la visite du salon "Batibouw", j'avais vraiment besoin de souffler un peu... Alors j'ai repris mon player XM et j'ai ajouté le support du vibrato, pour rigoler. Bon, je n'ai peut-être pas encore les bons règlages sur la vitesse et l'amplitude des vagues, mais je peux vous garantir une chose,: ça ~vibre~ bien.

Oh, au passage, vous remarquerez que j'ai repris les petits smileys faits en collaboration avec Junkboy pour illustrer cette rubrique. J'espère que vous aimez ^_^

edit: Hmm. I might have found what's going wrong with all the effects. 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. This is not the way libntxm works atm, so i may need to check out previous stuff in HandleTickEffects() ...

Thursday, March 06, 2008

tuuiiiii tiiiuuuuu

Hey dudes, i have some good news! My fairy's got a steady job!

Oh, well ... You want another kind of good news ? well, i managed to get "portamento to note" effect played correctly by libntxm ;) It's been a bit more complex than "portamento up" and "portamento down" because the player wasn't ready for notes that aren't played immediately. Especially, 0xtob's technique of fading a new note a couple of milliseconds before the new row wasn't aware that "effect_porta_note" means "don't fade, for i'm not going to re-play the note".

I also wonder what it should sound like when one issue a Gxx command (porta-to-note. I'm used to S3M/IT effects names, sorry) with an instrument different from the current one. Atm, the new instrument information would be discarded (afaik) and the portamento would go on with the current instrument. Click the smiley to see what's new in the code ^_^.

Bonne nouvelles, les amis: ma fée s'est trouvé un boulot quotidien !
Comment ça "c'est pas les nouvelles qu'on attendait" ?? Vous voulez des nouvelles du player XM ? Bin j'vais vous en donner, moi, des nouvelles du player XM. J'ai un effet "portamento-to-note" qui marche. Et puisque c'est comme ça, je fais pas de release, tiens! NA! Ca vous apprendra!

(ps: non, en fait, je ne fais pas de release parce que j'aurai un article à terminer pour mercredi prochain, et qu'il devra faire 6 pages et pas une douzaine comme je le pensais... donc au dodo parce que demain, on se lève tôt, mais vous pouvez cliquer sur le smiley pour regarder ce qui a changé dans le code ^_^).

Tuesday, March 04, 2008

Les joies des mod'players

Schism Tracker (linux) editing 'beek-beercan-pyramid.xm' chiptune, my current test module for portamentos and arpeggiosAah ... les joies de la programmation de modplayers. Je crois que tout bien réfléchi, c'est le type d'application qui est le plus obscur à debugger. Ca doit provenir de son côté "temps-réel", à moins que ce ne soit le fait que tous ces blocs de codes s'enchaînent pour finalement donner *un* résultat tout mixé que seul votre oreille (si elle est bien dressée) peut identifier comme correct ou incorrect.

Après avoir introduit une petite interface de débugging toute simple dans le player de libntxm, de haute lutte, j'ai frayé mon chemin jusqu'au bug par-delà les appels de fonctions pour reprendre le son que j'avais perdu.

(euh. je m'égare). Bref. Un simple "inst = pattern[pat][chan][row]" placé un peu trop tôt dans le mod et c'est la quasi-totalité des effets (existants et ajoutés) qui se sont mis à foirer. Heureusement, je suis mieux armé qu'il y a 10 ans avec la soundblaster. J'ai le CVS pour me rappeler ce que j'ai changé, par exemple.

Mais j'adore ça ^_^

petite release sources avec la nouvelle structure "Channel".
edit: Tiens, je devrais penser à ajouter un widget pour activer/désactiver des pistes pendant que l'on écoute le module. Ca aiderait ...

Thursday, February 28, 2008

portamento ...

Retour pas mal d'année en arrière ? Alors que j'essaie d'ajouter les portamento (variation continue de la fréquence d'une des notes) à la bibliothèque ntxm, je me heurte aux même(s) difficulté(s) que lorsque je développais mon player S3M pour mes jeux DOS/Assembleur...

  • Pas évident de structurer les données des channels pour que les effets s'expriment proprement. Là, par exemple, je ne saurais probablement pas gérer la valeur 00 pour les portamento (qui permet de réutiliser la dernière valeur non-nulle).
  • Pas évident non plus de savoir quel est l'effet exact ... d'un effet. autre exemple: mon "portamento up" a une mémoire trop "longue" : au fur et à mesure que le morceau est rejoué, le portamento emmène la note de plus en plus haut au lieu de rejouer toujours do--ré--mi.
edit: au moins, j'ai réussi à avoir des "portamento" qui marchent à la bonne vitesse:
  1. le 'pas' défini par le format XM est "1/256ème d'octave par tick"
  2. la fonction BendNote(note,finetune) de ntxmlib considère qu'il y a 128 niveaux de "finetune" entre deux notes successives (p.ex. C et C#)
  3. le player exécute l'effet "portamento" uniquement sur un "tick". Le nombre de tick par ligne est défini par l'effet "set speed" du morceau. La durée de chaque tick (en millisecondes) est calculée à partir du tempo (en bpm). En clair, si je double le nombre de tick par ligne, le morceau semble défiler plus lentement, mais la même commande "portamento" me conduira deux fois plus loin dans les notes.
oh, just to let you know : portamento up is fixed. I need to reorganize a couple of things in the player to better capture (and manipulate) the "state of a playing sample" (since Sample is simply a static structure that represent "a sample in the module's sound repository"): atm. the new note won't clear the current "drift" of the previous slide (and thus it'll keep on sliding higher and higher).
// our finetune is 12 times finer than the XM 'octave interval'
effstate.actual_finetune[channel]+=param*12;
Instrument *inst = song->instruments[state.channel_instrument[channel]];
inst->bendNote(state.channel_note[channel]+(effstate.actual_finetune[channel]>>7),
state.channel_note[channel],
effstate.actual_finetune[channel]&0x7f,
channel);
break;

Wednesday, February 27, 2008

Beam it, play it, fix it, repeat

I had an argument with the CVS repository last night, but i finally managed to make it accept a new branch with the sources for runme featuring the NTXM player. I hope 0xtob won't be against the re-diffusion of his sources (well, he shouldn't since they're LGPL) ... I am now able to upload any .xm to the DS (up to 512KB) and play it with NTXM. I can also upgrade the software to a new build by just pressing SELECT (and test new effects). All it required was a small rewrite of the XMTransport class so that it works with an (abstract) DataReader rather than plain FILE* ... It even makes it more elegant ^_^

Après moult adverses commandes contre Sieur CVS, m'est avis que la nouvelle branche du projest ustilisant le ménestriciel NTXM estoit fièrement campée. Eh oui. Je vais laisser libmikmod derrière moi et poursuivre avec le code (lgpl) de 0xtob. Je peux donc uploader un .XM (jusqu'à 512KB) sur ma DS puis l'écouter avec NTXM. un p'tit SELECT et c'est le player que je mets à jour (histoire de tester le support de nouveaux effets). ça ne m'aura demander qu'une légère réécriture de XMTransport.

edit: okay, i've got "set tempo/speed" effect added. I also added (untested) offset effect and wrote a small tool that inspect .xm to report what effects they're using... I'm not that happy with the way the player keeps state, anyway. Both "Instrument" and "Sample" classes are used as an "samples database", but nothing capture the current state of a playing note, which makes e.g. offset effect tedious to implement ... I fear similar boring edits to be required when we'll have to support retrig and the like.