Published on

Une boîte à histoire OpenSource - Partie 5

Authors
  • Name
    Anthony Rabine

La boîte à histoires Lunii, création française, est un objet électronique épatant pour les enfants : pas d'écran (quelques images seulement), une molette et un haut parleur suffisent pour écouter des histoires à créer. Les gosses sont accrocs ! Dans ce cinquième chapitre, nous avançons node éditeur d'histoires en nous inspirant de la boîte commerciale.

On continue le lecteur

Petit rappel sur les différents fichiers qui se trouvent dans un package :

  • node index (fichier 'ni') : en clair
  • list/menu index (fichier 'li') : les 512 premiers octets sont chiffrés
  • raster/image index (fichier 'ri') : les 512 premiers octets sont chiffrés
  • sound index (fichier 'si') :les 512 premiers octets sont chiffrés

Les deux fichiers RI et SI sont vraiment très simples. Ce sont des tableaux qui contiennent la liste des fichiers audios et images. Chaque nom de fichier est limité à 12 octets. Le nom de fichier ne contient pas d'extension.

Le fichier NI

Nous allons commencer par le fichier NI qui est au sommet de la logique des histoires. Ce fichier en clair est découpé en deux parties : au début, quelques informations sur le pack, puis à un certain offset (généralement 512) on obtient le début des noeuds.

Les premiers 512 octets

01 00 ⇒ NI version (1)
01 00 ⇒ Pack version (1)
00 02 00 00 ⇒ node list start (512)
2C 00 00 00 ⇒ Node size (44)
37 00 00 00 ⇒ stages count (55)
0F 00 00 00 ⇒ images count (15)
25 00 00 00 ⇒ sounds count (37)

On voit que l'offset du début des noeuds est indiqué, donc c'est une variable, pas forcément toujours à 512! Les autres valeurs sont des indications de nombre d'éléments du pack, ce qui aide au décodage.

Si on procède au calcul de la taille du fichier NI, on obtient la bonne valeur :

taille NI file = (Stages count * Node size) + 512

La liste des noeuds (à partir de l'offset 512)

Chaque noeud, dans notre exemple, fait 44 octets (peut-être que ça peut changer pour certaines histoires ou dans le futur).

Le premier noeud est celui qui affiche l'image et annone le titre du pack, c'est toujours le premier de la liste.

Voici la structure d'un noeud :

00 00 00 00 ⇒ image file index (in RI file)   => image tina + fred
00 00 00 00 ⇒ sound file index (in SI file)  ==> son "Le pack dino"
00 00 00 00 ⇒ OK transition : action node index in LI file
01 00 00 00 ⇒ OK transition : number of options
00 00 00 00 ⇒ OK transition : selected option index
FF FF FF FF ⇒ home transition action node index in LI file (NO index)
FF FF FF FF ⇒ home transition : number of options
FF FF FF FF ⇒ home transition : selected option index
01 00 ⇒ Wheel enable
01 00 ⇒ ok button enable
00 00 ⇒ Home button enable
00 00 ⇒ pause enable
00 00 ⇒ Auto jump enable (after the sound ends)
00 00 ⇒ Alignement mémoire

Chaque noeud pourra (ou non) afficher une image et/ou jouer un son. C'est en gros une étape. Une série d'options permet d'activer non non l'usage des boutons pour contrôler le flux et le reste sont des indicateurs du noeud suivant (ou d'une série de noeuds, dans le cas d'une sélection de choix par exemple).

Une indication utile est le bit "auto-jump" qui permet de sauter au noeud suivant dès que le son est terminée. Dans le cas contraire, un appui sur OK est attendu.

Les transitions

01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 0A 00 00 00 0B 00 00 00 0C 00 00 00 0D 00 00 00 0E 00 00 00 0F 00 00 00 10 00 00 00 11 00 00 00 12 00 00 00 13 00 00 00 14 00 00 00 15 00 00 00 16 00 00 00 17 00 00 00 18 00 00 00 19 00 00 00 1A 00 00 00 1B 00 00 00 1C 00 00 00 1D 00 00 00 1E 00 00 00 1F 00 00 00 20 00 00 00 21 00 00 00 22 00 00 00 23 00 00 00 24 00 00 00 25 00 00 00 26 00 00 00 27 00 00 00 28 00 00 00 29 00 00 00 2A 00 00 00 2B 00 00 00 2C 00 00 00

Les transitions vont nous indiquer les différents embrenchements, notamment lorsque l'on va appuyer sur la touche 'ok' pour valider un choix. Cette zone mémoire est un tableau d'entiers 32-bits en little endian, donc ici on perd pas mal de place, les chiffres n'allant jamais vraiment bien haut. C'est donc rempli de zéros !

Chaque nombre indique quel noeud exécuter, tout simplement. Lorsqu'il y a une série de choix, comme lorsque l'on choisit les éléments de l'histoire, le noeud indique la transition de départ et le nombre de transitions.

On convertit au format projet

Une première étape est de convertir ces fichiers binaires en fichier projet qui servira dans notre éditeur. Le format choisi est le Json. Tout est regroupé dans un seule fichier : une liste de ressources, puis la liste des noeuds sous la forme d'une table. Voici un exemple tronqué d'un JSON généré à partir d'une histoire commerciale :

json
{
    "code": "BE8949F60D854F54828419A1BDAED36A",
    "name": "",
    "nodes": [
        {
            "auto_jump": false,
            "id": 0,
            "image": 0,
            "jump_size": 1,
            "jump_to": 1,
            "sound": 0
        },
        {
            "auto_jump": true,
            "id": 1,
            "image": -1,
            "jump_size": 3,
            "jump_to": 2,
            "sound": 1
        },
    ],
    "type": "lunii",
    "ri":[
      "000/7F193854",
      "000/59A9BC9B",
      "000/1EF0A406"
    ],
    "si":[
      "000/221389C7",
      "000/47952E79",
      "000/92054A98",
   ]
}

Dans le cas d'une ressource à ne pas chager, la valeur sera -1. Dans les autres cas, ce sont des offset dans les tableaux de noeuds ou de ressource.

Nous voilà avec un premier jet de fichier décrivant une histoire. Il va bien entendu évoluer par rapport à cette version car c'est un fichier de projet donc beaucoup d'autres informations seront incluses de façon à faciliter l'édition et la génération d'histoire.

Nous pouvons maintenant attaquer la création et la modification d'une histoire avec l'éditeur.

On charge l'histoire dans notre éditeur

Notre éditeur d'histoire est très simple. Il sera capable de créer ou modifier une histoire, gérer les ressources associées et lire une histoire.

Au début j'étais parti sur un éditeur graphique à base de noeuds à relier. Franchement, un peu compliqué pour débuter, mon idée est d'avoir une vesion fonctionnelle assez rapidement afin d'avancer sur le firmware et les bundles de référence. Nous avons donc un simple tableau et un arbre de noeuds. Des boutons permettent d'ajouter et de paramétrer les noeuds. On verra plus tard pour un système plus intuitif !

Les autres fenêtres sont :

  • Le gestionnaire de ressources (images et sons)
  • L'émulateur de boîte à histoire
  • Une console pour les erreurs / le déboage

Concernant la partie technique, il est développé en C++ ce qui permet de ré-utiliser plein de code en commun avec le logiciel embarqué (en C, lui). La partie graphique sera réalisée à l'aide du toolkit ImGui + SDL2, les deux étant complètement multi-plateformes.

Le fichier créé précédemment est alors chargé en mémoire et les différents tableaux mis à jour.

On compile l'histoire

Le format Json est un format de projet de travail. Le fichier utilisé dans la boîte à histoire, en embarqué

Conclusion et prochaine étape

Nous voilà donc avec un lecteur d'histoires et un éditeur sur PC. La prochaine étape sera d'embarquer ce lecteur dans l'embarqué et de lire une première histoire !