Tout à fait de l'avis de Nine.
Je suis allé un peu plus loin, mais il reste énormément de travail pour en faire quelquechose de robuste et complet.
Je n'ai pas traité les "extra data".
Il faut coder pour tous les types manquants.
Il faut réorganiser la structure pour lire les "subrecords" récursivement.
Code : Tout sélectionner
#include <FileConstants.au3>
#include <Date.au3>
Local $aRecTypes = [ _
[ 0, "Header1", Decode_0], _
[ 1, "Header2", Decode_1], _
[ 2, "Waypoint", Decode_2], _
[ 3, "Alert", Decode_3], _
[ 4, "Bitmap reference", Decode_4], _
[ 5, "Bitmap", Decode_5], _
[ 6, "Category reference", Decode_6], _
[ 7, "Category", Decode_7], _
[ 8, "Area", Decode_8], _
[ 9, "POI Group", Decode_9], _
[10, "Comment", Decode_10], _
[11, "Address", Decode_11], _
[12, "Contact", Decode_12], _
[13, "Image", Decode_13], _
[14, "Description", Decode_14], _
[15, "Product info", Decode_15], _
[16, "Alert circles", Decode_16], _
[17, "Copyright", Decode_17], _
[18, "Media", Decode_18], _
[19, "Safety camera", Decode_19], _
[20, "Type 20 ???", Decode_Unknown], _
[21, "Additions", Decode_21], _
[22, "Type 22 ???", Decode_Unknown], _
[23, "Type 23 ???", Decode_Unknown], _
[24, "Type 24 ???", Decode_Unknown], _
[25, "Type 25 ???", Decode_Unknown], _
[26, "Type 26 ???", Decode_Unknown], _
[27, "Alert trigger options", Decode_27], _
[0xFFFF, "End", Decode_End] _
]
Local $tRecHeader = DllStructCreate("ushort rectype;ushort flags;uint size")
Local $tRecHeader_ = DllStructCreate("byte header[" & DllStructGetSize($tRecHeader) & "]", DllStructGetPtr($tRecHeader))
; lecture du fichier binaire
Local $hFile = FileOpen("test.gpi", $FO_BINARY)
Local $vData = FileRead($hfile)
FileClose($hfile)
Local $iDataSize = BinaryLen($vData)
Local $iIndex = 1
Local $vHeader
Local $iSize
Local $iType
Local $iIndent
; tant qu'on n'a pas fini de tout décoder
While $iIndex < $iDataSize
; lecture de l'en-tête du prochain record
$iSize = DllStructGetSize($tRecHeader)
$tRecHeader_.header = BinaryMid($vData, $iIndex, $iSize)
$iIndex += $iSize
$iType = $tRecHeader.rectype
$iIndent = 0
Print($aRecTypes[$iType][1])
$iIndent = 1
$aRecTypes[$iType][2]()
$iIndent = 0
WEnd
Func Decode_0()
Local Static $t = DllStructCreate("align 1;char mark[6];char version[2];uint gdate; byte flags1;byte obfusc;ushort size")
Local Static $t_ = DllStructCreate("byte header[" & DllStructGetSize($t) & "]", DllStructGetPtr($t))
$iSize = DllStructGetSize($t)
$t_.header = BinaryMid($vData, $iIndex, $iSize)
$iIndex += $iSize
Print("Marqueur : " & $t.mark)
Print("Version : " & $t.version)
Print("Date : " & Decode_Gdate($t.gdate))
Print("Flags : 0x" & Hex($t.flags, 2))
Print("Obfusc. : 0x" & Hex($t.obfusc, 2))
$iSize = $t.size
Print("Nom : " & BinaryToString(BinaryMid($vData, $iIndex, $iSize)))
$iIndex += $iSize
EndFunc
Func Decode_1()
Local Static $t = DllStructCreate("align 1;char mark[3]; byte[3];char version[2];ushort cp; ushort flags")
Local Static $t_ = DllStructCreate("byte header[" & DllStructGetSize($t) & "]", DllStructGetPtr($t))
Local Static $mCP[]
$mCP[0x036A] = "Windows Thai"
$mCP[0x03B6] = "Big5 Traditional Chinese"
$mCP[0x04E2] = "Windows Central Europe"
$mCP[0x04E3] = "Windows Cyrillic"
$mCP[0x04E4] = "Windows Latin"
$mCP[0xFDE9] = "UTF-8"
$iSize = DllStructGetSize($t)
$t_.header = BinaryMid($vData, $iIndex, $iSize)
$iIndex += $iSize
Print("Marqueur : " & $t.mark)
Print("Version : " & $t.version)
Print("Codepage : " & $mCP[$t.cp])
Print("Flags : 0x" & Hex($t.flags, 4))
EndFunc
Func Decode_2()
Print()
EndFunc
Func Decode_3()
Print()
EndFunc
Func Decode_4()
Print()
EndFunc
Func Decode_5()
Print()
EndFunc
Func Decode_6()
Print()
EndFunc
Func Decode_7()
Print()
EndFunc
Func Decode_8()
Print()
EndFunc
Func Decode_9()
Print()
EndFunc
Func Decode_10()
Print()
EndFunc
Func Decode_11()
Print()
EndFunc
Func Decode_12()
Print()
EndFunc
Func Decode_13()
Print()
EndFunc
Func Decode_14()
Print()
EndFunc
Func Decode_15()
Print()
EndFunc
Func Decode_16()
Print()
EndFunc
Func Decode_17()
Print()
EndFunc
Func Decode_18()
Print()
EndFunc
Func Decode_19()
Print()
EndFunc
Func Decode_21()
Print()
EndFunc
Func Decode_27()
Print()
EndFunc
Func Decode_End()
Print()
EndFunc
Func Decode_Unknown()
Print("Type inconnu " & $iType & " : décalage probable dans les données !")
EndFunc
Func Decode_Gdate($n)
; $n est le nombre de secondes depuis 1989-12-31 00:00:00 (un format alakon !)
; la valeur de unixepoch('2000-01-01 00:00:00') - unixepoch('1989-12-31 00:00:00') est 315619200 (secondes)
; car notre _DateAdd ne fonctionne qu'à partir de 2000-01-01 00:00:00
Return StringReplace(_DateAdd("s", $n - 315619200, "2000-01-01 00:00:00"), "/", "-")
EndFunc
Func Print($s)
For $i = 1 To $iIndent
ConsoleWrite(@TAB)
Next
ConsoleWrite($s & @CRLF)
EndFunc