Skip to main content
Description du Logo Fralacticus

DBZ Buu's Fury : Les textes en couleur



Introduction #

En préambule, je précise que l'étude présentée n'a pas été créée de toute pièce et fait partie des mes travaux préparatoires à la traduction de DBZ Buu's Fury en français.

Dans le jeu, de nombreux textes sont en couleur, et je vais vous expliquer comment utiliser la palette et le mécanisme de colorisation pour bien replacer les couleurs ou les modifier. Le mécanisme de colorisation est le même pour textes d'interface en clairs dans la rom et ceux des dialogues compressés. Je vais cependant détailler celui des dialogues qui possède certaines subtilités.




La palette de couleur #

L'ensemble des textes utilisent la même palette de 256 couleurs indexées. Pour reconnaitre et choisir plus facilement les couleurs, j'ai vais extraire la palette et la transformer en tableau de couleurs.

Export du fichier pal de la palette #

Palette de couleurs mGBA

Dans mGBA :
> Je lance le jeu et je clique sur Outils > Voir la palette..., puis j'attends l'apparition la palette encadrée ci-contre.
> Je clique sur Exporter l'OBJ pour enregistrer le fichier .pal

Conversion du fichier pal en fichier csv #

Ensuite, mon programme Dart affiche et produit un fichier csv : chaque ligne est une couleur représentée par sa position hexadécimale dans la palette, son code RVB et son code HTML.

import 'dart:convert';
import "dart:io";

void main() {
    print("> Lecture du fichier .pal");
    File fichierPal = File("lib/obj_mgba.pal");
    List<code><</code>int> pal =  List.from(fichierPal.readAsBytesSync());

    int positionDebutCouleurs = 24;
    int j = 0;
    List<code><</code>String> listeCouleurs = [];
    print("\n> Liste des couleurs : ");
    for ( int i = positionDebutCouleurs; i < pal.length ; i+=4 ) {
      String couleur =
          "${IntToHex(j)},"
          "${pal[i]},${pal[i+1]},${pal[i+2]},"
          "#${IntToHex(pal[i])}${IntToHex(pal[i+1])}${IntToHex(pal[i+2])}";
      listeCouleurs.add(couleur);
      print(couleur);
      j += 1;
    }

    print("\n> Ecriture du fichier .csv");
    File fichierCsv = File ("lib/obj_mgba.csv");
    fichierCsv.writeAsStringSync(
        listeCouleurs.join("\n"),
        mode:FileMode.write,
        encoding:Utf8Codec());
}

String IntToHex (int val) => val.toRadixString(16).padLeft(2, '0').toUpperCase();
obj_mgba.csv
00,0,0,0,#000000
01,0,0,0,#000000
02,255,255,255,#FFFFFF
03,255,0,0,#FF0000
04,255,132,0,#FF8400
05,255,255,0,#FFFF00
06,0,255,0,#00FF00
07,0,255,255,#00FFFF
[etc]

Conversion du fichier csv en un tableau de couleurs #

Enfin, une fois le fichier csv ouvert dans Excel, je créer une macro appliquée à la feuille qui se déclenche  à l'évènement SelectionChange :

J'obtiens le tableau final avec le rendu des couleurs !

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim tHex As String
    If (Left(ActiveCell.Text, 1) = "#" And Len(ActiveCell.Text) = 7) Then
        tHex = Mid(ActiveCell.Text, 6, 2) 
             & Mid(ActiveCell.Text, 4, 2) 
             & Mid(ActiveCell.Text, 2, 2)
         ActiveCell.Offset(0, 1).Interior.Color = WorksheetFunction.Hex2Dec(tHex)
    End If
End Sub

🔗 Ouvrir la page web du tableau de couleurs




Décodage du texte #

Pour la suite, je vais prendre pour exemple le bloc de dialogue suivant :

You have to take a plane. It's called "The Higher Plane" and it's docked next to King Yemma's Castle at the end of Snake Way.


Décodage personnalisé #

59 00 6F 00 75 00 20 00 68 00 61 00 76 00 65 00 20 00 74 00 6F 00 20 00 74 00 61 00 6B 00 65 00 20 00 61 00 20 00 70 00 6C 00 61 00 6E 00 65 00 2E 00 20 00 49 00 74 00 27 00 73 00 20 00 63 00 61 00 6C 00 6C 00 65 00 64 00 20 00 22 00 08 00 07 00 54 00 68 00 65 00 20 00 48 00 69 00 67 00 68 00 65 00 72 00 20 00 50 00 6C 00 61 00 6E 00 65 00 08 00 02 00 22 00 20 00 61 00 6E 00 64 00 20 00 69 00 74 00 27 00 73 00 20 00 64 00 6F 00 63 00 6B 00 65 00 64 00 20 00 6E 00 65 00 78 00 74 00 20 00 74 00 6F 00 20 00 08 00 07 00 4B 00 69 00 6E 00 67 00 20 00 59 00 65 00 6D 00 6D 00 61 00 27 00 73 00 20 00 43 00 61 00 73 00 74 00 6C 00 65 00 08 00 02 00 20 00 61 00 74 00 20 00 74 00 68 00 65 00 20 00 65 00 6E 00 64 00 20 00 6F 00 66 00 20 00 53 00 6E 00 61 00 6B 00 65 00 20 00 57 00 61 00 79 00 2E 00

Y�o�u� �h�a�v�e� �t�o� �t�a�k�e� �a� �p�l�a�n�e�.� �I�t�'�s� �c�a�l�l�e�d� �"���T�h�e� �H�i�g�h�e�r� �P�l�a�n�e��[1]�"� �a�n�d� �i�t�'�s� �d�o�c�k�e�d� �n�e�x�t� �t�o� ���K�i�n�g� �Y�e�m�m�a�'�s� �C�a�s�t�l�e��[1]� �a�t� �t�h�e� �e�n�d� �o�f� �S�n�a�k�e� �W�a�y�.�

You have to take a plane. It's called "\x08\x07The Higher Plane\x08\x02" and it's docked next to \x08\x07King Yemma's Castle\x08\x02 at the end of Snake Way.


Explications #

Dans la rom, le texte en hexadécimal est manifestement encodé en UCS2-2LE.

Cela a deux conséquences :
- Chaque caractère est codé sur 2 octets dans une plage théorique de 0000 à FFFF, ce qui équivaut à 65336 caractères possibles.
- Chaque groupe de 2 octets est ordonné en petit-boutiste (little-endian LE), l'octet de poids faible est en deuxième position.
Exemple : la lettre Y est codée en 59 00

Le jeu n'utilise que la plage 00 à FF donc le deuxième octet est toujours à 00, ce qui donne cette impression de séparateur entre chaque caractère.

Pour traduire le texte facilement, il faut le décoder dans une représentation "humaine".
Les éditeurs hexadécimaux ou textuels n'y parviennent que partiellement, avec des points d'interrogations ou des caractères bizarres.

C'est ainsi que j'ai créé mon propre décodage qui supprime le 2ème octet de chaque caractère et échappe les caractères de contrôle en affichant l'octet brut préfixé de '\x'.




Mécanisme de colorisation #

Définition d'une couleur #

Par défaut, le texte d'un bloc de dialogue est en blanc (n°03 dans la palette).

Pour le coloriser il faut écrire deux octets à la suite :

1er octet : \x08 <- marqueur de colorisation
2ème octet : numéro hexadécimal de la couleur dans la palette

Donc \x08\x07 signifie : afficher le texte qui suit avec la couleur n°07 (cyan)

Dbz Buu's Fury, Discussion Goku et Kaio multicolor

Un joli arc-en-ciel :

You have to take a plane. It's called "\x08\x03T\x08\x04h\x08\x05e\x08\x06 H\x08\x07i\x08\x08g\x08\x09h\x08\x0Ae\x08\x02r Plane" and it's docked next to King Yemma's Castle at the end of Snake Way.


Portée de la colorisation #

La couleur s'applique jusqu'à la définition d'une autre couleur ou sinon jusqu'à la fin du bloc de dialogue.
Dans l'exemple du jeu, le cyan et le blanc s'alternent, d'où les enchaînements de \x08\x07 et \x08\x02.

La couleur n'est pas réinitialisée après un saut de fenêtre, qu'il est important de différencier d'une fin de bloc.

Le saut de fenêtre change de fenêtre sans effet de transition, et c'est toujours le même personnage qui parle.
Ce saut peut-être :
- Automatique : Quand la fenêtre est remplie et qu'il reste encore du texte à afficher du bloc de dialogue.
- Manuel : Quand le saut de fenêtre est écrit avec \x0B. Cela permet d'aérer la lecture en affichant moins de texte dans une fenêtre.

La fin d'un bloc de dialogue ferme la fenêtre avec un effet de transition.
Cela se produit quand un personnage a finis de parler pour qu'un autre personnage prenne la parole, que le joueur reprenne le contrôle, ou qu'une cinématique se lance.
Cependant, il arrive aussi que le même personnage enchaine avec un autre bloc de dialogue, ce qui ménage une pause dans la lecture ou un effet de suspens.

Dbz Buu's Fury, Discussion Goku et Kaio avec couleur cyan qui reste

Dans cet exemple, la couleur cyan s'applique jusqu'à la fin du bloc de dialogue.

You have to take a plane. It's called "\x08\x07The Higher Plane" and it's docked next to King Yemma's Castle at the end of Snake Way.