Showing posts with label done. Show all posts
Showing posts with label done. Show all posts

Wednesday, October 30, 2024

October update

That week off has been pretty B-usy ... The 'three rooms' demo now actually feature 2 additional rooms, including one that is level-sized. There are still quite some things to fix, tileset updates, adjusting to .more loading, and the like... 

Bienvenue dans un post-qui-change... ma petite semaine de congé d'automne aura été bien remplie de p'tits Bilous (entre autres choses), avec en objectif #1 l'ajout de deux "niveaux" dans la démo "Three Rooms", comme proposé en Mars. Evidemment, comme ils datent tout deux d'avant SchoolRush, il y a eu pas mal de mini-couacs à corriger pour éviter de se retrouver avec un niveau au décor psychédélique qui se termine dès qu'on casse une craie

Well, some recent development are incompatible with some old mistakes... especially bounding boxes. I remember being puzzled by what worked and what did not worked when I introduced the 'sand waves', which did require one bbox x y w h command to align the visuals with the slope ... but it really was almost blind guesses.

For some reason, the "box size" bits were ignored, and the "offset" bits were ... well, it will work better with offsets that says "pictures starts 4 pixels on the right in the 16x16 frame. Of course, fixing the size first made most of the offset wrongs until I've got new offsets computed.

Even after one more afternoon of map fixing, there are weird things happening in that school zone level, like 

  • [todo, not critical] Bilou not always hidden by front layer (e.g. hidden if you jump, but not if you're idle or walk)
  • [todo, not critical] Inkjets not moving up and down following rails

Le plus gros morceau, ça aura été de corriger le code qui permet à un simple sprite 16x16 d'être considéré comme étant plus grand ou plus petit ... une modification essentielle pour passer du furblock à la branche mais qui interférait avec les gouttes d'encres d'inkjet et les vagues de sable ...
Alors, voilà: un joli bouton vert vers une nouvelle démo à essayer chez vous. Bien sûr, ça reste très en chantier et vous trouverez pleins de trucs pas au point, mais au moins, les horreurs ont été éliminées. Rendez-vous en Décembre avec une démo incorporant BangBash ?

Ah, and it's not in the school zone, but [done] that ugly pink background showing up in the green2 level, too... I'd rather have that fixed before uploading a new demo...

edit: There we are: 2 work-in-progress levels can be found if you explore the three rooms properly. There is still much to do, but also much to explore if you've never launched anything earlier than School Rush.

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

Friday, March 17, 2023

Conveyed ...

It's not a surprise (or it shouldn't) if there are waterfalls and sandfalls in the Three-rooms demo. And especially, if there is ground between two of them. I want my game engine to be able to 'push' you when you're on some ground, like it would if the ground was actually a conveyer belt. And it's been a few years now that using sand/water falls for that integrates better than mere mechanical belts in most levels. 

I have notes in my notebook for quite some times, too, about how the game script should indicate what those blocks do. They're not quite "special blocks" (that interact with collision code), but rather "physical types" that could be polled by frame-per-frame controllers.

I'm not completely satisfied with the proposed syntax, though. I'd rather use type %d {...} and is %s "%x" for level editor identification (like for block %d {} describing interactive special blocks), and I'd use props %x, like we already have for special blocks.

The truly innovative part is %s.%s = ... pattern to setup variables into controller factories. That one will be a bit more complex to get running, because the map of factories is actually managed directly by the GobState class, and I'd rather not re-inforce the Using... anti-pattern here.


Tuesday, September 28, 2021

just another breakpoint in the wall

Since last week, I've been tweaking the state machine of my meka-tester trying to make it better mimmic the behaviour of Bilou when it gets into the walls. I finally get the kind of error I wanted, but it makes little sense.

. . .  Well, I initially wanted to tell you about how it suddenly hops into the wall, 4 pixels further than it was without ever seeing the 'building up' delayed move explain anything of that. but I feel so tired. s/4f.f, S/ffe6.0 ... I'd have to dig up my notebook (page 14) to decode what that means. I just can't. my eyes don't want to look at the screen anymore. See you later.

Pendant près de deux semaines, j'ai fait des essais et des ajustements pour avoir un meka-apple qui reproduise les bugs et-vlan-me-n'là-dans-l'mur que je rencontre systématiquement dès que j'essaie de jouer dans le nouveau niveau de mon fiston. J'ai fini par y parvenir, mais on ne peut pas dire que ça m'aide à comprendre ce qui se passe. Une téléportation de 4 pixels d'un coup, alors que tout semblait aller bien jusque là...

Un peu de repos, un peu d'astuce, et j'ai des pistes pour améliorer la situation. Mais alors que je refais un essai dans "Dreams.nds", je me rends compte que le problème est toujours là. Et il est très facile à reproduire manette en main sur ce niveau, en plus. Est-ce que j'ai tenté de faire du unit-testing trop tôt ?

<later> over the week, I managed to identify some issues and possibly fix some, but it is still possible (and actually easy) to trigger. 

It makes me feel like I tried to unit-test the issue too early. Maybe what I actually need is a way to get a bunch of data out of the emulator, and monitor them when I'm done reproducing the issue.

Let's see what we would need ...

Je change d'approche, du coup : il existe dans l'organisation de mes jeux une classe indépendante du Game Engine, mais qui a accès aux objets du Game Script et qui peut exécuter une méthode à chaque frame, le HUD. Si je fais tourner mon niveau dans un émulateur avec débuggeur, et si je rajoute un break pointau cas où Bilou serait arrivé dans un mur, je devrais pouvoir creuser le problème.

  • [done] access game object position and variables.
  • [done] record them, e.g. in the GameObjectState structure defined in unit-tests
  • [done] check whether game object got into a wall (cando(0,0, PLAYER_THRU)
  • [done] switch to 'investigation' mode when we're in a wall
  • track state changes and controllers reports (through a custom inspector)

edit:A class deriving from iHud met all the criterion above. If I'm okay with using ddd to inspect the content of the last GameObjectState array, I can start investigating ...

Sauf que ça n'a pas été si simple. Même en ré-important le code des tests qui enregistre les mouvements des dernières seconde de jeu, l'information restait trop sommaire pour pouvoir retracer pas à pas ce qui ne "marchait" pas au cœur de la fonction do-slopes.
Mais Murad-dib m'a sauvé la mise  (oui, depuis qu'on est allé voir Dune avec les collègues, je me suis replongé dans le bouquin.) Et si comme lui je balayais de la main toutes les règles et les conventions (du c++, ici, pas du C.H.O.M.)... si je prenais avant chaque appel à bilan.PlaY Une copie de la mémoire contenant l'objet 'Bilou' ... je pourrais en cas de mur réappeler 'play' sur la copie ! le moteur de jeu est ainsi fait qu'il n'y verrait que du feu, et je pourrais faire mon débugging pas à pas en étant sûr que je suis dans un cas où le bug va se manifester

It wasn't quite sufficient, unfortunately. Hopefully, I was reading Dune again, and going through the moment when Muad'Dib decides to break all the rules so he could get victory, I realised that I could go for Muad'dibugging too: create an empty GameObject in addition to the real one for Bilou, and memcpy a snapshot of the current state before every 'play()' call. If we turn out to end up in a wall, I could just call 'play()' on the copied state to reproduce step-by-step what the first one had encountered.

Of course, that goes against all established rules about how to deal with C++ instances, and make the 'NOCOPY(GameObject);' macro look like a fool. But it worked.

And at last, on 2021-10-13, 22:**, I think I nailed that stuck-in-the-wall bug that had been since my kid drew his pyramid level.
 

Monday, March 29, 2021

3 rooms milestone.

My next first milestone for Bilou Dreamland will be to create a .nds where you can use doors to visit the 3 available environments. Ideally, each of the "room" (need not to be single-screen, but should stay simple) would feature the key gameplay mechanics I want to work on / repair before I go for more complete level designs. Sandboxes, in a sense.

On dirait bien que mes éditeurs sont maintenant prêts pour le travail sur Bilou's Dreamland. Support des nouveaux types de collisions et de pentes, support du choix de palette sur les deux plans. Et les spritesheets/tilesheets ont été nettoyées et prêtes à l'emploi aussi.

Il me faut donc un prochain objectif, et ce sera les trois portes salles. Une pour chaque environnement, pas trop grande, mais assez pour qu'on puisse y placer les différents éléments de gameplay critiques pour le jeu comme les cascades, l'eau qui change de niveau, le sable qui glisse, les portes, les plate-forme crocos, les branches qui plient, etc.

(Eh, CJ, ça fait penser à tes niveaux-téléporteurs du jeu d'origine, ça, non?)

Tuesday, March 16, 2021

Oops! I did it again!

Novembre 2020. J'ai voulu pouvoir ouvrir n'importe quel .spr dans mon Sprite Editor et j'ai rajouté un discret petit "dir" qui ouvre OtherFileWindow. Oui, parce que jusque là, c'était toujours A pour spriteA.spr, B pour spriteB.spr et ainsi de suite jusqu'Y. 

Sauf que quand j'ai voulu essayer de re-sauver ça n'avait pas marché. Pas de quoi fouetter un chat, mais j'ai moins ri quand je me suis rendu compte l'éditeur de niveau ne marchait plus. J'ai tenté un patch, j'ai voulu l'uploader dans runMe, mais runMe ne savait plus rien uploader non plus...

For over 15 years (!), Sprite Editor for DS has been satisfying to use with only 4 files directly accessible. It no longer is, with Furries experiments, demo projects and dreamland target that will use 4 different environment plus bilou.spr.

Hopefully, back in November, I added a new window in SEDS that let you pick a .spr when tapping the (poorly named) "dir." button.

There's unfortunately an unforeseen interference between SpriteSet::SaveBack() and OtherFileWindow::event(). One expects that the string you passed to SpriteSet::Load() megacycles ago is constant and hasn't changed. The other needs to drop the 'file' part of the path so that you can pick another file later on and not end up with fat:/moving/bilou.spr/desert.spr/green.spr ...

The unfortunate consequence of all this comes as SaveBack tries to make a .bakup of your .spriteset ... the name is now just the directory's name and thus the directory is renamed. None of my tools are ready to face that. Do you think future self-as-a-user will take notice of past-self-as-coder warnings written in the comments part of commit logs ?

Heureusement, je n'avais pas bousillé toute ma carte mémoire, mais par contre, au moment de faire la sauvegarde, mon "fat:/moving/oldies.spr" était redevenu "fat:/moving/", prêt à traiter un nouveau fichier et en faire un chemin d'accès. Et le code qui crée le fichier .bak à partir du .spr est ... disons ... vieux et innocent. Il à renommé fat:/moving/ en fat:/movibak qu'aucun de mes outils ne reconnait.

Et bien sûr, ça m'est re-arrivé hier en voulant changer quelque-chose dans mon bilouchk.spr ... Donc cette fois j'ai sorti mon callepin et le code-sur-boox

  • [done] fix SpriteSet so that it uses a std::string rather than const char* to remember the filename to save
  • [done] make sure SpriteSet::SaveBack() checks there is a .spr at the end of the file name
  • [done] add a check window in runMe that triggers when there is no /moving/ folder and offers to create one or to restore /movibak as /moving (if exists)
  • [done] also browse for files in AnimEDS

Thursday, February 25, 2021

spr.more et sprdo

J'avais prévu de commencer par "Bon, ça commence à prendre forme", mais le temps que me mette à blogger, j'ai presque fini. L'idée est donc de montrer qu'il est possible de charger les sprites d'un jeu GEDS en deux fois, avec un morceau pour le personnage principal et un morceau pour les monstres, par exemple, histoire de pouvoir avoir des monstres liés à l'environnement traversé par notre personnage (comme dans quasiment tous les jeux assez longs).

Si je dis "les monstres" et pas "les blocs", c'est que dans leur cas, le fichier .spr contient aussi les animations, et que ces animations font directement référence à des numéros de page. Charger en deux fois, ça voudra donc aussi dire modifier à la volée les animations pour s'adapter aux nouveaux numéros de pages. C'est codé, mais pour le tester, il me faut des fichiers à fusionner. Or jusqu'ici, je n'ai pas énormément de fichiers .spr avec des animations. J'ai l'école, le personnage-easter-egg de la présentation de AnimEDS, peut-être un 'papa Noël' quelque part (mais où?) et peut-être un badman (mais où??).

Bref, j'ai fini par me dire que le plus direct, c'était sans doute de couper bilou+école.spr en deux fichiers bilou.spr et école.spr pour montrer qu'on pouvait les recombiner ensuite. Pour ça, ça m'a semblé utile de revenir sur un de mes outils de hacking de fichiers .spr: sprdo. Il s'agit d'un programme linux tournant en ligne de commande et qui utilise le même modèle de manipulation des .spr que le Sprite Editor lui-même. (mon collègue parlerait-il de code métier?). 

Un argument Lfilename.spr, et voici un fichier chargé. Un deuxième argument pk6, et on fait comme si on effaçait la page n°6. un p? et on voit des informations sur chaque page présente dans le fichier en mémoire. C'est un peu primitif, mais ça fait l'affaire.

Il fallait donc y ajouter une commande "montrer l'animation unetelle" puis faire en sorte que "supprimer la page unetelle" supprime aussi automatiquement les animations qui y font référence.

ça n'a pas été sans mal, mais j'y suis presque (reste à "nettoyer" les fichiers .spr de tous ces sprites qui n'ont plus de raison d'être, histoire de ne pas dépasser les 64K au moment de fusionner les deux. (normalement, j'ai déjà du code pour ça)

edit: on y était presque. Inkjet et les power-ups se sont chargés correctement. une partie de Bilou.cmd ausi, puis on arrive à une animation située sur la "deuxième page" d'animations avec Bilou (0311) et là bardaf: il n'y a plus personne. En compactant le spriteset les doigts dans le nez, sprdo m'a visiblement perdu certaines animations (la plus haute étant la n° 107 alors qu'il faudrait que j'aille jusqu'à la 129)

  • [done] use the right anim (the one using the right page) for the waves
  • [done] apply waves animation from the proper page (that also fix blinking of Bilou's limbs)
  • [done] pendat and blador use proper shared limbs page
  • [done] understand why the heal pick-up is gone
  • [done] proper animation when we pick up a bonus
  • [done] proper animation when we bounce on an eraser.



Wednesday, October 09, 2019

[done] remove import statement

Bion. Voilà une chose de presque faite. On pourra donc faire le nettoyage des commandes "import" (définissant les ennemis, etc) directement à partir de LEDS. De quoi permettre un peu plus facilement de passer d'un type de niveau à un autre en mode 'gamedev nomade'.

Je suis encore loin d'un outil qui soit "game-jam friendly": c'est pas avec SEDS+LEDS que vous allez remporter la Ludum Dare (mais si vous y arrivez, postez-moi le lien vers votre jeu, hein ^_^), même comme ça. Et avant de mettre ça sur ma DS, je devrai au minimum prévoir un message du type "êtes-vous sûr" ([done]), parce qu'en revanche, je n'ai encore rien pour permettre de rajouter des blocs définissant les machines d'états (ou autres) dans LEDS ^^"

---

Ah. Vous êtes toujours là ... je vous dois peut-être bien des excuses, du coup. C'est vraiment du micro-posting, je le reconnais. Le fait que j'aie commencé à parler de la feature il y a deux mois ne rends pas ceci beaucoup plus intéressant. C'était du micro-coding, aussi. Je dois m'y faire. Euh, bon, c'est vrai: je joue beaucoup à la switch ces derniers temps. Et j'ai repris une série de bouquins (Hyperion / Endymion) que j'adore depuis près de 20 ans, vu que ma collègue-et-les-méthodes-de-la-rationalité ne les avaient pas encore lus...

Sunday, November 18, 2018

Finishing School Rush ...

Bon, après une série de pépins sur la voiture, c'est visiblement à la maison d'y aller avec ses revendications d'entretiens. Le lave-vaisselle, l'aspirateur, même le porte-manteaux. On se croirait dans l'intro d'une video de la développeuse du dimanche!
Avec tout ça, j'ai un peu du mal à me souvenir en fin de journée si j'ai des choses en attente pour finir school Rush ou non. Donc, retour de la todo-list.

  • [done] provide a TypeName widget that do not require users training
  • [done] only let the players enter their name when they beat some high score.
  • [unneeded, but done anyway] sleepy eraser
  • [done] preload "forever heroes" with SD card file
  • [done] do something useful with the pointing hand.
  • [done] Save new scores [on demand].
These are the things that are still pending to get the final build of School Rush, iirc. I've started converting some 'todo' items into 'newfeatures' (to be addressed out of the 'finish that game' track) because the 'todo' tag was starting to be quite unhelpful.
on the other hand, maybe it isn't that wise to think about starting to edit code on evenings where I feel too tired to remember what are the things that still need my attention before the final School Rush release...

Friday, June 29, 2018

Grand nettoyage de printemps ?

Bon, j'ai presque fini avec la révision des "évènements" provenant des contrôleurs de comportement (juste encore un peu de cleanup). Les histoires de signe sont réglées, Bilou fait à nouveau ses pirouettes comme il faut... et oui, j'ai encore fait du débugging avec des p'tits dessins.

Le dernier sur la liste des "grands nettoyages de printemps" devrait être l'élimination de GobExpression::xcontext, et je devrais avoir quelques notes là-dedans sur mon boox.

Après ça, il sera temps de tourner la page (parce que ça devient limite trop long, comme "printemps") vers de nouvelles aventures. J'ai bien progressé dans les recherches sur l'évolution du langage de scripting. Suis-je prêt pour attaquer le "behaviour editor on DS" ?

I'm almost done with revision of the events-from-controllers effort. Bilou at last does his sommersaults when expected ... and yes, I've been drawing while debugging again (that's one of my favourite part of gamedev ^_^). Finally, I'll be able to get rid of the infamous "GobExpression::xcontext" static array. That should conclude the "spring code cleanup", so I'll be free to move on.

What next ? Script language revision research made nice progress lately ... am I ready to start "Behaviour Editor on DS" ?

Tuesday, June 26, 2018

Guru Meditation again

Bon, je me suis retrouvé après avoir fait quelques essais du nouveau système de gestion des évènements de mon moteur de jeu avec un bel écran bleu. Sur DS uniquement, évidemment. Après quelques tentatives infructueuses de régler ça en une demie-heure, j'ai fini par profiter du fait que ma fée était en réunion pour me faire une soirée "guru méditation" à l'ancienne.

Papier quadrillé, désassemblage des fonctions impliquées (au moins, la position dans le programme était correcte), déduction de quel registre contient quelle variable (pour pouvoir exploiter le contenu de l'écran bleu) et structure physique des différents objets impliqués à grand coup de ddd en comparant le contenu "brut" de la mémoire et des affichages haut-niveau.

Vu que le crash se produit à cause d'un accès à la mémoire via quelque-chose qui n'a rien à voir avec un pointeur, j'étais prêt à rajouter des "nombres magiques" ça et là pour pouvoir reconnaître une transition, un état, une expression, etc. Mais en réalité, je n'ai besoin de rien de tout cela. Tous mes objets critiques ont au moins une méthode virtuelle, ce qui signifie que je peux utiliser la référence vers la vtable pour déterminer directement si une zone de mémoire donnée contient toujours un objet d'un type donné ou si elle a été écrasée.

A partir de là, c'est de la navigation dans la mémoire de la DS en suivant les pointeurs retrouvés sur l'écran bleu pour reconstruire l'état des objets impliqués dans le crash. Et au terme de tout ce sudoku-géant je finis par trouver deux indices troublant:
- l'adresse d'une des transitions à tester en cas d'évènement est un anagramme de l'adresse qui a causé le crash
- l'adresse de la liste de transitions correspondante n'est pas multiple de 4 alors que toutes les adresses ont une taille de 4 (bytes, mon cher Wattson).

L'émulateur voyant cet accès étrange aura "redresser" l'adresse, ignorant les bits les plus faibles. Parce que, oui, la machine sait que je veux prendre 32 bits quand-même. Le CPU de la DS, lui ... eh bien, il m'a sorti une variante mélangée des 32-bits se trouvant à l'adresse utilisée par l'émulateur. Les 8 bits "les plus à droite" de la valeur en mémoire se sont retrouvés à gauche pendant que tous les autres étaient décalés vers la droite.

Friday, June 22, 2018

deep blue InfiniMap

CommonMap revision changed the lookAt/scrollTo interface of background layers to take unsigned positions. After all, it shouldn't be possible to set the center of the screen into negative coordinates when the top-most corner is (0,0).

But I will need to keep internal computation of signed integers anyway. else I get blue meditation screens...

The core of the problem is that processors have two main way to understand numbers: one where the top bit of the number has no special meaning (we call them 'unsigned' numbers and they're all positive), and one where it tells whether the number is positive or negative (with some tweaks, and we call them 'signed' numbers). And among the operations the CPU can perform on number one behaves very differently on signed and unsigned numbers: division. Divide an unsigned number by two, and you'll always have to insert a zero in the top bit. Divide a signed number by two and the top bit remains sticky.

If you mess with the numbers signedness (issue unsigned operations when you should have used signed operations) and you may easily turn a small, negative number into a big, positive number during a division. That's what I did with my update ... this is what I have to fix now... hmm... tomorrow. It's time I give my eyes and brain some rest.

Sunday, June 10, 2018

simplifying events engine

I want to get rid of some static pointers in the management of events. The idea turned cleaner as I was flying over Denmark. But the result isn't convincing yet.
- you can't jump out of inkjets anymore (event from dpad controller is ignored - apparently because TrackAttached produced an event too -- although it has no corresponding transitions)
- you might get pushed away from spongebops when you try to grab them -- weird things still occur here with my best solution for inkjets.
- if Bilou starts swimming up, he'll keep swimming up forever -- that's fixed with swapped-priorities
- the little stars shining around you when you pick a health bonus keep shining forever. -- seems fixed with swapped-priorities too.

The thing is, when I want to combine the "thoughts" of two controllers, only one events list can survive. And of course, things don't get fixed if I swap the order in which they are produced (unless I swap them properly, that is). Weird things remains with that swapped-priorities, though. Like why don't we play the 'roll-in-the-air' animation anymore when Bilou's direction is changed while jumping ? I'll have to re-activate InspectorWidget and use the combined powers of InspectorWidgets and DDD to find out.

By the way, did you know that we could have methods, operators overloading and constructors for unions ?

Friday, June 08, 2018

GameObject::useEvent() should go away.

https://sourceforge.net/p/dsgametools/hg/ci/refactory-engine/tree/libgeds/include/GameObject.h#l175
That shouldn't happen. The way controllers fire an event is not satisfying. A static pointer set by class X so that it is used by class Y with no restriction on who does what and that merely works because we know X calling ::useEvent() and Y checking *::doevents happens to take place with the right timing ? No.

I mean, look at the documentation: "assumes no re-entrance until gobRunController". That has turned false the minute I introduced 'attach-to-other-game-object' feature where you might have to run the object you're attached to before you can run yourself.

I'd like to convert {NONE, FAIL, EVENT}  enum into something else that allow "EVENT" to carry the list of transitions to check by itself.

Wednesday, December 27, 2017

[done] fargrounds

Eh bien, ça en aura fait des rebondissements pour débloquer le "super décor du dernier niveau"! Mais on y est. Du coup, les derniers éléments sur la "todo list" de School Rush, je vais les rassembler ici façon "bullet journal"

  • [done] la séquence de fin pour de vrai
  • [cancelled] le niveau bonus
  • le mécanisme pour se rendre dans le niveau bonus
  • une éponge qui monte-et-descend à la surface de l'encre, svp ?
  • [done] un affichage du nombre de vie (intégré aux images de chargement ?) 
At last, I have proper background graphics for my final secret level. The time is right to review the to do items, close some and bring here what will have to be done to get the game completed, bullet-journal style (as I don't have phabricator-for-sourceforge).
None of the things that are still on the todo list for School Rush could really be completed by the end of the year. But none is blocking a release either. I think we can call the vertical level .done. That took almost half the year, but I think it worked. Enjoy your season holidays.



Rien de tout ça ne semble faisable en quelques jours de super-papa-bros, donc on va emballer ce que j'ai pour boucler 2017 et prendre le temps de faire le reste correctement en 2018. Bonnes vacances.

Ce niveau vertical aura occupé une grosse partie de l'année donc, du mois d'Avril à la fin décembre, mais au moins il est testé et validé. Il reste sans doute un peu mystérieux à la lecture de ces lignes ... forcément, c'est quand-même un niveau secret ;-)

    Thursday, December 21, 2017

    Refactored, but freezing

    ok donc, j'ai eu du code qui compilait en un rien de temps, malgré un refactoring plutôt osé. Par contre, plus moyen d'atteindre la fin du premier niveau: le jeu freeze, à peu près tout le temps au même endroit, juste avant de m'afficher les premiers "inkjet" mobiles.

    Good joke! How useful is it to get refactored code compiling if you cannot reach the exit of level 1 anymore? The game now freezes every time roughly at the same spot, just before the first moving inkjets. I will need my mercurial time machine...

    Je prends donc ma machine à remonter le temps (comprenez mercurial) ... le bug semble aussi se produire avant la refactorisation ... j'évite donc de passer pour un clown qui fait des effets d'annonce sur son flux twitter, mais je n'ai quand même pas du code qui marche. J'ai noté que A. avait réussi à rejouer aux premiers niveaux après avoir fini le niveau vertical, donc il existe un point pas trop éloigné dans l'espace-temps où j'ai du code qui n'a pas ce problème.

    "Good" news is that the bug wasn't introduced by the refactory -- at least, my twitter-honor is safe. But honor does not make code run. I know that A/S-team could beat levels 1 and 2 during the last playtesting session, so the bug must have been introduced fairly recently. If I could find the last working commit, that would help understanding what went wrong and how to fix it.

    Reste à le trouver pour comprendre ce qui cloche. Pour ça, j'ai maintenant mon programme automatique de "unit-testing" qui simule un va-et-vient dans les niveaux.
    Et le programme de test en question crashe, lui. Un beau gros "segmentation fault", dû à un débordement de pile. Et la fonction "backtrace" capable de m'indiquer où s'est planté le programme et comment on en est arrivé là prend un plombe à s'exécuter (en fait, j'ai intérêt à l'interrompre):
    • CompoundGob::collide(#288)
    • BlockArea::collision(#1934)
    • InfiniMap::getflags(#350)
    • GameObject::cando(#1786)
    • CompoundGob::loadAnim(#178)
    • CompoundGob::setstate(#52)
    • CompoundGob::collide(#288)
    • BlockArea::collision(#1934)

    Hopefully, I now have an automated test that moves back and forth through the levels. And that test program crashes (big segmentation fault) when running one failing build. The backtrace function of my debugger takes ages to point out where the crash occurs (and how the program reached that state). When I interrupt it, I see no memory reference on the "call" instruction. All registers have valid values, no invalid opcode to be spotted around. The only suspicious thing is the fact that there seems to be a repetitive pattern in the function calls.
    Then I checked the value of the stack pointer and Captain Obvious knocked on my head.


    Oui, vous avez bien vu: on tourne en rond. Et le code fautif serait apparu pendant que j'essayais de corriger le problème des personnages qui jouent à Philadelphia Expérimental avec le plafond.

    Mais comme j'ai une release à assurer demain au boulot, je vais pas la faire trop longue. On sait où chercher. On cherchera pendant les congés entre les paquets de Noël et les cotillons ;-)

    This is a stack Overflow, caused by something in the new code that enforces alignments when resizing bounding boxes. It is obvious because the stack pointer has the lowest allowed value, given the area allocated as stack according to /proc/self/maps. It is too late to start searching what and why, but at least I know what to look for and roughly where.

    edit: trouvé en 20 minutes de "cybook" pendant que *deline travaillait sa danse. Corrigé en à peine davantage. On va pouvoir reprendre le travail sur les plans de scrolling ;-)

    got it located while *deline was having her dancing lessons, fixed in about half an hour. I thought it would take me at least a week-end. Good. I'll be able to go on with the rest (todo: figure out what still has to be done)

    Sunday, December 03, 2017

    Far ground

    Je tente d'intégrer mes bouquins-totems comme décor de fond du niveau vertical ... après quelques essais/erreurs pour faire le bon montage, qui ne consomme pas trop de mémoire vidéo, quelques corrections pour que le moteur de jeu puisse utiliser effectivement les 256KB dont il dispose plutôt que de s'auto-brider à 128K, je commence à avoir quelque chose... Enfin presque. L'état du code pour la gestion du décor en parallaxe n'est franchement pas terrible

    I'm trying to integrate the tiki-books as the background of the secret vertical level. it took a few trials to get something that fits in the renaining video memory, which is much easier after I grant access to the full 256KB allocated. well, sort of ... Unfortunately, the code for parallax scrolling is carrying lots of legacy, hard-coded settings suited for 512x256 -picture, while this new level needs it the other way round. The wale also picks camera coordinates directly, leading to a. weird offset on screen.

    • le code qui effectue le chargement de l'image ne supportait que la taille de 512x256 pixels alors que je veux maintenant utiliser le système en 256x512.
    • le code de scrolling utilise directement les coordonnées de la "caméra" en les divisant par deux, de sorte qu'il me décale le décor de 64 pixels sur la droite
    • on dirait que seul un des deux "écrans" est utilisé, en boucle, plutôt que d'avoir un décor deux fois plus haut que large ... à l'exception de certains endroits où le décors est sans dessus dessous.
    Il va y avoir un peu de travail pour corriger tout ça.
    plus, l have only half the picture showing up, rather than two sets stacked onto each other. And at some place, the scenery is completely messed up. it will take some work to get all that fixed. Maybe if I hack some forced, auto-scrolling, the defects will become clearer.

    edit: je devrais essayer de mettre un auto-scrolleur sur le plan de décor, tiens... ça simplifierait les tests.
    edit2: en effet, ça simplifie.
    • [done] le coup des décors sans dessus-dessous vient probablement du fait que je ne chargeait que la moitié de ma map (eh oui, il faut 2 bytes par pavé, pas un seul)
    • [done] par contre il y a clairement quelque-chose qui annule l'effet du réglage "32x64" (l'ordre d'appel des fonctions, en fait). 
    • [done] Et pourquoi ai-je un VBL handler appelé deux fois, pour deux maps différentes, et qui modifient les registres des deux plans ? 

    Monday, November 27, 2017

    MMU9 write32 to undefined register 04001058h

    While working on a solution to get-into-walls bug, I had a ugly alignment bug to fix. I have many debugging tool, but none was really helpful (once again), partly due to my lovely HUD that now takes the bottom of the screen...

    InspectorWidget est en vacances,
    iprintf en arrêt maladie,
    ddd fait la grève du code optimisé,
    Qui reste-t'il pour sauver la journée ?
    Qui, sinon 0xbadb07 !

    Ouaip, y'a une adresse-mémoire qui provoque un message sur le terminal quand l'émulateur la rencontre, avec la valeur posant problème, et même l'emplacement dans le programme. Alors j'ai rajouté comme un malpropre des accès direct à cette adresse pour envoyer un diagnostic d'erreur à travers le subespace de l'émulateur.
    Du coup, je peux corriger mon code. Ciao.

    And then i've seen that error message from desmume while launching the system: something in the boot code tries to write at some place where NDS documentation doesn't claim any register. A non-fatal condition. But that means I have a way to export a series of values as the program is running. Crude debugging, non-portable and likely to be broken at the next desmume update, but debugging nonetheless.

    The fix is thus made. I can commit and go to the bathroom ^_^

    Saturday, November 18, 2017

    power-button bug

    On the game design axis, I am quite satisfied with the final level of school Rush and how it integrates with the earlier levels. It took A. (from the S-Team) Some 30 attempts to beat it, but she hasn't turned mad or bored, and even enjoyed being wrapped to level 1 afterwards.

    On the technical side, my latest personal tests hit me with a bug I thought I fixed long time ago: getting stuck in a ceiling, There are few places where this can happen in the game, but if it happens, you will remain stuck, possibly forever unless you use the power button to trash all your progress and reboot. Would a player feel like starting the game again in such conditions? I don't think so.
     
    The thing is, the basis pretty hard to track, a bit tedious to reproduce and all my attempts to fix it have failed ... so far.

    What I truly need is a tool that will allow me to identify the sequence of state transitions that led to the offending state when I finally manage to reproduce it. Another debugging tool that would complement Inspector widget for cases that cannot be solved by single-stepping on setting breakpoints.

    edit: let's stop rambling, let's start cracking ...

    Bug is tedious to reproduce

    Then let's make it easier to reproduce. Let's have e.g. a build of the game with much more lives, more hitpoints if needed, that drop you in a place where it is easy to try reproducing the bug. Let's go to that level with the DS, too, and try to get into the wall in as many ways as possible (runMe is neat for that because it let me launch any level), to get a better understanding of the conditions that make it happen.

    Moreover, we're running on an emulator, here. And emulator typically have a free save-state mechanism. I'm unsure whether it works flawlessly with desmume, but it's worth giving it a try.


    Bug is hard to track

    Then let's make our best to get as much information as we can from a succesful run.

    Granted, the ideal would be to have a curve plotted, annotated with state changes, in readable colors and where I could get any set of gob variable at any time by just pointing at a spot on the curve. But we don't have that. Granted, last time I had to use both ddd breakpoints and Inspector widget, but that doesn't mean I cannot do better this time.

    So the ideal would be a time machine that let me replay things if I ever manage to produce the bug, and view what happened in slow motion, eh ? Wait ... that tool exists already. That tool is ... recording game + Inspector widget as an animation and replaying it!


    Bug couldn't be fixed so far.

    I thought I knew what happened by looking at the code that makes Verso bounce, because I know I had to fix the problem for Verso (the bouncing eraser). And the solution was to detect the impact's vertical speed to tell ceilings apart from floors, and prevent the 'fail [assuming on the ground]' from happening when what really happened was 'fail [on the ceiling]'.

    So after I located something similar with the "HIT" state of Bilou, I thought I got rid of the problem. But since I don't have well-isolated test cases for the state machine (yet), seeing the bug again doesn't mean that the fix wasn't effective: simply that it might not be an isolated case.

    To be continued ...