Friday, September 18, 2026

--dump=D

Okay, I need to remember this once for all. I'm frequently using gcc [OPTIONS] someFile.c -E to understand some of the error messages from the compiler, but too often, I have to ask a crawling duck what preprocessor option would let me see the values of the #define statements, not just the lines of code with all substitutions applied. So it's time I post something to remember me it's -dD

...

Or maybe I could just add some line in my cpp-output-colorizer that would remind me of it ?

Thursday, September 17, 2026

Retrobar pour Windaube 11

Avec les écrans toujours plus larges et les fenêtre toujours plus hautes, vous ne croyez pas qu'on va finir par avoir des ennuis ? A priori, chez M$, ça ne les choque pas. La barre des tâches de W11 est une horreur à utiliser même après avoir défait tous les pré-réglages foireux, mais ça non plus, ça ne les gêne pas. C'est que pour W10, j'avais pris l'habitude de la mettre en mode vertical, moi. Bon, ok, même ça, c'était mal codé, mais au moins c'était là.

Heureusement, il y a l'open source et pour le coup, il y a retrobar. Alors oui, ça pique peut-être un peu aux yeux, en particulier avec le thème "Windows 98 / Windows NT" que j'ai fini par choisir, mais le mode vertical marche comme une fleur et j'ai pu trouver le coin du code où on définit la largeur minimale et forcer quelque-chose de plus proche de ce que j'utilisais habituellement.

Au moins, j'ai l'heure en permanence dans le coin inférieur droit sans devoir gérer une barre qui apparaît et disparaît à tout bout de champ.

Les fenêtres que j'avais "épinglées sur la barre des tâche" dans W10 se retrouvent dans M:\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar, prêtes à être customisées si je veux. 

(ah oui, je me suis fait un subst pour que mon répertoire utilisateur apparaisse comme M: ... il faut juste se souvenir que les autres utilisateurs ne voient pas ce disque virtuel, y compris le compte admin)

Et oui, j'aurais pu/du vous en parler depuis Mai 2025. Scsi.
 

 

edit: passer 1 jour à relancer des recherches Internet sur "comment faire pour qu'il n'y ait pas de boîte `cmd.exe` qui traine pour mon raccourci", tomber sur start /MIN ma_commande qui ne marche pas parce que la boîte de dialogue du raccourci ne connaît pas l'emplacement de "start" ... et finalement remarquer le Run: Normal Window [v] juste sous "Shortcut key:" .. qu'il suffisait de passer sur "Minimized" T_T

Tuesday, September 08, 2026

Terra Ninfa

Prenez le coeur historique de votre ville, tournez-lui le dos pour vous diriger vers le coeur folklorique. Là, au bout du boulevard, à côté des ruines classées du vieil hôpital se tient le nouveau centre multi-culturel combinant bibliothèque, fab lab, salle de spectacle et "classes" de conférences ... et à l'étage, dans "l'espace des possibles" se tient en plus de l'apéro jeu-videos la soirée du "gaming club" où on retrouve des consoles rétros, des tables de jeu de rôle et de jeu de société.

Et une tablette où les développeurs peuvent mettre leur prototype à l'épreuve du playtest. Parmi eux, en juin, il y avait l'ami Tog qui présentait le prototype de jeu Godot qu'il a développé avec sa dame. Le jeu a un petit côté "monument valley" et fait la part belle à la manipulation de l'eau.

Tog n'était pas présent en ce début de Septembre, mais quelques-uns de ses colocataires-de-tablette avaient insisté pour que je revienne avec ma DS même si Dreamland n'est pas encore un jeu. Je suis repassé, donc et récolté quelques "tu me ramènes à mes 8 ans" ou "Franchement, chapeau! On ne dirait pas un jeu fait en solo!", voire même "J'adore les cahiers! Il faut que tu fasses un livre pour nous raconter le dev!"
 

 

Thursday, September 03, 2026

Inspector Widget Improved

Inspector Widget ... le mode pause du moteur de jeu de GEDS qui permet de voir à travers la Matrice. Repérer les zones de collision, mais aussi visualiser le terrain autour des personnages tel que les contrôleur le perçoivent. Sauf que le code qui faisait l'affichage du terrain date de l'époque Apple Assault  et qu'il est plus ou moins inutile avec le nouveau système de map physique.

During AppleAssault and SchoolRush development, the "playfield" feature of InspectorWidget has proven an extremely valuable feature of the GEDS engine. I could get an overview of what the engine sees of the level without having to manually decode contents of the physics map. But with the evolution towards a new, richer encoding, the information it was showing became mostly useless. But hopefully, during the "Blador-vs-Spike" episode, I located where the responsible code was and could start fixing it. Initially, it was looking like the listing below.

Le code qu'il aurait fallu que je retrouve il y a un moment était caché dans InspectorWidget::clearmain(). 

for (int ty=sy; ty<=ey; ty++)
  for (int tx=sx; tx<=ex; tx++) {
    unsigned f=gob[0]->world->getflags(tx,ty);
    unsigned c=BCHECK; // pattern for the "outer ring" of the zoomed tile
    if (f&F_BLOCKING) c=BON; // plain light ring = solid block
    if (f&F_PLAYERTHRU) c=BOFF; // dark ring = air / water / etc.
    if (f&0x10000) c=BCHECK; // checkered ring = special block
    if (f&F_SLOPE) c=97; // striked through = slopes
    char sq[16];
    memset(sq,c,16);
    if ((f&(F_FLOOR|F_SLOPE))==F_FLOOR) memset(sq,BON,4);

    sq[5]=80+((f>>12)&0xf); // 4-digits code in the inner area
    sq[6]=80+((f>>8)&0xf); // encodes the F_* flags for cando() calls.
    sq[9]=80+((f>>4)&0xf);
    sq[10]=80+(f&0xf);
    u16* v = vram+MAP+(ty-sy)*128+(tx-sx)*4;
    for (int i=0;i<16;i++) {
      *v++=sq[i];
      if ((i&3)==3) v+=28;
    }
  }

Pour ceux qui ne parlent pas le C couramment, le listing ci-dessus raconte que chaque pavé de la map va être représenté par un code à 4 caractères entouré d'une bordure dont le pattern est variable. 

  • bordure solide pour ce qui ne laisse pas passer le personnage
  • bordure en damier pour les blocs spéciaux
  • bordure en hachure pour les pentes.

Le code au centre du carré, ce sont les propriétés utilisée par la fameuse fonction cando(). Et il faut bien admettre que maintenant qu'il y a plusieurs types de pentes différents, plus de blocs spéciaux et des blocs aux propriétés particulières, juste les flags pour cando(), c'est devenu à la limite de l'inutile. Parce que la plupart des blocs spéciaux ont les mêmes propriétés et que celles des pentes sont prédéfinies.

Mais heureusemement, j'ai trouvé l'occasion d'améliorer ça.

  • un code à 2 chiffres, c'est un tile à encodage direct. on voit littéralement le byte de la map physique et chacun de ses bits nous renseigne pour une propriété. 44, c'est de l'air.
  • un code à 2 chiffres sous une petite ligne à damier, c'est un bloc spécial. Ici aussi, la valeur et celles du byte de la map. Les valeurs ff, fe et fd servent pour les fameuses "flèches jaunes" de l'éditeur.
  • les pentes sont toujours identifiées par leur contour hachuré. Le code à 4 chiffres donne les hauteurs des pixels au centre du tile. 3456 ou 6543 pour des pentes à 45°. 2233 et 6677 pour des pentes plus faibles en "montée" de droite à gauche, etc.
  • Enfin, pour les autres blocs, on reste sur un code à 4 chiffres qui contient les flags. à l'ancienne. 

The new code varies the shapes a bit more. Some tiles will only have a 2-digit code (the byte straight out of the map), sometimes with a checkered line on top of them for special blocks. Slope tiles still have a 4-digit code, but it now shows how heights ramp up or down along the tile. And the so-called "indirect" tiles, those which can be assigned physical properties such as friction and flow, keep showing the 16-bit cando() flags as before ... at least so far.   

 

 

Tuesday, September 01, 2026

CompoundGob::RefreshPage

I guess you can hardly tell what's going on on the picture below, and I can't blame you for that. It's supposed to be a stomped scorpeye shell, but since I've added crawling animation for the scorpeye, we see that glitchy mess of sprite parts instead.


Ah oui, je m'étais fait un joli scorpion qui marche, mais si vous parvenez à l'assommer, tout à coup, il ne ressemble plus qu'à un tas de pixels complètement glitché. Comme j'envisage de passer refaire un coucou au "gaming club" de vendredi, ça ne serait pas mal de corriger un peu ça.

La cause du problème, je la connais: l'animation de la marche est construite avec 5 sprites hardware: un "large" pour la carapace du scorpeye et un carré pour chaque "patte". En revanche, les animations "carapace seule" et "carapace qui tourne parce qu'on l'a lancée" sont toujours inchangées et n'utilisent que 3 sprites hardware. Et le couac, c'est qu'en plus, le sprite large n'est pas sur le même d'une animation à l'autre. Il était donc temps que je me gratte un peu la tête et que je retrouve les fonctions-clé pour gérer ça, en particulier loadAnim() dans CompoundGob et setupOAM() qui peut redéfinir les tailles et aspects des sprites.

What happens is that you have dedicated bits in the hardware sprite entries to indicate whether you want a square, tall or wide sprite and of what size. So far, in my engine, those properties are defined once when you allocate hardware sprites for an object and then preserved as we just update coordinates, VRAM location and optionally palette slot of each sprite as we animate them. But by mixing the new crawl and the old spinning animations, I'm breaking an old habit of sharing the same structure for all animations of a given game object. So I need to extend the game engine with the following function:

  void refreshPages(const GobAnim *ani) {
    unsigned nlimbs = ani->getnlimbs();
    unsigned i;
    pages = ani->getpages();
    for (i = 0; i < nlimbs; i++) {
      if (oam[i]==NO_OAM) continue;
      pages[i]->setupOAM(sprites + oam[i], 0 /*?*/);
    }
    for (; i < nboam; i++) {
      if (oam[i]==NO_OAM) continue;
      sprites[oam[i]].attribute[0] = ATTR0_DISABLED;
    }
    nboam = nlimbs;
  } 

Je dois dire qu'au départ, je m'attendais à plus compliqué, mais la petite fonction ci-dessus et une brave ligne de plus, les animations se sont réparées presque d'elles-même. à utiliser avec prudence tout de même: le système ne se déclenche que si les deux animations ont un nombre différent de sprites.

To be honest, I was expecting it to be harder to code. It was a bit tedious to locate where to act in the code (state transition? animation loading ?) and I spent a significant part of a holiday afternoon in ddd setting conditional breakpoints to figure it out. Then I got puzzled by the update/setup/allocate functions manipulating hardware sprites through the "SpritePage" class: the one that is used at every frame to update what we see on screen keeps aspect ratio and size of the sprite unchanged... but after all, it was just a matter of a small function called when we detect that the current number of OAMs (aka hardware sprites) is different from the number of limbs the animation uses. Pretty and straightforward.

Monday, August 24, 2026

Crawling Scorpeye

Sur bsky, MagicalScope nous poste d'impressionnants designs d'objets magiques qui sont ensuite vendus à des internautes. Parmi eux, je suis tombé sur une potion-qui-marche particulièrement inspirante. J'ai d'abord eu le réflexe de voir comment je pourrais l'intégrer comme nouveau perso dans la pyramide jusqu' ce que je réalise que mon brave scorpeye pourrait simplement profiter du type de déplacement que suggère cette potion tout en restant lui-même. 

Après des mois où on voyait un scorpeye tout immobile dans un coin de la salle pyramidique, voici enfin une petite animation (encore un brin brouillonne) du scorpeye patrouillant autour de son trésor. J'aurai probablement un peu de travail à faire sur le moteur de jeu: l'animation de la carapace lancée supposait 3 sprites hardware alors que la marche en crabe en utilise 5 ... le résultat est assez bizarre à voir quand on assomme et ramasse notre scorpeye.

At last! After months (years ?!) of design blockage on how-the-heck-am-I-going-to-make-scorpeye-walk, I can propose you a prototype animation for the crawling scorpeye ! Maybe not as "crawling" as I had imagined after seeing MagicalScope's mimmic potion, but that shall be a start.

Key idea for the redesign is to embrace the "limbless" nature of Bilou's world and grant the scorpeyes 4 versatile spike sattelites. It can use them to crawl, pinch or sting depending on the situation's need. It will make it clear whether it's currently safe to stomp on its shell to stun it.

"Mais où sont passées ses pinces ?" me demanderez-vous ? Eh bien c'est justement là tout le sel du redesign: les même membre lui serviront soit de pattes, soit de pinces, soit de morceau de queue de scorpion. Je décide que ce sera plus fun et plus lisible qu'un vrai arachnide avec tous ses chéli-chose (J.L.N ? c'est quoi le bon nom, encore ?) 

As a bonus, an intermediate step where I was studying the design of the magic potion and considering "well, why not. It would be an extended version of Inkjet that can move along... quite fits the universe. You lose some part of the crab-like suggestion by not having limbs between the pinching part and the body, but that's how I came up with the idea of keeping scorpeye and having it walk on its pincher, so I'm okay with it.


 

The Lost Tiled Tutorials

Many of the tutorials I had encountered between SEDS and LEDS are now out of the web. Too bad, they were key material I sent readers towards when I did not feel like translating some lengthy explanation about tiled games in general. Since I'm editing some part of the blog as if it was going to be the Chapter 1: Tiled Games of a book, I found myself digging through archive.org to find the original material, print it and review it as much as possible. 

The most influential of them all was certainly the MC Kids big post. Where we have Greggman discussing *really* how they made the game back on NES days. It details several clever tricks that help making a quite-sized game on limited resources, some of which make mostly sense if you're on #6502 CPU (like having a set of byte tables rather than structures), but also the key gamedev concept of a "hotspot", a single point that will be used to model the position of the character on slopes.

It is also the most official one, as the post was originally written in 1992 for the Journal of Computer Game Design while the game was from 1992 as well. And since there was an official body publishing it, I can't quite just bring in many pictures of it ... but I guess it's fair to study it, take notes and then post my own notes about what was being said.  

Entre la création de SEDS et celle de LEDS, il y a eu pas mal de posts qui faisaient référence à l'un ou l'autre tutoriel sur la conception de jeux à base de tiles. Evidemment, là-maintenant, un grand nombre de ces tutos ont disparu d'Internet ... juste au moment où je me dis que ce sujet serait bien comme premier chapitre.

Le plus gros d'entre eux, c'était sans doute la présentation du code de gestion des collisions perso/monde dans le jeu NES M.C. Kids, auquel je faisais référence pour les lecteurs Anglophones en 2007 ... Pas trop question d'en faire des captures d'écran dans tous les sens par contre: le truc avait quand-même été publié dans un journal officiel à l'époque. Mais un scan de mes notes, ça, ça me semble honnête. 

The paper goes into significant details of how the levels are encoded (1 byte per 16x16 block, that is used to lookup the 4 tiles composing the block and its type among 100 possible types), how collision with terrain are handled (with direction-conditional testpoints and 5 collision functions per tile type). The author relates the fight to get that extra memory and how you could map the whole level into memory and thus make it easily explorable and transformable thanks to this, but how 8x8 granularity would have explosed the RAM space budget.

It is also completed with retrospective thought of the author about how they'd have inserted "beginning of hill" and "end of hill" types (helpful to save lookups in the slope management) and how they'd have made the "how do I move left[tiletype, xpos]" array providing absolute position rather than relative (+1, 0, -1) positions in a revised version of the engine.

Bon, par contre, près de 20 ans plus tard, il faut bien avouer que pas grand-chose de tout ce qui est présenté là ne se sera retrouvé dans le moteur de jeu de SchoolRush. Entre les ruses propres au 6502 et les choix d'implémentation que l'auteur lui-même indique qu'il n'aurait pas refait pareil rien qu'un an plus tard, il reste juste le concept de "hot-spot" -- réduire le personnage à 1 point quand il faut décider où il se trouve dans une pente -- et le conseil général que "mettre des pentes dans un jeu, ça complique significativement le code". Mais c'était intéressant à relire malgré tout.  

Retrospectively, most of it did not end up in the GEDS engine. With a 66MHz CPU, if you realize that you need one extra memory lookup to get proper slope implementation, you go for that extra lookup. And if you may need more than one, you just write a loop. It's not about being lazy or not, it's about getting the most of what you have. And nowadays, you could "easily" add some "start-of-slope", "end-of-slope" meta tiles by means of auto-tiling rules.

The second note-worthy series are Tony PA tutorials about tiled games development. These were for flash games, with full-running examples at each step and detailed ActionScript code. Smartly enough, Tony starts his tutorials with top-down playfield in which the character can move freely, and then step by step introduces gravity, moving platforms, ladders and finally slopes. 

I was enjoyed to start reading it as it featured a picture of Charlie the Duck (which may explain why I was researching about it in 2007 and certainly why I just posted about it, btw :P) and saying "Sure if our hero is a jumper-type of hreo, he could still [proceed forward in a stair-like, slopeless ground], but normal heroes are very happy if they can avoid jumping. It could have been a good resource, but I knew from the time I've spotted a drawing with "impossible slopes" that I couldn't derive from what was presented there.

Un autre tuto qui sortait du lot, c'était la page sur les pentes de TonyPA. On lui doit la phrase sur les héros qui sont content de faire des bonds (hmmm ... Jill of the Jungle ?) et ceux qui trouvent que les pentes, c'est bien. J'avais laissé tombé assez vite à l'époque constatant que plusieurs interdits allaient sans doute me pourrir la vie ... Il faut noter que Tony faisait ses tuto pour de l'ActionScript, ce qui lui permettait d'avoir une petite démo interactive dès sa page web, mais ce qui donnait aussi du code plutôt étrangeoïdal pour qui a fait un minimum de C/Pascal/Basic dans sa vie.

A côté de ça, il faut reconnaître à Tony que sa petite démo s'inscrivait dans la continuation d'autres tutos qui démarrent dès le niveau "sokoban" pour ajouter petit à petit la gravité, les échelles, etc. Par contre, les "combinaisons interdites" qui proviennent du fait qu'on désactive tout test de collision horizontal dès qu'on est sur une pente ? Le personnage qui logiquement grimpe des escaliers tandis que son image se déplace le long d'une droite continue ? Non. Je me félicite de ne pas avoir insisté. Mais il aura le mérite de m'avoir aidé à déterminer pourquoi je veux des pentes dans Bilou. Je n'ai pas la physique de Sonic, mais depuis Keen 4, les niveaux à pentes semblent plus intéressants que leurs équivalents tout à angle droit. Et une pente, ça permet aussi de faire prendre de la hauteur à un projectile du type carapace de tortue, en plus de rendre le niveau plus organique.

During this 2026 retro-review, I noted that most of the slope logic seems to imply that only the display of the character is aligned with the slope. The logic entity made of testpoints and hitboxes simply moves along a stair. The two locations are only re-aligned if we jump from a slope. It also bypass the problem of solid-ground-tiles-and-slopes by disabling all horizontal checks while you're on a slope. That explains some of the "forbidden tile combinations", and implies that if you make a slope in a path that is high enough for certain characters in your game but not all, the engine will completely ignore the fact that the monster you're fleeing through that narrow passage should get hit in the face and not be able to follow you. And that has been a critical thing to address for my games even before I started working with the Nintendo DS.

So why would you put slopes in a Mario game ? so that your koopa shell keeps flowing forward and not bounce back in your face. Here's why. (Or simply to make your organic level feel organic and not just look organic). 

A last one ? Hopefully, the video from Vblank Entertainment about the conversion of Retro City Rampage into ROM City Rampage is still online. It goes into details about what tiles are and how it allows a large world to run on a sub-MegaByte cartridge, what palettes are, why you need to care about not putting too many sprites per line and so on. If you ever need a primer to the "Retro Game Mechanics Explained" series and feel like sitting idle for 10 minutes, this is the best I can think of at the moment.

(The author ended up writing his own NES emulator full with debugging features and his own high-level assembly -- NESHLA hosted on sourceforge -- in the process)