Outils pour utilisateurs

Outils du site


Action unknown: copypageplugin__copy
back2root:reverse-engineering:planet-x3:part2-savegame_dat

Planet X3 - Format of "savegame.dat"

Ce fichier est un “dump mémoire” du jeu, il n'est pas compressé ni crypté; on y retrouve la meme structure que dans le code source.

Le fichier est composé de 3 “blocs” de données:

  • 1 block de 32 Kb (0x8000 bytes) avec la carte en cours
  • 1 block de 2560 bytes (0x1010 bytes) contenant les unités/batiments des 2 factions
  • 1 block de 5 bytes (0x0005 bytes) contenant principalement les timers du jeu.

une sauvegarde fait donc TOUJOURS 36885 bytes

Function de sauvegarde/chargement

Dans le code source, la sauvegarde se fait uniquement dans le fichier SAVEGAME.DAT.

Game_WriteSaveGame:
		MOV	AH,0x3c				; bug no mod selected : random ?
		MOV	CX,0x0
		MOV	DX,fname_SaveGame_DAT		; = "SAVEGAME.DAT"
		MOV	AH,0x3c
		INT	0x21				; Create/truncate file
		JC	exitError			; exit function without handling
		MOV	[fhandler_SaveGame],AX		; preserve file handler
	   	JMP	continue
exitError:	RET

On découvre ici que cette fonction ne gère aucune erreur, la sauvegarde est simplement abandonnée en cas d'erreur d'ouverture de fichier.

L'usage du JMP pour sauter au dessus du RET d'erreur ressemble beaucoup à une structure de gestion d'erreurs (qui a été éliminée de la version finale) propre aux processeurs sans caches (8088, 8086, 6502, etc).

Personnellement, je n'aurais pas rompu le flux avec un JMP j'aurais placé la gestion (ou non) des erreurs à la fin de la fonction, et réservé le saut (rupture de flux) aux erreurs, afin de ne pas forcer un “flush cache” sur des processeurs plus puissant (x386 et suivant).

continue:	MOV	BX,word ptr [fhandler_SaveGame]	; fhandler
 
		; save current game map
		MOV	DX,0x0
		MOV	CX,0x8000			; 0x8000 = 256*128 
		MOV	AH,0x40
		PUSH	DS				; switch to map's Segment
		MOV	DS,word ptr [g_Seg_GameMap]
		INT	0x21				; write map (32kb)
		POP	DS				; restore DS

la carte du jeu est sauvegardée “tel quel” sans aucune encryption ni compression.

		; save unit/building records
		MOV	BX,word ptr [fhandler_SaveGame]
		MOV	DX,Game_UnitsArr_Type
		MOV	CX,0x1010			; Write 256 units/buildings (10 attributes)
		MOV	AH,0x40
		INT	0x21

Pareil pour la structure des unités/batiments, sauvegardée “tel quel” sans aucune encryption ni compression.

		; save Ingame timers
		MOV	BX,word ptr [fhandler_SaveGame]
		MOV	DX,Timer_InGame_Counter
		MOV	CX,0x5				; 1 word (total seconds) + 3 bytes (Hours:minutes:seconds)
		MOV	AH,0x40
		INT	0x21

Avant de fermer le fichier, Planet X3 sauvegarde le compteur de temps générale (1 mot) et le temps “en jeu” 3 bytes

		MOV	AH,0x3e				; close file
		MOV	BX,word ptr [fhandler_SaveGame]
		INT	0x21
		RET	

Block Map

Offset Size Description
0x0000 0x8000 Carte
0x8000 0x1010 Unités/batiments
0x9010 0x0005 timers

Block d'unités/Batiments

Offset Size Description
+0x0000 0x0100 Type d'Unités/batiments
+0x0100 0x0100 Position X
+0x0200 0x0100 Position Y
+0x0300 0x0100 Target X
+0x0400 0x0100 Target Y
+0x0500 0x0100 OOT Type
+0x0600 0x0100 Unknow
+0x0700 0x0100 Points de Vie
+0x0800 0x0100 Unknow
+0x0900 0x0100 Generic Parameter A
+0x0A00 0x0100 Generic Parameter B
+0x0B00 0x0100 Generic Parameter C
+0x0C00 0x0100 Generic Parameter D
+0x0D00 0x0100 AL
+0x0E00 0x0100 Unknow
+0x0F00 0x0100 Etat du Silo Missile
+0x1000 0x0010 Bloc de configuration

Pour n'importe quel sous-block de 0x100 bytes est divisé en 2 sous sections, 1 pour les humains (offset 0x0000), 1 pour l'ordinateur (offset 0x0080).

Offset Taille Description
+0x0000 0x14 Unités mobiles Humaines
+0x0014 0x6C Batiments Humains
+0x0080 0x14 Unités mobiles Ordinateur
+0x0094 0x6C Batiments Ordinateur

Suivant le code, le nombre maximum d'unités mobiles humaine diffère.

  • Dans 2 fonctions, PX3 vérifie le status (offset 0x0000) pour les indices de 0 à 20 (0x00-0x14)
  • Dans 1 fonction, PX3 vérifie le status (offset 0x0000) pour les indices de 20 à 50 (0x14-0x32)
  • Dans 5 fonctions, PX3 vérifie le status (offset 0x0000) pour les indices de 0 à 64 (0x00-0x40)
  • Dans 2 fonctions, PX3 vérifie le status (offset 0x0000) pour les indices de 20 à 64 (0x14-0x40)

meme si le code présente bien des limites pour le joueur, je n'ai pas trouvé trace de limite similaire pour l'ordinateur (logiquement placée aux offset 0x80, 0x94, …)

Block de configuration

offset byte Description
+0 1 Décors de la carte ('1','2','3')
+1 1 Unité sélectionnée
+2 1 Réserve de minerais
+3 1 Réserve de Gaz
+4 1 Réserve d'électricité
+5 0xB inconnu

Block "Timer"

offset byte description
+0 2 temps global en jeu (en ms)
+2 1 Temps : Secondes
+3 1 Temps : minutes
+4 1 Temps : heures

Information détaillée

Offset Taille Taille en Bytes Joueur/
Ordinateur
Type Description
0000 8000 32768 256×128 tableau de case (carte de jeu) 0x0000 = coin haut-gauche
8000 14 20 Joueur Unité type
8014 6C 108 Joueur Batiment type
8080 80 128 Ordinateur mixte type
8100 14 20 Joueur Unité position X
8114 6C 108 Joueur Batiment position X
8180 80 128 Ordinateur mixte position X
8200 14 20 Joueur Unité position Y
8214 6C 108 Joueur Batiment position Y
8280 480 1152 Ordinateur mixte position Y
8700 14 20 Joueur Unité Vie
8714 6C 108 Joueur Batiment Vie
8780 190 400 Ordinateur Batiment Vie
8910 6F0 1776 Joueur Missile Silot Vide/Plein
9000

Type de Carte/Décors

Valeur Description
0x31 Champs “green valey”
0x32 Monde de glace (ice)
0x33 désert

Type d'Unité mobiles

Valeur Description
0x01 builder
0x02 tank
0x03 Heavy Tank
0x04 frigate
0x1F Missile ?

Type de Batiments

Valeur Proriétaire Description
0x14 Joueur Headquarters
0x15 Joueur Radar
0x16 Joueur Power Station
0x17 Joueur Solar Panel
0x19 Joueur factory
0x1A Joueur Missile Silo
0x1B Joueur Smelter
Joueur Refenery
0x21 Ennemi Headquarters (Pyramids)
Ennemi Academy
Ennemi Clone Facility
Ennemi Research Building
Ennemi Factory
Ennemi Sentry Pod

Tiles

back2root/reverse-engineering/planet-x3/part2-savegame_dat.txt · Dernière modification : 2023/01/17 09:07 de frater