Initial commit: Complete open-source Decal rebuild

All 5 phases of the open-source Decal rebuild:

Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil)
Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs
  - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters
  - Decal.Core, DecalControls, DecalRender, D3DService
Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL
Phase 4: DenAgent WinForms tray application
Phase 5: WiX installer and build script

25 C# projects building with 0 errors.
Native C++ projects require VS 2022 + Windows SDK (x86).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
erik 2026-02-08 18:27:56 +01:00
commit d1442e3747
1382 changed files with 170725 additions and 0 deletions

View file

@ -0,0 +1,380 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using Decal.Adapter.Support;
using Decal.Interop.Core;
using Decal.Interop.Render;
namespace Decal.Adapter.Wrappers;
[CLSCompliant(true)]
public class HudRenderTarget : MarshalByRefObject, IDisposable
{
private IRenderTarget myTarget;
private bool isDisposed;
private Rectangle areaRect;
private bool inRender;
private bool inText;
public bool Lost => myTarget.Lost;
[EditorBrowsable(EditorBrowsableState.Never)]
public Rectangle Constraint
{
get
{
Rectangle region = Region;
return new Rectangle(0, 0, region.Width, region.Height);
}
}
public Rectangle Region
{
get
{
return Util.toRectangle(myTarget.Region);
}
set
{
tagRECT pVal = Util.toTagRECT(value);
myTarget.Region = pVal;
areaRect.Width = value.Width;
areaRect.Height = value.Height;
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public object UnsafeSurface => myTarget.GetSurface();
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public tagRECT UnsafeRegion
{
get
{
return myTarget.Region;
}
set
{
myTarget.Region = value;
}
}
protected bool IsDisposed => isDisposed;
[CLSCompliant(false)]
protected HudRenderTarget(IRenderTarget newTarget)
{
if (newTarget == null)
{
throw new ArgumentNullException("newTarget");
}
myTarget = newTarget;
tagRECT region = myTarget.Region;
areaRect = new Rectangle(0, 0, region.right - region.left, region.bottom - region.top);
}
~HudRenderTarget()
{
Dispose(disposing: false);
}
public void BeginRender()
{
BeginRender(enableTextureFilter: false);
}
public void BeginRender(bool enableTextureFilter)
{
if (!inRender)
{
myTarget.BeginRender(enableTextureFilter);
inRender = true;
return;
}
throw new RenderViolationException("Cannot call 'BeginRender' when already rendering");
}
public void EndRender()
{
if (inRender)
{
myTarget.EndRender();
inRender = false;
return;
}
throw new RenderViolationException("Cannot call 'EndRender' without a previous call to 'BeginRender'");
}
public void BeginText(string fontName, int pixelHeight)
{
BeginText(fontName, pixelHeight, FontWeight.Normal, italic: false);
}
public void BeginText(string fontName, int pixelHeight, FontWeight weight, bool italic)
{
UnsafeBeginText(fontName, pixelHeight, (int)weight, italic);
}
public void WriteText(string text)
{
WriteText(text, Color.Black, WriteTextFormats.None, areaRect);
}
public void WriteText(string text, Color color)
{
WriteText(text, color, WriteTextFormats.None, areaRect);
}
public void WriteText(string text, Color color, WriteTextFormats format, Rectangle region)
{
UnsafeWriteText(Util.toTagRECT(region), color.ToArgb(), (int)format, text);
}
public void WriteText(string text, int color, WriteTextFormats format, Rectangle region)
{
UnsafeWriteText(Util.toTagRECT(region), color, (int)format, text);
}
public void EndText()
{
if (inRender && inText)
{
myTarget.EndText();
inText = false;
return;
}
throw new RenderViolationException("Cannot call 'EndText' without a previous call to 'BeginText'");
}
public void Clear()
{
Clear(areaRect);
}
public void Clear(Rectangle clearArea)
{
UnsafeClear(Util.toTagRECT(clearArea));
}
public void DrawPortalImage(int portalFile, Rectangle destinationArea)
{
UnsafeDrawPortalImage(portalFile, Util.toTagRECT(destinationArea));
}
public void DrawPortalImage(int portalFile, int alpha, Rectangle srcArea, Rectangle destinationArea)
{
UnsafeDrawPortalImage(portalFile, alpha, Util.toTagRECT(srcArea), Util.toTagRECT(destinationArea));
}
public void DrawPortalImage(int portalFile, Rectangle srcArea, Rectangle destinationArea)
{
UnsafeDrawPortalImage(portalFile, 255, Util.toTagRECT(srcArea), Util.toTagRECT(destinationArea));
}
public void TilePortalImage(int portalFile, Rectangle destinationArea)
{
UnsafeTilePortalImage(portalFile, Util.toTagRECT(destinationArea));
}
public void TilePortalImage(int portalFile, Rectangle srcArea, Rectangle destinationArea)
{
UnsafeTilePortalImage(portalFile, Util.toTagRECT(srcArea), Util.toTagRECT(destinationArea));
}
public void DrawImage(Image image, Rectangle destinationRegion)
{
DrawImage(image, destinationRegion, Color.Cyan.ToArgb());
}
public void DrawImage(Image image, Rectangle destinationRegion, Color colorKey)
{
DrawImage(image, destinationRegion, colorKey.ToArgb());
}
public void DrawImage(Image image, Rectangle destinationRegion, int colorKey)
{
if (image == null)
{
throw new ArgumentNullException("image");
}
MemoryStream memoryStream = new MemoryStream();
image.Save((Stream)memoryStream, ImageFormat.Bmp);
byte[] buffer = memoryStream.GetBuffer();
IntPtr zero = IntPtr.Zero;
int num = buffer.Length;
zero = Marshal.AllocCoTaskMem(num);
try
{
Marshal.Copy(buffer, 0, zero, num);
if (zero != IntPtr.Zero)
{
UnsafeDrawImage(zero, num, Util.toTagRECT(destinationRegion), colorKey);
}
}
finally
{
Marshal.FreeCoTaskMem(zero);
memoryStream.Dispose();
}
}
public void Fill(Color color)
{
Fill(areaRect, color);
}
public void Fill(Rectangle fillArea, Color color)
{
Fill(fillArea, color.ToArgb());
}
public void Fill(Rectangle fillArea, int color)
{
UnsafeFill(Util.toTagRECT(fillArea), color);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeBeginText(string fontName, int pixelHeight, int weight, bool italic)
{
if (inRender && !inText)
{
myTarget.BeginText(fontName, pixelHeight, weight, italic);
inText = true;
return;
}
if (inRender && inText)
{
throw new RenderViolationException("Cannot call 'BeginText' when already rendering text");
}
throw new RenderViolationException("Cannot call 'BeginText' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeWriteText(tagRECT region, int color, int format, string text)
{
if (inRender && inText)
{
myTarget.WriteText(ref region, color, format, text);
return;
}
throw new RenderViolationException("Cannot call 'WriteText' outside of a BeginText/EndText block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeClear(tagRECT clearArea)
{
if (!inRender)
{
myTarget.Clear(ref clearArea);
return;
}
throw new RenderViolationException("MUST call 'Clear' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeDrawPortalImage(int portalFile, tagRECT destinationArea)
{
if (inRender)
{
myTarget.DrawPortalImage(portalFile, ref destinationArea);
return;
}
throw new RenderViolationException("Cannot call 'DrawPortalImage' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeDrawPortalImage(int portalFile, int alpha, tagRECT srcArea, tagRECT destinationArea)
{
if (inRender)
{
myTarget.DrawPortalImageEx(portalFile, alpha, ref srcArea, ref destinationArea);
return;
}
throw new RenderViolationException("Cannot call 'DrawPortalImageEx' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeTilePortalImage(int portalFile, tagRECT destinationArea)
{
if (inRender)
{
myTarget.TilePortalImage(portalFile, ref destinationArea);
return;
}
throw new RenderViolationException("Cannot call 'TilePortalImage' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeTilePortalImage(int portalFile, tagRECT srcArea, tagRECT destinationArea)
{
if (inRender)
{
myTarget.TilePortalImageEx(portalFile, ref srcArea, ref destinationArea);
return;
}
throw new RenderViolationException("Cannot call 'TilePortalImageEx' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeDrawImage(IntPtr buffer, int size, tagRECT destinationRegion, int colorKey)
{
if (inRender)
{
myTarget.DrawImage((int)buffer, size, ref destinationRegion, colorKey);
return;
}
throw new RenderViolationException("Cannot call 'DrawImage' outside of a BeginRender/EndRender block");
}
[CLSCompliant(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeFill(tagRECT fillArea, int color)
{
if (!inRender)
{
myTarget.Fill(ref fillArea, color);
return;
}
throw new RenderViolationException("MUST call 'Fill' outside of a BeginRender/EndRender block");
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnsafeSetSurface(object pSurface)
{
myTarget.SetSurface(pSurface);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
}
if (myTarget != null)
{
Marshal.ReleaseComObject(myTarget);
}
myTarget = null;
isDisposed = true;
}
}