Skip to content

Commit

Permalink
Initial changes for unserializing the total count of all child object…
Browse files Browse the repository at this point in the history
…s for the object pool dictionaries optimization.
  • Loading branch information
VladiStep committed Feb 1, 2023
1 parent 735e2fc commit 0bc4fed
Show file tree
Hide file tree
Showing 7 changed files with 361 additions and 9 deletions.
11 changes: 11 additions & 0 deletions UndertaleModLib/Models/UndertaleGeneralInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,17 @@ public void Unserialize(UndertaleReader reader)
reader.Bytecode14OrLower = BytecodeVersion <= 14;
}

/// <inheritdoc cref="UndertaleObject.UnserializeChildObjectCount(UndertaleReader)"/>
public static uint UnserializeChildObjectCount(UndertaleReader reader)
{
reader.Position++; // "IsDebuggerDisabled"
bool readDebugPort = reader.ReadByte() >= 14; // "BytecodeVersion" >= 14
reader.Position += (uint)(122 + (readDebugPort ? 4 : 0));

// "RoomOrder"
return UndertaleSimpleResourcesList<UndertaleRoom, UndertaleChunkROOM>.UnserializeChildObjectCount(reader);
}

/// <summary>
/// Generates "info number" used for GMS2 UIDs.
/// </summary>
Expand Down
17 changes: 17 additions & 0 deletions UndertaleModLib/UndertaleBaseTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ public interface UndertaleObject
/// </summary>
/// <param name="reader">Where to deserialize from.</param>
void Unserialize(UndertaleReader reader);

/*
* As for C# 10, it's impossible to inherit static methods from an interface :(
* (so this method is for inheriting XML commentary only)
*/
/// <summary>
/// Deserializes the total child object count of this object from specified <see cref="UndertaleReader"/>.
/// </summary>
/// <param name="reader">Where to deserialize from.</param>
/// <returns>The object count.</returns>
static uint UnserializeChildObjectCount(UndertaleReader reader) => 0;

}

public interface UndertaleObjectLenCheck : UndertaleObject
Expand Down Expand Up @@ -107,4 +119,9 @@ public interface ISearchable
/// <paramref name="filter"/> is the empty string (""); otherwise, false.</returns>
bool SearchMatches(string filter);
}

public interface IStaticChildObjCount
{
public static readonly uint ChildObjectCount = 0;
}
}
53 changes: 52 additions & 1 deletion UndertaleModLib/UndertaleChunkTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public abstract class UndertaleChunk

internal abstract void SerializeChunk(UndertaleWriter writer);
internal abstract void UnserializeChunk(UndertaleReader reader);
internal abstract uint UnserializeObjectCount(UndertaleReader reader);

public void Serialize(UndertaleWriter writer)
{
Expand Down Expand Up @@ -79,7 +80,8 @@ public static UndertaleChunk Unserialize(UndertaleReader reader)
}

UndertaleChunk chunk = (UndertaleChunk)Activator.CreateInstance(type);
Util.DebugUtil.Assert(chunk.Name == name);
Util.DebugUtil.Assert(chunk.Name == name,
$"Chunk name mismatch: expected \"{name}\", got \"{chunk.Name}\".");
chunk.Length = length;

reader.SubmitMessage("Reading chunk " + chunk.Name);
Expand Down Expand Up @@ -124,6 +126,41 @@ public static UndertaleChunk Unserialize(UndertaleReader reader)
throw new UndertaleSerializationException(e.Message + "\nat " + reader.Position.ToString("X8") + " while reading chunk " + name, e);
}
}
public static uint CountChunkChildObjects(UndertaleReader reader)
{
string name = "(unknown)";
try
{
name = reader.ReadChars(4);
uint length = reader.ReadUInt32();

Type type = Type.GetType(typeof(UndertaleChunk).FullName + name);
if (type == null)
throw new IOException("Unknown chunk " + name + "!!!");

UndertaleChunk chunk = (UndertaleChunk)Activator.CreateInstance(type);
Util.DebugUtil.Assert(chunk.Name == name,
$"Chunk name mismatch: expected \"{name}\", got \"{chunk.Name}\".");
chunk.Length = length;

uint chunkStart = reader.Position;

reader.SubmitMessage("Counting objects of chunk " + chunk.Name);
uint count = chunk.UnserializeObjectCount(reader);

reader.Position = chunkStart + chunk.Length;

return count;
}
catch (UndertaleSerializationException e)
{
throw new UndertaleSerializationException(e.Message + " in chunk " + name, e);
}
catch (Exception e)
{
throw new UndertaleSerializationException(e.Message + "\nat " + reader.Position.ToString("X8") + " while counting objects of chunk " + name, e);
}
}
}

public interface IUndertaleSingleChunk
Expand Down Expand Up @@ -156,6 +193,8 @@ internal override void UnserializeChunk(UndertaleReader reader)
Object = reader.ReadUndertaleObject<T>();
}

internal override uint UnserializeObjectCount(UndertaleReader reader) => 1;

public UndertaleObject GetObject() => Object;

public override string ToString()
Expand All @@ -179,6 +218,11 @@ internal override void UnserializeChunk(UndertaleReader reader)
List.Unserialize(reader);
}

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
return reader.ReadUInt32();
}

public IList GetList() => List;
public void GenerateIndexDict()
{
Expand Down Expand Up @@ -256,6 +300,11 @@ internal override void UnserializeChunk(UndertaleReader reader)
List.Unserialize(reader);
}

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
return reader.ReadUInt32();
}

public IList GetList() => List;
}

Expand All @@ -268,5 +317,7 @@ internal override void SerializeChunk(UndertaleWriter writer)
internal override void UnserializeChunk(UndertaleReader reader)
{
}

internal override uint UnserializeObjectCount(UndertaleReader reader) => 0;
}
}
52 changes: 52 additions & 0 deletions UndertaleModLib/UndertaleChunks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using UndertaleModLib.Models;
Expand Down Expand Up @@ -96,16 +97,45 @@ internal override void UnserializeChunk(UndertaleReader reader)
}
}
}

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
uint totalCount = 0;
uint startPos = reader.Position;

while (reader.Position < startPos + Length)
totalCount += reader.CountChunkChildObjects();

return totalCount;
}
}

public class UndertaleChunkGEN8 : UndertaleSingleChunk<UndertaleGeneralInfo>
{
public override string Name => "GEN8";

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

count += UndertaleGeneralInfo.UnserializeChildObjectCount(reader);

return count;
}
}

public class UndertaleChunkOPTN : UndertaleSingleChunk<UndertaleOptions>
{
public override string Name => "OPTN";

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

count += reader.GetChildObjectCount<UndertaleOptions>();

return count;
}
}

public class UndertaleChunkLANG : UndertaleSingleChunk<UndertaleLanguage>
Expand Down Expand Up @@ -655,6 +685,12 @@ internal override void UnserializeChunk(UndertaleReader reader)
while (reader.Position + varLength <= startPosition + Length)
List.Add(reader.ReadUndertaleObject<UndertaleVariable>());
}

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
int varLength = reader.Bytecode14OrLower ? 12 : 20;
return Length / (uint)varLength;
}
}

public class UndertaleChunkFUNC : UndertaleChunk
Expand Down Expand Up @@ -698,6 +734,7 @@ internal override void UnserializeChunk(UndertaleReader reader)
{
uint startPosition = reader.Position;
Functions.Clear();
Functions.SetCapacity(Length / 12);
while (reader.Position + 12 <= startPosition + Length)
Functions.Add(reader.ReadUndertaleObject<UndertaleFunction>());
}
Expand All @@ -707,6 +744,21 @@ internal override void UnserializeChunk(UndertaleReader reader)
CodeLocals = reader.ReadUndertaleObject<UndertaleSimpleList<UndertaleCodeLocals>>();
}
}

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

if (!reader.Bytecode14OrLower)
{
count += reader.GetChildObjectCount<UndertaleSimpleList<UndertaleFunction>>();
count += reader.GetChildObjectCount<UndertaleSimpleList<UndertaleCodeLocals>>();
}
else
count = Length / 12;

return count;
}
}

public class UndertaleChunkSTRG : UndertaleAlignUpdatedListChunk<UndertaleString>
Expand Down
5 changes: 5 additions & 0 deletions UndertaleModLib/UndertaleDebugChunks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ internal override void UnserializeChunk(UndertaleReader reader)
}
}
}

internal override uint UnserializeObjectCount(UndertaleReader reader)
{
throw new NotImplementedException();
}
}

public class UndertaleDebugChunkSCPT : UndertaleListChunk<UndertaleScriptSource>
Expand Down
Loading

0 comments on commit 0bc4fed

Please sign in to comment.