Snes : calculer/fixer le checksum + lire/editer le header d'une rom super famicom (super nintendo / super nes)


Description

Hey hey.
Ce petit outil permet de calculer et fixer les bad checksum de vos roms sfc (eviter donc les "checksum: failed" de zsnes),
mais aussi lire, et modifier les informations qui se trouvent dans le header de la rom comme le nom du jeu (affiché par les emulateurs lorsque vous lancez un jeu),
la taille de la rom, l'editeur, le type de sauvegarde, le type de rom lui meme, etc etc).
Il permet enfin d'ajouter ou de supprimer le 512Header au debut des fichiers rom snes et de lister dans un fichier texte les infos de toutes les roms d'un dossier.
Je voulais mettre ce programme depuis longtemps puis comme d'hab j'ai arreté le projet (il etait devenu
un frontend pour zsnes et snes9x).
Mais etant donné que je trouve cette partie de code plus qu'interessante, je la met a disposition.
L'algo de calcul du checksum est un portage d'un code en C trouvé sur le net il y a longtemps (quand je ne comprenais pas
encore ce que c'etait... ^^)... mais je ne trouve plus la source :( Desolé pour l'auteur.
Ensuite la liste des editeurs vient de l'excellente doc "SNES KART" qui m'a beaucoup aidé pour pas mal de corrections.
Voila voila, j'espere que certains y verront une utilité (le programme vise, il est vrai, une minorité de gens... les FANS de la sfc qui
en plus, ont le framework .net v1.1 ... lol =D )
voyez le zip pour un exemple d'utilisation de la classe de calcul.
En esperant voir quelques commentaires.

EDIT :
Vous pouvez trouver le fichier executable compilé sur http://batto.online.fr/Roms/HbSnesToolsv0.9.zip

Source / Exemple :


Imports System.IO
Public Class checksumcalc

    Public formz1 As Form1
    Public resultstrz As String
    Const LO_ROM = 0
    Const HIGH_ROM = 1
    Const NUMB_VALUES = 39
    Const LOROM_BANKSIZE = 32768
    Const TRUEz = 1
    Const FALSEz = 0
    Const ARG_NUMB = 3
    Const ROM_NAME_LOROM_ADDR = 33216
    Const ROM_NAME_HIROM_ADDR = 65984
    Const REVERSE_CHKSM_ADDR_LOROM = 33244
    Const CHKSM_ADDR_LOROM = 33246
    Const REVERSE_CHKSM_ADDR_HIROM = 66012
    Const CHKSM_ADDR_HIROM = 66014
    Const CPL_VALUE = &HFFFF&
    Const SIZE_HEADER = 512
    Const SMALL_SIZE = 1049088
    Const MAJOR_SIZE = 2097664
    Const MAX_SIZE = 4194816
    Public rom As String
    Public TailleFichier, TypeRom, Correction, Is512Header As Long
    Public RomChecksum As Integer
    Public ChecksumCpl As Integer
    Public RealChecksum As Integer
    Public tmpromchecksum As String
    Public tmpchecksumcpl As String
    Public romname As String
    Public romtype As String
    Public romsram As Integer
    Public romvideo As Integer
    Public romlicense As Integer
    Public romversion As Integer
    Public rommakeup As Integer
    Public romsizeinrom As Integer
    Dim titre As String = "Batto checksum algorithm"

    Public Function DefineTypeRom() As Integer
        'defini le type de rom
        Dim tmpb As Boolean = False
        Dim n As Integer
        For n = 0 To 38
            If StandardSizes(n).size = TailleFichier Then
                tmpb = True
                Exit For
            End If
        Next
        tmpromchecksum = Convert.ToString(CLng(F_array(REVERSE_CHKSM_ADDR_HIROM - Correction + 1)), 16).PadLeft(2, "0") & Convert.ToString(CLng(F_array(REVERSE_CHKSM_ADDR_HIROM - Correction)), 16).PadLeft(2, "0")
        If tmpromchecksum = "0000" Then
            ChecksumCpl = 0
        Else
            ChecksumCpl = Convert.ToInt64(tmpromchecksum, 16)
        End If
        tmpchecksumcpl += Convert.ToString(CLng(F_array(REVERSE_CHKSM_ADDR_HIROM - Correction + 3)), 16).PadLeft(2, "0") & Convert.ToString(CLng(F_array(REVERSE_CHKSM_ADDR_HIROM - Correction + 2)), 16).PadLeft(2, "0")
        RomChecksum = Convert.ToInt64(tmpchecksumcpl, 16)
        If (RomChecksum + ChecksumCpl) = CPL_VALUE Then Return HIGH_ROM Else Return LO_ROM
        If tmpb = True Then
            Return LO_ROM
        Else
        End If
    End Function

    Sub GetRomInfos()
        'on lit les infos contenues dans la rom et on place les offsets dans le tableau offsetz
        Dim seekint As Integer
        Dim n As Integer
        Select Case TypeRom
            Case LO_ROM
                seekint = ROM_NAME_LOROM_ADDR - Correction
                offsetz(0) = seekint
                For n = 0 To 20
                    romname += Chr(F_array(seekint + n))
                Next
                offsetz(1) = seekint + 22
                romtype = F_array(seekint + 22)
                offsetz(2) = seekint + 24
                romsram = F_array(seekint + 24)
                offsetz(3) = seekint + 25
                romvideo = F_array(seekint + 25)
                offsetz(4) = seekint + 26
                romlicense = F_array(seekint + 26)
                offsetz(5) = seekint + 27
                romversion = F_array(seekint + 27)
                rommakeup = F_array(seekint + 21)
                offsetz(6) = seekint + 21
                romsizeinrom = F_array(seekint + 23)
                offsetz(7) = seekint + 23
                seekint = REVERSE_CHKSM_ADDR_LOROM - Correction
                tmpchecksumcpl = Convert.ToString(CLng(F_array(seekint + 1)), 16).PadLeft(2, "0") & Convert.ToString(CLng(F_array(seekint)), 16).PadLeft(2, "0")
                ChecksumCpl = Convert.ToInt64(tmpchecksumcpl, 16)
                tmpromchecksum = Convert.ToString(CLng(F_array(seekint + 3)), 16).PadLeft(2, "0") & Convert.ToString(CLng(F_array(seekint + 2)), 16).PadLeft(2, "0")
                RomChecksum = Convert.ToInt64(tmpromchecksum, 16)
            Case HIGH_ROM
                seekint = ROM_NAME_HIROM_ADDR - Correction
                offsetz(0) = seekint
                For n = 0 To 20
                    romname += Chr(F_array(seekint + n))
                Next
                rommakeup = F_array(seekint + 21)
                romtype = F_array(seekint + 22)
                romsizeinrom = F_array(seekint + 23)
                romsram = F_array(seekint + 24)
                romvideo = F_array(seekint + 25)
                romlicense = F_array(seekint + 26)
                romversion = F_array(seekint + 27)
                offsetz(1) = seekint + 22
                offsetz(2) = seekint + 24
                offsetz(3) = seekint + 25
                offsetz(4) = seekint + 26
                offsetz(5) = seekint + 27
                offsetz(6) = seekint + 21
                offsetz(7) = seekint + 23
                seekint = REVERSE_CHKSM_ADDR_HIROM - Correction
                tmpchecksumcpl = ""
                tmpromchecksum = ""
                tmpchecksumcpl = Convert.ToString(CLng(F_array(seekint + 1)), 16).PadLeft(2, "0") & Convert.ToString(CLng(F_array(seekint)), 16).PadLeft(2, "0")
                ChecksumCpl = Convert.ToInt64(tmpchecksumcpl, 16) 's
                tmpromchecksum = Convert.ToString(CLng(F_array(seekint + 3)), 16).PadLeft(2, "0") & Convert.ToString(CLng(F_array(seekint + 2)), 16).PadLeft(2, "0")
                RomChecksum = Convert.ToInt64(tmpromchecksum, 16)
        End Select
    End Sub

    Public Function analyse_rom() As Boolean
        'verifie que la rom est une roms snes par sa taille, avec ou sans headers
        Dim lenfile As Integer = FileLen(rom)
        hbread = New BinaryReader(File.OpenRead(rom))
        '-1 back

        ReDim F_array(lenfile) ' - 1)
        hbread.Read(F_array, 0, lenfile)
        hbread.BaseStream.Flush()
        hbread.Close()
        Dim seekint As Integer
        Dim n As Integer
        Dim i As Integer
        TailleFichier = F_array.GetUpperBound(0) '+1
        For i = 0 To NUMB_VALUES - 1
            If StandardSizes(i).size = TailleFichier Then
                InfosRom = StandardSizes(i)
                Correction = 0
                Is512Header = True
                Exit For
            ElseIf StandardSizes(i).size - SIZE_HEADER = TailleFichier Then
                InfosRom = StandardSizes(i)
                Correction = SIZE_HEADER
                Is512Header = False
                Exit For
            End If
        Next
        If i = NUMB_VALUES Then Return False
        TypeRom = DefineTypeRom()
        GetRomInfos()
        Return True
    End Function

    Sub CalculChecksum(ByVal TypeAlgo As Integer)
        'calcul le checksum selon le type d'algo defini en argument
        Dim bytez As Long
        Dim rompart1 As Integer = 0
        Dim seekint As Integer
        Dim n As Integer
        Dim tmprealchecksum As String
        RealChecksum = 0
        Select Case TypeAlgo
            Case 1
                seekint = SIZE_HEADER - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    bytez = F_array(n)
                    RealChecksum += Int(bytez)
                Next
            Case 2
                seekint = SIZE_HEADER - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    bytez = F_array(n)
                    RealChecksum += bytez
                Next
                seekint = SMALL_SIZE - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    rompart1 += F_array(n)
                Next
                RealChecksum -= rompart1
                RealChecksum += rompart1 * 4
            Case 3
                seekint = SIZE_HEADER - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    bytez = F_array(n)
                    RealChecksum += bytez
                Next
                seekint = SMALL_SIZE - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    rompart1 += F_array(n)
                Next
                RealChecksum -= rompart1
                RealChecksum += rompart1 * 2
            Case 4
                seekint = SIZE_HEADER - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    bytez = F_array(n)
                    RealChecksum += bytez
                Next
                seekint = MAJOR_SIZE - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    rompart1 += F_array(n)
                Next
                RealChecksum -= rompart1
                RealChecksum += rompart1 * 4
            Case 5
                seekint = SIZE_HEADER - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    bytez = F_array(n)
                    RealChecksum += bytez
                Next
                seekint = MAJOR_SIZE - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    rompart1 += F_array(n)
                Next
                RealChecksum -= rompart1
                RealChecksum += rompart1 * 2
            Case 6
                seekint = SIZE_HEADER - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    bytez = F_array(n)
                    RealChecksum += bytez
                Next
                seekint = MAX_SIZE - Correction
                For n = seekint To F_array.GetUpperBound(0)
                    rompart1 += F_array(n)
                Next
                RealChecksum -= rompart1
                RealChecksum += rompart1 * 2
        End Select
    End Sub
End Class

Conclusion :


Il y a plein d'ammeliorations à faire, (à commencer par un design, un vrai ^^) mais pour l'instant
je n'ai pas trop le temps de le faire evoluer.
Je mettrais la version frontend si ça peut interesser quelqu'un, mais je dois revoir quelques problemes de configs avec zsnes.

Codes Sources

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.