Tuesday, December 12, 2017

branches, reviews and cannelloni

The idea is hanging around. It has been for some times, now. Possibly since I re-started exporting code to e-book readers through Doxygen, or since I tried to use apple assault as a tutorial to libgeds. I'd like to go for some in-depth review of my engine code. I'd like to use powers of code versioning system to slice code into readable, purpose-supported chunks, which would help the reader which components bring what feature and how they interact together.

But now, I started it. I've got a "bare minimum" DS application with corresponding library code (mine or 3rd-party), and its build system.
[done] found the source of Noda's EFs tool again.
[todo] have it built as part of the dsgametools host-tools binaries, bui


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
  • 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.

edit: je devrais essayer de mettre un auto-scrolleur sur le plan de décor, tiens... ça simplifierait les tests.
  • en effet, ça simplifie. Et 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)
  • par contre il y a clairement quelque-chose qui annule l'effet du réglage "32x64". 
  • Et pourquoi ai-je un VBL handler appelé deux fois, pour deux maps différentes, et qui modifient les registres des deux plans ? 

cando grow?

Not so easy to fix the state machine bug about Bilou entering ceiling And that is mostly because it is not in the state machine itself. It happens because Bilou has two sizes, and the "HIT" state is one where he is big. Since"HIT" is a state that you can reach from almost any other state, we can't really "fix" the problem by conditional transition.

So I took my code back and started looking around the call to CompoundGob::setbbox() for inspiration.
1. the "grow'shrink." mechanism can be nicely separated along axes. I shall try it on the vertical axis alone so far.

2. I should use cando() function to detect potential issues with virtual movements before I actually change the size. That should be much easier to have something where we check whether we could move up by dy (actually grow upwards) and align coordinates if we can't.

3 . That will work for small resizing, and .can be extended to duck/stand for.human-sized characters  with a simpe - iteration. I haven't tested that, because all shrink/grow changes in Bilou change size by a mere few pixels. And I presume it wouldn't be completely satisfying for something like granting mushrooms for Super Mario. For one thing, the code assume that it is possible to grow. It won't catch the situation where small Mario would get a mushroom in a narrow corridor of bricks.

It took quite some sketching to find the right adjustments and avoid ending up with tons of tests to find all corner cases, but instead do the right computations, taking advantage of the fact that some terms are just zero in some cases. I think I might even no longer need hints about which side we should align against, but I prefer keeping them at the moment, until I get the proof that they indeed turned useless.

Saturday, December 02, 2017

spriteram vs . Resource

Using InspectorWidget to understand buggy situations has become abnormally hard. Just look at the picture we got earlier this season. Compare that to what it used to look like. I've got the "boxes" area all messed up. Of course: in School Rush I now have two things trying to use the sprites of the bottom screen: Inspector Widget and the HUD.

I needed to change a bit the code for the HUD (which uses a SpriteRam to load hud.spr) so that it tells the GUI engine that it used some resources, which are thus no longer available to the InspectorWidget... and let the Engine give some other tiles to Inspector Widget.

One thing I had overlooked is that I devoted up to 256KB of VRAM to background tiles on the main screen, leaving only 16KB for HUD sprites. At 256 bytes per 16x16 block, that means I can have at most 64 different blocks at all. I have 20 different sprites used, 44 left.

Inspector Widget uses 1 such block for "box-borders" (with 4 different flips), and then it has 4 areas-reporting sprites (made of 64x64, 16-color sprites that get scaled up and down to match the effective area shape). That's 32 "tiles" count each for the engine, or 8 of the "blocks" I've used above. So with proper values, I can get it right.

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 ...

Friday, November 17, 2017

most vexing (gobscript) parse

My scripting language is far from perfect, but this one is really the most vexing issue I have encountered so far. I mean, it is hard to debug, counter-intuitive, and it feels more like a question block turned into a thWomp and smashed you. It gave no clue, no warning, you did nothing wrong, but still get smashed.

The core of the issue lies in how collisions are handled:

  • There is always an active "collider" and a passive "collided" object. 
  • collider area is allowed to expand to any size (within int size limits). 
  • collided area will only be checked if the object's boundary box intersected with the active area.

The third constraint comes from performances considerations. But unfortunately, it means if you create a passive area larger than the object's own size, nothing will complain, you will see boxes intersecting, bar no collision will ever occur.

I'll need to take some time to add warnings