field -section9- : backgrounds

Organisation générale de la section

La section 9 est divisée en trois :

  • L'en-tête
  • Les Zones Sprites (2 ou 4 zones)
  • Les données brutes de l'image

Les textes colorés sont les truc importants ou les truc explicités plus bas dans la page

PositionTailleDescription
Header
02 octets0
22 octets1 (utilise des palettes) ou 2 (n'utilise pas de palettes)
41 octet1 (activé, si 0 le jeu ne lit pas la suite)
57 octetsPALETTE
1220 octetsActivité des premiers pixels des palettes -actPixPal-
324 octets0
364 octetsBACK
Zone Sprites 1
402 octetsPseudo-Largeur
422 octetsPseudo-Hauteur
442 octetsNombre de sprites Infos 1
462 octetsSi =1 : utilise des palettes, Si =2 : utilise les couleurs directement
482 octets0
50nbSprites1 * 52Sprites Infos 1
50 + NbSprite1 * 522 octets0
52 + NbSprite1 * 521 octetSi =0 La zone 2 n'existe pas.
Zone Sprites 2
53 + NbSprite1 * 522 octetsPseudo-Largeur640
55 + NbSprite1 * 522 octetsPseudo-Hauteur480
57 + NbSprite1 * 522 octetsNombre de sprites Infos 2
59 + NbSprite1 * 5216 octets??? (en savoir plus...)
75 + NbSprite1 * 522 octets0
77 + NbSprite1 * 52nbSprites2 * 52Sprites Infos 2
77 + 52 (NbSprite1 + NbSprite2)2 octets0
79 + 52 (NbSprite1 + NbSprite2)1 octetSi =0 La zone 3 n'existe pas.
Zone Sprites 3
80 + 52 (NbSprite1 + NbSprite2)2 octetsPseudo-Largeur640
82 + 52 (NbSprite1 + NbSprite2)2 octetsPseudo-Hauteur480
84 + 52 (NbSprite1 + NbSprite2)2 octetsNombre de sprites Infos 3
86 + 52 (NbSprite1 + NbSprite2)12 octets0
98 + 52 (NbSprite1 + NbSprite2)nbSprites3 * 52Sprites Infos 3
98 + 52 (NbSprite1 + NbSprite2 + NbSprite3)2 octets0
100 + 52 (NbSprite1 + NbSprite2 + NbSprite3)1 octetSi =0 La zone 4 n'existe pas.
Zone Sprites 4
101 + 52 (NbSprite1 + NbSprite2 + NbSprite3)2 octetsPseudo-Largeur640
103 + 52 (NbSprite1 + NbSprite2 + NbSprite3)2 octetsPseudo-Hauteur480
105 + 52 (NbSprite1 + NbSprite2 + NbSprite3)2 octetsNombre de sprites Infos 4
107 + 52 (NbSprite1 + NbSprite2 + NbSprite3)2 octets0
109 + 52 (NbSprite1 + NbSprite2 + NbSprite3)8 octets??? (en savoir plus...)
117 + 52 (NbSprite1 + NbSprite2 + NbSprite3)2 octets0
119 + 52 (NbSprite1 + NbSprite2 + NbSprite3)nbSprites4 * 52Sprites Infos 4
119 + 52 (NbSprite1 + NbSprite2 + NbSprite3 + NbSprite4)2 octets0
Données
121 + 52 (NbSprite1 + NbSprite2 + NbSprite3 + NbSprite4)7 octetsTEXTURE
128 + 52 (NbSprite1 + NbSprite2 + NbSprite3 + NbSprite4)nb de pages * 65 540 + 84Données de l'image
212 + 52 (NbSprite1 + NbSprite2 + NbSprite3 + NbSprite4) + nb de pages * 65 5403 octetsEND

Sprite Data : organisation

Dans chaque zone, Il y a nbSprites sprites Infos de 52 octets. Un Sprite Infos fait donc 52 octets, il commence et finit toujours par 2 octets nuls. Un sprite info donne tout ce qu'il faut pour construire un sprite de 16*16 pixels (ou 32*32 pixels) et pour le placer dans l'image finale.

Voila comment est fait un sprite Infos (en fonction de la zone) :

Sprites Infos zone 1

02 octets0
22 octetsPosition cible X
42 octetsPosition cible Y
62 octetsInutilisé
82 octetsInutilisé
102 octetsPosition source X
122 octetsPosition source Y
142 octetsInutilisé
162 octetsInutilisé
182 octetsInutilisé (largeur tile : 16 ou 0)
202 octetsInutilisé (hauteur tile : 16 ou 0)
222 octetsNuméro paletteCommence à la palette n°0
242 octetsId4095
261 octetInutilisé
271 octetInutilisé
281 octet0
291 octet0
302 octets0
322 octetsPage
342 octetsInutilisé
362 octetsOctets par couleur0 (peu de couleurs), 1 (palettes) ou 2 (sans palettes)
384 octetsInutilisé
424 octetsCoordonnée X texture
464 octetsCoordonnée Y texture
502 octets0

Sprites Infos zone 2

02 octets0
22 octetsPosition cible X
42 octetsPosition cible Y
62 octetsInutilisé
82 octetsInutilisé
102 octetsPosition source X
122 octetsPosition source Y
142 octetsPosition source X (2) (pour les effectPages)
162 octetsPosition source Y (2) (pour les effectPages)
182 octetsLargeur bloc16
202 octetsHauteur bloc16
222 octetsNuméro paletteCommence à la palette n°0
242 octetsId
261 octetParamètre
271 octetÉtat
281 octetTransparence par additionBooléen
291 octetTransparence par addition ?Booléen
302 octetsTransparence par addition ?0, 1, 2 ou 3
322 octetsPage
342 octetsEffectPage
362 octetsOctets par couleur0 (peu de couleurs), 1 (palettes) ou 2 (sans palettes)
384 octetsCoordonnée Z
424 octetsCoordonnée X texture
464 octetsCoordonnée Y texture
502 octets0

Sprites Infos zone 3

02 octets0
22 octetsPosition cible X
42 octetsPosition cible Y
62 octets0
82 octets0
102 octetsPosition source X
122 octetsPosition source Y
142 octetsPosition source X (2) (pour les effectPages)
162 octetsPosition source Y (2) (pour les effectPages)
182 octetsLargeur bloc32
202 octetsHauteur bloc32
222 octetsNuméro paletteCommence à la palette n°0
242 octetsId4096
261 octetParamètre
271 octetÉtat
281 octetTransparence par additionBooléen
291 octetTransparence par addition ?Booléen
302 octetsTransparence par addition ?0 ou 1
322 octetsPage
342 octetseffectPage
362 octetsType de palette0 (peu de couleurs) ou 1 (palette normale) ou 2 (sans palettes)
384 octets0
424 octetsCoordonnée X texture
464 octetsCoordonnée Y texture
502 octets0

Sprites Infos zone 4

02 octets0
22 octetsPosition cible X
42 octetsPosition cible Y
62 octets0
82 octets0
102 octetsPosition source X
122 octetsPosition source Y
142 octetsPosition source X (2) (pour les effectPages)
162 octetsPosition source Y (2) (pour les effectPages)
182 octetsLargeur bloc32
202 octetsHauteur bloc32
222 octetsNuméro paletteCommence à la palette n°0
242 octetsId0
261 octetParamètre
271 octetÉtat
281 octetTransparence par additionBooléen
291 octetTransparence par addition ?Booléen
302 octetsTransparence par addition ?0, 1 ou 3
322 octetsPage
342 octetseffectPage
362 octetsType de palette0 (peu de couleurs) ou 1 (palette normale)
384 octetsCoordonnée Z0 ou 999
424 octetsCoordonnée X texture
464 octetsCoordonnée Y texture
502 octets0

Paramètres

Dans la deuxième et troisième zone, il y a les deux octets que j'appelle “paramètre” et “états”. Ceux-ci permettent de donner un numéro à un petit bout de l'image qui sera sous plusieurs états différents.

Sur Final Fantasy VII, le plus grand numéro de paramètre observé est 51, on peut aller en théorie jusqu'au numéro 256 (soit 255 paramètres).

États

Les états sont rangés dans un octet où chaque bit correspond à un état (il y a donc 8 états). Si un bit est à 1, l'état correspondant existe. Par exemple si l'octet des états est à 00000010, l'état 2 est activé.

Parfois les numéros de certains paramètres ne se suivent pas.

Les données de l'image

Voila la première page du fichier anfrst_1 affichée en brut, et je me suis servi de la première palette.

Elles sont toujours précédées par le mot-clé “TEXTURE”.

Les données de l'image sont séparées en 42 pages. Si le premier mot de la page est différent de zéro, c'est qu'il y a des données dans la page, dans le cas contraire la page ne fait que deux octets de longueur.

Shéma d'une page :

PositionTailleDescription
02 octetsSi =0, il n'y a pas de page.
Header
22 octets0 (sprites 16*16) ou 1 (sprites 32*32)
42 octetscoulPixSi =1 : un octet = un pixel (utilisation d'une palette) ;
Si =2 : deux octets = un pixel
Données de la page
665536 * coulPixDonnées de la page

Si vous voulez afficher directement ces pages, vous devez afficher des images de 256*256 pixels (utilisez les palettes). Comme dans l'illustration, vous verrez des lignes de 16 pixels de hauteur.

Je vous conseille vivement de collecter tous les points de départ des pages dans un tableau bien rangé, par exemple :

[0] => 0
[1] => 65542
[15] => 131110

Par la suite je vais appeler ce tableau “$pages”.

Groupement des pages (supposition)

  • 0 → 14 :
  • 15 → 23 : ~effectPages
  • 24 → 26 :
  • 27 → 28 : pages sans palettes
  • 29 → 84 : inused

Construction d'une image

Avant la construction : collecter les informations

Pour correctement construire l'image, nous avons besoins des véritables dimensions, et de la liste des premiers états de chaque paramètre.

Pour cela nous allons parcourir toutes les zones Sprites Infos, et à chaque Sprite Info récupérer les position cibles. Je vous laisse comprendre mon code (qui est en PHP…).

$largeurMax=0;$hauteurMax=0;
$largeurMin=0;$hauteurMin=0;
for($zone = 0 ; $zone < $nbZones ; $zone++) {
 
	for($numSpriteInfo = 0 ; $numSpriteInfo < $nbSpritesInfo[$zone] ; $numSpriteInfo++){
 
		$spriteInfo = substr($spriteData[$zone], 52*$numSpriteInfo, 52*$numSpriteInfo+52);
 
		$page = bin2dec_2($Block,32);
		if(($page2 = bin2dec_2($Block,34)) != 0)
			$page = $page2;
		if(empty($pages[$page]))	continue;//Si référence à une page inexistante (fix trnad_3)
 
		$X = bin2dec_2($spriteInfo, 2);
		$Y = bin2dec_2($spriteInfo, 4);
 
		//Unsigned int 2 signed int, ça c'est si vous ne pouvez pas déclarer une variable signed int ^^
		if($X > 32768)	$X-=65536;
		if($Y > 32768)	$Y-=65536;
 
		if($X==10000 || $X==-3184)	continue;//fix
 
		if($X > $largeurMax && $X > 0)		$largeurMax = $X;
		elseif($X < 0 && -$X > $largeurMin)	$largeurMin = -$X;
 
		if($Y > $hauteurMax && $Y > 0)		$hauteurMax = $Y;
		elseif($Y < 0 && -$Y > $hauteurMin)	$hauteurMin = -$Y;
 
		//Listing des paramètres
		$param = bin2dec_2($spriteInfo, 26);
 
		if($param && ($paramList[$param % 256] > $param || !$paramList[$param % 256]))
			$paramList[$param % 256] = $param;
	}
}
$largeur = $largeurMax + $largeurMin + 16;
$hauteur = $hauteurMax + $hauteurMin + 16;

Sprites zone 1

Juste la première zone du fichier ancnt3

Pour construire une image, on utilise les Infos sprites. Dans la zone 1, un sprite est une image de 16*16 pixels. On construit cette image grâce aux Infos sprites (positions et autres infos), aux données de l'image (pour créer les pixels) et aux palettes (pour les couleurs).

Regardez plus haut pour savoir où trouver la zone 1 des Infos sprites, et comment elle est faite. C'est la plus simple des zones. Elle est scindée en nbSpritesInfos parties de 52 octets chacune. Ces 52 octets vous donnent les infos pour pouvoir construire le sprite.

Chercher les pixels du sprite

$SrcX = bin2dec_2($spriteInfo, 10);
$SrcY = bin2dec_2($spriteInfo, 12);
$page = bin2dec_2($spriteInfo, 32);
$uneCoul = bin2dec_2($imageData, $pages[$Page]+4); //les deux derniers octets du header de la page (qui disent si 1 octet = 1 pixel ou si 2 octets = 1 pixel)
 
$pos = $pages[$page] + 6 + ($srcY * 256 + $srcX) * $uneCoul; //Position de départ du sprite dans les données de l'image

Ce code nous donne le point de départ du sprite dans la partie données de l'image. Elle utilise les variables extraites des infos du sprite.

Explications :

  • le tableau $pages[] donne les points de départ des pages
  • + 6 : c'est la taille du header de la page.
  • 'SrcY' est la position Y dans l'image de 256*256 pixels.
  • la largeur de l'image d'une page = 256. Pour aller d'un ligne à l'autre dans les données, il faut faire des bonds de 256 octets.
  • 'SrcX' est la postion X dans l'image de 256*256 pixels.
  • $uneCoul = 1 ou 2. Quand c'est égal à deux, on a pas besoin de palettes.

Il vous faut extraire à partir de StartOffset un carré de 16*16 pixels. Mais remontez un peu et regardez l'illustration. Prendre 16*16 pixels, c'est pas si simple. Au début on prend l'octet StartOffset, puis l'octet StartOffset + 1, etc, jusqu'à l'octet StartOffset + 15. On a une ligne ! Mais on est bien embêté pour passer à la ligne suivante ! Il faut aller à StartOffset + 256, donc en gros faire un bond de 240 octets… jusqu'à ce qu'on ait finalement 16*16 octets, pour construire le sprite.

Mini récapitulatif
  • On regarde un info Sprite, celui-ci permet de placer un petit carré de 16*16 pixels sur l'image finale ;
  • donc dans l'info Sprite, on prend le numéro de la page utilisée et les position sources pour savoir où dans les données on trouve le petit carré à reproduire sur l'image finale.

Chercher les couleurs du sprite

$Palette = substr($PaletteData, 512*$Pal, 512); //Partie données de la section palette

Pour chaque octets du sprite de 16*16 pixels, il faut aller chercher la couleur dans la palette (le numéro de palette est donné dans les données du sprites). Un exemple : vous avez l'octet 0x5d, alors il faut aller chercher la 0x5d-ième couleur de la palette. Comme il y a deux octets par couleur dans une palette, la position dans la palette est 0x5d*2. Et pour savoir quelle palette utiliser, prenez l'info dans les sprites data (ça va de 0 à nbPalette - 1). J'ai développé dans l'article palette la manière de traduire les deux octets de la couleur en une couleur RVB.

Si il n'y a pas de palettes, les couleurs sont données directement dans les données de l'image, un pixel = 2 octets. Couleurs sur deux octets : rrrrrvvv vvmbbbbb (avec r=rouge, v=vert, b=bleu, m=inconnu).
Par contre ne tracez pas les pixels noirs (r=0,v=0,b=0) !

Complications sur les palettes
  • Dans l'en-tête (celle au tout début de l'article :-p ), vous avez extrait l'activité des premiers pixels des palettes (que j'ai nommé actPixPal). Celui-ci est une suite de vingt-quatre 0 et 1. En fait, si par exemple le premier octet est 0, cela signifie que toutes les couleurs de la palette n°0 doivent être utilisées, si le premier octet est 1, cela signifie que la première couleur de la palette n°0 ne doit pas être utilisée.
    Autre exemple : si le quatrième octet est sur 1, cela signifie qu'on peut utiliser toutes les couleurs de la palette n°3, si il est sur 0, cela signifie qu'on ne peut pas utiliser la première couleur de la palette n°3.
  • Si vous rencontrez un pixel noir (r=0,v=0,b=0,m=0), remplacez-le par la première couleur de la palette (peu importe la valeur de actPixPal).
Mini récapitulatif
  • On se demande si on doit utiliser une palette pour construire notre petit carré ;
  • Si oui, on utilise le sprite data pour connaitre le numéro de la palette ;
  • Sinon, on passe à la suite, en retenant qu'il faut utiliser la méthode sans palette.

Chercher la position cible

Les infos du sprite vous donnent des positions cibles. Mais l'origine se trouve bien souvent (pas tout le temps) au milieu de l'écran, on se retrouve donc avec des coordonnées parfois négatives. Voila comment retrouver des coordonnées positives (xCible et yCible sont deux signed int extraits du Sprite infos en cours, largeurMin et hauteurMin sont les plus grandes valeurs cible en dessous de 0, en valeur absolue) :

xCible = xCible + largeurMin;
yCible = yCible + hauteurMin;

Voila, vous pouvez tracer le petit carré.

Sprites zone 2

Première et deuxième zone (sans les effectPages) du fichier ancnt3

Dans la zone 2, on utilise le même procédé que dans la zone 1, sauf pour les infos sprites qui ont un effectPage supérieur à 0. En tout cas en traçant la zone 1 et la zone 2 sauf les effectPage, vous aurez déjà un beau background. Allez faire un tour en bas de l'article pour prendre conscience de la séparation page/effectPage de la zone 2.

Les effectPage

Première et deuxième zone (avec les effectPages) du fichier ancnt3

Vous devez utiliser les positions source X (2) et Y (2) :

$srcX2 = bin2dec_2($spriteInfo, 14);
$srcY2 = bin2dec_2($spriteInfo, 16);
$id = bin2dec_2($spriteInfo, 24);
$effectPage = bin2dec_2($spriteInfo, 34);
 
if($effectPage && $id!=4095) { //Quand id==4095, cela signifie qu'on est dans la zone 1, pour éviter les problème j'évite d'utiliser les effectPage si je suis dans la zone 1
	$srcX = $srcX2;
	$srcY = $srcY2;
	$page = $effectPage;
}
"Transparence"

Dans le cas d'un effectPage, la plupart des couleurs sont indiquées comme transparentes. En fait quand on trace un pixel transparent, il ne faut pas utiliser le canal alpha, mais regarder quelles sont les couleurs du pixel qui était déjà tracé là où on veut tracer notre pixel transparent, et additionner ces couleurs avec les couleurs du pixel transparent pour obtenir les véritables couleurs !
Exemple : vous voulez tracer un pixel transparent, et là où vous voulez le tracer il y a déjà un pixel de couleur r=56 v=64 b=28, et votre pixel est de couleur r=8 v=16 b=8 ; la nouvelle couleur sera donc r=56+8 v=64+16 b=28+8.

Les paramètres

J'ai réussi à trouver les bonnes conditions pour n'afficher que le premier état de chaque paramètre. Quand on a collecté des informations précédemment, on a créé le liste $paramList qui contient les numéros des premiers états de chaque paramètre. Si vous avez suivit la construction de paramList, les conditions suivantes devraient fonctionner, on ne trace que si le paramètre = 0 ou bien si le paramètre = premier état.

$param == $paramList[$param % 256]

Sprites zone 3

Changement majeur : on trace des sprites de 32*32 pixels. Cette zone est une sorte de background répété au centre de l'écran (comme la propriété background: repeat; en css).

Sprites zone 4

Sprites de 32*32. Cette zone est une sorte de background fixé là où se trouve la caméra (comme la propriété background: fixed; en css).

L'ordre des couches

L'ordre des couches est donné par l'Id des infos Sprites. Cet id est compris entre 0 et 4096 (inclus), avec 0 le plus près et 4096 le plus éloigné. Dans les scripts, on peut changer cette valeur entre -32768 et +32767 (signed short). Il est donc judicieux de trier les tiles par leur Id.

Par défaut, les couches ont des id prédéfinis :

  • Zone 1 : 4095
  • Zone 2 : variable
  • Zone 3 : 4096
  • Zone 4 : 0

La zone 4 est toujours devant, la zone 3 derrière, la zone 1 juste devant la 3 et la 2 ça dépend. Ces valeurs peuvent changer par les scripts, si vous voulez optimiser l'affichage, il faut savoir lire les scripts :-) .

Recent changes RSS feed Valid XHTML 1.0 Valid CSS Powered by DokuWiki GNU FDL

Qui sommes-nous ?
Aidez WikiSquare en le faisant connaître !
Sauf mention contraire, tous les textes sont disponibles sous les termes de la GNU Free Documentation License.
Les images sont sous le copyright de leurs auteurs.

Page générée en 0.15258812904358 seconde.