Skip to content

Commit 4163881

Browse files
committed
Support EntryPoint VariableDef's
1 parent c1d561a commit 4163881

File tree

4 files changed

+189
-17
lines changed

4 files changed

+189
-17
lines changed

src/Core/EntryPoint.cs

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
using BfevLibrary.Common;
1+
using System.Net.Http.Headers;
2+
using BfevLibrary.Common;
23
using BfevLibrary.Parsers;
34

45
namespace BfevLibrary.Core;
56

67
public class EntryPoint : IBfevDataBlock
78
{
89
public List<short> SubFlowEventIndices { get; set; }
10+
11+
public RadixTree<VariableDef>? Variables { get; set; }
12+
913
public short EventIndex { get; set; }
1014

11-
public EntryPoint() { }
15+
public EntryPoint()
16+
{
17+
}
18+
1219
public EntryPoint(BfevReader reader)
1320
{
1421
Read(reader);
@@ -17,36 +24,63 @@ public EntryPoint(BfevReader reader)
1724
public IBfevDataBlock Read(BfevReader reader)
1825
{
1926
long subFlowEventIndicesPtr = reader.ReadInt64();
20-
reader.BaseStream.Position += 8 + 8; // unused (in botw) VariableDef pointers (ulong, ulong)
27+
long variableDefNamesPtr = reader.ReadInt64();
28+
long variableDefsPtr = reader.ReadInt64();
2129
ushort subFlowEventIndicesCount = reader.ReadUInt16();
22-
reader.BaseStream.Position += 2; // unused (in botw) VariableDef count (ushort)
30+
ushort variableDefCount = reader.ReadUInt16();
2331
EventIndex = reader.ReadInt16();
2432
reader.BaseStream.Position += 2; // padding
25-
SubFlowEventIndices = reader.ReadObjectsPtr(new short[subFlowEventIndicesCount], reader.ReadInt16, subFlowEventIndicesPtr).ToList();
33+
34+
SubFlowEventIndices = reader.ReadObjectsPtr(
35+
new short[subFlowEventIndicesCount], reader.ReadInt16, subFlowEventIndicesPtr).ToList();
36+
37+
Variables = reader.ReadObjectPtr(() => new RadixTree<VariableDef>(reader), variableDefNamesPtr);
38+
Variables?.LinkToArray(
39+
reader.ReadObjectsPtr(new VariableDef[variableDefCount], () => new VariableDef(reader), variableDefsPtr)
40+
);
41+
42+
reader.Align(8);
2643
return this;
2744
}
2845

2946
public void Write(BfevWriter writer)
3047
{
3148
Action insertSubFlowEventIndicesPtr = writer.ReservePtrIf(SubFlowEventIndices.Count > 0, register: true);
32-
writer.Write(0L); // Unused (in botw) VariableDef pointer (ulong)
33-
writer.WriteNullPtr(register: true); // Unused (in botw) VariableDef dict pointer (ulong)
49+
Action insertVariableDefDictPtr = writer.ReservePtrIf(Variables is { Count: > 0 }, register: true);
50+
Action insertVariableDefsPtr = writer.ReservePtrIf(Variables is { Count: > 0 }, register: true);
3451
writer.Write((ushort)SubFlowEventIndices.Count);
35-
writer.Write((ushort)0); // Unused (in botw) VariableDefs count
52+
writer.Write((ushort)(Variables?.Count ?? 0));
3653
writer.Write(EventIndex);
37-
writer.Write((ushort)0); // Padding
38-
writer.ReserveBlockWriter("EntryPointArrayDataBlock", () => {
54+
writer.Align(8);
55+
56+
writer.ReserveBlockWriter("EntryPointExtraDataBlock", () => {
3957
if (SubFlowEventIndices.Count > 0) {
4058
insertSubFlowEventIndicesPtr();
41-
for (int i = 0; i < SubFlowEventIndices.Count; i++) {
42-
writer.Write(SubFlowEventIndices[i]);
59+
foreach (short s16 in SubFlowEventIndices) {
60+
writer.Write(s16);
4361
}
62+
4463
writer.Align(8);
4564
}
4665

47-
// Not really sure what this is for, based
48-
// off evfl by leoetlino (evfl/entry_point.py)
49-
writer.Seek(24, SeekOrigin.Current);
66+
if (Variables is not { Count: > 0 }) {
67+
return;
68+
}
69+
70+
insertVariableDefDictPtr();
71+
writer.WriteRadixTree(Variables.Keys.ToArray());
72+
writer.Align(8);
73+
74+
insertVariableDefsPtr();
75+
foreach (VariableDef variableDef in Variables.Values) {
76+
variableDef.Write(writer);
77+
}
78+
79+
writer.WriteReserved("VariableDefData", alignment: 8);
80+
81+
// The size for each entry point is sizeof(event_idx_array)
82+
// rounded up to the nearest multiple of 8 + 0x18 bytes.
83+
writer.Seek(0x18, SeekOrigin.Current);
5084
});
5185
}
52-
}
86+
}

src/Core/Flowchart.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public void Write(BfevWriter writer)
103103

104104
writer.WriteReserved("EventArrayDataBlock", alignment: 8);
105105
writer.WriteReserved("ActorArrayDataBlock", alignment: 8);
106-
writer.WriteReserved("EntryPointArrayDataBlock", alignment: 8);
106+
writer.WriteReserved("EntryPointExtraDataBlock", alignment: 8);
107107
writer.Align(8);
108108
}
109109

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using BfevLibrary.Parsers;
2+
3+
namespace BfevLibrary.Core;
4+
5+
public class VariableDef : VariableDefValue
6+
{
7+
public VariableDef()
8+
{
9+
}
10+
11+
public VariableDef(BfevReader reader)
12+
{
13+
long value = reader.ReadInt64();
14+
ushort count = reader.ReadUInt16();
15+
var type = (ContainerDataType)reader.ReadByte();
16+
reader.Align(8);
17+
Read(reader, value, count, type);
18+
}
19+
20+
public void Write(BfevWriter writer)
21+
{
22+
Action? ptr = WriteData(writer);
23+
ContainerDataType type = GetDataType();
24+
writer.Write((ushort)GetCount(type));
25+
writer.Write((byte)type);
26+
writer.Align(8);
27+
28+
if (ptr is null) {
29+
return;
30+
}
31+
32+
writer.ReserveBlockWriter("VariableDefData", () => {
33+
ptr();
34+
35+
if (IntArray is not null) {
36+
foreach (int s32 in IntArray) {
37+
writer.Write((long)s32);
38+
}
39+
}
40+
else if (FloatArray is not null) {
41+
foreach (int f32 in FloatArray) {
42+
writer.Write((long)f32);
43+
}
44+
}
45+
});
46+
}
47+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using BfevLibrary.Parsers;
2+
3+
namespace BfevLibrary.Core;
4+
5+
public class VariableDefValue
6+
{
7+
public int? Int { get; set; }
8+
9+
public float? Float { get; set; }
10+
11+
public int[]? IntArray { get; set; }
12+
13+
public float[]? FloatArray { get; set; }
14+
15+
protected VariableDefValue()
16+
{
17+
}
18+
19+
protected void Read(BfevReader reader, long value, ushort count, ContainerDataType type)
20+
{
21+
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
22+
switch (type) {
23+
case ContainerDataType.Int:
24+
Int = (int)value;
25+
break;
26+
case ContainerDataType.Float:
27+
Float = (float)value;
28+
break;
29+
case ContainerDataType.IntArray: {
30+
IntArray = reader.ReadObjectsPtr(new int[count], reader.ReadInt32, value);
31+
break;
32+
}
33+
case ContainerDataType.FloatArray: {
34+
FloatArray = reader.ReadObjectsPtr(new float[count], reader.ReadSingle, value);
35+
break;
36+
}
37+
}
38+
}
39+
40+
protected Action? WriteData(BfevWriter writer)
41+
{
42+
if (Int != null) {
43+
writer.Write((ulong)Int);
44+
return null;
45+
}
46+
47+
if (Float != null) {
48+
writer.Write((ulong)Float);
49+
return null;
50+
}
51+
52+
if (IntArray != null || FloatArray != null) {
53+
return writer.ReservePtr();
54+
}
55+
56+
throw new InvalidOperationException("Invalid variable def data");
57+
}
58+
59+
protected int GetCount(ContainerDataType type)
60+
{
61+
// ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault
62+
return type switch {
63+
ContainerDataType.Int => 1,
64+
ContainerDataType.Float => 1,
65+
ContainerDataType.IntArray => IntArray!.Length,
66+
ContainerDataType.FloatArray => FloatArray!.Length,
67+
_ => throw new NotSupportedException($"Unsupported variable type: {type}")
68+
};
69+
}
70+
71+
public ContainerDataType GetDataType()
72+
{
73+
if (Int != null) {
74+
return ContainerDataType.Int;
75+
}
76+
77+
if (Float != null) {
78+
return ContainerDataType.Float;
79+
}
80+
81+
if (IntArray != null) {
82+
return ContainerDataType.IntArray;
83+
}
84+
85+
if (FloatArray != null) {
86+
return ContainerDataType.FloatArray;
87+
}
88+
89+
throw new NullReferenceException("Missing variable data. All possible union types were null.");
90+
}
91+
}

0 commit comments

Comments
 (0)