Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some misc issues with deserializing pre-Bytecode 13 games #2020

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
25 changes: 3 additions & 22 deletions UndertaleModLib/Models/UndertaleGameObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,15 +180,7 @@ public void Serialize(UndertaleWriter writer)
writer.Write(Solid);
writer.Write(Depth);
writer.Write(Persistent);
// This apparently has a different notation than everything else...
if (_parentId.Resource == null)
{
writer.Write(-100);
}
else
{
writer.WriteUndertaleObject(_parentId);
}
writer.WriteUndertaleObject(_parentId);
writer.WriteUndertaleObject(_textureMaskId);
writer.Write(UsesPhysics);
writer.Write(IsSensor);
Expand Down Expand Up @@ -221,18 +213,7 @@ public void Unserialize(UndertaleReader reader)
Solid = reader.ReadBoolean();
Depth = reader.ReadInt32();
Persistent = reader.ReadBoolean();
_parentId = new UndertaleResourceById<UndertaleGameObject, UndertaleChunkOBJT>();
int parent = reader.ReadInt32();
if (parent == -100)
{
_parentId.UnserializeById(reader, -1);
}
else
{
if (parent < 0 && parent != -1) // Technically can be -100 (undefined), -2 (other), or -1 (self). Other makes no sense here though
throw new Exception("Invalid value for parent - should be -100 or object id, got " + parent);
_parentId.UnserializeById(reader, parent);
}
_parentId = reader.ReadUndertaleObject<UndertaleResourceById<UndertaleGameObject, UndertaleChunkOBJT>>();
_textureMaskId = reader.ReadUndertaleObject<UndertaleResourceById<UndertaleSprite, UndertaleChunkSPRT>>();
UsesPhysics = reader.ReadBoolean();
IsSensor = reader.ReadBoolean();
Expand Down Expand Up @@ -270,7 +251,7 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader)
int physicsShapeVertexCount = reader.ReadInt32();
reader.Position += 12 + (uint)physicsShapeVertexCount * UndertalePhysicsVertex.ChildObjectsSize;

count += 2 + 1 + UndertalePointerList<UndertalePointerList<Event>>.UnserializeChildObjectCount(reader);
count += 3 + 1 + UndertalePointerList<UndertalePointerList<Event>>.UnserializeChildObjectCount(reader);

return count;
}
Expand Down
26 changes: 21 additions & 5 deletions UndertaleModLib/Models/UndertaleGeneralInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,20 @@ public void Unserialize(UndertaleReader reader)
LicenseMD5 = reader.ReadBytes(16);
Timestamp = reader.ReadUInt64();
DisplayName = reader.ReadUndertaleString();
ActiveTargets = reader.ReadUInt64();
FunctionClassifications = (FunctionClassification)reader.ReadUInt64();
SteamAppID = reader.ReadInt32();
if (BytecodeVersion >= 14)
{
ActiveTargets = reader.ReadUInt64();
FunctionClassifications = (FunctionClassification)reader.ReadUInt64();
}
else if (BytecodeVersion >= 12)
{
FunctionClassifications = (FunctionClassification)reader.ReadUInt64();
ActiveTargets = reader.ReadUInt64(); // FIXME: What actually is this?
}
else
FunctionClassifications = (FunctionClassification)reader.ReadUInt64();
if (BytecodeVersion >= 13)
SteamAppID = reader.ReadInt32();
if (BytecodeVersion >= 14)
DebuggerPort = reader.ReadUInt32();
RoomOrder = reader.ReadUndertaleObject<UndertaleSimpleResourcesList<UndertaleRoom, UndertaleChunkROOM>>();
Expand Down Expand Up @@ -550,9 +561,14 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader)
{
reader.Position++; // "IsDebuggerDisabled"
byte bytecodeVer = reader.ReadByte();
bool readDebugPort = bytecodeVer >= 14;

reader.Position += (uint)(122 + (readDebugPort ? 4 : 0));
reader.Position += 110;
if (bytecodeVer >= 12)
reader.Position += 8; // "ActiveTargets"
if (bytecodeVer >= 13)
reader.Position += 4; // "SteamAppID"
if (bytecodeVer >= 14)
reader.Position += 4; // "DebuggerPort"

// "RoomOrder"
return 1 + UndertaleSimpleResourcesList<UndertaleRoom, UndertaleChunkROOM>.UnserializeChildObjectCount(reader);
Expand Down
46 changes: 38 additions & 8 deletions UndertaleModLib/UndertaleChunks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,16 @@ internal override void UnserializeChunk(UndertaleReader reader)
public class UndertaleChunkFONT : UndertaleListChunk<UndertaleFont>
{
public override string Name => "FONT";

/// <summary>
/// Padding bytes at the end of the chunk.
/// </summary>
/// <remarks>
/// Appeared at some point after bytecode version 6, according to the existing copy of GMS 1.0.98.
/// Before bytecode version 12 (observed in bytecode 11), this contained unknown data of varying length.
/// Afterwards, this contains UTF-16 codepoints representing ASCII's 0x00-0xFF, and is consistently
/// 512 bytes long.
/// </remarks>
public byte[] Padding;

private static bool checkedFor2022_2;
Expand Down Expand Up @@ -795,14 +805,22 @@ internal override void SerializeChunk(UndertaleWriter writer)
{
base.SerializeChunk(writer);

if (Padding == null)
if (writer.undertaleData.GeneralInfo.BytecodeVersion > 6)
{
for (ushort i = 0; i < 0x80; i++)
writer.Write(i);
for (ushort i = 0; i < 0x80; i++)
writer.Write((ushort)0x3f);
} else
writer.Write(Padding);
if (Padding == null)
{
// TODO: Before bytecode 12 the size of Padding is variable.
// (though we don't properly support them in other places yet)
for (ushort i = 0; i < 0x80; i++)
writer.Write(i);
for (ushort i = 0; i < 0x80; i++)
writer.Write((ushort)0x3f);
}
else
{
writer.Write(Padding);
}
}
}

internal override void UnserializeChunk(UndertaleReader reader)
Expand All @@ -815,7 +833,19 @@ internal override void UnserializeChunk(UndertaleReader reader)

base.UnserializeChunk(reader);

Padding = reader.ReadBytes(512);
if (reader.undertaleData.GeneralInfo.BytecodeVersion > 6)
{
if (reader.undertaleData.GeneralInfo.BytecodeVersion >= 12)
{
Padding = reader.ReadBytes(512);
}
else
{
// FIXME: how did GMAC the calculate the size of padding?
int remainingBytes = (int)(Length - (reader.Position - 8));
Padding = reader.ReadBytes(remainingBytes);
}
}
}

internal override uint UnserializeObjectCount(UndertaleReader reader)
Expand Down
9 changes: 5 additions & 4 deletions UndertaleModLib/UndertaleIO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public int SerializeById(UndertaleWriter writer)
if (CachedId < 0)
throw new IOException("Unregistered object");
}
else
else if (CachedId != -100)
{
if (typeof(ChunkT) == typeof(UndertaleChunkAGRP))
CachedId = 0;
Expand All @@ -89,7 +89,8 @@ public int SerializeById(UndertaleWriter writer)

public void UnserializeById(UndertaleReader reader, int id)
{
if (id < -1)
// In rare cases -100 (undefined in GML) is used instead of -1
if (id < -1 && id != -100)
throw new IOException("Invalid value for resource ID (" + typeof(ChunkT).Name + "): " + id);
CachedId = id;
reader.RequestResourceUpdate(this);
Expand Down Expand Up @@ -650,7 +651,7 @@ public void ToHere()

public void Align(int alignment, byte paddingbyte = 0x00)
{
while ((AbsPosition & (alignment - 1)) != paddingbyte)
while ((AbsPosition & (alignment - 1)) != 0)
{
DebugUtil.Assert(ReadByte() == paddingbyte, "Invalid alignment padding");
}
Expand Down Expand Up @@ -860,7 +861,7 @@ public void ThrowIfUnwrittenObjects()

public void Align(int alignment, byte paddingbyte = 0x00)
{
while ((Position & (alignment - 1)) != paddingbyte)
while ((Position & (alignment - 1)) != 0)
{
Write(paddingbyte);
}
Expand Down
Loading