From a415c6d6ac1573883a56539b4343a9944e8ebbd6 Mon Sep 17 00:00:00 2001 From: erik Date: Sun, 8 Feb 2026 18:29:49 +0100 Subject: [PATCH] Add project plan and next steps documentation Covers all 5 completed phases, project structure, Phase 6 verification strategy (bottom-up one-DLL-at-a-time testing), and known pitfalls. Co-Authored-By: Claude Opus 4.6 --- docs/PLAN.md | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 docs/PLAN.md diff --git a/docs/PLAN.md b/docs/PLAN.md new file mode 100644 index 0000000..843032a --- /dev/null +++ b/docs/PLAN.md @@ -0,0 +1,155 @@ +# Plan: Open-Source Decal Rebuild + +## Context +Decal is a plugin framework for Asheron's Call. The game's official servers shut down, but the community runs it via ACEmulator. The modern Decal installer (v2.9.8.3) is closed-source. We have old C++ source code (partial match) and have decompiled all .NET assemblies. Goal: produce a fully open-source Decal that works with the original AC client, buildable from a single Visual Studio 2022 solution. + +## Architecture Decision +- **Rewrite native C++ DLLs as C# COM servers** — same GUIDs, same interfaces, different implementation language +- **Keep only 2 components in C++:** `Inject.DLL` (D3D hooking, ~500-800 lines) and `LauncherHook.DLL` (~200 lines) +- **Use Vortice.DirectX** for D3D9 rendering in C# (DecalRender, D3DService) +- **Preserve plugin compatibility** by matching all COM CLSIDs/IIDs exactly + +## Project Structure +``` +reconstructed/ +├── Managed/ # 25 C# projects +│ ├── Decal.sln # Solution file (25 projects, 0 errors) +│ ├── Directory.Build.props # Shared: net472, x86, LangVersion 12 +│ ├── Decal.Interop.*/ # 11 COM interface assemblies (decompiled) +│ ├── Decal.Adapter/ # Plugin adapter (decompiled) +│ ├── Decal.FileService/ # File service (decompiled) +│ ├── DecalUtil/ # Utility exe (decompiled) +│ ├── Decal.DecalDat/ # DAT file I/O (COM server) +│ ├── Decal.DHS/ # Hotkey system (COM server) +│ ├── Decal.SpellFilter/ # Spell data (COM server) +│ ├── Decal.DecalInput/ # Input handling (COM server) +│ ├── Decal.DecalNet/ # Network packets (COM server) +│ ├── Decal.DecalFilters/ # Game data/world objects (COM server) +│ ├── Decal.Core/ # Plugin manager/lifecycle (COM server) +│ ├── Decal.DecalControls/ # UI widgets (COM server) +│ ├── Decal.DecalRender/ # HUD rendering (COM server) +│ ├── Decal.D3DService/ # 3D markers (COM server) +│ └── Decal.DenAgent/ # System tray app (WinForms) +├── Native/ +│ ├── InjectModern/ # Inject.DLL - D3D9 vtable hooking (C++) +│ ├── LauncherHookModern/ # LauncherHook.DLL - process injection (C++) +│ ├── CMakeLists.txt # Top-level CMake for native builds +│ ├── Inject/ # Old C++ source (reference only) +│ ├── LobbyHook/ # Old C++ source (reference only) +│ ├── Decal/ # Old C++ source (reference only) +│ └── ... # Other old native source (reference) +├── Installer/ +│ ├── Package.wxs # WiX v5 MSI package definition +│ └── Decal.Installer.wixproj # WiX project file +├── build.cmd # Top-level build script +└── docs/ + └── PLAN.md # This file +``` + +--- + +## Status: Phases 1-5 Complete (Skeleton) + +All 5 phases are structurally complete. The solution compiles with 0 errors. +Most COM server methods are **stubs** — they implement the correct interfaces +and preserve GUIDs, but many methods are no-ops that need real logic. + +--- + +## Phase 1: Build Existing .NET Layer ✅ COMPLETE +- 14 decompiled .NET projects building from `Decal.sln` +- `Directory.Build.props` centralizes build settings +- All Interop projects use ProjectReference + +## Phase 2: Rewrite Native DLLs as C# COM Servers ✅ COMPLETE (stubs) + +| # | Component | CLSID | Status | +|---|-----------|-------|--------| +| 1 | DecalDat | IDatService, IDatReader | Stub | +| 2 | DHS | IHotkeySystem, IHotkey | Stub | +| 3 | SpellFilter | ISpells, ISpell | Stub | +| 4 | DecalInput | IInputService, IKeyboard, IMouse | Stub | +| 5 | DecalNet | INetService, IMessage2, INetworkFilter2 | Stub | +| 6 | DecalFilters | IWorld, IWorldObject, ICharacterStats | Stub | +| 7 | Decal.Core | IDecalCore, IPluginSite2, IACHooks, IDecalEnum | Stub | +| 8 | DecalControls | 16 control types | Stub | +| 9 | DecalRender | IRenderService, IHUDView, IHUDBackground | Stub | +| 10 | D3DService | ID3DService, ID3DObj | Stub | + +All preserve original CLSIDs/GUIDs for plugin compatibility. + +## Phase 3: C++ Shims ✅ COMPLETE +- `Native/InjectModern/` — Inject.DLL (~530 lines) — D3D9 vtable hooking, lifecycle +- `Native/LauncherHookModern/` — LauncherHook.DLL (~330 lines) — CreateProcess IAT hook +- CMake build: `cmake -G "Visual Studio 17 2022" -A Win32` + +## Phase 4: DenAgent ✅ COMPLETE +- `Managed/Decal.DenAgent/` — System tray, plugin management, options dialog + +## Phase 5: Build System & Installer ✅ COMPLETE +- `Installer/Package.wxs` — WiX v5 MSI +- `build.cmd` — Top-level build script + +--- + +## Phase 6: Verification & Implementation (NEXT) + +Goal: **Pixel-perfect drop-in replacement** for the closed-source Decal v2.9.8.3. + +Strategy: **Bottom-up, one DLL at a time.** Replace one original DLL with our C# +version while keeping all other original DLLs in place. Test. Move to the next. + +### Step 1: Build on Windows +``` +# C++ native projects (requires VS 2022 + Windows SDK) +cd Native +cmake -G "Visual Studio 17 2022" -A Win32 -B build +cmake --build build --config Release + +# Managed solution +dotnet build Managed\Decal.sln -c Release +``` + +### Step 2: COM Registration Test +Register all C# COM servers and verify GUIDs match originals: +``` +regasm /codebase Managed\bin\Release\Decal.Core.dll +regasm /codebase Managed\bin\Release\Decal.DecalDat.dll +... (all 10 COM server DLLs) +``` +Then verify in registry: `HKCR\CLSID\{GUID}\InprocServer32` points to our DLLs. + +### Step 3: Smoke Test — DenAgent +Run `Decal.DenAgent.exe` and verify: +- Tray icon appears +- Configure dialog opens +- Plugin list populates from registry + +### Step 4: Integration Test (one DLL at a time) +Install original Decal v2.9.8.3, then swap one DLL at a time: +1. Replace `DecalDat.DLL` → test DAT file reading +2. Replace `DHS.dll` → test hotkeys +3. Replace `SpellFilter.dll` → test spell data +4. Continue through all 10... +Each swap that fails tells us exactly which stubs need real implementations. + +### Step 5: Plugin Compatibility Test +Load community Decal plugins and verify they work: +- VTank +- Mag-Tools +- Other popular plugins + +--- + +## Known Pitfalls +- `record` types need IsExternalInit, unavailable in net472 → use class instead +- `CollectionsMarshal.AsSpan` unavailable in net472 +- LongValueKey enum: correct names are `keyStackCount`, `keyContainer` +- tagPOINT defined in Interop.Inject, needed by Interop.Render → add ProjectReference +- ICommandEvents delegates ambiguous between Interop.Controls and Interop.Inject → use `using` aliases + +## Build Requirements +- .NET SDK 8.0+ (targets net472 via NuGet reference assemblies) +- Visual Studio 2022 with C++ Desktop workload (for native DLLs) +- Windows SDK (for d3d9.h, Win32 APIs) +- WiX Toolset v5 (optional, for MSI installer)