Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 48 additions & 10 deletions Ultima/Art.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,16 @@ static Art()
}

/// <summary>
/// Validates if a static bitmap will fit within the MUL format limits.
/// The format uses 16-bit lookup table offsets, limiting total encoded data to ~65,535 ushorts.
/// Validates if a static bitmap will fit within the MUL format limits by computing
/// the exact encoded size. The format uses 16-bit lookup table offsets, limiting total
/// encoded data to 65,535 ushorts. A pixel is considered opaque when its alpha bit
/// (0x8000) is set in 16bppArgb1555 — callers that want pure-black/white treated as
/// transparent must run the bitmap through Utils.ConvertBmp first (mirrors the save path).
/// Per-row encoded cost: 2 ushorts header per opaque run + 1 ushort per opaque pixel + 2 end markers.
/// </summary>
/// <param name="bmp">The bitmap to validate</param>
/// <param name="estimatedSize">Estimated size in ushorts (output)</param>
/// <returns>True if the image should fit, false if it exceeds limits</returns>
/// <param name="estimatedSize">Encoded size in ushorts (output)</param>
/// <returns>True if the image fits, false if it exceeds limits</returns>
public static unsafe bool ValidateStaticSize(Bitmap bmp, out int estimatedSize)
{
estimatedSize = 0;
Expand All @@ -50,14 +54,48 @@ public static unsafe bool ValidateStaticSize(Bitmap bmp, out int estimatedSize)
return true;
}

// Estimate worst case: each scanline has full width of visible pixels
// Format: 2 ushorts for offset/run + width ushorts for data + 2 ushorts for end markers per line
int maxUshortsPerLine = 4 + bmp.Width;
estimatedSize = bmp.Height * maxUshortsPerLine;
BitmapData bd = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format16bppArgb1555);

// The lookup table uses 16-bit offsets, so we're limited to 65535 ushorts
const int maxUshorts = 65535;
int total = 0;
try
{
var line = (ushort*)bd.Scan0;
int delta = bd.Stride >> 1;

for (int y = 0; y < bmp.Height; ++y, line += delta)
{
ushort* cur = line;
int x = 0;
while (x < bmp.Width)
{
while (x < bmp.Width && (cur[x] & 0x8000) == 0)
{
++x;
}
if (x >= bmp.Width)
{
break;
}

int runStart = x;
while (x < bmp.Width && (cur[x] & 0x8000) != 0)
{
++x;
}
total += 2 + (x - runStart);
}
total += 2;
}
}
finally
{
bmp.UnlockBits(bd);
}

estimatedSize = total;

const int maxUshorts = 65535;
return estimatedSize <= maxUshorts;
}

Expand Down
36 changes: 36 additions & 0 deletions UoFiddler.Controls/Classes/AppLog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/***************************************************************************
*
* $Author: Turley
*
* "THE BEER-WARE LICENSE"
* As long as you retain this notice you can do whatever you want with
* this stuff. If we meet some day, and you think this stuff is worth it,
* you can buy me a beer in return.
*
***************************************************************************/

using System;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace UoFiddler.Controls.Classes
{
/// <summary>
/// Static logger façade for sites that cannot accept ILogger via constructor injection
/// (static helpers, designer-built UserControls, plugins instantiated via Activator).
/// Constructor-injectable types should take ILogger&lt;T&gt; directly instead of using this.
/// </summary>
public static class AppLog
{
private static ILoggerFactory _factory = NullLoggerFactory.Instance;

public static void Initialize(ILoggerFactory factory)
{
_factory = factory ?? NullLoggerFactory.Instance;
}

public static ILogger<T> For<T>() => _factory.CreateLogger<T>();

public static ILogger For(Type type) => _factory.CreateLogger(type.FullName);
}
}
4 changes: 3 additions & 1 deletion UoFiddler.Controls/Classes/DynamicItemsConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
using System.Globalization;
using System.IO;
using System.Xml;
using Microsoft.Extensions.Logging;
using Ultima;

namespace UoFiddler.Controls.Classes
{
public static class DynamicItemsConfig
{
private static readonly ILogger _log = AppLog.For(typeof(DynamicItemsConfig));
private static bool _loaded;

public static void EnsureLoaded()
Expand All @@ -33,7 +35,7 @@ public static void EnsureLoaded()
string path = Path.Combine(Options.AppDataPath, "DynamicItems.xml");
if (!File.Exists(path))
{
Options.Logger?.Warning("DynamicItems.xml not found at {Path}", path);
_log.LogWarning("DynamicItems.xml not found at {Path}", path);
return;
}

Expand Down
11 changes: 0 additions & 11 deletions UoFiddler.Controls/Classes/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,11 @@
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using Serilog;

namespace UoFiddler.Controls.Classes
{
public static class Options
{
/// <summary>
/// Logger instance
/// </summary>
public static ILogger Logger { get; private set; }

public static void SetLogger(ILogger logger)
{
Logger = logger;
}

/// <summary>
/// Defines Element Width in ItemShow
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions UoFiddler.Controls/Plugin/PluginBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
***************************************************************************/

using System.Windows.Forms;
using Microsoft.Extensions.Logging;
using UoFiddler.Controls.Classes;
using UoFiddler.Controls.Plugin.Interfaces;

namespace UoFiddler.Controls.Plugin
Expand All @@ -23,6 +25,12 @@ public abstract class PluginBase
public abstract string Author { get; }
public abstract string Version { get; }

/// <summary>
/// Per-plugin logger, categorized by the concrete plugin type. Resolved on demand
/// since plugins are instantiated via Activator and cannot take constructor parameters.
/// </summary>
protected ILogger Logger => AppLog.For(GetType());

public abstract void Initialize();
public abstract void Unload();

Expand Down
13 changes: 8 additions & 5 deletions UoFiddler.Controls/Plugin/PluginServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System;
using System.IO;
using System.Reflection;
using Microsoft.Extensions.Logging;
using UoFiddler.Controls.Classes;
using UoFiddler.Controls.Plugin.Interfaces;
using UoFiddler.Controls.UserControls;
Expand All @@ -21,6 +22,8 @@ namespace UoFiddler.Controls.Plugin
{
public class PluginServices : IPluginHost
{
private static readonly ILogger _log = AppLog.For(typeof(PluginServices));

/// <summary>
/// A Collection of all Plugins Found
/// </summary>
Expand All @@ -40,12 +43,12 @@ public void FindPlugins()
/// <param name="path">Directory to search for Plugins in</param>
public void FindPlugins(string path)
{
Options.Logger.Information("FindPlugins - searching for plugins in [AppDomain.CurrentDomain.BaseDirectory = {Path}]", path);
_log.LogInformation("FindPlugins - searching for plugins in [AppDomain.CurrentDomain.BaseDirectory = {Path}]", path);

AvailablePlugins.Clear();
if (!Directory.Exists(path))
{
Options.Logger.Warning("FindPlugins - plugin directory doesn't exist: {Path}", path);
_log.LogWarning("FindPlugins - plugin directory doesn't exist: {Path}", path);
return;
}

Expand All @@ -57,7 +60,7 @@ public void FindPlugins(string path)
}
catch (Exception ex)
{
Options.Logger.Fatal(ex, "FindPlugins - exception caught");
_log.LogCritical(ex, "FindPlugins - exception caught");
}
}
}
Expand All @@ -74,7 +77,7 @@ public void ClosePlugins()
continue;
}

Options.Logger.Information("FindPlugins - disposing plugin: {Plugin}", plugin.Type.ToString());
_log.LogInformation("FindPlugins - disposing plugin: {Plugin}", plugin.Type.ToString());
plugin.Instance.Unload();
plugin.Instance = null;
}
Expand Down Expand Up @@ -106,7 +109,7 @@ private void AddPlugin(string fileName)

if (Options.PluginsToLoad?.Contains(pluginType.ToString()) == true)
{
Options.Logger.Information("FindPlugins - AddPlugin of type: {Type} from file: {FileName}", pluginType.ToString(), newPlugin.AssemblyPath);
_log.LogInformation("FindPlugins - AddPlugin of type: {Type} from file: {FileName}", pluginType.ToString(), newPlugin.AssemblyPath);
newPlugin.CreateInstance();
newPlugin.Instance.Host = this;
newPlugin.Instance.Initialize();
Expand Down
6 changes: 3 additions & 3 deletions UoFiddler.Controls/UoFiddler.Controls.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,9 @@
<None Include="Resources\staticPlayButton.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="System.Drawing.Common" Version="10.0.5" />
<PackageReference Include="System.Resources.Extensions" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.7" />
<PackageReference Include="System.Drawing.Common" Version="10.0.7" />
<PackageReference Include="System.Resources.Extensions" Version="10.0.7" />
<PackageReference Include="AnimatedGif" Version="1.0.5" />
</ItemGroup>
</Project>
8 changes: 4 additions & 4 deletions UoFiddler.Controls/UserControls/ItemsControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -519,11 +519,11 @@ private void OnClickReplace(object sender, EventArgs e)
MessageBox.Show(
$"Image is too large for MUL format!\n\n" +
$"Image dimensions: {bitmap.Width}x{bitmap.Height}\n" +
$"Estimated encoded size: {estimatedSize:N0} ushorts\n" +
$"Encoded size: {estimatedSize:N0} ushorts\n" +
$"Maximum allowed: 65,535 ushorts\n\n" +
$"Recommended maximum for solid color images: ~254x254 pixels\n" +
$"Images with transparency can be larger.\n\n" +
$"Please use a smaller image.",
$"The static art format encodes opaque pixel runs only; cost per row is\n" +
$"2 ushorts per run + 1 ushort per opaque pixel + 2 end markers.\n" +
$"Reduce the image size or the amount of opaque content.",
"Image Too Large",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
Expand Down
3 changes: 0 additions & 3 deletions UoFiddler.Plugin.Compare/UoFiddler.Plugin.Compare.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
<OutputPath>..\UoFiddler\bin\$(Configuration)\plugins\</OutputPath>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<Compile Update="UserControls\CompareCliLocControl.cs">
<SubType>UserControl</SubType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
<OutputPath>..\UoFiddler\bin\$(Configuration)\plugins\</OutputPath>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<Compile Update="Forms\ExampleForm.cs">
<SubType>Form</SubType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@
<OutputPath>..\UoFiddler\bin\$(Configuration)\plugins\</OutputPath>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<Compile Update="Forms\MassImportForm.cs">
<SubType>Form</SubType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="System.Resources.Extensions" Version="10.0.5" />
<PackageReference Include="System.Resources.Extensions" Version="10.0.7" />
</ItemGroup>
</Project>
3 changes: 0 additions & 3 deletions UoFiddler.Plugin.SendItem/UoFiddler.Plugin.SendItem.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
<OutputPath>..\UoFiddler\bin\$(Configuration)\plugins\</OutputPath>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<Compile Update="Forms\SendItemOptionsForm.cs">
<SubType>Form</SubType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ultima\Ultima.csproj">
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading