From 4bdda32f5d6ac5ddaae743824e36c98a0984e045 Mon Sep 17 00:00:00 2001
From: AsY!um- <377468+AsYlum-@users.noreply.github.com>
Date: Wed, 11 Nov 2026 23:07:58 +0100
Subject: [PATCH] Fix UOP frame header bounds and center off-by-one
Reject frame payloads shorter than the 40-byte header or without the AMOU magic.
---
Ultima/AnimationsUopLoader.cs | 11 ++++++++++-
UoFiddler.Controls/Forms/AnimationEditForm.cs | 2 +-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/Ultima/AnimationsUopLoader.cs b/Ultima/AnimationsUopLoader.cs
index c2a2dac7..e0ec0143 100644
--- a/Ultima/AnimationsUopLoader.cs
+++ b/Ultima/AnimationsUopLoader.cs
@@ -22,6 +22,9 @@ internal static class AnimationsUopLoader
internal const int _maxAnimActions = 80;
private const int _maxDirections = 5;
+ /// "AMOU", the first four bytes of every animation frame payload.
+ private const uint _frameMagic = 0x554F4D41;
+
///
/// Size of the fixed part of one AnimationSequence group record: the four leading fields,
/// the per frame bytes and the reserved block. Two variable length lists follow it.
@@ -568,7 +571,8 @@ private static byte[] ReadEntryData(UopEntry entry)
private static AnimationFrame[] ParseUopFrames(byte[] data, int direction, bool flip)
{
- if (data.Length < 36)
+ // The header is 40 bytes; frame count and table offset sit at 32 and 36
+ if (data.Length < 40)
{
return null;
}
@@ -576,6 +580,11 @@ private static AnimationFrame[] ParseUopFrames(byte[] data, int direction, bool
using var memoryStream = new MemoryStream(data);
using var reader = new BinaryReader(memoryStream);
+ if (reader.ReadUInt32() != _frameMagic)
+ {
+ return null;
+ }
+
reader.BaseStream.Seek(32, SeekOrigin.Begin);
int frameCount = reader.ReadInt32();
uint dataStart = reader.ReadUInt32();
diff --git a/UoFiddler.Controls/Forms/AnimationEditForm.cs b/UoFiddler.Controls/Forms/AnimationEditForm.cs
index 89006bfc..01a63ec1 100644
--- a/UoFiddler.Controls/Forms/AnimationEditForm.cs
+++ b/UoFiddler.Controls/Forms/AnimationEditForm.cs
@@ -1043,7 +1043,7 @@ private void OnFrameCountBarChanged(object sender, EventArgs e)
}
AnimIdx edit = AnimationEdit.GetAnimation(_fileType, _currentBody, _currentAction, _currentDir);
- if (edit != null && edit.Frames.Count >= FramesTrackBar.Value)
+ if (edit != null && edit.Frames.Count > FramesTrackBar.Value)
{
CenterXNumericUpDown.Value = edit.Frames[FramesTrackBar.Value].Center.X;
CenterYNumericUpDown.Value = edit.Frames[FramesTrackBar.Value].Center.Y;