Friday, September 26, 2008

Screwed up terminals: the solution

Anyone who has been doing C programming on Linux has encountered this at least one, or is a very rigourous programmer. A certain binary sequence (that you normally never encounter in ASCII text, but that might be present in that binary file you accidentally dumped on your terminal) will switch you to the "graphical and lines" character set where everything gets completely unreadable.

Si vous programmez sous Linux ce genre d'écran illisible ne vous est forcément pas inconnu. Tôt ou tard, vous (ou un de vos collègues) a forcément malencontreusement envoyé un fichier mp3 ou une image ou un programme sur la sortie du terminal et pas de chance: il contenait cette petite séquence ANSI qui force la console à passer sur le jeu de caractères graphiques, utilisé entre autres par ncurses pour dessiner ses boites et ses menus.

It was fairly easy to fix under SuSE and RedHat back in Y2K as a simple "reset" command typed on the terminal restored the display. Unfortunately, ubuntu Linux distributions do not seem to think a terminal reset should include reset the character set to its default value...

It occurred once again today. Once too much. I dug the ANSI commands set and wrote a small perl tool that let me toy with ANSI escape codes. Here it comes: ANSIHACK.PL (in uppercase so that you can recognize it even when your terminal is screwed :P)

#!/usr/bin/perl
print "\x1b($1\nMODE $1 ENABLED.\n" if $ARGV[0]=~/\-\-SET([0-9A-B])/;
print "\x1bc\x1b(A" if $ARGV[0] eq '--RESET';
shift @ARGV if $ARGV[0]=~/^\-\-/;
print "\x1b[$ARGV[0]\n";
print "done/DONE.\n";
exit(0);
Actually, the commands that trigger a charset switch are Esc(x and Esc)x. Charset A is our default, regular 'ascii' charset (used in --RESET form) but you can also toy with other charsets (B, 0, 1 and 2) with e.g. ANSIHACK.PL --SET0 (that screws things up) and ANSIHACK.PL --SETA (which restores things to normal).

C'était assez simple à résoudre du temps de SuSE et RedHat (tapez 'reset' en aveugle, puis appuyez sur ENTER les doigts croisés en sautant sur un pied un soir de pleine lune avec un baton de réglisse entre les dents). Mais sous ubuntu. Rien. reset efface le contenu du terminal, mais ne résoud pas le problème qui nous occupe. D'où ce petit script pour jouer avec les commandes ANSI. Les vieux de la vieille pourront se faire un alias reset='bin/ANSIHACK.PL --SETA' ;)

|-|oPe !7 |-|e|_p$ ;)

edit: the real explanation is that a '0x0e' character (shift out) had been issued and only a '0x0f' character (shift in) would bring the default charset. The ANSI hack almost works, but it screws up the '#' character into some £...

Tuesday, September 23, 2008

Biokid NT : countermeasures

Quelque part en 1996, mon frère Piet me pond une storyline un peu abracadabrante inspirée d'un vieux souvenir (le Stoner): votre PC est infecté par le terrible virus Terminator 007. Le seul moyen d'en venir à bout, c'est le nouvel anti-virus interactif de PPP Team Software: Biokid.

Back in 1996, my brother's mind give birth to a curious story: your PC is infected by a dangerous virus -- the Terminator 007 -- and the only thing that can get rid of it is the brand-new interactive antivirus from PPP Team Software: Biokid. To put it simpler, Biokid is a crossing over between Megaman character and Commander Keen level design where you hunt for keys and weapon upgrades in maze-like platformer. It turned into one of our best production on RSD Game Maker.

L'idée, c'était de tenter de s'approcher du gameplay d'un Megaman. Mais là, j'ai envie d'un petit jeu au principe plus simple (un shoot'm'up) que Bilou pour roder un peu mon Game Engine, et plutôt que de ressortir Bilou Sky Quest (C64) ou d'essayer un portage de Out'm'up (assembleur, Y2K), je me suis dit que j'allais ressortir Biokid dans un nouveau mode de jeu: "Counter Measures".

Plus question d'assurer passivement la défense de votre réseau: Biokid prend les devant et part vaillamment à l'assaut du plus grand Botnet qu'il vous a jamais été donné de combattre.

I was thinking of giving my game engine for DS a try in a different setup : a shoot-m-up. I could have reused "Out'm'Up", our brain-free shooter that won the 100K game competition at Inscene Y2K. Or I could have revived "Bilou Sky Quest", the test game I made on C64 with the "Shoot-Em-Up Construction Kit". For some reason I started dreaming of a shooter featuring Biokid who'd now have to protect your corporate network proactively and fight the largest and scariest Botnet ever fought. (hmm. I could have been "inspired" by the Bionet EU project a colleague of mine is working on, btw).

edit: bon, comme vous le voyez, côté graphique, il y aura du boulot ... je voudrais recréer une ambiance "newschool" inspirée de Matrix, Tron et autres Space Invaders Extreme ... on verra ce que ça donne ...

Monday, September 15, 2008

Programmatically surrealistic


Earlier in the day, i had an argument with the update-manager of my test machine who was refusing to update my Dapper Drake because of some "hash mismatch" at the mirror. For some reason, i didn't trust the ubunutu forums that state that "this occur when you try to update while mirrors are synchronizing" and finally discovered that the way hashes (that confirm your softwares' authenticity) are managed has changed with Hardy Heron ... Doh. Fortunately enough, someone is still thinking that some user prefer to update from a text console rather than having a "user-friendly" graphical interface but only at the cost of burning a new ISO distribution and moving your feets two level down in the lab.

So my thanks fly to the maintainers of the update-manager-core package and the sudo do-release-upgrade -m desktop trick that did the whole upgrade without pop'ing any window and without silly hashing bugs.

You thought that would have been the weirdest thing around? You were wrong.

With the machine updated, i'm now able to test the new release of that European project i'm working on ... The software has a thing called "the minmex" which spawns thread for various sub-tasks and i thought it would be handy to catch those "logfile " lines it produces on stdout, and process them in a script that would automatically start following each new log. Easy as (s)hell :

# invoke this as:
# sudo bin/minmex | perl myscript.pl
while ($_=) {
print;  # just echo back the filename
chomp;
sleep 1; # just let the minmex actually create the file
system "tail -f $1 &" if (/logfile (.*)/);
print "waiting for more ...\n";
}


Except it didn't worked. Only the "master thread" displayed something. Of course, running a plain "sudo bin/minmex" show you all you wish to know on the console :-/
And of course, as usual with the latest libc6, you don't even see any write(1, ...) in the output of an strace bin/minmex. My colleague Cyril supposed something odd with termcaps, but there was absolutely nothing that sophisticated in the minmex. Just a very plain printf("logfile %s"); ...

Fairly puzzling, don't you think ?

Well, now it started getting funny when i realised that i actually was facing this in the 'master' thread:

mkdir("/tmp/log", 0777) = -1 EEXIST (File exists)
fstat64(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf97285c) = -1 ENOTTY (Inappropriate ioctl for device)
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f7f000
write(1, "logfile /tmp/log/26274_"..., 71logfile /tmp/log/26274_anaMinmex
) = 71
brk(0)                                  = 0x806b000
brk(0x808c000)                          = 0x808c000
open("/tmp/log/26274_anaMinmex", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
.

I'm not very comfortable with those termcaps things, but that ENOTTY error clearly suggested that Cyril was right and that the source code was wrong 0_o ... Using plain write(1,...) instead of printf(...) let me see all the stuff i wanted, but that can hardly be called a solution. After a bit crawling in the sourcecode of libc6, i could not find any direct relationship between tcgetattr (the function using that TCGETS argument) and printf, but some reference to glibc-2.6.1/misc/getpass.c did ring a bell in my mind ...
What if the problem was actually coming from the sudo not liking me to redirect the program's output ? what if, for some reason, it *had* to ensure the access to a terminal (e.g. to prompt me for a password) and failed to properly restore the output-to-next process ?

And indeed, running the whole chain in a regular root session has now shown a perfectly regular behaviour, in other terms:
  • either you shouldn't try to redirect stdout when using printf
  • or you shouldn't try to build multitasking programs
  • or you shouldn't try to run those programs as a sudoer
  • and you certainly shouldn't do all these three things "for chaos and maddness awaits thou at thee end" ...
For your mind's sanity, i just hope that you'll never ever find such a post useful. But in case you happen to struggle with such a debugging nightmare, i hope i've got a sufficiently high pagerank to get ahead all these mailing list that discuss about whether a bug is a bug or not and that you'll get a clear understanding of the situation faster than i did...

HAve a nice day,
/Pype, the crazy coder.

edit: the problem seems to be tcsh-specific (e.g. doing the plain sudo bin/minmex | perl myscript.pl in bash will work) and there are two possible (and both equally surrealistic) work-around for those who don't want to switch to bash:
  • sudo -c tcsh "bin/minmex | perl myscript.pl"
  • sudo -c tcsh "bin/minmex" | perl myscript.pl
I'm accepting any explanation for this, and myself strongly suspecting tcsh to do something wrong when building the pipes between minmex and perl...

Friday, September 12, 2008

Model, View, Controller

Tout à commencé par ED, l'éditeur le plus imbuvable que l'on puisse imaginer (à moins que l'on ne soit un VIMeur auquel cas le pire éditeur possible est évidement EMACS :).

Au commencement, il n'y avait rien que des 1 et des 0
et le souffle d'ED qui planait au-dessus du tout qui n'était rien.
Puis ED dit "# Que le Code soit"
Et le Code fut.

ED sépara les Données du Code;
Il appela le Code ".text" et les données ".stack"
Et il vit que c'était bon.

Bref. Tout ça m'a amené à télécharger la chanson Model View Controller sur le blog de Peteris Krumins. Non seulement c'était bien drôle, mais je crois que c'est l'explication la plus claire du modèle "MVC" qui m'ait jamais été donnée de lire (et écouter). Au départ, j'avais plus ou moins tenté de respecter ce modèle dans la construction de SEDS, quoi que la plupart du temps le "modèle" n'était que des données brutes ... un tableau de bytes ou de shorts dont le rendu est assuré par les widgets.
Model objects represent your applications raison d’tre.
Custom classes that contain data logic and et cetra.
You create custom classes in your app’s problem domain,
then you can choose to reuse them with all the views,
but the model objects stay the same.

Les "fenêtres", elles, assuraient la "glu": c'était mes contrôleurs. Mais là, ça ne va plus du tout. Je me retrouve avec ma fenêtre "éditeur en grille" qui commence a avoir des méthodes "remplir_grille(un_sprite)" ou "remplace_couleurs(une_couleur, autre_couleur)" sans parler de "affiche_tiles_utilisant(une_couleur)" etc.

Bref, il serait sans doute temps de promouvoir le tableau affiché par la Grille en un objet à part entière, et idem pour la palette ... Ca m'éviterait, soit dit-en passant, de copier/coller le code de "affiche_tiles_utilisant(une_couleur)" pour avoir la "méthode" "tue_les_couleurs_inutiles()" sur l'éditeur de palette.

edit: en fait, non. La majorité de SEDS n'a rien à voir avec du MVC. Ce serait presque l'inverse, en fait ^^"
Il faut dire que (paradoxalement), la programmation d'interface graphiques dans les règles de l'art, j'ai toujours trouvé ça chiant comme la pluie >_<

Et pour ceux qui se demanderaient toujours dans quel cerveau dérangé un outil aussi anti-ergonomique que ED a bien pu germer ... regardez donc cette antiquité, encore commune au temps du dévelopement d'Unix: le terminal teletype. Remis à jour pour s'interfacer par RS-232 avec Linux.

On ne sait pas "effacer" de caractère avec ce truc. On ne sait même pas se déplacer de haut en bas dans l'écran. La seule interface, c'est la ligne en cours. On aurait aussi bien pu fonctionner avec des numéros de lignes, façons MS-BASIC...

Wednesday, September 10, 2008

Sharp lane pour moi

L'application tomboy devient de plus en plus un élément central de mon activité professionnelle. Ce n'est plus simplement un moyen de me faire des todo-list, mais c'est devenu à la fois la "fournaises à idées" où je prépare mes articles, un substitut à mon ancien "meta-do comment" pour conserver mes réflexions à propos de mes lectures, et même dernièrement ze moyen de corriger les TP des étudiants.

Bref, tomboy (l'éditeur de post-it) est devenu mon blog non-publié ... mon wiki perso. Si bien que je voudrais pouvoir commencer à bricoler un peu autour ... annotation d'image, lien vers des fichiers, intégration avec mon outil "doclocate", etc. Je m'attends donc à me lancer dans la programmation mono (c#) d'ici peu ... Avec comme premier contact un "gmcs not found" lors de la tentative de ./configuration du bazar. Heureusement, depuis mes premiers pas dans RedHat 5 et SuSE6, la gestion des packages sous linux a méchamment évolué. J'enfile donc ma toge de guru et déclame un

$> sudo apt-get build-dep tomboy

et mon gibbon, si vaillant soit-il, ne peut faire autrement que de me demander la confirmation des 65MB de bibliothèques, compilateurs et autres qui vont faire de beetle une bête de développement mono. Quelques instant auparavant, un simple
$> apt-get source tomboy
avait suffit à obtenir les dernières sources de l'application telle que je l'utilise.

En comparaison, j'avais essayé en 2001 de compiler moi-même gnome, qui manquait alors sur ma SuSE, et après de vaillants combats avec le Gardien des Parchemins (traduisez scrollkeeper, un obscur gestionnaire de config pour gtk/gnome), j'étais bon pour réinstaller tout mon serveur X avec la SuSE suivante ...

Bref, je n'ai plus qu'à arriver à éditer un billet sans repasser en mode HTML et je serais définitivement 21eme-siècle-ready.

et si ça vous a plus, vous allez adorer les incantations magiques de Drake dans le webcomic 0xbabf000L, malheureusement en veille

edit. J'ai eu droit à un cryptique The following assembly referenced from Tomboy.exe could not be loaded en essayant de démarrer le programme compilé. Je crois que j'irai voir quelques liens histoire de rattraper mes années de retard :P

Tuesday, September 09, 2008

Color Reduction.

au centre: mon arbre, sans les couleurs inutiles; à gauche: mon arbre, revu et corrigé par Helm; à droite: j'essaie d'appliquer les conseils de HelmA nouveau, ma palette de couleur est devenue quasiment inutilisable. J'ai bien un outil de "réorganisation" efficace pour construire des dégradés, mais à force d'importer et de réimporter les pixels depuis mes bricolages dans Gimp, je me retrouve avec 3 ou 4 instances de la même couleur (à quelques variantes près, voire exactement les mêmes). Bref, l'arbre que j'avais soumis faisait 28 couleurs, alors qu'il n'y avait que 16 teintes vraiment uniques (au centre). Ce n'est qu'après cette étape de "réduction du nombre de couleurs" qu'on peut commencer à jouer sur le contraste des éléments (à droite) pour arriver à ce que Helm proposait (à gauche).

Je ne suis pas pour la réduction du nombre de couleurs à tout prix, mais là, j'avoue que ça devient ingérable. Trop de micro-variation sur la même couleur, je ne sais plus laquelle utiliser quand ... Bref, si je veux pouvoir continuer à faire des mockups facilement, à ajuster les niveaux de contraste, etc. , il faut que je bricole quelques nouvelles fonctions dans l'éditeur de palettes.

Once again, my palette is a big mess, which makes my art more and more difficult to manage, since some colors do not fit any raster any longer ... If i want to save hours of "clean up" duty when publishing a mock up, i'll have to improve the palette editor too ...

  • [done] zap unused colors in the palette.
  • click on color in the preview, and see where it is on the palette
  • R recalls the former color (undo) ?
  • swap mode for the PaletteEditor widget
  • [done] click a color in the palette and see on the upper screen the n first blocks featuring that color
  • [done] flashing the color for easier identification. This happens on the spritesheet only (not on the grid, nor on the lone tiles) when you hold on the color square.
  • split the color square view out of the Palette widget, though, to be implement flashing correctly
  • [done] after such identification, allow color to be replaced by another one. (but only the grid is modified)
  • [done] fix block mode
  • [done] fix overlay-loading
  • remember grid size when switching windows
  • [done] provide some "undo" for accidental (misplaced) R-R combos.
  • [now] fix imlib2spr script so that it picks the *closest* SNES color for a given RGB color (not simply killing bits) and that it kills redundant SNES colors (even if they differ in the initial RGB space)
  • [now] allow spr-addpage tool to understand the "extra tileset" ... and do a major rewrite of that tool to ease further development.
Parmi les outils manquant, identifier les tiles qui utilisent une couleur donnée est évidemment primordial ... Vient ensuite la possibilité de remplacer cette couleur par une autre. Curieusement, ne lister que les tiles véritablement utilisé se révèle plus complexe que prévu.

Monday, September 08, 2008

Gravity Hook

Quittons un moment le monde du homebrew pour nous intéresser à ce qui a été rebaptisé le "casual gaming". Un phénomène prétendument nouveau qui existait déjà en 1980 (pensez à Frogger, Congo Bongo, Pooyan ...) d'un jeu pas prise de tête, dont le gameplay est axé sur un ou deux mécanismes faciles à expliquer et dont l'intérêt principal réside dans la table des highscores. Oui, en gros, un jeu d'arcade mais sans le monnaieur.

Bref, voici un petit jeu tout simple, mais au gameplay inédit (à ma connaissance) où vous allez devoir, tel un Spiderman acharné, grimper toujours plus haut en vous accrochant à des espèces de mines anti-gravité qui vous propulseront toujours plus loin, toujours plus haut. Mais si jamais vous heurtez une mine ou que vous redescendez trop bas (l'écran ne vous suit jamais que vers le haut) c'est fini. c'est le game over assuré.

Tout ça avec du tout bon pixel art de Adam Atomic, sur une petite musique chippy et un concept de Arne (l'homme à la palette magique). Allez, laissez-vous tenter.

You may call it "casual gaming", i do call it "quarterless arcade games". Anyway. AdamAtomic released a nice little game (that i wish i could run as a homebrew on my DS) where you have to swing from node to node to climb up an apparently endless pit. A fairly novel gameplay that is easy to learn and hard to master, but definitively fun to play.

Beware, though: those apparently helpful nodes turn into deathly mines as soon as you hook on them, so you'll have to get as close as possible, but not closer.

Or read the whole story on Pixelation board.


edit: si vous êtes plutôt "développement flash" que "DS", Adam nous a offert flixel, le moteur avec lequel Gravity Hook avait été programmé. Merci qui ? ...