Skip to content

Commit

Permalink
Refactor, Add binary data processing
Browse files Browse the repository at this point in the history
  • Loading branch information
Vilsol committed Apr 28, 2020
1 parent 2471d81 commit 3dc2151
Show file tree
Hide file tree
Showing 10 changed files with 1,085 additions and 892 deletions.
78 changes: 78 additions & 0 deletions parser/class.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package parser

import (
log "github.com/sirupsen/logrus"
"strings"
)

type ClassResolver func(parser *PakParser, export *FObjectExport, size int32, uAsset *FPackageFileSummary) interface{}

var classResolvers = map[string]ClassResolver{
"DataTable": func(parser *PakParser, export *FObjectExport, size int32, uAsset *FPackageFileSummary) interface{} {
return parser.ReadUDataTable(uAsset)
},
"ObjectProperty": func(parser *PakParser, export *FObjectExport, size int32, uAsset *FPackageFileSummary) interface{} {
// TODO Figure out
parser.Read(24)
return parser.ReadFPackageIndex(uAsset.Imports, uAsset.Exports)
},
"BoolProperty": func(parser *PakParser, export *FObjectExport, size int32, uAsset *FPackageFileSummary) interface{} {
// TODO Figure out
parser.Read(25)
return parser.Read(1)[0] != 0
},
"StructProperty": func(parser *PakParser, export *FObjectExport, size int32, uAsset *FPackageFileSummary) interface{} {
// TODO Figure out
parser.Read(24)
return parser.ReadFPackageIndex(uAsset.Imports, uAsset.Exports)
},
"DelegateProperty": func(parser *PakParser, export *FObjectExport, size int32, uAsset *FPackageFileSummary) interface{} {
// TODO Figure out
parser.Read(24)
return parser.ReadFPackageIndex(uAsset.Imports, uAsset.Exports)
},
}

type ClassType struct {
Type string `json:"type"`
Value interface{} `json:"value"`
}

func (parser *PakParser) ReadClass(export *FObjectExport, size int32, uAsset *FPackageFileSummary) (interface{}, bool) {
var className string

if classNameTemp := export.TemplateIndex.ClassName(); classNameTemp != nil {
className = *classNameTemp
} else {
return nil, false
}

trimmedType := strings.Trim(className, "\x00")

resolver, ok := classResolvers[trimmedType]

if !ok {
return nil, false
}

if resolver != nil {
value := resolver(parser, export, size, uAsset)

if value != nil {
return value, true
}
}

// TODO Read types correctly
log.Warningf("Unread Class Type [%d]: %s", size, trimmedType)
// fmt.Println(utils.HexDump(data[offset:]))
if size > 0 {
parser.Read(size)
}

return nil, true
}

func RegisterClassResolver(classType string, resolver ClassResolver) {
classResolvers[classType] = resolver
}
24 changes: 24 additions & 0 deletions parser/class_data_table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package parser

// https://github.com/SatisfactoryModdingUE/UnrealEngine/blob/4.22-CSS/Engine/Source/Runtime/Engine/Classes/Engine/DataTable.h#L56
type UDataTable struct {
Values map[string][]*FPropertyTag `json:"values"`
}

func (parser *PakParser) ReadUDataTable(uAsset *FPackageFileSummary) *UDataTable {
// Unknown
parser.Read(4)

count := parser.ReadUint32()

values := make(map[string][]*FPropertyTag)

for i := uint32(0); i < count; i++ {
name := parser.ReadFName(uAsset.Names)
values[name] = parser.ReadFPropertyTagLoop(uAsset)
}

return &UDataTable{
Values: values,
}
}
102 changes: 102 additions & 0 deletions parser/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package parser

import (
"fmt"
"github.com/spf13/viper"
)

type PakParser struct {
reader PakReader
tracker *readTracker
preload []byte
}

type readTracker struct {
child *readTracker
bytesRead int32
}

func (tracker *readTracker) Increment(n int32) {
tracker.bytesRead += n

if tracker.child != nil {
tracker.child.Increment(n)
}
}

func NewParser(reader PakReader) *PakParser {
return &PakParser{
reader: reader,
}
}

func (parser *PakParser) TrackRead() *readTracker {
parser.tracker = &readTracker{
child: parser.tracker,
}

return parser.tracker
}

func (parser *PakParser) UnTrackRead() {
if parser.tracker != nil {
parser.tracker = parser.tracker.child
}
}

func (parser *PakParser) Seek(offset int64, whence int) (ret int64, err error) {
parser.preload = nil
return parser.reader.Seek(offset, whence)
}

func (parser *PakParser) Preload(n int32) {
if viper.GetBool("NoPreload") {
return
}

buffer := make([]byte, n)
read, err := parser.reader.Read(buffer)

if err != nil {
panic(err)
}

if int32(read) < n {
panic(fmt.Sprintf("End of stream: %d < %d", read, n))
}

if parser.preload != nil && len(parser.preload) > 0 {
parser.preload = append(parser.preload, buffer...)
} else {
parser.preload = buffer
}
}

func (parser *PakParser) Read(n int32) []byte {
toRead := n
buffer := make([]byte, toRead)

if parser.preload != nil && len(parser.preload) > 0 {
copied := copy(buffer, parser.preload)
parser.preload = parser.preload[copied:]
toRead = toRead - int32(copied)
}

if toRead > 0 {
read, err := parser.reader.Read(buffer[n-toRead:])

if err != nil {
panic(err)
}

if int32(read) < toRead {
panic(fmt.Sprintf("End of stream: %d < %d", read, toRead))
}
}

if parser.tracker != nil {
parser.tracker.Increment(n)
}

return buffer
}
Loading

0 comments on commit 3dc2151

Please sign in to comment.