CacheLib - GCF/NCF Library

    • VB.NET

    Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von razor8.

      CacheLib - GCF/NCF Library

      CacheLib - GCF/NCF Library

      CacheLib (GCFLib/SteamCacheLib) ist eine Bibliothek zum lesen, schreiben und entpacken von GameCacheFiles und NonCacheFiles bekannt aus dem SteamService. Diese Beta beinhaltet nur Standartfunktionen und ist in einem sehr frühen Entwicklungsstadium und da die Entwicklung noch lange dauern wird (aufgrund von Zeitmangel) veröffentliche ich diese frühe Version damit ich ein erstes Feedback bekomme und das Projekt den Ansprüchen entsprechend anpassen kann.

      Funktionen:
      Lesen, schreiben und manipulieren/modifizieren aller Strukturen(Manifest,FileAllocationTable,Checksums...)
      Extrahieren von (jetzt auch 4gb+) GCF/NCF-Datein

      Funktionen die noch in Entwicklung sind:
      Defragmentieren
      Diff-Files (Updates)
      GCF >>> ZIP Converter
      FileInjection


      (Diese Übersicht ist sehr stark vereinfacht)

      Hier einige Beispiele:
      siehe folgende posts bzw. enthaltenes Testprojekt!


      Sprache: VB.Net (4.0)
      IDE: VS2010
      Größe: 618Kb

      Download: Hier
      Projekt-Seite: singularity.us.to/razors-tools/gcflib/

      Wenn ihr diese Dll in einem eurer Programme benutzt sagt mir bitte bescheid und nennt meinen Namen in den Credits. Ihr könnt die Dll gerne einkompilieren.

      mfg

      rAzoR
      Dateien

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „razor8“ () aus folgendem Grund: neue version hinzugefügt

      ich kann den Beitrag leider nicht editieren da der Editor den Inhalt immer vervielfacht/aneinanderhänt, also kommen hier noch ein paar Infos:

      Den Original-Beitrag findet ihr hier oder auf cs.rin.ru im Developer-Forum. Wenn ihr am SourceCode Interessiert seit, ihn benutzen oder weiter entwickeln wollt, empfehle ich euch unbedingt diese Dokumentationen zu lesen: Game-Cache File Format und Non-Cache File Format.

      Hier könnt ihr von SteamCooker[RiN] erstellte NCF/GCF-Files zum testen der Lib runterladen.

      Noch ein weiteres Bild aus dem original Beitrag:


      Wenn ihr Fehler im Code findet,Verbesserungsvorschläge habt oder euch neue Funktionen wünscht, könnt ihr gerne in diesem Threat antworten, ich werde von Zeit zu Zeit hier vorbei sehen.
      Außerdem: Wenn ihr wollt das ich eine von euch programmierte Funktion zum SourceCode hinzufüge könnte diese auch einfach hier posten.

      mfg rAzoR
      1. Dies soll sowas wie ein Gemeinschaftsprojekt werden und der Code für jeden zugänglich sein... deshalb => Showroom
      2.
      Hawk1337: lies am besten die Dokumentation. Ein komplexe erkläre würde den rahmen sprengen, also in kurz:
      Eine GCF besteht aus:
      Einem FileHeader mit Informationen zur gesamten Datei.
      EinemBlockAllocationTable der als Index für komprimierte und verschlüsselte
      Datein zu verstehn ist. Hier handelt es sich immer nur um Offsets, Attribute und Zeiger
      Einem FileAllocationTable als Index für alle anderen Datein(Cluster)
      Dem Manifest(Map) das Informationen wie Dateinamen, relativ-pfad und größe beinhaltet
      Einer ChecksumTable die Checksummen der Blöcke/Cluster beinhaltet
      Dem DataFileHeader der angibt wo der erste Cluster (Offset) ist.
      Und zum Schluss kommen die Datein selbst.

      Also so etwas ähnliches wie ein archive zb ZIP. Der Steam-Service (ein Programm der Firma Valve) benutz dieses Format. Spieldatein werden in solchen Konstrukten(Cache) gespeichert.

      Anmerkung: GCF-Datein enhalten Spiel/Engine-Datein, diese können aber fragmentiert und unvollständing sein. NCF-Datein enthalten lediglich die Informationen über die Datein.

      zu deiner zweiten Frage:

      [line]=========================================================[/line]
      Als erstes musst du die Dll natürlich improtieren:

      VB.NET-Quellcode

      1. Imports CacheLib


      Dann kannst du eine GCF/NCF "Mounten" also laden, d.h. alle oben genannten Strukturen werden eingelesen:

      VB.NET-Quellcode

      1. Dim
      2. i As New SteamCache("DateiPfad") ' Es gibt noch mehre Überladungen mit anderen Parametern wie zb: Exceptions Ignoriren (nützlich bei beschädigten datein); Checksummen wiederherstellen/reparieren; Und natürlich die EntschlüsslungsKey falls die Gcf/Ncf verschlüsselte datein beinhaltet, zu findend sind diese Keys in der ContentDescription im Steam-Verzeichnis
      3. i.Mount(FileAccess.ReadWrite, FileShare.ReadWrite)' die Mountmethode lad nun alle nötigen informationen. wenn die Datei von anderen noch gelesen oder beschrieben werden soll müssen FileAccess und FileShare entsprechend gesetz werden
      4. 'danach solltest du überprüfen ob sie auch tatsächlich geladen wurde oder ob etwas schief gelaufen ist.
      5. If i.IsMounted = True Then
      6. Console.WriteLine(i.filepath & " successfully mounted")
      7. Else
      8. Console.WriteLine("Unable to mount " & i.FilePath)
      9. Console.Read()
      10. End If


      Nun da die Datei geladen ist kannst du damit arbeitn und sie zb entpacken, man kann dies auf mehrere Arten machen:
      AlleDatein sind in der FileMap eingetragen und mit einer Schleife kann man alle Einträge durchlaufen und entpacken. Ihr etwas code aus dem Debuggingprogram "TestTool":

      VB.NET-Quellcode

      1. Sub ExtractAllFiles(ByVal DestinationDir As String)
      2. Select Case i._CacheType
      3. Case SteamCache.CacheType.GameCacheFile
      4. For Each thing In i.MountedGCF.FileMap 'in der FileMap werden die Datein als FileObject, einer zusammenfasung aller wichten informationen,angelegt. Mit diesen ist es möglich exakt die gewünschte datei zu entpacken.
      5. ExtractFileObject(thing, DestinationDir)
      6. Next
      7. Case SteamCache.CacheType.NonCacheFile
      8. For Each thing In i.MountedNCF.FileMap
      9. ExtractFileObject(thing, DestinationDir)
      10. Next
      11. Case Else
      12. PostError("Invalid CacheType")
      13. End Select
      14. End Sub
      15. Sub ExtractFileObject(ByVal FileObject As Object, ByVal destinationdir As String)
      16. If destinationdir = Nothing Then
      17. destinationdir = CurDir()
      18. End If
      19. Select Case FileObject.GetType
      20. Case GetType(SteamCache.FileObject.GcfFileObject) 'die Typbestimmung wäre auch über i._CacheType möglich gewesen.
      21. Dim fobject As SteamCache.FileObject.GcfFileObject = FileObject
      22. destinationdir = destinationdir & fobject.ValidPathTree
      23. If fobject.Attribute <>
      24. SteamCache.Manifest.Nodes.NodeAttribute.Directory Then 'nun wird festgestellt ob es sich um eine Datei oder ein verzeichniss handelt(dies dient nur zur ausgabe, die extract-methoden handln das selbst)
      25. Console.Write("Extracting " & fobject.ValidPathTree & fobject.FileName & "...")
      26. Else
      27. Console.Write("Extracting " & fobject.FileName & "...")
      28. End If
      29. If (fobject.IsStoredInCache = True And fobject.NumOfSectors > 0) Or
      30. (fobject.IsStoredInCache = False And fobject.NumOfSectors = 0) Then ' esgibt Fälle das sind Datein nicht in der GCF(Cache)-Datei enthalten oder sind Leer deshalb kann man schon hier entscheiden ob man die Datein trotzdem als "Dummy" ohne Inhalt entpackt will.
      31. i.Extract(fobject, destinationdir, True, False) 'Der dritte Parameter "IgnoreLocalCopyHasPriority" legt fest ob eine datei entpack werden soll auch wenn sie als "NichtÜberschreiben" markiert ist. der vierte Parameter "Empty" gibt an ob die datei leer (0bytes) als "dummy"
      32. Entpackt werden soll.
      33. Console.ForegroundColor = ConsoleColor.Green
      34. Console.Write("Done!")
      35. Else
      36. Console.ForegroundColor = ConsoleColor.Yellow
      37. Console.Write("Skipped!")
      38. End If
      39. Console.WriteLine()
      40. Case GetType(SteamCache.FileObject.NcfFileObject)
      41. Dim fobject As SteamCache.FileObject.NcfFileObject = FileObject
      42. destinationdir = destinationdir & fobject.ValidPathTree
      43. If fobject.Attribute <> SteamCache.Manifest.Nodes.NodeAttribute.Directory Then
      44. Console.Write("Extracting " & fobject.ValidPathTree & fobject.FileName & "...")
      45. Else
      46. Console.Write("Extracting " & fobject.FileName & "...")
      47. End If
      48. i.Extract(fobject, destinationdir, True, False)'Bei NCF-Datein kann dies nützlich sein da man diese ja eigentlich nicht entpacken kann. Wenn Empty = False werden bei NCF-DAtein Dummy-Datein mit der größe der original datein entpackt. Bei Empty=True haben diese dann 0 byte
      49. Console.ForegroundColor = ConsoleColor.Green
      50. Console.Write("Done!")
      51. Console.WriteLine()
      52. End Select
      53. End Sub


      Natürlich könnte man auch einfach die ExtractAll-Funktion benutzen, diese ermöglicht aber keine so schöne Ausgabe^^:

      VB.NET-Quellcode

      1. i.ExtractAll("ZielPfad")


      Natürlich
      kann man Datein auch über den DateiNamen entpacken, dies ist aber
      weniger genau als die methode mit FileObject da erst die DateiNamen aus
      der FileMap gesucht werden müssen und da kann es vorkommen das es
      gleichnamige Datein in verschiedenen Ordner gibt. In diesem Fall werden
      beide entpackt.

      VB.NET-Quellcode

      1. i.Extract("0x0000800A.bin", "ZielPfad", True,
      2. False, False)' Der Explicit-Parameter bestimmt ob der gesuchte Dateiname nur den angegeben enthalten soll (Explict = false) oder ob sie identisch sein sollen(explicit = true)

      Mit der SearchFileObject-Funktion kann man selbst nach Datein(Dateinamen) in der FileMap suchen:

      VB.NET-Quellcode

      1. Dim
      2. fobject As SteamCache.FileObject.GcfFileObject = i.SearchFileObject("hallo.dat", True) 'Als rückgabewert bekommt man das erste FileObject das diesem Namen entspricht das man dann zb. entpacken könnte. Aber vorsicht! denn hier müsst ihr wissen ob ihr eine GCF oder eine NCF Datei geladen habt da es jeweils ein entsprechendes FileObject gibt.


      Zu letzt komm ich noch zu den Write-Funktionen, diese sind noch nicht ausgereift und Produziern daher offt felerhafte Datein.

      VB.NET-Quellcode

      1. Console.WriteLine("Writing fake_" & Path.GetFileName(i.FilePath))
      2. Dim
      3. fs As FileStream = File.Create("H:\temp\fake_" & Path.GetFileName(i.FilePath))' zuerst braucht ihr einen FileStream um eine neue Datei schreiben zu können
      4. i.Write(fs) ' hier wird werden nur FileHeader, Manifest etc geschriebn. Datein enthält dieses archiv nicht
      5. fs.Close()
      6. '=================================================
      7. Console.WriteLine("Reading Datablock...")
      8. Dim data As Byte() = i.ReadData()' mit dieser Funktion könnt ihr die restlichen Daten auslesen
      9. Console.WriteLine("Writing fake_" & Path.GetFileName(i.FilePath))
      10. Dim fs_ As FileStream = File.Create("H:\temp\fake_" & Path.GetFileName(i.FilePath))
      11. i.Write(fs_, data)'und dann mit dem Manifest etc in den stream schreibn. Leider gibtes hier noch einge problem da die Dokumentation unvollständig und alt ist. Ihr werden also probleme bekommen diese datein wieder zu mounten/laden.
      12. fs.Close()
      13. data = Nothing


      Das wars soweit für heute. Viel spaß beim probieren!

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „razor8“ ()

      Neue version hinzugefügt

      Ich habe in den Weihnachtsferien wieder ein bischen Zeit für dieses Nebenprojekt gefunden und es etwas modifiziert: Es unterstützt nun GCF-Datein die 4Gb oder größer sind. Außerdem habe ich einige unnötige sachen entfernt und ein paar bugs behoben. Das Archiv im Anhang enthält den gesamten SourceCode und ein Testprojekt mit dem ihr z.b. Gcf/Ncf-Datein entpacken könnt.

      mehr Informationen gibts wie immer im Originalthread: serialexperience.co.cc/thread-65.html

      mfg rAzoR
      Ich hab mal die neuste version zum anhang hinzugefügt

      Alpha 30:
      Writing (cloning) GCF/NCF's works fine now
      Optimized extraction performance
      Added option to validate files (check blockchecksums) while extracting a file
      New Function: IsEncrypted(FileObject.GcfObject) returns True if the file is encrypted (independant of BlockFlag)
      Optimized reading/writing gcf/ncf structure
      New Class: Compare.rAzoR:
      • SearchInList(List(Of FileObject.GcfFileObject),String) returns FileObject with fobject.PathTree & fobject.FileName = FilePath
      • FindNewFiles(List(Of FileObject.GcfFileObject),List(Of FileObject.GcfFileObject)) returns a list of updated files
      • Compare(FileObject.GcfFileObject,FileObject.GcfFileObject) returns True if file is identical
      So könnte zb ein Extractor aussehen: