VB/VB.Net Décryptage des Maps

Inscrit
23 Mars 2017
Messages
1
Reactions
0
#1
Bonjour à tous,

Après quelques jours de réflexions sur le sujet, j'ai enfin réussi à recréer les classes Map, Fixture, Layer, Cell, CellData et les classes Elements.
Mon objectif final consiste à obtenir la position des éléments interactifs, dont les ressources, sur les cartes.

Cela fait un bon moment déjà que j'essayais de décrypter les d2p, j'ai enfin compris cette histoire de zlib et j'obtiens bien le header à 77.

Au début tout se passe bien, mais comme je vais le détailler par la suite, j'obtiens des résultats incohérents.

Je pense que j'ai raté une étape quelque part, et j'en appelle à votre bienveillance pour m'aider à l'identifier.

J'obtiens un cryptage à vrai, en version 1 et avec 8236 de dataLenght. Etant en position 12, et ayant 8248 de données, jusque là tout semble bon.

Donc ensuite on décrypte les données, qu'on peut traiter. Sauf qu'à la fin, j'arrive seulement en position 7294 !

Les points sur lesquels je m'interroge :
- les boucles sur les backgrounds, foregrounds, layers et celldata vont-elle de 0 à *count ou de 0 à *count -1 ?
- les unsignedbyte, quelle est la différence avec un simple readbyte ? -128 ?

Cela fait deux jours maintenant que je n'avance plus, je me permets donc de solliciter l'aide d'experts pour m'aider ! Je vous remercie d'avance :p

Voici mes classes actuellement, j'en appelle à votre indulgence, je débute avec le langage :p

On part d'un flux décompressé via ionic.zlib.decompress contenant les bytes du d2p (je fais mes tests sur 0/103549440.dlm et 0/119013380.dlm jusqu'à présent).

Class Map:
Imports System.IO
Imports System.Text
Public Class Map

    Private zipReader As BigEndianReader

    'Attributes
    Private header As Integer
    Private mapVersion As Integer
    Private id As Integer
    Private encrypted As Boolean
    Private encryptionVersion As Integer
    Private dataLen As Integer

    Private relativeId As Integer
    Private mapType As Integer
    Private subAreaId As Integer
    Private topNeighbourId As Integer
    Private bottomNeighbourId As Integer
    Private leftNeighbourId As Integer
    Private rightNeighbourId As Integer
    Private shadowBonusOnEntities 'As ULong

    Private backgroundAlpha 'As Integer
    Private backgroundRed 'As Integer
    Private backgroundGreen 'As Integer
    Private backgroundBlue ' As Integer
    Private gridColor 'As Integer
    Private backgroundColor 'As Integer

    Private zoomScale As Double
    Private zoomOffsetX As Integer
    Private zoomOffsetY As Integer

    Private tacticalModeTemplateId As Integer

    Private useLowPassFilter As Boolean
    Private useReverb As Boolean
    Private presetId As Integer
    Private backgroundsCount As Integer
    Private foregroundsCount As Integer
    Private cellsCount As Integer
    Private groundCRC As Integer
    Private layersCount As Integer

    Public backgroundFixtures As Dictionary(Of Integer, Fixture)
    Public foregroundFixtures As Dictionary(Of Integer, Fixture)
    Public layers As Dictionary(Of Integer, Layer)
    Public cells As Dictionary(Of Integer, CellData)
    Public elements As Dictionary(Of Integer, BasicElement)

    Public Sub New(ByVal str As Stream)
        Dim decryptionKey As Byte()
        Dim decryptionKeyString As String
        decryptionKeyString = "649ae451ca33ec53bbcbcc33becf15f4"
        'decryptionKey = Hex.toArray(Hex.fromString(decryptionKeyString))
        decryptionKey = Encoding.UTF8.GetBytes(decryptionKeyString)
        Dim i As Integer
        zipReader = New BigEndianReader(str)
        zipReader.Seek(0)
        header = zipReader.ReadBytes(1)(0)
        If header = 77 Then
            mapVersion = zipReader.ReadBytes(1)(0)
            id = zipReader.readUInt
            If mapVersion >= 7 Then
                encrypted = zipReader.ReadBoolean
                encryptionVersion = zipReader.ReadBytes(1)(0)
                dataLen = zipReader.ReadInt32
                Dim encryptedData As Byte()
                encryptedData = zipReader.ReadBytes(dataLen)
                For i = 0 To encryptedData.Length - 1
                    encryptedData(i) = encryptedData(i) Xor decryptionKey(i Mod decryptionKey.Length)
                Next
                zipReader = New BigEndianReader(New MemoryStream(encryptedData))
                zipReader.Seek(0)
            End If
            relativeId = zipReader.readUInt
            mapType = zipReader.ReadBytes(1)(0)
            subAreaId = zipReader.ReadInt32
            topNeighbourId = zipReader.ReadInt32
            bottomNeighbourId = zipReader.ReadInt32
            leftNeighbourId = zipReader.ReadInt32
            rightNeighbourId = zipReader.ReadInt32
            shadowBonusOnEntities = zipReader.readUInt 'uint mais ça chie
            Dim readColor 'As Long
            Dim gridAlpha 'As Long
            Dim gridRed 'As Long
            Dim gridGreen ' As Long
            Dim gridBlue 'As Long
            If mapVersion >= 9 Then
                readColor = zipReader.ReadInt32
                backgroundAlpha = (readColor And 4278190080) >> 32
                backgroundRed = (readColor And 16711680) >> 16
                backgroundGreen = (readColor And 65280) >> 8
                backgroundBlue = readColor And 255
                readColor = zipReader.readUInt
                gridAlpha = (readColor And 4278190080) >> 32
                gridRed = (readColor And 16711680) >> 16
                gridGreen = (readColor And 65280) >> 8
                gridBlue = readColor And 255
                gridColor = ((gridAlpha And 255) << 32) Or ((gridRed And 255) << 16) Or ((gridGreen And 255) << 8) Or (gridBlue And 255)
            ElseIf mapVersion >= 3 Then
                backgroundAlpha = 0
                backgroundRed = zipReader.ReadInt32
                backgroundGreen = zipReader.ReadInt32
                backgroundBlue = zipReader.ReadInt32
            End If
            backgroundColor = ((backgroundAlpha And 255) << 32) Or ((backgroundRed And 255) << 16) Or ((backgroundGreen And 255) << 8) Or (backgroundBlue And 255)

            If mapVersion >= 4 Then
                zoomScale = zipReader.readUShort / 100
                zoomOffsetX = zipReader.ReadShort
                zoomOffsetY = zipReader.ReadShort
                If zoomScale < 1 Then
                    zoomScale = 1
                    zoomOffsetX = 0
                    zoomOffsetY = 0
                End If
            End If

            If mapVersion > 10 Then
                tacticalModeTemplateId = zipReader.ReadInt32
            End If

            useLowPassFilter = zipReader.ReadBoolean
            useReverb = zipReader.ReadBoolean
            If useReverb = True Then
                presetId = zipReader.ReadInt32
            Else
                presetId = -1
            End If
            backgroundsCount = zipReader.ReadBytes(1)(0)
            backgroundFixtures = New Dictionary(Of Integer, Fixture)
            'If backgroundsCount > 0 Then
            For i = 0 To backgroundsCount
                backgroundFixtures.Add(i, New Fixture(zipReader))
            Next
            'End If
            foregroundsCount = zipReader.ReadBytes(1)(0)
            foregroundFixtures = New Dictionary(Of Integer, Fixture)
            'If foregroundsCount > 0 Then
            For i = 0 To foregroundsCount
                foregroundFixtures.Add(i, New Fixture(zipReader))
            Next
            'End If
            cellsCount = 560 'Original dans map.as, c'est une constante dans AtouinConstants 
            zipReader.ReadInt32() 'Original dans maps.as
            groundCRC = zipReader.ReadInt32
            layersCount = zipReader.ReadBytes(1)(0)
            layers = New Dictionary(Of Integer, Layer)
            For i = 0 To layersCount
                layers.Add(i, New Layer(zipReader, mapVersion))
            Next
            cells = New Dictionary(Of Integer, CellData)
            For i = 0 To cellsCount
                cells.Add(i, New CellData(zipReader, i, mapVersion))
                'un truc sur le système de movement, skip
            Next
        End If
    End Sub

End Class
Class Fixture:
Public Class Fixture
    Private fixtureId As Integer
    Private offset As Point
    Private rotation As Integer
    Private xScale As Integer
    Private yScale As Integer
    Private redMultiplier As Integer
    Private greenMultiplier As Integer
    Private blueMultiplier As Integer
    Private hue As Integer
    Private alpha As Integer

    Public Sub New(ByVal reader As BigEndianReader)
        fixtureId = reader.ReadInt32
        Dim offsetX As Integer
        Dim offsetY As Integer
        offsetX = reader.ReadShort
        offsetY = reader.ReadShort
        offset = New Point(offsetX, offsetY)
        rotation = reader.ReadShort
        xScale = reader.ReadShort
        yScale = reader.ReadShort
        redMultiplier = reader.ReadBytes(1)(0) - 128
        greenMultiplier = reader.ReadBytes(1)(0) - 128
        blueMultiplier = reader.ReadBytes(1)(0) - 128
        hue = redMultiplier Or greenMultiplier Or blueMultiplier
        alpha = reader.ReadBytes(1)(0)
    End Sub
End Class
Class Layer:
Public Class Layer
    Private layerId As Integer
    Private cellsCount As Integer
    Public cells As Dictionary(Of Integer, Cell)

    Public Sub New(ByVal reader As BigEndianReader, ByVal mapVersion As Integer)
        If mapVersion >= 9 Then
            layerId = reader.ReadBytes(1)(0)
        Else
            layerId = reader.ReadInt32
        End If
        cellsCount = reader.ReadShort()
        If cellsCount > 0 Then
            Dim i As Integer
            cells = New Dictionary(Of Integer, Cell)
            For i = 0 To cellsCount
                cells.Add(i, New Cell(reader, mapVersion))
            Next
            Dim maxMapCellId As Integer
            maxMapCellId = 560 - 1
            'si la dernière cellule est inférieure à 560, créer des cellules vides jusqu'à la 560ème
        End If
    End Sub

End Class
Class Cell:
Public Class Cell
    Private cellId As Integer
    Private elementsCount As Integer

    Private elements As Dictionary(Of Integer, BasicElement)

    Public Sub New(ByVal reader As BigEndianReader, ByVal mapVersion As Integer)
        Dim be As BasicElement
        Dim i As Integer
        cellId = reader.ReadShort
        elementsCount = reader.ReadShort
        elements = New Dictionary(Of Integer, BasicElement)
        For i = 0 To elementsCount
            be = New BasicElement().getElementFromType(reader, mapVersion)
            elements.Add(i, be)
        Next
    End Sub
End Class
Class CellData:
Public Class CellData
    Private id As Integer

    Private _floor As Integer
    Private _mov As Boolean
    Private _nonWalkableDuringFight As Boolean
    Private _nonWalkableDuringRP As Boolean
    Private _los As Boolean
    Private _blue As Boolean
    Private _red As Boolean
    Private _visible As Boolean
    Private _farmCell As Boolean
    Private _havenbagCell As Boolean

    Private _losmov As Integer = 3

    Private speed As Integer
    Private mapChangeData As Integer

    Private moveZone As Integer

    Private _linkedZone As Integer
    Private _arrow As Integer = 0

    Public Sub New(ByVal reader As BigEndianReader, ByVal cellId As Integer, ByVal mapVersion As Integer)
        id = cellId
        _floor = reader.ReadBytes(1)(0) * 10
        If _floor = -1280 Then
            Exit Sub
        End If
        Dim tmpbytesv9 As Integer
        Dim topArrow As Boolean = False
        Dim bottomArrow As Boolean = False
        Dim rightArrow As Boolean = False
        Dim leftArrow As Boolean = False
        Dim tmpBits As Integer = 0
        If mapVersion >= 9 Then
            tmpbytesv9 = reader.ReadBytes(1)(0)
            _mov = (tmpbytesv9 & 1) = 0
            _nonWalkableDuringFight = (tmpbytesv9 & 2) <> 0
            _nonWalkableDuringRP = (tmpbytesv9 & 4) <> 0
            _los = (tmpbytesv9 & 8) = 0
            _blue = (tmpbytesv9 & 16) <> 0
            _red = (tmpbytesv9 & 32) <> 0
            _visible = (tmpbytesv9 & 64) <> 0
            _farmCell = (tmpbytesv9 & 128) <> 0
            If mapVersion >= 10 Then
                _havenbagCell = (tmpbytesv9 & 256) <> 0
                topArrow = (tmpbytesv9 & 512) <> 0
                bottomArrow = (tmpbytesv9 & 1024) <> 0
                rightArrow = (tmpbytesv9 & 2048) <> 0
                leftArrow = (tmpbytesv9 & 4096) <> 0
            Else
                topArrow = (tmpbytesv9 & 256) <> 0
                bottomArrow = (tmpbytesv9 & 512) <> 0
                rightArrow = (tmpbytesv9 & 1024) <> 0
                leftArrow = (tmpbytesv9 & 2048) <> 0
            End If
        Else
            _losmov = reader.ReadBytes(1)(0)
            _los = (_losmov & 2) >> 1 = 1
            _mov = (_losmov & 1) = 1
            _visible = (_losmov & 64) >> 6 = 1
            _farmCell = (_losmov & 32) >> 5 = 1
            _blue = (_losmov & 16) >> 4 = 1
            _red = (_losmov & 8) >> 3 = 1
            _nonWalkableDuringRP = (_losmov & 128) >> 7 = 1
            _nonWalkableDuringFight = (_losmov & 4) >> 2 = 1
        End If
        speed = reader.ReadBytes(1)(0)
        mapChangeData = reader.ReadBytes(1)(0)
        If mapVersion > 5 Then
            moveZone = reader.ReadBytes(1)(0)
        End If
        If mapVersion > 10 And ((_mov And Not _farmCell) Or (_mov And Not _nonWalkableDuringFight And Not _farmCell And Not _havenbagCell)) Then
            _linkedZone = reader.ReadBytes(1)(0)
        End If
        If mapVersion = 8 Then
            tmpBits = reader.ReadBytes(1)(0)
            _arrow = 15 & tmpBits
        End If
    End Sub
End Class
Class Elements:
Public Class BasicElement

    Public Function getBe(ByVal be As BasicElement)
        Return be
    End Function
    Public Function getElementFromType(ByVal reader As BigEndianReader, ByVal mapVersion As Integer) As BasicElement
        Dim type As Integer
        type = reader.ReadBytes(1)(0)
        If type = 2 Then
            Return New GraphicalElement(reader, mapVersion)

        ElseIf type = 33 Then
            Return New SoundElement(reader, mapVersion)
        Else
            Return Nothing
        End If
    End Function
End Class

Public Class GraphicalElement
    Inherits BasicElement
    Private elementId As Integer
    Private hue As Integer
    Private shadow As Integer
    Private offset As Point
    Private pixelOffset As Point
    Private altitude As Integer
    Private identifier As Integer
    Public Sub New(ByVal reader As BigEndianReader, ByVal mapVersion As Integer)
        elementId = reader.readUInt
        'hue colormultiplicator skip
        hue = reader.ReadBytes(1)(0)
        hue = reader.ReadBytes(1)(0)
        hue = reader.ReadBytes(1)(0)
        'shadow colormultiplicator skip
        shadow = reader.ReadBytes(1)(0)
        shadow = reader.ReadBytes(1)(0)
        shadow = reader.ReadBytes(1)(0)

        offset = New Point(0, 0)
        pixelOffset = New Point(0, 0)

        If mapVersion <= 4 Then
            offset.x = reader.ReadBytes(1)(0)
            offset.y = reader.ReadBytes(1)(0)
            pixelOffset.x = offset.x * 43
            pixelOffset.y = offset.y * 21.5
        Else
            pixelOffset.x = reader.ReadShort
            pixelOffset.y = reader.ReadShort
            offset.x = pixelOffset.x / 43 'atouin half width const
            offset.y = pixelOffset.y / 21.5 'atouin half height const
        End If
        altitude = reader.ReadBytes(1)(0)
        identifier = reader.readUInt
        'CalculateFinalTeint
    End Sub
End Class

Public Class SoundElement
    Inherits BasicElement
    Private soundId As Integer
    Private baseVolume As Integer
    Private fullVolumeDistance As Integer
    Private nullVolumeDistance As Integer
    Private minDelayBetweenLoops As Integer
    Private maxDelayBetweenLoops As Integer

    Public Sub New(ByVal reader As BigEndianReader, ByVal mapVersion As Integer)
        soundId = reader.ReadInt32
        baseVolume = reader.ReadShort
        fullVolumeDistance = reader.ReadInt32
        nullVolumeDistance = reader.ReadInt32
        minDelayBetweenLoops = reader.ReadShort
        maxDelayBetweenLoops = reader.ReadShort
    End Sub
End Class
Class BigEndianReader:
Imports System.IO
Imports System.Text

Public Class BigEndianReader
    Protected self As BinaryReader

    'Flash info on how to read binary data
    'http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/IDataInput.html

    Public Sub New(Stream As Stream) 'old: filestream
        self = New BinaryReader(Stream, Encoding.UTF8)
    End Sub

    Public Function ReadInt32()
        Dim Bits As Byte() = self.ReadBytes(4)
        Array.Reverse(Bits)
        Return BitConverter.ToInt32(Bits, 0)
    End Function

    Public Function ReadBoolean()
        Dim bool As Boolean = BitConverter.ToBoolean(self.ReadBytes(1), 0)
        If bool Then
            Return 1
        Else
            Return 0
        End If
    End Function

    Public Function ReadShort()
        Dim Bits As Byte() = self.ReadBytes(2)
        Array.Reverse(Bits)
        Return BitConverter.ToInt16(Bits, 0)
    End Function

    Public Function ReadUTF()
        Dim n As Integer = ReadShort()
        Dim Bits As Byte() = self.ReadBytes(n)
        Return Encoding.UTF8.GetString(Bits)
    End Function

    Public Function ReadBytes(ByVal Number As Integer)
        Return self.ReadBytes(Number)
    End Function

    Public Function readDouble()
        Dim Bits As Byte() = self.ReadBytes(8)
        Array.Reverse(Bits)
        Return BitConverter.ToDouble(Bits, 0)
    End Function

    Public Function readUInt()
        Dim Bits As Byte() = self.ReadBytes(4)
        Array.Reverse(Bits)
        Return BitConverter.ToUInt32(Bits, 0)
    End Function
    Public Function readUShort()
        Dim Bits As Byte() = self.ReadBytes(2)
        Array.Reverse(Bits)
        Return BitConverter.ToUInt16(Bits, 0)
    End Function

    Public Function Position()
        Return self.BaseStream.Position
    End Function

    Public Function Seek(ByVal offset As Long)
        self.BaseStream.Seek(offset, SeekOrigin.Begin)
        Return True
    End Function
End Class
Etant novice, les conseils tant sur la forme que sur le fond du code sont également fort bienvenus ! Merci
 
Haut Bas