Skip to content

Commit

Permalink
Fixed all count unserialization inaccuracies.
Browse files Browse the repository at this point in the history
  • Loading branch information
VladiStep committed Feb 18, 2023
1 parent 802ebd6 commit 7628bb0
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 44 deletions.
2 changes: 1 addition & 1 deletion UndertaleModLib/Models/UndertaleAnimationCurve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader)
else
reader.Position += 12 * count;

return count;
return 1 + count;
}

/// <inheritdoc/>
Expand Down
2 changes: 1 addition & 1 deletion UndertaleModLib/Models/UndertaleFeatureFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void Unserialize(UndertaleReader reader)
/// <inheritdoc cref="UndertaleObject.UnserializeChildObjectCount(UndertaleReader)"/>
public static uint UnserializeChildObjectCount(UndertaleReader reader)
{
return 1 + UndertaleSimpleListString.UnserializeChildObjectCount(reader);
return UndertaleSimpleListString.UnserializeChildObjectCount(reader);
}

/// <inheritdoc/>
Expand Down
15 changes: 13 additions & 2 deletions UndertaleModLib/Models/UndertaleGeneralInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,19 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader)
reader.Bytecode14OrLower = bytecodeVer <= 14;

reader.Position += 42;
reader.GMS2 = reader.ReadUInt32() >= 2; // "Major" >= 2
reader.Position += (uint)(76 + (readDebugPort ? 4 : 0));

uint major = reader.ReadUInt32();
reader.Position += 8;
uint build = reader.ReadUInt32();
reader.Position += (uint)(64 + (readDebugPort ? 4 : 0));

reader.GMS2 = major >= 2; // "Major" >= 2

// UndertaleData.GetBuiltinSoundGroupID()
if (major > 1 || (build >= 1354 || (build >= 161 && build < 1000)))
reader.BuiltinSoundGroupID = 0;
else
reader.BuiltinSoundGroupID = 1;

// "RoomOrder"
return 1 + UndertaleSimpleResourcesList<UndertaleRoom, UndertaleChunkROOM>.UnserializeChildObjectCount(reader);
Expand Down
34 changes: 12 additions & 22 deletions UndertaleModLib/Models/UndertaleRoom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public enum RoomEntryFlags : uint
/// </summary>
public UndertaleSimpleList<UndertaleResourceById<UndertaleSequence, UndertaleChunkSEQN>> Sequences { get; private set; } = new UndertaleSimpleList<UndertaleResourceById<UndertaleSequence, UndertaleChunkSEQN>>();

private static bool checkedForGMS2_2_2_302;
public static bool CheckedForGMS2_2_2_302;

/// <summary>
/// Calls <see cref="OnPropertyChanged(string)"/> for <see cref="BGColorLayer"/> in order to update the room background color.<br/>
Expand Down Expand Up @@ -287,12 +287,18 @@ private static void CheckForGMS2_2_2_302(UndertaleReader reader)
secondPtr = reader.ReadUInt32();

if (secondPtr - firstPtr == 48)
{
reader.undertaleData.GMS2_2_2_302 = true;

//"GameObject.ImageSpeed" + "...ImageIndex"
uint newSize = GameObject.ChildObjectsSize + 8;
reader.SetStaticChildObjectsSize(typeof(GameObject), newSize);
}
}

reader.Position = returnTo;

checkedForGMS2_2_2_302 = true;
CheckedForGMS2_2_2_302 = true;
}

/// <inheritdoc />
Expand Down Expand Up @@ -372,7 +378,7 @@ public void Unserialize(UndertaleReader reader)
Views = reader.ReadUndertaleObjectPointer<UndertalePointerList<View>>();
GameObjects = reader.ReadUndertaleObjectPointer<UndertalePointerList<GameObject>>();

if (!checkedForGMS2_2_2_302)
if (!CheckedForGMS2_2_2_302)
CheckForGMS2_2_2_302(reader);

Tiles = reader.ReadUndertaleObjectPointer<UndertalePointerList<Tile>>();
Expand Down Expand Up @@ -441,7 +447,7 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader)
uint backgroundPtr = reader.ReadUInt32();
uint viewsPtr = reader.ReadUInt32();
uint gameObjsPtr = reader.ReadUInt32();
if (!checkedForGMS2_2_2_302)
if (!CheckedForGMS2_2_2_302)
CheckForGMS2_2_2_302(reader);
uint tilesPtr = reader.ReadUInt32();
uint layersPtr = 0;
Expand All @@ -456,20 +462,6 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader)
sequencesPtr = reader.ReadUInt32();
}

if (reader.undertaleData.GMS2_2_2_302)
{
//"GameObject.ImageSpeed" + "...ImageIndex"
GameObject.ChildObjectsSize += 8;
}

if (reader.BytecodeVersion >= 16)
{
// "GameObject._preCreateCode"

GameObject.ChildObjectCount += 1;
GameObject.ChildObjectsSize += 4;
}

reader.Position = backgroundPtr;
count += 1 + UndertalePointerList<Background>.UnserializeChildObjectCount(reader);
reader.Position = viewsPtr;
Expand Down Expand Up @@ -940,12 +932,11 @@ public void Dispose()
public class GameObject : UndertaleObject, IRoomObject, INotifyPropertyChanged, IDisposable,
IStaticChildObjCount, IStaticChildObjectsSize
{
// It's an exception that these two variables are not readonly
/// <inheritdoc cref="IStaticChildObjCount.ChildObjectCount" />
public static uint ChildObjectCount = 2;
public static readonly uint ChildObjectCount = 2;

/// <inheritdoc cref="IStaticChildObjectsSize.ChildObjectsSize" />
public static uint ChildObjectsSize = 36;
public static readonly uint ChildObjectsSize = 36;

private UndertaleResourceById<UndertaleGameObject, UndertaleChunkOBJT> _objectDefinition = new();
private UndertaleResourceById<UndertaleCode, UndertaleChunkCODE> _creationCode = new();
Expand Down Expand Up @@ -1682,7 +1673,6 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader)
{
uint count = 0;

count += 1; // "_background"
uint tilesX = reader.ReadUInt32();
uint tilesY = reader.ReadUInt32();
reader.Position += tilesX * tilesY * 4;
Expand Down
7 changes: 5 additions & 2 deletions UndertaleModLib/Models/UndertaleSound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,20 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader)
AudioEntryFlags flags = (AudioEntryFlags)reader.ReadUInt32();
reader.Position += 20;

int audioGroupID = -1;
int audioGroupID;

if (flags.HasFlag(AudioEntryFlags.Regular) && reader.BytecodeVersion >= 14)
{
audioGroupID = reader.ReadInt32();
count++;
}
else
{
audioGroupID = reader.BuiltinSoundGroupID;
reader.Position += 4; // "Preload"
}

if (audioGroupID == -1)
if (audioGroupID == reader.BuiltinSoundGroupID)
{
reader.Position += 4; // "_audioFile"
count++;
Expand Down
2 changes: 1 addition & 1 deletion UndertaleModLib/Models/UndertaleTags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader)
{
uint count = 0;

count += 1 + UndertaleSimpleListString.UnserializeChildObjectCount(reader);
count += UndertaleSimpleListString.UnserializeChildObjectCount(reader);
count += 1 + UndertalePointerList<TempAssetTags>.UnserializeChildObjectCount(reader);

return count;
Expand Down
8 changes: 2 additions & 6 deletions UndertaleModLib/UndertaleChunkTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,7 @@ internal override void UnserializeChunk(UndertaleReader reader)

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
uint count = 1;

count += UndertalePointerList<T>.UnserializeChildObjectCount(reader);

return count;
return UndertalePointerList<T>.UnserializeChildObjectCount(reader);
}

public IList GetList() => List;
Expand Down Expand Up @@ -307,7 +303,7 @@ internal override uint UnserializeObjectCount(UndertaleReader reader)
throw new InvalidOperationException(
"\"UndertaleAlignUpdatedListChunk<T>\" supports the count unserialization only for backgrounds and strings.");

return 1 + count;
return count;
}
}

Expand Down
46 changes: 37 additions & 9 deletions UndertaleModLib/UndertaleChunks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ internal override void SerializeChunk(UndertaleWriter writer)

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
checkedFor2022_6 = false;

if (reader.GMS2_3)
CheckFor2022_6(reader);

Expand Down Expand Up @@ -446,6 +448,8 @@ internal override void UnserializeChunk(UndertaleReader reader)

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
checkedFor2022_2 = false;

if (reader.BytecodeVersion >= 17)
CheckForGM2022_2(reader);

Expand Down Expand Up @@ -511,6 +515,8 @@ internal override void UnserializeChunk(UndertaleReader reader)

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
checkedFor2022_5 = false;

if (reader.undertaleData.GMS2_3)
CheckFor2022_5(reader);

Expand All @@ -532,8 +538,23 @@ internal override void UnserializeChunk(UndertaleReader reader)

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
checkedFor2022_1 = false;
UndertaleRoom.CheckedForGMS2_2_2_302 = false;

CheckForEffectData(reader);

if (reader.BytecodeVersion >= 16)
{
// "GameObject._preCreateCode"

Type gameObjType = typeof(GameObject);

uint newValue = GameObject.ChildObjectCount + 1;
reader.SetStaticChildCount(gameObjType, newValue);
newValue = GameObject.ChildObjectsSize + 4;
reader.SetStaticChildObjectsSize(gameObjType, newValue);
}

return base.UnserializeObjectCount(reader);
}

Expand Down Expand Up @@ -685,7 +706,7 @@ internal override uint UnserializeObjectCount(UndertaleReader reader)
return 0;

if (reader.undertaleData.UnsupportedBytecodeVersion)
return 1 + reader.ReadUInt32();
return reader.ReadUInt32();

reader.GMS2BytecodeAddresses = new((int)reader.ReadUInt32());
reader.Position -= 4;
Expand Down Expand Up @@ -757,7 +778,7 @@ internal override void UnserializeChunk(UndertaleReader reader)
else
varLength = 12;
List.Clear();
List.Capacity = (int)(Length / varLength) - 1;
List.Capacity = (int)(Length / varLength);
while (reader.Position + varLength <= startPosition + Length)
List.Add(reader.ReadUndertaleObject<UndertaleVariable>());
}
Expand All @@ -770,8 +791,13 @@ internal override uint UnserializeObjectCount(UndertaleReader reader)
if (reader.undertaleData.UnsupportedBytecodeVersion)
return 0;

int varLength = reader.Bytecode14OrLower ? 12 : 20;
return Length / (uint)varLength - 1;
if (!reader.Bytecode14OrLower)
{
reader.Position += 12;
return (Length - 12) / 20;
}
else
return Length / 12;
}
}

Expand Down Expand Up @@ -1010,6 +1036,8 @@ internal override void UnserializeChunk(UndertaleReader reader)

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
checkedFor2022_3 = false;

CheckFor2022_3And5(reader);

// Texture blobs are already included in the count
Expand Down Expand Up @@ -1040,7 +1068,7 @@ internal override uint UnserializeObjectCount(UndertaleReader reader)
{
// Though "UndertaleEmbeddedAudio" has dynamic child objects size,
// there's still no need to unserialize the count for each object.
return 1 + reader.ReadUInt32();
return reader.ReadUInt32();
}
}

Expand Down Expand Up @@ -1134,6 +1162,8 @@ internal override void UnserializeChunk(UndertaleReader reader)

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
checkedFor2022_8 = false;

if (!reader.GMS2)
throw new InvalidOperationException();

Expand Down Expand Up @@ -1219,7 +1249,7 @@ internal override void UnserializeChunk(UndertaleReader reader)

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
uint count = 1;
checkedForGMS2_3_1 = false;

// Padding
while (reader.Position % 4 != 0)
Expand All @@ -1232,9 +1262,7 @@ internal override uint UnserializeObjectCount(UndertaleReader reader)
if (!reader.undertaleData.GMS2_3_1)
CheckForGMS2_3_1(reader);

count += base.UnserializeObjectCount(reader);

return count;
return base.UnserializeObjectCount(reader);
}
}

Expand Down
9 changes: 9 additions & 0 deletions UndertaleModLib/UndertaleIO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ public void SubmitMessage(string message)
public bool GMS2_3 = false;
public byte BytecodeVersion = 0;
public bool Bytecode14OrLower = false;
public int BuiltinSoundGroupID = -1;

public UndertaleChunk ReadUndertaleChunk()
{
Expand Down Expand Up @@ -467,6 +468,14 @@ public uint GetStaticChildObjectsSize(Type objType)

return res;
}
public void SetStaticChildCount(Type objType, uint count)
{
staticObjCountDict[objType] = count;
}
public void SetStaticChildObjectsSize(Type objType, uint size)
{
staticObjSizeDict[objType] = size;
}

public Dictionary<uint, UndertaleObject> GetOffsetMap()
{
Expand Down

0 comments on commit 7628bb0

Please sign in to comment.