> 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.
Petit rappel sur les différents fichiers qui se trouvent dans un package :
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.
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.
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
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.
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.
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 :
{
"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.
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 :
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.
Le format Json est un format de projet de travail. Le fichier utilisé dans la boîte à histoire, en embarqué
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 !