{"id":51359231,"url":"https://github.com/mikemequis/asher","last_synced_at":"2026-07-02T22:00:44.430Z","repository":{"id":331555117,"uuid":"1119715723","full_name":"MikeMequis/Asher","owner":"MikeMequis","description":"Dust: An Elysian Tail launcher-based modding platform","archived":false,"fork":false,"pushed_at":"2026-07-02T20:16:06.000Z","size":27223,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"develop","last_synced_at":"2026-07-02T20:19:14.384Z","etag":null,"topics":["csharp","dust-an-elysian-tail","harmony","launcher","modding-tools","patch"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MikeMequis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-19T18:13:29.000Z","updated_at":"2026-07-02T20:16:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/MikeMequis/Asher","commit_stats":null,"previous_names":["mikemequis/asher"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MikeMequis/Asher","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MikeMequis%2FAsher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MikeMequis%2FAsher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MikeMequis%2FAsher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MikeMequis%2FAsher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MikeMequis","download_url":"https://codeload.github.com/MikeMequis/Asher/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MikeMequis%2FAsher/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35064251,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dust-an-elysian-tail","harmony","launcher","modding-tools","patch"],"created_at":"2026-07-02T22:00:37.568Z","updated_at":"2026-07-02T22:00:44.422Z","avatar_url":"https://github.com/MikeMequis.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"﻿# 🧱 Asher Modding Platform\n\n**Asher** is a launcher-based modding platform for *Dust: An Elysian Tail*, designed to support **runtime code patching** and **content replacement** in a safe, modular, and reversible way.\n\nInspired by mature mod loaders such as **SMAPI**, Asher prioritizes **explicit initialization order**, **runtime lifecycle control**, and **clean debugging**, deliberately avoiding fragile early-injection patterns.\n\n---\n\n## 🎯 Project Goals\n\n- Runtime code patching using **Harmony**\n- Asset replacement without modifying `.xnb` files\n- Modular and reversible mod loading\n- UI-based patch selection and configuration\n- Full compatibility with **Steam**, **XNA**, and **.NET Framework**\n\n---\n\n## 🧠 Core Architecture (Launcher-First)\n\nAsher is built around a **custom launcher**, which guarantees a deterministic initialization order and reliable runtime behavior.\n\n**Key principle:**  \nInjection and patching are **controlled and delayed**, never performed blindly at process startup.\n\nThis design mirrors proven approaches used by SMAPI and other stable modding platforms.\n\nA companion **WPF manager app** (`Asher.App`) handles installation, mod management, and user settings without touching the game process directly.\n\n---\n\n## 🗂️ Solution Structure\n\n```\n/Asher.sln\n│\n├── Asher.App/                  → WPF installer \u0026 mod manager (.NET 8, x86)\n├── Asher.UserInterface/        → WPF views, view models, theming\n├── Asher.Services/             → Installation, launch, patch manager, shortcuts\n├── Asher.Core/                 → Paths, settings, shared models\n├── Asher.Localization/         → UI strings (en-US, pt-BR)\n│\n├── Asher.Launcher/             → Custom game launcher (.NET Framework 4.8)\n│   └── Program.cs              → Entry point and bootstrap orchestration\n│\n├── Asher.Runtime/              → Runtime mod loader foundation (.NET Framework 4.8)\n│   ├── Bootstrap/\n│   │   ├── AssemblyLoader.cs            → Dynamic mod assembly loading\n│   │   ├── GameLifecycleHooks.cs        → Game lifecycle event hooks\n│   │   ├── GameTitleBootstrap.cs        → Sets game window title\n│   │   ├── HarmonyLifecycleBootstrap.cs → Optional lifecycle hook injection\n│   │   ├── PreInitBootstrap.cs          → PreInit module discovery \u0026 execution\n│   │   ├── PatchModuleLoader.cs         → Harmony patch application\n│   │   └── LifecycleModuleLoader.cs     → Lifecycle event registration\n│   ├── Core/\n│   │   ├── GameContext.cs               → Game instance access\n│   │   ├── RuntimeContext.cs            → Configuration and paths\n│   │   ├── RuntimeController.cs         → Initialization and shutdown\n│   │   └── RuntimeResult.cs             → Operation result wrapper\n│   ├── Lifecycle/\n│   │   ├── LifecycleEvent.cs            → Lifecycle state enum\n│   │   └── GameLifecycleEventBus.cs     → Lifecycle state management\n│   ├── RuntimeEntry.cs                  → Public runtime API\n│   ├── RuntimeLogger.cs                 → File-based logging system\n│   └── RuntimeLoggerAdapter.cs          → SDK logger bridge\n│\n├── Asher.SDK/                  → API for mod developers (.NET Framework 4.8)\n│   ├── Logging/\n│   │   ├── AsherLog.cs                  → Static logger facade\n│   │   └── IAsherLogger.cs              → Logger interface\n│   └── Patching/\n│       ├── AsherLifecycleModuleBase.cs  → Base class for lifecycle monitoring\n│       ├── IAsherLifecycleModule.cs     → Lifecycle event interface\n│       ├── IAsherPatchModule.cs         → Harmony patch module interface\n│       └── IAsherPreInitModule.cs       → PreInit module interface\n│\n├── Asher.Patching.*/           → Built-in patch mods (DebugEnabler, IntroSkipper, etc.)\n│\n├── PrepareDistribution.ps1     → Bundles Distribution/ folder for install \u0026 deploy\n└── Distribution/               → Output folder (generated, not committed)\n```\n\n---\n\n## 🖥️ Asher Manager App\n\n`Asher.App` is a WPF application built with **Prism**, **Material Design**, and a modular service layer.\n\n### Installation mode\n\nWhen Asher is not yet installed in a game folder, the app opens in **installation mode** and starts on the **Start** page:\n\n1. **Start** — welcome and begin installation\n2. **Detect Game** — auto-detect or browse for the Dust folder\n3. **Installing** — deploy runtime, launcher wrapper, and default mods\n4. **Complete** — summary with optional **desktop shortcut** creation\n\nOn finish, the app switches to mod manager mode and navigates to **Home**. If the installer was run from `Distribution\\`, the distribution app closes and the installed copy at `[Game]\\Asher\\Asher.App\\Asher.App.exe` is launched automatically.\n\n### Mod manager mode\n\nWhen Asher is already installed (detected from settings or from running inside `[Game]\\Asher\\Asher.App\\`), the app opens in **manager mode** and starts on **Home**:\n\n| Page | Description |\n|------|-------------|\n| **Home** | Quick actions — launch game, open Patch Manager, Settings |\n| **Content Patcher** | Asset replacement UI (planned functionality) |\n| **Patch Manager** | Enable/disable mods by moving DLLs between `Mods/` and `Mods/disabled/` |\n| **Settings** | Game path, language, theme, backups, auto-launch |\n\n### App features\n\n- **Localization** — English and Portuguese (Brazil); language changes refresh labels without resetting the current page\n- **Light / Dark theme** — full-window Material Design theming via Settings\n- **Settings persistence** — `settings.json` in AppData, game manager folder, and local app directory\n- **Game launch** — launches `DustAET.exe` (Asher launcher wrapper) from the detected game folder\n- **Desktop shortcut** — optional shortcut to `Asher.App.exe` after installation\n- **Legacy layout migration** — automatically moves old root-level `Asher.App`, `Asher.Backup`, and `patches` into `Asher/`\n\n---\n\n## 🚀 Runtime Flow Overview\n\n### Initialization Sequence\n\n```\n1. User launches DustAET.exe via Steam or Asher Manager (Asher.Launcher wrapper)\n   ↓\n2. Launcher validates game installation\n   ↓\n3. RuntimeEntry.Init(context)\n   ├─\u003e RuntimeLogger initialized\n   ├─\u003e Directories prepared (Asher/Mods/, Asher/AsherLogs/)\n   └─\u003e Configuration loaded\n   ↓\n4. Assembly.LoadFrom(DustAET.real.exe)\n   ↓\n5. AssemblyLoader.LoadAssembliesFrom(\"Asher/Mods/\")\n   └─\u003e All *.dll files in Mods/ loaded dynamically\n   ↓\n6. PreInitBootstrap.ExecutePreInitModules()\n   └─\u003e Scans all loaded assemblies for IAsherPreInitModule\n   └─\u003e Executes each module's Execute() method\n   ↓\n7. GameTitleBootstrap.Apply(gameAssembly)\n   └─\u003e Sets window title to \"Dust - An Elysian Tail (Asher)\"\n   ↓\n8. PatchModuleLoader.Load()\n   ├─\u003e Creates Harmony instance (\"com.asher.runtime.mods\")\n   ├─\u003e Scans for IAsherPatchModule implementations\n   ├─\u003e Applies each module's patches via Harmony\n   ├─\u003e LifecycleModuleLoader.Load()\n   └─\u003e HarmonyLifecycleBootstrap.InitializeIfNeeded()\n   ↓\n9. Dust.Program.Main(args) invoked via Reflection\n   ↓\n10. Game executes normally with patches applied\n```\n\n\u003e **Important:** Launch the game through **Steam** or the manager's **Launch Game** button. Do not run `Asher.Launcher.exe` directly from the distribution folder — it must sit in the game root as `DustAET.exe` with `DustAET.exe.config` probing `Asher` and `Asher\\Mods`.\n\n---\n\n## 📁 Installed Game Folder Layout\n\nAfter installation, the game directory looks like this:\n\n```\n/GameFolder/\n├── DustAET.exe                  (Asher.Launcher copy — Steam entry point)\n├── DustAET.exe.config           (assembly probing: Asher; Asher\\Mods)\n├── DustAET.real.exe             (original game executable, renamed)\n│\n└── Asher/\n    ├── Asher.Runtime.dll\n    ├── Asher.SDK.dll\n    ├── 0Harmony.dll             (net472 build — required)\n    │\n    ├── Mods/                    (active runtime mods)\n    │   ├── Asher.Patching.DebugEnabler.dll\n    │   ├── Asher.Patching.IntroSkipper.dll\n    │   ├── Asher.Patching.GraphicsDeprofiler.dll\n    │   └── disabled/            (mods disabled via Patch Manager)\n    │\n    ├── AsherLogs/\n    │   └── runtime_YYYYMMDD_HHMMSS.log\n    │\n    ├── patches/                 (content patcher assets, future)\n    ├── Asher.Backup/            (original exe backup)\n    │\n    └── Asher.App/               (manager app + install payload)\n        ├── Asher.App.exe\n        ├── settings.json\n        ├── Asher.Launcher.exe\n        └── DefaultMods/\n```\n\nFolders are created automatically during installation.\n\n---\n\n## 🔧 Build \u0026 Distribution\n\n### Requirements\n\n- Visual Studio 2022 (or `dotnet` CLI)\n- **Platform: x86**\n- **Configuration: Release** (for distribution)\n\n### Steps\n\n1. Build the solution as **x86 Release** in Visual Studio\n2. Run the distribution script from the repo root:\n\n```powershell\n.\\PrepareDistribution.ps1\n```\n\n3. Run `Distribution\\Asher.App.exe` to install Asher into a game folder\n4. After install, use `[GameFolder]\\Asher\\Asher.App\\Asher.App.exe` for day-to-day management\n5. Launch the game via **Steam** or the manager's **Launch Game** button\n\n### Distribution notes\n\n- `PrepareDistribution.ps1` explicitly bundles the **net472** `0Harmony.dll` — using the wrong Harmony build will cause `System.Runtime` version errors at launch\n- The script copies launcher, runtime, SDK, default mods, and the manager app into `Distribution/`\n- `Distribution/` is generated output and should not be committed\n\n---\n\n## 📊 Project Status Overview\n\n| Area                      | Status      | Notes                                          |\n| ------------------------- | ----------- | ---------------------------------------------- |\n| Solution structure        | ✅ Done     | Multi-project architecture stabilized          |\n| Launcher-based runtime    | ✅ Done     | Wrapper EXE approach validated                 |\n| Steam compatibility       | ✅ Done     | Game launches normally via Steam               |\n| Runtime initialization    | ✅ Done     | Logs, lifecycle and folders working            |\n| Injection strategy        | ✅ Done     | No blind injection, controlled bootstrap       |\n| Harmony bootstrap         | ✅ Done     | Runtime patching confirmed and working         |\n| PreInit system            | ✅ Done     | Flag configuration before patches              |\n| Lifecycle hooks           | ✅ Done     | Optional event system for game lifecycle       |\n| Mod SDK                   | ✅ Done     | Clean interfaces for mod developers            |\n| First gameplay patch      | ✅ Done     | Debug Menu Enabler working                     |\n| External mod loader       | ✅ Done     | Dynamic .dll loading from Asher/Mods/          |\n| **Installer / Manager UI**| ✅ Done     | WPF app with install wizard \u0026 mod manager      |\n| **Patch Manager UI**      | ✅ Done     | Enable/disable mods via folder move            |\n| **Localization**          | ✅ Done     | English and Portuguese (Brazil)                |\n| **Light / Dark theme**    | ✅ Done     | Full-window Material Design theming            |\n| **Game window title**     | ✅ Done     | Shows \"Dust - An Elysian Tail (Asher)\"         |\n| Content patcher           | 🔜 Planned  | XNA ContentManager interception                |\n| Mod metadata (json)       | 🔜 Planned  | mod.json for description, dependencies, etc.   |\n| Public Mod API docs       | 🔜 Planned  | Developer documentation and examples           |\n\n---\n\n## 🧩 Learning \u0026 Implementation Kanban\n\n### 🟢 DONE — Consolidated Phases\n\n#### 🟢 Task 0 — Core Architecture \u0026 Bootstrap\n**Status:** ✔ Completed\n\n**Deliverables achieved:**\n- Stable multi-project solution architecture\n- Clear separation between Launcher, Runtime, SDK, and Manager App\n- Wrapper EXE approach validated:\n  - `DustAET.exe` → Asher Launcher\n  - `DustAET.real.exe` → original game executable\n- Full Steam compatibility preserved\n- Explicit runtime initialization order guaranteed\n\n#### 🟢 Task 1 — Runtime Modding Foundations\n**Status:** ✔ Completed\n\n**Concepts mastered:**\n- Generics (used for Asher infrastructure)\n- Reflection (runtime inspection, private member access)\n- Harmony (Prefix / Postfix / Transpiler patterns)\n\n**Key decisions locked in:**\n- Harmony is the official runtime patch engine\n- No permanent modification of game binaries or `.xnb` files\n\n#### 🟢 Task 2 — Launcher-Based Runtime Control\n**Status:** ✔ Completed\n\n- Custom launcher fully controls game startup\n- Runtime initialization occurs before game execution\n- Logging, folders, and context prepared deterministically\n- Runtime survives Steam launches transparently\n\n#### 🟢 Task 3 — Module System Architecture\n**Status:** ✔ Completed\n\n1. **PreInit System** — configuration before patches\n2. **Patch System** — Harmony patch application via `IAsherPatchModule`\n3. **Lifecycle System** — optional game event hooks\n\n#### 🟢 Task 4 — First Runtime Patch (Debug Enabler)\n**Status:** ✔ Completed ✨\n\n- First working gameplay patch: **Debug Menu Enabler**\n- PreInit → Patch → Lifecycle flow validated\n\n#### 🟢 Task 5 — Installer \u0026 Manager App\n**Status:** ✔ Completed\n\n**What was implemented:**\n- `Asher.App` WPF installer with guided setup flow\n- Game folder auto-detection (Steam, manual browse)\n- Deploys runtime, launcher wrapper, and default mods into `Asher/`\n- Mod manager with Home, Patch Manager, Settings, and Content Patcher shell\n- Patch enable/disable by moving DLLs between `Mods/` and `Mods/disabled/`\n- Launch game from manager\n- Settings: language, Light/Dark theme, game path, backups\n- Desktop shortcut option after installation\n- `AsherPaths` helpers and legacy layout migration\n- `PrepareDistribution.ps1` for repeatable builds\n\n---\n\n### 🟨 DOING — Current Phase\n\n#### 🟨 Task 6 — Patch Porting \u0026 Reverse Engineering\n\n**Status:** 🔄 In Progress\n\nPort and modernize existing gameplay patches from **DustAetPatchingPlatform** into the Asher runtime architecture.\n\n**Current workflow:**\n1. Analyze original patch behavior\n2. Inspect game internals using **dnSpy** when required\n3. Reimplement using `IAsherPreInitModule`, `IAsherPatchModule`, and optional lifecycle hooks\n4. Validate with runtime logs\n\n---\n\n### 🟥 BACKLOG — Short Term\n\n#### 🔴 Task 7 — Mod Metadata System\n- Design `mod.json` schema\n- Parse metadata on mod load\n- Load priority and dependency support\n\n#### 🔴 Task 8 — Content Patcher (Core)\n- Intercept `ContentManager.Load\u003cT\u003e()`\n- Resolve replacements via `content.json`\n- Support external assets (textures, fonts, data files)\n\n#### 🔴 Task 9 — Mod Configuration System\n- `IAsherConfigModule` interface\n- Per-mod configuration files\n- UI integration for settings\n\n#### 🔴 Task 10 — Mod Dependency System\n- Declare dependencies in `mod.json`\n- Validate dependency graph on load\n- Automatic load order resolution\n\n---\n\n## 🧠 Project Principles (Non-Negotiable)\n\n- 🚫 No `.xnb` editing\n- 🚫 No permanent binary modification\n- ✅ 100% runtime patching\n- ✅ Fully reversible (remove mod = original behavior)\n- ✅ Modular and extensible\n- ✅ Inspired by SMAPI, adapted to Dust\n- ✅ Clean separation: Launcher → Runtime → SDK → Mods\n- ✅ Comprehensive logging for debugging\n\n---\n\n## 🎮 Confirmed Working Features\n\n### Runtime \u0026 Modding\n- ✅ Dynamic mod loading from `Asher/Mods/`\n- ✅ Three-stage mod lifecycle: PreInit → Patch → Lifecycle\n- ✅ Clean SDK for mod developers\n- ✅ Comprehensive logging in `Asher/AsherLogs/`\n- ✅ Game window title: **Dust - An Elysian Tail (Asher)**\n\n### Manager App\n- ✅ Guided installation into any valid Dust game folder\n- ✅ Patch Manager — toggle mods on/off without deleting files\n- ✅ Launch game from manager\n- ✅ English and Portuguese (Brazil) UI\n- ✅ Light and Dark theme (full window)\n- ✅ Desktop shortcut creation after install\n- ✅ Settings persisted across sessions\n\n### Working Mods\n* ✅ **Debug Menu Enabler** — Tab in pause menu opens debug menu\n* ✅ **Intro Skipper** — Skips ESRB rating, splash screens, and startup videos\n* ✅ **Graphics Deprofiler** — Bypasses HiDef GPU profile restrictions\n\nAll implemented as external, runtime-loaded mods in `Asher/Mods/`.\n\n---\n\n## 📘 References\n\n- **Harmony** — https://github.com/pardeike/Harmony\n- **SMAPI** — https://github.com/Pathoschild/SMAPI\n- **SMAPI Content Patcher** — https://stardewvalleywiki.com/Modding:Content_Patcher\n- **DustAetPatchingPlatform** — https://github.com/GMMan/DustAetPatchingPlatform\n  - Steam Forum Discussion — https://steamcommunity.com/app/236090/discussions/0/540744936409038540/\n\n*Last Updated: July 2, 2026*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikemequis%2Fasher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikemequis%2Fasher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikemequis%2Fasher/lists"}