International patching system ( gba rom tools ) : appliquer ou créer un patch ips


Description

Voila un petit prog tout simple, tiré de mon GBATOols (les patchs pour les roms game boy advance sont
tous des IPS) permettant de créer ou d'appliquer un patch ips (system de patch dit universel).
En regardant un peu la structure de ces fichiers .ips, on voit qu'elle est plus que simple :
"PATCH" & Offset_des_octets_a_modifié_sur_3_octets & Longueur_du_groupe_d_octets & Octets_a_modifié &
Offset_des_octets_a_modifié_sur_3_octets & Longueur_du_groupe_d_octets & Octets_a_modifié & (etc..) & EOF
Ce qui m'a donc permis d'ecrire ce code en vitesse.
Il peut surement être optimisé, je n'ai pas passé beaucoup de temps dessus.
J'ai mis un projet exemple dans le zip.

Source / Exemple :


Private Sub createips(ByVal chemin1 As String, ByVal chemin2 As String, ByVal chemin3 As String)
        Dim ips As String
        Dim ipsz() As Byte
        '     Try
        Dim hbread1 As New BinaryReader(File.OpenRead(chemin1))
        Dim hbread2 As New BinaryReader(File.OpenRead(chemin2))
        Dim smallestfile As Integer
        Dim F_array1(FileLen(chemin1) - 1) As Byte
        Dim F_array2(FileLen(chemin2) - 1) As Byte
        hbread1.BaseStream.Seek(0, SeekOrigin.Begin)
        hbread1.Read(F_array1, 0, FileLen(chemin1))
        hbread1.BaseStream.Flush()
        hbread1.Close()
        hbread2.BaseStream.Seek(0, SeekOrigin.Begin)
        hbread2.Read(F_array2, 0, FileLen(chemin2))
        hbread2.BaseStream.Flush()
        hbread2.Close()
        Dim maxi As Long
        Dim mini As Long
        Dim isastring As Boolean
        Dim n As Long
        Dim intlength As Integer
        Dim tmp As String
        Dim tmp2 As String
        Dim tmpstring As String

        If F_array1.GetUpperBound(0) > F_array2.GetUpperBound(0) Then
            maxi = F_array1.GetUpperBound(0)
            mini = F_array2.GetUpperBound(0)
        End If
        If F_array1.GetUpperBound(0) < F_array2.GetUpperBound(0) Then
            'Si le fichier modifié est + gros que le fichier source
            'on commence le fichier ips (par la fin) en ecrivant les octets suplémentaire 
            'suivi de la traditionel syntaxe offset sur 3 bytes, length sur 2 bytes
            maxi = F_array2.GetUpperBound(0)
            mini = F_array1.GetUpperBound(0)
            For n = maxi To mini + 1 Step -1

                tmpstring = Convert.ToChar(F_array2(n)) & tmpstring
                intlength += 1
            Next
            tmp = convertfrombase10(mini + 1).PadLeft(6, "0")
            tmp2 = convertfrombase10(intlength).PadLeft(4, "0")
            ips = Convert.ToChar(convertfrombase16(tmp.Substring(0, 2))) & _
   Convert.ToChar(convertfrombase16(tmp.Substring(2, 2))) & _
   Convert.ToChar(convertfrombase16(tmp.Substring(4, 2))) & _
   Convert.ToChar(convertfrombase16(tmp2.Substring(0, 2))) & _
   Convert.ToChar(convertfrombase16(tmp2.Substring(2, 2))) & tmpstring
        End If
        If F_array1.GetUpperBound(0) = F_array2.GetUpperBound(0) Then
            maxi = F_array2.GetUpperBound(0)
            mini = F_array2.GetUpperBound(0)
        End If

        intlength = 0

        For n = mini To 0 Step -1
            If F_array1(n) <> F_array2(n) Then 'si les deux octets sont differents :
                If isastring = False Then
                    intlength = 1
                    tmp2 = convertfrombase10(intlength).PadLeft(4, "0")
                    tmp = convertfrombase10(n).PadLeft(6, "0")
                    tmpstring = Convert.ToChar(F_array2(n))
                    isastring = True
                Else
                    'si isastring = true c'est que le caractere precedent etait different lui aussi
                    intlength += 1
                    tmp2 = convertfrombase10(intlength).PadLeft(4, "0")
                    tmp = convertfrombase10(n).PadLeft(6, "0")
                    tmpstring = Convert.ToChar(F_array2(n)) & tmpstring
                End If
                isastring = True
            Else
                If intlength >= 1 Then
                    'on ecrit offset sur 3 bytes, length sur 2 bytes puis l'(les) octet(s)
                    'different(s) au debut de la variable ips (on ecrit le fichier à l'envers)
                    ips = Convert.ToChar(convertfrombase16(tmp.Substring(0, 2))) & _
   Convert.ToChar(convertfrombase16(tmp.Substring(2, 2))) & _
   Convert.ToChar(convertfrombase16(tmp.Substring(4, 2))) & _
   Convert.ToChar(convertfrombase16(tmp2.Substring(0, 2))) & _
   Convert.ToChar(convertfrombase16(tmp2.Substring(2, 2))) & tmpstring & ips
                End If
                isastring = False
                intlength = 0
            End If
        Next
        ips = "PATCH" & ips & "EOF"

        'on ecrit au sens propre le fichier
        Dim F_array3(ips.Length - 1) As Byte
        For n = 0 To ips.Length - 1
            F_array3(n) = Convert.ToByte(ips.Chars(n))
        Next
        Dim hbwrite As New BinaryWriter(File.OpenWrite(chemin3))
        hbwrite.BaseStream.Seek(0, SeekOrigin.Begin)
        hbwrite.Write(F_array3, 0, ips.Length)
        hbwrite.BaseStream.Flush()
        hbwrite.Flush()
        hbwrite.Close()
        MsgBox("Ips creation succesful")
        '      Catch ex As Exception
        '         MsgBox(ex.Message)
        '       End Try
    End Sub

    Private Sub apply_ips(ByVal chemin1 As String, ByVal chemin2 As String, ByVal chemin3 As String)
        Dim ips As String
        Dim ipsz() As Byte
        Dim n As Integer
        '   Try
        Dim hbread1 As New BinaryReader(File.OpenRead(chemin1))
        Dim hbread2 As New BinaryReader(File.OpenRead(chemin2))
        Dim F_array1(FileLen(chemin1) - 1) As Byte
        Dim F_array2(FileLen(chemin2) - 1) As Byte
        hbread1.BaseStream.Seek(0, SeekOrigin.Begin)
        hbread1.Read(F_array1, 0, FileLen(chemin1))
        hbread1.BaseStream.Flush()
        hbread1.Close()
        hbread2.BaseStream.Seek(0, SeekOrigin.Begin)
        hbread2.Read(F_array2, 0, FileLen(chemin2))
        hbread2.BaseStream.Flush()
        hbread2.Close()
        Dim patch As String
        Dim tmphexoffset As String
        Dim tmphexlength As String
        Dim tmplength As Integer
        Dim tmpoffset As Integer
        Dim tmpstring As String
        Dim m As Integer
        Dim a As Integer
        Dim l As Integer
        patch = Convert.ToChar(F_array2(0)) & Convert.ToChar(F_array2(1)) & Convert.ToChar(F_array2(2)) & Convert.ToChar(F_array2(3)) & Convert.ToChar(F_array2(4))
        If patch = "PATCH" Then
            n = 5
            Do
                'on lit dans tmphexoffset les 3 prochains octets, qui represente 
                'l'offset des octets à modifier
                tmphexoffset = convertfrombase10(F_array2(n)).PadLeft(2, "0") & convertfrombase10(F_array2(n + 1)).PadLeft(2, "0") & convertfrombase10(F_array2(n + 2)).PadLeft(2, "0")
                'si on rencontre les 3 octets E O F , on sort de la boucle
                If tmphexoffset = "454f46" And n >= F_array2.Length - 4 Then Exit Do
                'on lit dans tmphexlength les 2 prochains octets, qui represente
                'la taille des octets à modifier
                tmphexlength = convertfrombase10(F_array2(n + 3)).PadLeft(2, "0") & convertfrombase10(F_array2(n + 4)).PadLeft(2, "0")
                '(conversions)
                tmplength = convertfrombase16(tmphexlength)
                tmpoffset = convertfrombase16(tmphexoffset)
                tmpstring = ""
                'on lit maintenant les octets a modifier dans tmpstring
                For m = n + 5 To n + 5 + tmplength - 1
                    tmpstring += Convert.ToChar(F_array2(m))
                Next
                l = 0
                'si les octets sont a ecrire plus loin que la fin du fichier, on agrandi le tableau
                If (tmpoffset + tmplength - 1) > F_array1.Length Then ReDim Preserve F_array1(tmpoffset + tmplength - 1)
                'on modifie les octets lues precedements dans le tableau de byte du fichier à patcher
                For a = tmpoffset To tmpoffset + tmplength - 1
                    F_array1(a) = Convert.ToByte(tmpstring.Chars(l))
                    l += 1
                Next
                n = n + 5 + tmplength
            Loop
            'on ecrit le tableau
            Dim hbwrite As New BinaryWriter(File.OpenWrite(chemin3))
            hbwrite.BaseStream.Seek(0, SeekOrigin.Begin)
            hbwrite.Write(F_array1, 0, F_array1.Length)
            hbwrite.BaseStream.Flush()
            hbwrite.Flush()
            hbwrite.Close()
        Else
            MsgBox("bad ips file")
        End If
        MsgBox("Ips patching succesful")
        '       Catch ex As Exception
        '           MsgBox(ex.Message)
        '       End Try
    End Sub

    Public Function convertfrombase16(ByVal hexa As String) As Integer
        Return Convert.ToInt64(hexa, 16) 'converti en type int64(equivalent de long) et en base 10 la valeur de "hexa" à partir d'une base 16 
    End Function

    Public Function convertfrombase10(ByVal dec As Integer) As String
        Return Convert.ToString(dec, 16)  'converti la valeur Long de "dec" en base 16
    End Function

Conclusion :


Commentaires...?

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.