Wednesday, December 22, 2010

So long, exec.cpp

Since August 2007 the exec.cpp file from GrizzlyAdams has been a corner stone of my activities on the Nintendo DS. It allowed me to launch NDS files from other NDS files -- a functionality that was missing of the "standard" features of libnds by then. Combined with dswifi and a small HTTP retriever, it allowed me to introduce a "self-update" feature that replaced the media card mounting/unmounting that was previously taking most of my development time. Since I mostly work on my DS project on lunch time or in the evening, it had a major impact on my ability to keep going on.
En août 2007, mes projets sur DS ont pris un grand tournant avec l'ajout d'un morceau de code de DsChannel de GrizzlyAdams, qui permettait d'enchaîner un NDS vers un autre. Combiné à un petit code HTTP, je devenais capable d'écrire des programmes se mettant à jour eux-même. Et il n'y a pas à dire, celà a nettement boosté le travail sur le Sprite Editor, le Level Editor, la lecture de modules et plus tard, le moteur de jeu à la base d'Apple Assault ...

But here we are, 3 years later, at devkitArm revision 32, with all the libraries changed. The handling of FIFO code, among other things, received a major revision, that breaks the compatibility with the custom loader. Meanwhile, too, Wintermute included a similar feature in HBMenu and made several part of the libnds dependent of its own approach. Reseting the ARM7 on request from the ARM9, for instance, is directly located in fifosystem.c, and a C++ exception will try to return to the launcher of a program. Rather than fighting against this, I decided to try and see to what extent the bare bones of "HBmenu" can be converted to support runME.

Mais voilà. Ce code utilisait le FIFO -- pratiquement inutilisé du temps du devkitArm 21 -- qui entretemps a subit une refonte importante, et Wintermute et ses accolytes ont cherché à intégrer une fonction similaire dans la libnds. L'astuce, en fait, c'est que la fonction n'est pas directement offerte aux programmes, mais intégrée dans HBmenu, qui laisse une partie de son code à un emplacement "persistant" qui (si je comprends bien) est uniquement capable de revenir au programme qui a installé ce programme persistant. Plutôt que de me battre à essayer de faire cohabiter le code de GrizzlyAdams dans le nouvel environnement, j'ai donc repris la base de HBMenu pour reconstruire runMe par-dessus. Ca marche plutôt bien, dirait-on, même si je n'ai pas encore fini le portage ... mais curieusement, ça me fait un peu chose de laisser tomber cet "exec.cpp" qui m'a soutenu tout ce temps ...

The result is encouraging, although I've got a small tear in my eye for that piece of software that I analysed and debugged to make it fully support DLDI ... Although the code from the devkitpro project shares many similarities with "my" previous approach, a larger part of the stub executes from the ARM7 (as far as I understood), meaning that it's not possible to perform debugging for it. The new code consists of
  • nds_loader_arm9.c, acting as a library and directly linked to your program (runme or HBMenu), that mainly ensure software reset of the two processors and DLDI patching of the loader
  • bootstub.bin, installed from the end of the ARM9 memory (the upper 48K of the 4MB area) by installBootStub() function in the "library" file
  • loader.bin, copied in VRAM by runNdsFile(). It contains its own (stripped-down) FAT access, the DLDI patcher.
PS: loader.bin and bootstub.bin are thus by-products of HBMenu compilation. To get them, you need to gather the latest sources from SVN, compile them (make all is enough provided that you have devkitpro installed with the appropriate libraries), and find them in the hbmenu/data directory.


cyborgjeff said...

Profond toute la ré-écriture que tu as à faire il me semble !!

sylvainulg said...

Assez oui. Mais je suppose que tu connais ça ... update de PHP, de wordpress. La compatibilité ancestrale n'est clairement pas une priorité dans le projet devkitpro, et vu que je saute près de 11 versions d'un coup :P