diff --git a/UndertaleModLib/Models/UndertaleEmbeddedTexture.cs b/UndertaleModLib/Models/UndertaleEmbeddedTexture.cs index f412c8964..f10e0487f 100644 --- a/UndertaleModLib/Models/UndertaleEmbeddedTexture.cs +++ b/UndertaleModLib/Models/UndertaleEmbeddedTexture.cs @@ -18,6 +18,7 @@ public class UndertaleEmbeddedTexture : UndertaleNamedResource public UndertaleString Name { get; set; } public uint Scaled { get; set; } = 0; public uint GeneratedMips { get; set; } + public uint TextureBlockSize { get; set; } public TexData TextureData { get; set; } = new TexData(); public void Serialize(UndertaleWriter writer) @@ -25,6 +26,8 @@ public void Serialize(UndertaleWriter writer) writer.Write(Scaled); if (writer.undertaleData.GeneralInfo.Major >= 2) writer.Write(GeneratedMips); + if (writer.undertaleData.GM2022_3) + writer.Write(TextureBlockSize); writer.WriteUndertaleObjectPointer(TextureData); } @@ -33,6 +36,8 @@ public void Unserialize(UndertaleReader reader) Scaled = reader.ReadUInt32(); if (reader.undertaleData.GeneralInfo.Major >= 2) GeneratedMips = reader.ReadUInt32(); + if (reader.undertaleData.GM2022_3) + TextureBlockSize = reader.ReadUInt32(); TextureData = reader.ReadUndertaleObjectPointer(); } diff --git a/UndertaleModLib/Models/UndertaleFont.cs b/UndertaleModLib/Models/UndertaleFont.cs index b433e67cc..b802a85a5 100644 --- a/UndertaleModLib/Models/UndertaleFont.cs +++ b/UndertaleModLib/Models/UndertaleFont.cs @@ -140,43 +140,9 @@ public void Unserialize(UndertaleReader reader) if (reader.undertaleData.GeneralInfo?.BytecodeVersion >= 17) { AscenderOffset = reader.ReadInt32(); - // TODO: Add a second check so it doesn't iterate over every font twice (just the first should do) - if (!reader.undertaleData.GMS2022_2) - { - /* This code performs three checks to identify GM2022.2. - * First, as you've seen, is the bytecode version. - * Second, we assume it is. If there are no Glyphs, we are vindicated by the impossibility of null values there. - * Third, in case of a terrible fluke causing this to appear valid erroneously, we verify that each pointer leads into the next. - * And if someone builds their game so the first pointer is absolutely valid length data and the next font is valid glyph data- - * screw it, call Jacky720 when someone constructs that and you want to mod it. - * Maybe try..catch on the whole shebang? - */ - uint positionToReturn = reader.Position; - reader.ReadUInt32(); // We assume this is the ascender - uint glyphsLength = reader.ReadUInt32(); - reader.undertaleData.GMS2022_2 = true; - if (glyphsLength != 0) - { - List glyphPointers = new List(); - for (uint i = 0; i < glyphsLength; i++) - glyphPointers.Add(reader.ReadUInt32()); - foreach (uint pointer in glyphPointers) - { - if (reader.Position != pointer) - { - reader.undertaleData.GMS2022_2 = false; - break; - } - reader.Position += 14; - ushort kerningLength = reader.ReadUInt16(); - reader.Position += (uint)2 * kerningLength; // combining read/write would apparently break - } - } - reader.Position = positionToReturn; - } + if (reader.undertaleData.GMS2022_2) + Ascender = reader.ReadUInt32(); } - if (reader.undertaleData.GMS2022_2) - Ascender = reader.ReadUInt32(); Glyphs = reader.ReadUndertaleObject>(); } diff --git a/UndertaleModLib/UndertaleChunks.cs b/UndertaleModLib/UndertaleChunks.cs index 82ebcd43d..cd32989f5 100644 --- a/UndertaleModLib/UndertaleChunks.cs +++ b/UndertaleModLib/UndertaleChunks.cs @@ -264,6 +264,44 @@ internal override void SerializeChunk(UndertaleWriter writer) internal override void UnserializeChunk(UndertaleReader reader) { + if (reader.undertaleData.GeneralInfo?.BytecodeVersion >= 17) + { + /* This code performs three checks to identify GM2022.2. + * First, as you've seen, is the bytecode version. + * Second, we assume it is. If there are no Glyphs, we are vindicated by the impossibility of null values there. + * Third, in case of a terrible fluke causing this to appear valid erroneously, we verify that each pointer leads into the next. + * And if someone builds their game so the first pointer is absolutely valid length data and the next font is valid glyph data- + * screw it, call Jacky720 when someone constructs that and you want to mod it. + * Maybe try..catch on the whole shebang? + */ + uint positionToReturn = reader.Position; + if (reader.ReadUInt32() > 0) // Font count + { + uint firstFontPointer = reader.ReadUInt32(); + reader.Position = firstFontPointer + 48; // There are 48 bytes of existing metadata. + uint glyphsLength = reader.ReadUInt32(); + reader.undertaleData.GMS2022_2 = true; + if (glyphsLength != 0) + { + List glyphPointers = new List(); + for (uint i = 0; i < glyphsLength; i++) + glyphPointers.Add(reader.ReadUInt32()); + foreach (uint pointer in glyphPointers) + { + if (reader.Position != pointer) + { + reader.undertaleData.GMS2022_2 = false; + break; + } + reader.Position += 14; + ushort kerningLength = reader.ReadUInt16(); + reader.Position += (uint)4 * kerningLength; // combining read/write would apparently break + } + } + } + reader.Position = positionToReturn; + } + base.UnserializeChunk(reader); Padding = reader.ReadBytes(512); @@ -505,6 +543,27 @@ internal override void SerializeChunk(UndertaleWriter writer) internal override void UnserializeChunk(UndertaleReader reader) { + // Detect GM2022.3 + if (reader.undertaleData.GMS2_3) + { + uint positionToReturn = reader.Position; + uint texCount = reader.ReadUInt32(); + if (texCount == 1) // If no textures exist, this could false positive. + { + reader.Position += 16; // Jump to either padding or length, depending on version + if (reader.ReadUInt32() > 0) // Check whether it's padding or length + reader.undertaleData.GM2022_3 = true; + } + else if (texCount > 1) + { + uint firstTex = reader.ReadUInt32(); + uint secondTex = reader.ReadUInt32(); + if (firstTex + 16 == secondTex) + reader.undertaleData.GM2022_3 = true; + } + reader.Position = positionToReturn; + } + base.UnserializeChunk(reader); // texture blobs diff --git a/UndertaleModLib/UndertaleData.cs b/UndertaleModLib/UndertaleData.cs index d11395bc5..9c78acad3 100644 --- a/UndertaleModLib/UndertaleData.cs +++ b/UndertaleModLib/UndertaleData.cs @@ -117,6 +117,7 @@ public class UndertaleData public bool UseBZipFormat = false; public bool GMS2022_1 = false; public bool GMS2022_2 = false; + public bool GM2022_3 = false; public ToolInfo ToolInfo = new ToolInfo(); public int PaddingAlignException = -1;