Showing posts with label libfat. Show all posts
Showing posts with label libfat. Show all posts

Saturday, September 29, 2012

Yellowl and Redowl

I tried again, with the updated SEDS and properly charged battery. I could save a first draft (just the shadow lines), and then when I tried to save my "finished" work, the editor crashed again. That's *really* getting on my nerves, now.
Hopefully enough, I had a real camera powered up and ready-to-shoot just one floor below, this time, so I've shot pictures of my screen and did some Gimp post-processing to try to enhance and restore the picture into something that could be shown or fixed afterwards. I started the owl again, from the 'shadow lines' that were saved, using the version of SEDS I submitted to NEOflash compo. Everything went fine, and I made tons of intermediate saves. Then I thought "oh, well, that should be it for now", and clapped the lid of the DSi. As usual, I then thought of a small last improvement I could do, so I opened the lid, applied the change and tried to save again ... stalled. So this is what goes wrong: I cannot read/write to the SD media card anymore after I put the device in "sleep mode" for a while. And that happens regardless of whether I use the "1.x" or "2.0" version of my GUI engine.

Sunday, September 16, 2012

Linker de Bisounours pour DaySi

Yes! ça y est! Grâce au matos gracieusement donné par ZeBlackOS -- à savoir un linker de bisounours iplayer -- je peux enfin faire tourner mes homebrews sur la DSi rachetée à Mr. Proper l'an dernier! Vu qu'elle avait même un chargeur de poche pour brancher sur port USB, ç'aurait vraiment été dommage de la cantoner à faire tourner Zuma Revenge pour ma fée :P

Il pourra se vanter de m'avoir fait suer, note, au point que j'ai fini par craindre de l'avoir mis hors-circuit au moment de lui faire son "upgrade kernel" ... mais non. C'était tout simplement un problème de formattage. Si les gars de SuperCard insistent sur le fait que la carte microSD soit formattée avec leur outil dédié sous Windows, ils ont en fait une bonne raison: la mémoire de la DS étant limitée, il faut que la table d'allocation puisse tenir dedans.

If you just found an iPlayer, but that it seems to stall after showing a blue logo screen but without going to the screen that says "DS Video Expert", chances are that you overlooked the vendors' recommendation for using their own formatting tool for your media microSD card. Granted, that sounds plain ridiculous. Every OS (decent or not) comes with a FAT formatting tool, and you shouldn't have to install third party to do that, and certainly not on a Microsoft OS!.

Still, as the DS has limited memory, and given that using their formatting tool *did* unleash the linker's full potential, I can imagine the following scenario: the FAT driver of the linker's firmware is so crude that it *needs* to fit the whole FAT within 1Mo of RAM. A conventional formatting tool will instead try to come with settings that minimizes cluster size, so that you're doing the most of your filesystem... and dismiss FAT size as a significant issue.


En l'occurence, ici, la carte de 8Go a été formattée avec des clusters de 32Ko (ce qui est modérément large, mais large quand-même), de sorte que la FAT soit juste un rien plus petite que 1Mo ...
(Bien sûr ça pourrait être un autre détail: taille du répertoire racine, le nombre de clusters réservés ...)

En toute logique, j'aurais pu obtenir l'effet souhaité sous Linux avec mkdosfs -s 64 -F 32 -f 2 -h 8192 ... Mais pour une autre taille de carte SD, il faut ajuster le paramètre -s en conséquence (#Go*8, je dirais).

Here's the result of a filesystem analysis after supercard's tool "correctly" formatted my 8GB media card for iPlayer:

SchoolTest> sudo dosfsck -n -v /dev/mmcblk0p1
Boot sector contents:
System ID "        "
Media byte 0xf8 (hard disk)
   512 bytes per logical sector
 32768 bytes per cluster
  4404 reserved sectors
First FAT starts at byte 2254848 (sector 4404)
     2 FATs, 32 bit entries
969728 bytes per FAT (= 1894 sectors)
Root directory start at cluster 2 (arbitrary size)
Data area starts at byte 4194304 (sector 8192)
242304 data clusters (7939817472 bytes)
  8192 hidden sectors
15515648 sectors total
dosfsck /tmp/disk.img
Boot sector contents:
System ID "mkdosfs"
Media byte 0xf8 (hard disk)
     512 bytes per logical sector
    4096 bytes per cluster
      32 reserved sectors
First FAT starts at byte 16384 (sector 32)
       2 FATs, 32 bit entries
 3992576 bytes per FAT (= 7798 sectors)
Root directory start at cluster 2 (arbitrary size)
Data area starts at byte 8001536 (sector 15628)
  998046 data clusters (4087996416 bytes)
       0 hidden sectors
 8000000 sectors total
8GB formatted with special tool4GB formatted with mkdosfs under Ubuntu

Pourquoi "de bisounours" ? Eh bien, parce que ce linker permet de faire tourner les jeux amateurs (dits "homebrew"), mais refusera de lancer les ROMs commerciales. Merci, tata Raymonde. Et merci à Pierrick de m'avoir filé un coup d'EEE main, sur ce coup-là. Et bien sûr Merci à ZeBlackOs pour le linker ^_^
My last fear is gone, btw: although the linker's documentation mention directories such as MUSIC, VIDEO and HOMEBREW where we're supposed to place our files, it can still launch files that are at the root (e.g. beta versions of my tools) and that have been downloaded by runME (currently in /moving/) Mais du coup, je m'interroge: les difficultés que j'ai à faire tourner de manière fiable mes outils avec ce matériel pourraient-elles être liées à une libfat pas vraiment calibrée pour des clusters de cette taille ?

Monday, June 06, 2011

Welcome, libfat 1.0.9

While I was busy on a tons of things (including building up the first prototypes of AnimEDS) in february, Wintermute and his friends at devkitpro did a major revamp of the libfat, separating "what's good for the DS" from "what's good for the Wii". When it comes to mass storage performance, the two beasts are strongly different ... L1 cache, data transfer speeds, amount of L2 memory ... The release (1.0.7) I used in my "dkp-r32" setup tried (and failed) to provide a uniformised solution. I tried a few hacks that at some point looked to improve the performance, but didn't find the time to quantify the boost in a systemic way. I offered a patch, but ignoring the project's habbits made it doomed to /dev/null.

Hopefully, the new build seems to provide good performance again (PC->AP->DS transfer rates of 64-80KB/s at home).

Oh well, one annoying difference remain: i *have* to apply a DLDI patch manually for SCSD device (which used to have a built-in driver in former libfat). I also have an issue with directory scanning ... I hope it won't take too long to figure out what it is. it looks like I underestimated the MAX_FILENAME_LENGTH ... again ...


J'étais tellement à la bourre en février que j'ai complètement loupé la sortie de la version 1.0.9 de la libfat. Heureusement que je suis repassé jeter un oeil sur le forum de devkitpro après avoir tenté de refaire le point sur l'état du cache la semaine dernière, sinon j'aurais bêtement perdu plein de temps. Enfin, donc, une version qui traite la DS indépendamment de la Wii et de la gamecube, même si j'ai du ruser pour contourner les problèmes de __io_dsisd manquant et patchouiller mes programme pour m'ajuster à une augmentation de MAX_FILENAME_LENGTH visant à améliorer le support d'UTF8. Enfin, c'est réglé.

Une vitesse de transfer entre 64 et 80kB/s (@home en utilisant le wifi entre le PC et le routeur et entre le routeur et la DS), c'est tout ce que je demandais.

Bon, maintenant, 'faudra que je regarde comment faire en sorte que ma fonction die() marche à nouveau ...

(PS: oui, j'ai testé tout ça sur la PHAT de ma fée, histoire de limiter la casse et les pertes de données au cas où... honte à moi ^^" ... quoi que, avec le binaire de SEDS qui crèe systématiquement des fichiers de taille 0 datant de janvier 1979 ...)

Tuesday, May 31, 2011

Et ... qu'est-ce qu'on fait maintenant ?

Bion première release de AnimEDS: check, mise à jour de SEDS : check. Quoi d'autre ?

En premier, une petite uniformisation de mon environnement de compilation ne serait peut-être pas une mauvaise idée. J'avais identifié un problème de performances dans la libfat pendant les congés de Noël ... ça pourrait valoir la peine de revenir dessus histoire de soumettre un "vrai" patch pour le projet devkitpro. Pour l'instant:
- démarrer SEDSgama.nds depuis le menu R4 et faire un "QUIT" vers rungama.nds: ok
- mise à jour interne de SEDSgama et rungama: ok, mais lent (compilé sur beetle)
- démarrer SEDSgama depuis runbeta: ok, mais empèche d'utiliser le loader pour sortir de SEDSgama.

Ensuite, on pourra voir pour les histoires d'effets miroir dans AnimEDS, la définition d'autres structures de sprites (changer le nombre de membres et l'utilisation des pages de sprites) et le support de tout ça dans le moteur de jeu (eh oui, l'idée, ça reste de faire des jeux).

Friday, December 31, 2010

libFAT : hide and fseek ...

Well, initially I thought that the performance issue of TCP transfers would be worth another investigation-novel-styled post, but being somewhere between Christmas and New Year's Eve didn't allowed me to do so. Or maybe just digesting the source code of libfat, figuring out what kind of access pattern made it so slow and what more subtle access pattern was making my new cache policy go wrong was already demanding enough.

The patch is not ready for inclusion in libfat according to devkitpro's standards. Yet, having a look at it is the only way for you to have an idea of what can be changed to fix the performance issue.

The core idea of this patch is to allow pages in the cache to reflect only partially what is (should be) on disk. The new readable field gives the position in the page where we leave 'valid' data and enter uncharted, here-be-dragons, area which content shouldn't be relied upon. I proceeded with additional extensive checks (64M movies transfers, md5 checksum verification and fsck on the media card) and fixed one last bug affecting end of files. The patch released on Tuesday is thus invalidated.

Remember, kids: FAT is the worst filesystem ever.

Oh, and btw, server.pl, the PC-side data source for a PC-to-DS wifi transfer can now be invoked so that it will cycle within a list of files, allowing one to efficitently transfer the files one after the other, e.g. :

server.pl neoflash/*.nds [DS_IP_ADDR [PC_IP_ADDR]]

Tuesday, December 28, 2010

libFAT cache-cache

Après avoir instrumenté un brin le gestionnaire de cache de la libFAT, j'ai droit à une belle série de statistiques qui montrent que pour réécrire ~400K sur ma carte mémoire, il me faut au préalable lire à peu près autant (968 secteurs) ... En fait, puisque j'écris chaque paquet (~550 bytes) au fur et à mesure dans le fichier, et puisque le cache travaille par "page" de 4K, toutes les écritures sont partielles et le cache lit d'abord le contenu du disque avant de commencer à écrire la bonne valeur). Le hic, c'est bien sûr que dans mon cas, les anciennes données ne seront jamais utiles, puisque je les écraserai toutes :-P

J'essaie donc de modifier "cache.c" pour forcer une politique de "lecture paresseuse" où l'on ne remplirait une entrée du cache avec le contenu du disque que si une tentative de lecture a lieu. Il est donc possible de "préparer" progressivement un contenu à écrire et ne l'écrire qu'une fois complété. Bon, maintenant, il va falloir débugguer ça. A moi desmume, ddd et strace ...

Tout semble fonctionner sur émulateur, mais sur la DS "Phat" de ma fée, j'ai juste droit à un "FATinit failed" ... qui s'avère être dû à un petit problème de DLDI sur SuperCard SD. Après quelques hexdump et diff supplémentaires, je peux enfin vous proposer ma libfat revue et corrigée, jusqu'à 3 fois plus rapide sur les écritures de fichier.

PS: il restait un bug, donc voyez le post du 31 pour la version définitive.

Sunday, December 26, 2010

Speed Limit: 32

Now, that's fairly annoying. It looks like the TCP WiFi transfers with the "devkitpro r32" is roughly 3 times slowlier than its r21 counterpart (in purple) for the same receiving code. That's especially annoying since it significantly increase the duration of a self-upgrade cycle during development.

The new performance (in black, as reported by wireshark) is impaired by regular "waits" of ~200ms before the PC retransmits some data. And I'm doing the test with a local server here. A larger RTT would likely reduce the performance even more. Retransmissions happen form the start, and that's fairly normal for a wireless transmission. I ran some early code comparison between the ARM9 TCP code of the two dswifi versions, but I couldn't spot any major change that could explain this behaviour.


J'ai finalement suffisament rafistolé runMe pour qu'il puisse de nouveau faire sa mise à jour automatique -- la clé de voûte de mon cycle de développement sur DS. Je pouvais déjà jouer à redémarrer sous Moonshell, puis passer dans le menu R4, utiliser le vieux runMe "21" pour télécharger le nouveau tryMe "32", retourner à Moonshell puis au menu R4 pour démarrer le programme tryMe. Pas extraordinaire. Problème: les transfers par WiFi sont devenus nettement plus lents. Jusqu'à 3x plus lents si j'en crois mes captures wireshark (ci dessus, runme-21 en mauve, runme-32 en noir).

Pourtant, à en croire le code de TCP dans libdswifi9, rien n'a changé ... ou presque. Rien en tout cas qui puisse expliquer ces pauses de 200ms récurrentes dans le deuxième scénario. J'investigue un peu plus grâce au zoom infini de WireShark pour découvrir que la DS annonce juste avant cette pause une fenêtre de réception de plus en plus petite, qui finit par atteindre une taille nulle. Et ça, en langage TCP, c'est le signe que le récepteur ne suit plus: les buffers saturent.

One intriguing thing is that, somewhat prior one of these long wait is that the receiver's window size is reduced from 1400 bytes to 1127, then 591 and finally 55 bytes ... It will then remain with a 0 receiver window for a few packets and then move back to 1400. In TCP language, this is an indication that the receiver struggles to process the received data on time. But the code that invokes "recv()" hasn't changed either ... that sounds like a problem coming from the "write-to-filesystem" side of the program ... from the libFAT.

It looks like libFAT has received more substantial changes, especially regarding the cache management. I used runMe's "receive to memory" mode, which is limitted in file size, but still operated at the usual peak speed. If a sequence number graph doesn't talk to you, the performance monitor just on the right should. The first "bridge" bar is the transfer to disk, the second "tower" bar is the transfer to memory. I haven't figured how to fix that yet, but at least I am in position to say that TCP is clear of charges.


Puisque le code qui transfère les données de dswifi à libfat n'a pas changé d'un iota, le problème est plus que probablement dans la libfat, qui a subi des modifications relativement importantes -- notamment au niveau de la gestion de son cache. Et vu que les données arrivent par le réseau à une taille qui n'est pas la taille "naturelle" pour écrire sur disque, un petit défaut dans la libFAT pourrait facilement avoir un effet conséquent sur les performances. Dernier petit test pour me convaincre de continuer dans cette direction : un transfer Wifi en mémoire (et non pas vers un fichier), fonctionalité un peu désuète de runMe mais qui tombe à pic ici. Résultat sans appel: on retrouve la vitesse à laquelle runMe m'avait habitué.

C'est donc un dswifi blanchi qui quitte la garde à vue tandis que je m'apprète à jouer une âpre partie de cache-cache avec le gros lard louche connu sous le nom de libFAT.

Monday, December 13, 2010

Debugging sessions darker than night

Beyond Infinity, a fellow OS hobby developer back in 2002 used to twist Gandalf's quote into "I see debugging sessions coming, darker than night itself" ... I guess that could apply to the last week. After identifying the reason why DDD wasn't operating properly (not showing machine code) anymore and quickly applying a patch, I started investigating the internals of desmume's gdb stub ... the part of the emulator that allows one to perform source-level debugging as if it was a locally running program. With zeromus, we identified a couple of curious things in the emulator-debugger communication, and although we don't agree yet on how it should best be fixed, I managed to patch the emulator as well so that it behave the way I need.

J'aimais bien être développeur d'OS sur mega-tokyo. Une chose sympa avec les développeurs d'OS, c'est que comme on en prend tous pour 20 ans, on apprend à se connaître, à construire ensemble, etc. "Beyond Infinity" était l'un de ceux-là, geek de première dans sa manière de détourner les 'quotes' des grands films et livres. C'est à lui que je dois le parallèle entre les "jours plus sombres que la nuit elle-même" du Seigneur des Anneaux et ces scéances obscures de debugging ou plus rien ne semble marcher comme il se doit au point qu'on finit par débugguer la machine virtuelle et/ou le débuggueur lui-même.

D'une certaine manière, voilà qui colle parfaitement à mes activités homebrew de la semaine dernière ... Et après avoir surmonté des lignes de code sans nombre, triomphant de bugs inouïs, de haute lutte j'ai frayé mon chemin jusqu'au stub par-delà localhost:9999 pour reprendre la condition de course qui s'était infiltrée. Vouaip. Et du coup, je suis enfin en mesure de chercher pourquoi certains décors ne s'affichent pas dans Apple Assault sous "dkp-r32". Vous vous tenez bien les côtes ?

Bon, bin voilà: le comportement de fread() a changé. Il n'est désormais plus possible de transférer des données directement entre un fichier et la VRAM si la position dans le fichier n'est pas un multiple de 4. Quand on sait que la VRAM ne peut pas être adressée par bytes (mais uniquement par mot de 16 ou 32 bits) et qu'on a désassemblé quelques memcpy dans sa vie, on se dit "bon sang, mais c'est bien sûr" ... mais on a quand-même passé des heures dessus >_<

I am thus (at last) in position to think about why some of the background in AppleAssault don't show up anymore. It looks like something has changed either in newlib or in libfat that altered the way non-aligned memory transfers are handled by fread(). The problem is I regularly transfer tiles data straight from the file into the VRAM, but that the VRAM only support 16-bit or 32-bit wide writes. It is typical for a memcpy implementation to fall back to byte-per-byte copies as soon as a mis-alignment condition is detected, but in this case, it kills the whole transfer. I need to patch some pictures so that they have an even number of colours.


Là-dessus, maintenant que mon code est revenu à un état plus rassurant, il va falloir que je réattaque vaisselle et ménage ... Ma fée a beau avoir une patience d'ange, 'y'a des choses qui ne se font pas toutes seules.

cd /home/kitchen
make mrproper
/etc/init.d/dishwasher reload
cat /tmp/laundry > /dev/drier

Wednesday, July 09, 2008

00:00:00 January 1, 1970

"Epoch" Le commencement de toute mesure de temps pour les systèmes informatiques Unix et BSD ... Le premier janvier 1970. C'était aussi l'heure de création de tous les fichiers sur mes cartes-mémoire avec mes petits outils DS jusqu'ici ^_^

Côté ARM9, si tout ce passe bien, ce sont nos bonnes vieilles fonctions time() et ctime() de la bibliothèque standard qui vont faire tout le boulot. A noter aussi qu'on a bien le champ "ctime" et "mtime" pour connaître l'heure de la dernière modification de fichier, mais ça, ça n'a pas l'air terriblement au point (mon nouveau fichier est renseigné comme datant de 1998 :P)

Attention à ne pas oublier "initClockIRQ();" côté ARM7, après irqInit(), sans quoi l'heure restera définitivement bloquée à "epoch". Si vous utilisez l'ARM7 par défaut du devkitpro, aucun soucis.

Tiens, en parlant du devkit, j'avais migré vers la r21 essentiellement pour pouvoir faire des "delete" et des "rename" dans le système de fichier. Bin c'est pas encore ça (rename, notamment, foire bien). Si bien que j'en suis réduit à faire l'appel explicite à la libfat en court-circuitant la "newlib" intégrée :

#include <reent.h>
extern "C" int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName);
// ...
{
struct _reent err;
if (_FAT_rename_r(&err, name, "/data/seds/backup.spr")<0)
iprintf("failed to backup %s",name);
else
iprintf("%s moved to /data/seds/backup.spr")
}

Friday, September 08, 2006

SpriteEditor DS

Les choses prennent forme. Je peux éditer un sprite avec un outil 'crayon' ou 'block', et grâce au code de la "libfat" de chism & dragonminded, je peux charger et sauver mes sprites sur la carte SD.
J'ai rajouté hier une fonction "copier le sprite" en utilisant un truc venant de SCUMMVM (le moteur de jeux pointer-cliquer de Lucas Arts).

Un pression sur l'écran correspond à un clic simple, alors qu'une pression pendant que le bouton "L" est enfoncé correspond à un "clic droit". Pour la grille, celà correspond à prélever la couleur comme couleur en cours, et sur la table de sprites, à enregistrer la zone de travail.

Things starts getting in place ... i can edit the sprite (of course) using both 'pencil' and 'block' mode, and thanks to the "libfat" code from chishm and dragonminded, i can read sprite tables from the SD flash card and write them back. Yesterday, i've also been adding the "copy sprite" feature, using a trick found in SCUMMVM for DS (the maniac-mansion editor).

When you just click the screen, that's a regular click (GUI_CLICKED event in my engine), and if you click while pressing the "L" key, that's a GUI_ALT_CLICKED. So we now have a touchscreen with "left" and "right" click :P Right-clicking the grid is used to "pick" a color and right-clicking the sprite table is used to "save" the sprite edited.

Oh, and another goodie: just click "beyond" the current table to "extend" it with the newly saved sprite ...

Now the next step will be showing animations and supporting multi-layer sprites (with layer merging).


PS: avant ce post, il y avait mon skyblog. Les messages relatifs à la programmation DS ont été rassemblés dans ce post-anniversaire

Friday, August 25, 2006

Writing code that works ...

Deuxième petit programme pour la DS ... Hier matin, un peu avant le temps de midi, j'entends passer la musique que mon frère avait écrit pour un jeu jamais réalisé: XMASMAN vs Packs ... un concept de tetris ou le père noël doit empiler des cadeaux qui dégringolent...

A second small utility : picture grabber. It's pre-compiled with a .pcx file that is shown on the bottom screen and allows you to grab parts of the image into tiles for sprites (that moves on the upper screen) and that you can later save on the SD card).
The intent was to speed up porting of my former "pixel art" and do small games ... which never took of. But it was the starting point of "runme", the all-in-one DS-WiFi-PC converter stuff.

J'avais fait des super petits sprites (vous savez ce que c'est, hein, maintenant) avec un chouette programme (Delux Paint II, je l'avais déjà sur mon 8086, celui-là!), et je les ai toujours... alors je me dit "voilà le petit jeu que je pourrais facilement avoir réalisé pour noël!". Il marcherait nickel avec 2 écrans, pas trop még-à-l'eau ni rien. Mais bon, ce serait ridicule de devoir redessiner tout avec le SpriteEditor DS qui n'est pas encore au dixième des possibilités de DP2.

Donc je rebidouille un petit "sprite grabber", un outil qui affiche une image complète et qui permet d'en récupérer des morceaux. Première esquisse sur le temps de midi. Ca tourne dans l'émulateur. cool.
Je reviens le soir @home et ma fée est toujours à Maastricht pour la-journée-ou-les-magasins de-bricolages-sont-ouverts-jusque-21h ... Et je rattaque. A 20h30, j'ai intégré le code de Chishm et DragonMinded, et je fais le premier essai "temps réel" d'écriture de fichiers sur ma petite carte SD.

Et ça marche, les gars! Sortez les cotillons, c'est la journée du code qui fonctionne (après une semaine de combat avec les codes à redondance cycliques de ma carte-réseau-qui-tue qui s'est enfin mise à fonctionner le matin)!

Donc voilà, y'aura encore un peu de boulot pour qu'on puisse choisir n'importe qu'elle image et sauver dans plusieurs fichiers, mais le départ est là ^_^