+++

title = "Fabriquer un lecteur de carte mémoire Nintendo 64 (4)"
date = 2012-10-05
aliases = [ "post/2012/10/05/Fabriquer-un-lecteur-de-carte-mémoire-Nintendo-64-(4)"]
[taxonomies]
tags = [ "jouage", "rebours", "bricole-picole" ]
+++

Pour quelques lignes de C de plus…

<!-- more -->

Ah ah !

Bon, chose prosmise, chose dûe, maintenant que le machin marche à peu près et commence à ressemble à quelque chose, je peux enfin publier le code sous ma licence préférée : la licence Rien À Branler. Pour résumer : j'assume d'avoir codé ça comme un gros goret et que des fois ça marche pas et que je sais pas pourquoi. Pour l'instant, c'est à peu près présentable et à peu près utilisable. Si tu es un gentil monsieur du bien, tu peux prendre ce code, le copier et faire les améliorations dont il a (grandement) besoin.

Ceci dit, quelques explications sur la partie Arduino (et le pourquoi du comment j'ai fait ça comme ça).

# Le loop de base

Le `setup()` n'a rien de particulier : il met simplement le Arduino en 115200 (la vitesse maximale du port série). Cela permet d'accélérer sensiblement les sauvegardes et les restaurations, sachant que, quoiqu'il arrive, cela prend toujours un temps non négligeable (environ 1 minute et demi).

Le `loop()` est très classique aussi : en fonction de la touche reçue, on déclenche la fonction `Backup()` ou la fonction `Restore()`.

# Sauvegarde des cartes mémoire

La fonction de sauvegarde va effectuer deux boucles imbriquées qui permettent de balayer toutes les valeurs d'adresses de 0x0000 à 0x7fe0. Après avoir encodé l'adresse avec le CRC d'adresses, `n64cmd()` envoit ce qu'il faut à la manette et récupère la réponse. Celle-ci est affichée sous la forme `<adresse en clair>:<données sous forme de code hexadécimal>\n`.\

Ne reste plus qu'à lire ces données correctement depuis le port série. J'ai volontairement choisi de ne pas recoder ces informations sous forme binaire mais de conserver le format texte (ce qui fait qu'un dump complet d'une carte mémoire prend environ 71Kio au lieu des 32Kio du format « brut »). Il s'agit donc simplement de lire caractère caractère jusqu'à tomber sur deux `\n` de suite indiquant la fin de la lecture.\

Et pour les gens qui se poseraient la question : se connecter à un Arduino fait un reset automatique. Il faut donc attendre environ 2 secondes avant de commencer à envoyer du caca sur la ligne série, sinon tout est perdu. Si ça avait été mieux documenté ce truc-là, j'aurais pas galéré autant…

# Restauration des cartes mémoire

La restauration ne fonctionne pas tout à fait de la même manière : parce que le hardware est assez limité, il a fallu que je réinitialise complètement la variable `buffer` qui permet de lire ce qui est entré au niveau du port série à chaque itération. En effet, que ce soit avec un malloc ou avec une initialisation standard de tableau en C, Arduino recycle toujours le même secteur mémoire, laissant des trucs assez crade au passage. `memset` absolument obligatoire sur le coup, sous peine de grosse prise de tête au moment de la relecture de la mémoire… Bref.

Donc, il s'agit ensuite de convertir des couples de deux caractères en hexadécimal tout au long d'une chaîne exactement similaire à la précédente. `sscanf` est donc ton ami et avec plein de pointeurs bien crades et bien illisibles, on arrive à lire toute la chaîne dans la variable `command` et à passer cette dernière à `n64cmd()`. Voilà ce que j'appelle du code McDo : rapide, facile et indigeste.

# Et donc maintenant ?

Dans l'absolu tout fonctionne. Il y a encore quelques petits soucis de temps en temps : 
* pour une raison que j'ignore, le Arduino n'envoit des fois strictement aucune donnée. En général, il faut le débrancher et le rebrancher et ça se remet en marche.
* Je ne sais toujours pas si l'initialisation de la carte mémoire est toujours utile. A priori oui, mais je n'ai jamais réussi à trouver si c'était vrai ou pas.
* Il n'y a toujours pas de vérification du fameux 33ème octet correspondant au checksum de données. En pratiquement 3 semaines d'utilisation intensive, je n'ai eu toutefois qu'une seule lecture incohérente de la carte mémoire.

ême si c'est une première étape encourageante (et que cela permet de résoudre mon problème), il faudrait encore continuer pour compléter les fonctionnalités. D'abord, en essayant de lire le contenu de la carte mémoire à partir d'un dump. Je sais déjà comment trouver la liste des notes. Mais je ne sais malheureusement pas pour le moment comment isoler chaque note sur la carte mémoire. Ce serait quand même foutrement classe de pouvoir lire le contenu d'un dump pour savoir ce qu'i y a dedans !

Et cela pourrait amener à rendre le tout compatible avec les fichiers produits par DexDrive64, ce qui permettrait de récupérer des sauvegardes directement sur [GameFAQS](http://www.gamefaqs.com/) ou autres. Je n'ai pas encore pris le temps d'analyser dans le détail comment fonctionne les fichiers DexDrive64, mais je suis certain que cela ne doit pas être bien compliqué.

La compatibilité avec les émulateurs pourraient être intéressantes aussi. Pour le moment, je ne sais pas trop comment faire non plus : je récupère 32Kio de données dans mes `.ampk`, les émulateurs créent des fichiers `.mpk` qui font en général 128Kio. C'est quoi le vide autour ? Est-ce que je peux le remplir (non, il n'y a pas de sous-entendu scabreux ici. Jamais.) ? Aucune idée pour le moment.
