diff --git a/UndertaleModLib/Models/UndertaleEmbeddedTexture.cs b/UndertaleModLib/Models/UndertaleEmbeddedTexture.cs index 0d35e9770..529ccb19b 100644 --- a/UndertaleModLib/Models/UndertaleEmbeddedTexture.cs +++ b/UndertaleModLib/Models/UndertaleEmbeddedTexture.cs @@ -334,9 +334,11 @@ public GMImage Image public bool FormatBZ2 => _image.Format is GMImage.ImageFormat.Bz2Qoi; /// - /// If located within a data file, this is the maximum end position of the image data (or start of the next texture blob). - /// All data between the actual end position and this maximum end position should be padding. + /// If located within a data file, this is the upper bound on the end position of the image data (or start of the next texture blob). /// + /// + /// All data between the actual end position and this maximum end position should be 0x00 byte padding. + /// private int _maxEndOfStreamPosition { get; set; } = -1; /// diff --git a/UndertaleModLib/UndertaleChunks.cs b/UndertaleModLib/UndertaleChunks.cs index 94c69a127..c6a0ec8d4 100644 --- a/UndertaleModLib/UndertaleChunks.cs +++ b/UndertaleModLib/UndertaleChunks.cs @@ -1654,13 +1654,12 @@ internal override void UnserializeChunk(UndertaleReader reader) { // Skip this texture, as it's external searchIndex++; + continue; } - else - { - // Use start address of this blob - maxEndOfStreamPosition = (int)reader.GetOffsetMapRev()[searchObj.TextureData]; - break; - } + + // Use start address of this blob + maxEndOfStreamPosition = (int)reader.GetOffsetMapRev()[searchObj.TextureData]; + break; } if (maxEndOfStreamPosition == -1) diff --git a/UndertaleModLib/Util/GMImage.cs b/UndertaleModLib/Util/GMImage.cs index 20a138056..eef1eb7a7 100644 --- a/UndertaleModLib/Util/GMImage.cs +++ b/UndertaleModLib/Util/GMImage.cs @@ -111,7 +111,9 @@ public GMImage(int width, int height) _data = new byte[width * height * 4]; } - // Constructor for use by other creation methods + /// + /// Basic private constructor for use by other creation methods; just initializes the given fields. + /// private GMImage(ImageFormat format, int width, int height, byte[] data) { Format = format; @@ -195,15 +197,13 @@ private static long FindEndOfBZ2Search(IBinaryReader reader, long endDataPositio // Return position relative to the start of the data we read return (endDataPosition - data.Length) + endOfBZ2StreamPosition; } - else + + // Current search failed to make a full match, so progress to next bit, to search starting from there + searchStartBitPosition++; + if (searchStartBitPosition >= 8) { - // Current search failed to do a full match, so progress to next bit, to search starting from there - searchStartBitPosition++; - if (searchStartBitPosition >= 8) - { - searchStartBitPosition = 0; - searchStartPosition--; - } + searchStartBitPosition = 0; + searchStartPosition--; } } @@ -259,7 +259,7 @@ private static long FindEndOfBZ2Stream(IBinaryReader reader, long startOfStreamP /// Binary reader to read the image data from. /// /// Location where the image stream must end at or before, from within the . - /// There should only be 0 bytes (AKA padding), between the end of the image data and this position. + /// There should only be 0x00 bytes (AKA padding), between the end of the image data and this position. /// /// Whether using GameMaker version 2022.5 or above. Relevant only for BZ2 + QOI format images. /// If no supported texture format is found @@ -275,8 +275,8 @@ public static GMImage FromBinaryReader(IBinaryReader reader, long maxEndOfStream // PNG if (header.SequenceEqual(MagicPng)) { - // There's no overall PNG image length, so we parse image - // chunks until we find the end + // There's no overall PNG image length, so we parse image chunks, + // which do have their own length, until we find the end while (true) { // PNG is big endian, so swap endianness here manually diff --git a/UndertaleModLib/Util/TextureWorker.cs b/UndertaleModLib/Util/TextureWorker.cs index 659bb07d7..7c387b5fa 100644 --- a/UndertaleModLib/Util/TextureWorker.cs +++ b/UndertaleModLib/Util/TextureWorker.cs @@ -106,6 +106,7 @@ public IMagickImage GetTextureFor(UndertaleTexturePageItem texPageItem, st /// /// Image color format will always be converted to BGRA, with no compression. /// + /// File path to read the image from. /// An image, in uncompressed BGRA format, containing the contents of the image file at the given path. public static MagickImage ReadBGRAImageFromFile(string filePath) { diff --git a/UndertaleModTool/Editors/UndertaleEmbeddedTextureEditor.xaml.cs b/UndertaleModTool/Editors/UndertaleEmbeddedTextureEditor.xaml.cs index 014695169..98eaa5377 100644 --- a/UndertaleModTool/Editors/UndertaleEmbeddedTextureEditor.xaml.cs +++ b/UndertaleModTool/Editors/UndertaleEmbeddedTextureEditor.xaml.cs @@ -98,11 +98,11 @@ private void ReloadTextureImage(object sender, PropertyChangedEventArgs e) if (texture is null) return; + if (e.PropertyName != nameof(UndertaleEmbeddedTexture.TexData.Image)) + return; + // If the texture's image was updated, reload it - if (e.PropertyName == nameof(UndertaleEmbeddedTexture.TexData.Image)) - { - UpdateImage(texture); - } + UpdateImage(texture); } private void UnloadTexture(object sender, RoutedEventArgs e) diff --git a/UndertaleModTool/Editors/UndertaleTexturePageItemEditor.xaml.cs b/UndertaleModTool/Editors/UndertaleTexturePageItemEditor.xaml.cs index d6245647c..b6817b0cc 100644 --- a/UndertaleModTool/Editors/UndertaleTexturePageItemEditor.xaml.cs +++ b/UndertaleModTool/Editors/UndertaleTexturePageItemEditor.xaml.cs @@ -78,18 +78,18 @@ private void ReloadTexturePage(object sender, PropertyChangedEventArgs e) if (item is null) return; - if (e.PropertyName == nameof(UndertaleTexturePageItem.TexturePage)) - { - UpdateImages(item); + if (e.PropertyName != nameof(UndertaleTexturePageItem.TexturePage)) + return; - // Start listening for (new) texture image updates - if (_textureDataContext is not null) - { - _textureDataContext.PropertyChanged -= ReloadTextureImage; - } - _textureDataContext = item.TexturePage.TextureData; - _textureDataContext.PropertyChanged += ReloadTextureImage; + UpdateImages(item); + + // Start listening for (new) texture image updates + if (_textureDataContext is not null) + { + _textureDataContext.PropertyChanged -= ReloadTextureImage; } + _textureDataContext = item.TexturePage.TextureData; + _textureDataContext.PropertyChanged += ReloadTextureImage; } private void ReloadTextureImage(object sender, PropertyChangedEventArgs e) @@ -98,11 +98,11 @@ private void ReloadTextureImage(object sender, PropertyChangedEventArgs e) if (item is null) return; + if (e.PropertyName != nameof(UndertaleEmbeddedTexture.TexData.Image)) + return; + // If the texture's image was updated, reload it - if (e.PropertyName == nameof(UndertaleEmbeddedTexture.TexData.Image)) - { - UpdateImages(item); - } + UpdateImages(item); } private void UnloadTexture(object sender, RoutedEventArgs e)