Skip to content

Commit

Permalink
Add support for many native struct types
Browse files Browse the repository at this point in the history
  • Loading branch information
Vilsol committed Mar 5, 2020
1 parent 79dc126 commit 380df5b
Show file tree
Hide file tree
Showing 23 changed files with 457 additions and 118 deletions.
135 changes: 24 additions & 111 deletions parser/parser_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,16 +306,6 @@ func (parser *PakParser) ReadUint64() uint64 {
return binary.LittleEndian.Uint64(parser.Read(8))
}

func (parser *PakParser) ReadFGuid() *FGuid {
data := parser.Read(16)
return &FGuid{
A: binary.LittleEndian.Uint32(data),
B: binary.LittleEndian.Uint32(data[4:]),
C: binary.LittleEndian.Uint32(data[8:]),
D: binary.LittleEndian.Uint32(data[12:]),
}
}

func (parser *PakParser) ReadFGenerationInfo() *FGenerationInfo {
return &FGenerationInfo{
ExportCount: parser.ReadInt32(),
Expand Down Expand Up @@ -583,8 +573,9 @@ func (record *FPakEntry) ReadUExp(pak *PakFile, parser *PakParser, uAsset *FPack
exports := make(map[*FObjectExport][]*FPropertyTag)

for _, export := range uAsset.Exports {
log.Debugf("Reading export: %x", headerSize+int64(record.FileOffset)+(export.SerialOffset-int64(uAsset.TotalHeaderSize)))
parser.Seek(headerSize+int64(record.FileOffset)+(export.SerialOffset-int64(uAsset.TotalHeaderSize)), 0)
offset := headerSize + int64(record.FileOffset) + (export.SerialOffset - int64(uAsset.TotalHeaderSize))
log.Debugf("Reading export [%x]: %#v", offset, export.TemplateIndex.Reference)
parser.Seek(offset, 0)

properties := make([]*FPropertyTag, 0)

Expand All @@ -598,19 +589,18 @@ func (record *FPakEntry) ReadUExp(pak *PakFile, parser *PakParser, uAsset *FPack
properties = append(properties, property)
}

/*
if len(exportData[offset:]) > 4 {
/*if parser.preload != nil {
preloadData := parser.preload
if len(preloadData) > 0 {
fmt.Println()
spew.Dump(export)
fmt.Printf("Remaining: %d\n", len(exportData[offset:]))
// spew.Dump(export)
log.Warningf("Export leftovers: %d", len(preloadData))
if len(exportData[offset:]) < 10000 {
fmt.Println(utils.HexDump(exportData[offset:]))
if len(preloadData) < 1000 {
fmt.Println(utils.HexDump(preloadData))
}
fmt.Println()
}
*/
}*/

exports[export] = properties
}
Expand Down Expand Up @@ -681,7 +671,13 @@ func (parser *PakParser) ReadFPropertyTag(uAsset *FPackageFileSummary, readData
tag = parser.ReadTag(size, uAsset, propertyType, tagData, &name, depth)

if parser.tracker.bytesRead != size {
log.Warningf("%sProperty not read correctly: %d read out of %d", d(depth), parser.tracker.bytesRead, size)
log.Warningf("%sProperty not read correctly %s (%s)[%#v]: %d read out of %d",
d(depth),
strings.Trim(name, "\x00"),
strings.Trim(propertyType, "\x00"),
tagData,
parser.tracker.bytesRead,
size)

if parser.tracker.bytesRead > size {
log.Fatalf("More bytes read than available!")
Expand Down Expand Up @@ -794,96 +790,13 @@ func (parser *PakParser) ReadTag(size int32, uAsset *FPackageFileSummary, proper
log.Tracef("%sReading StructProperty: %s", d(depth), strings.Trim(tagData.(*StructProperty).Type, "\x00"))

if structData, ok := tagData.(*StructProperty); ok {
switch strings.Trim(structData.Type, "\x00") {
case "Guid":
fallthrough
case "VectorMaterialInput":
fallthrough
case "ExpressionInput":
fallthrough
case "LinearColor":
fallthrough
case "ScalarMaterialInput":
fallthrough
case "Vector":
fallthrough
case "Rotator":
fallthrough
case "IntPoint":
fallthrough
case "RichCurveKey":
fallthrough
case "Vector2D":
fallthrough
case "ColorMaterialInput":
fallthrough
case "Color":
fallthrough
case "Quat":
fallthrough
case "Box":
fallthrough
case "PerPlatformFloat":
fallthrough
case "SkeletalMeshSamplingLODBuiltData":
fallthrough
case "PointerToUberGraphFrame":
fallthrough
case "MovieSceneFrameRange":
fallthrough
case "FrameNumber":
fallthrough
case "MovieSceneSegmentIdentifier":
fallthrough
case "MovieSceneSequenceID":
fallthrough
case "MovieSceneTrackIdentifier":
fallthrough
case "MovieSceneEvaluationKey":
fallthrough
case "Box2D":
fallthrough
case "Vector4":
fallthrough
case "FontData":
fallthrough
case "FontCharacter":
fallthrough
case "MaterialAttributesInput":
fallthrough
case "MovieSceneByteChannel":
fallthrough
case "MovieSceneEventParameters":
fallthrough
case "SoftClassPath":
fallthrough
case "MovieSceneParticleChannel":
fallthrough
case "InventoryItem":
fallthrough
case "SmartName":
fallthrough
case "PerPlatformInt":
fallthrough
case "MovieSceneFloatValue":
fallthrough
case "MovieSceneSegment":
fallthrough
case "SectionEvaluationDataTree":
fallthrough
case "MovieSceneEvalTemplatePtr":
fallthrough
case "MovieSceneTrackImplementationPtr":
// TODO Read types correctly
log.Debugf("%sUnread StructProperty Type [%d]: %s", d(depth), size, strings.Trim(structData.Type, "\x00"))
// fmt.Println(utils.HexDump(data[offset:]))
if size > 0 {
parser.Read(size)
result, success := parser.ReadStruct(structData, size, depth)

if success {
return &StructType{
Type: structData.Type,
Value: result,
}
return tag
default:
// All others are fine
break
}
}
}
Expand Down
117 changes: 117 additions & 0 deletions parser/struct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package parser

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

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

func (parser *PakParser) ReadStruct(property *StructProperty, size int32, depth int) (interface{}, bool) {
switch strings.Trim(property.Type, "\x00") {
case "Vector":
return parser.ReadFVector(), true
case "LinearColor":
return parser.ReadFLinearColor(), true
case "Vector2D":
return parser.ReadFVector2D(), true
case "IntPoint":
return parser.ReadFIntPoint(), true
case "Rotator":
return parser.ReadFRotator(), true
case "Quat":
return parser.ReadFQuat(), true
case "Vector4":
return parser.ReadFVector4(), true
case "Color":
return parser.ReadFColor(), true
case "Box":
return parser.ReadFBox(), true
case "FrameNumber":
return parser.ReadFFrameNumber(), true
case "MovieSceneSequenceID":
return parser.ReadFMovieSceneSequenceID(), true
case "Box2D":
return parser.ReadFBox2D(), true
case "MovieSceneTrackIdentifier":
return parser.ReadFMovieSceneTrackIdentifier(), true
case "MovieSceneEvaluationKey":
return parser.ReadFMovieSceneEvaluationKey(), true
case "MovieSceneSegmentIdentifier":
return parser.ReadFMovieSceneSegmentIdentifier(), true
case "MovieSceneFloatValue":
return parser.ReadFMovieSceneFloatValue(), true
case "RichCurveKey":
return parser.ReadFRichCurveKey(), true
case "MovieSceneFrameRange":
return parser.ReadFMovieSceneFrameRange(), true
case "Guid":
if size == 16 {
return parser.ReadFGuid(), true
}

// TODO Something is not right
// return parser.ReadFGuid()
fallthrough
case "VectorMaterialInput":
fallthrough
case "ExpressionInput":
fallthrough
case "ScalarMaterialInput":
fallthrough
case "ColorMaterialInput":
fallthrough
case "PerPlatformFloat":
fallthrough
case "SkeletalMeshSamplingLODBuiltData":
fallthrough
case "PointerToUberGraphFrame":
fallthrough
case "FontData":
fallthrough
case "FontCharacter":
fallthrough
case "MaterialAttributesInput":
fallthrough
case "MovieSceneByteChannel":
fallthrough
case "MovieSceneEventParameters":
fallthrough
case "SoftClassPath":
fallthrough
case "MovieSceneParticleChannel":
fallthrough
case "InventoryItem":
fallthrough
case "SmartName":
fallthrough
case "PerPlatformInt":
fallthrough
case "MovieSceneSegment":
fallthrough
case "SectionEvaluationDataTree":
fallthrough
case "MovieSceneEvalTemplatePtr":
fallthrough
case "MovieSceneTrackImplementationPtr":
fallthrough
case "MovieSceneEvaluationTrack":
fallthrough
case "LevelSequenceBindingReferenceArray":
// TODO Read types correctly
log.Debugf("%sUnread StructProperty Type [%d]: %s", d(depth), size, strings.Trim(property.Type, "\x00"))
// fmt.Println(utils.HexDump(data[offset:]))
if size > 0 {
parser.Read(size)
}
return nil, true
default:
// All others are fine
break
}

return nil, false
}
15 changes: 15 additions & 0 deletions parser/struct_box.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package parser

type FBox struct {
IsValid uint8 `json:"is_valid"`
Min *FVector `json:"min"`
Max *FVector `json:"max"`
}

func (parser *PakParser) ReadFBox() *FBox {
return &FBox{
IsValid: parser.Read(1)[0],
Min: parser.ReadFVector(),
Max: parser.ReadFVector(),
}
}
15 changes: 15 additions & 0 deletions parser/struct_box2d.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package parser

type FBox2D struct {
IsValid uint8 `json:"is_valid"`
Min *FVector2D `json:"min"`
Max *FVector2D `json:"max"`
}

func (parser *PakParser) ReadFBox2D() *FBox2D {
return &FBox2D{
IsValid: parser.Read(1)[0],
Min: parser.ReadFVector2D(),
Max: parser.ReadFVector2D(),
}
}
17 changes: 17 additions & 0 deletions parser/struct_color.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package parser

type FColor struct {
R uint8 `json:"r"`
G uint8 `json:"g"`
B uint8 `json:"b"`
A uint8 `json:"a"`
}

func (parser *PakParser) ReadFColor() *FColor {
return &FColor{
R: parser.Read(1)[0],
G: parser.Read(1)[0],
B: parser.Read(1)[0],
A: parser.Read(1)[0],
}
}
11 changes: 11 additions & 0 deletions parser/struct_frame_number.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package parser

type FFrameNumber struct {
Value int32 `json:"value"`
}

func (parser *PakParser) ReadFFrameNumber() *FFrameNumber {
return &FFrameNumber{
Value: parser.ReadInt32(),
}
}
17 changes: 17 additions & 0 deletions parser/struct_guid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package parser

type FGuid struct {
A uint32 `json:"a"`
B uint32 `json:"b"`
C uint32 `json:"c"`
D uint32 `json:"d"`
}

func (parser *PakParser) ReadFGuid() *FGuid {
return &FGuid{
A: parser.ReadUint32(),
B: parser.ReadUint32(),
C: parser.ReadUint32(),
D: parser.ReadUint32(),
}
}
13 changes: 13 additions & 0 deletions parser/struct_int_point.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package parser

type FIntPoint struct {
X int32 `json:"x"`
Y int32 `json:"y"`
}

func (parser *PakParser) ReadFIntPoint() *FIntPoint {
return &FIntPoint{
X: parser.ReadInt32(),
Y: parser.ReadInt32(),
}
}
Loading

0 comments on commit 380df5b

Please sign in to comment.