A 2026 rebuild of Magellan 2 (Adam Wright, 2003) for Decal 3 on the End-of-Retail Asheron's Call client: a places database, dungeon identification, on-screen coordinates, and a live dungeon automap generated from the client's own DAT geometry.
The original was a native ATL/COM plugin that drew with GDI onto a device context Decal handed it. That device context, that DAT format, and that plugin contract are all gone. This is a clean reimplementation on the modern managed stack — but it starts from the original's data, window, and algorithm, all recovered from the 2003 binary and verified against independent sources.
GoArrow already does places and dungeon maps — but its dungeon maps are raster images downloaded
from a CDN that no longer exists. Magellan generates its map from client_cell_1.dat at
runtime, so it works offline and maps custom ACE-server dungeons nobody has ever drawn. That is the
differentiator; nostalgia is not.
- The main window is resizable -- drag the corner; taller is the point (long search/route
result lists). VVS sizes nothing automatically, so the plugin re-flows the notebook and all
three lists to the new client size (~5 Hz poll, no-op when unchanged), keeping the design's
margins. Your chosen size persists across sessions (VVS stores it in vvs.s3db);
/mag resetreturns the window to the stock 270x360. - List icons are the ORIGINAL 2003 icons again. The type->icon mapping was recovered by disassembling magellan2.dll from the original beta MSI (a 7-case jump table): Lifestone 0x06001355, Town 0x060012D3, Shop 0x0600100F, Interest/unknown 0x06001058, and Portal/Random Portal/Dungeon 0x0600106B. The previous ids were near-miss guesses that mostly don't exist in portal.dat -- the pink missing-image boxes in the result lists.
- List columns re-flow too, and coordinates are never clipped. VVS fixes column widths at
parse time (a resized list kept its original narrow coords column), so on every list resize the
plugin redistributes widths via
HudList.SetColumnWidth: the coords column is pinned at 92px (widest possible coordinate fits) and the NAME column absorbs all remaining width -- so widening the window now lengthens names, and coords are complete even at stock size.
The v1.2.2 field result was decisive in the unexpected direction: the full texture self-test came back GREEN on the affected machine while its window body stayed blank -- and a follow-up screenshot showed garbled, double-struck glyphs. Freshly-created textures work; what's dead is VVS's cached GPU resources (theme element textures, the glyph atlas) -- the classic result of a D3D device loss/reset that the caches didn't survive. Two additions to test and fix that in-game:
/mag theme--reloadassigns a brand-new instance of the current theme (same look), forcing VVS to rebuild its element textures without a client restart;<name>switches themes; barethemelists what's available. All reflective and guarded./mag diagcounts D3D device losses (viaVirindiViewService.Service.DeviceLost). Blank or garbled UI + green self-test + a nonzero count = stale caches after a reset; a machine that racks up losses (fullscreen alt-tab, resolution changes) against a healthy machine's 0 is the smoking gun. Windowed mode is the standing workaround if confirmed.
Follow-up from the first v1.2.1 field diag, which cleared the backend/wireup/ghost/alpha layers on the affected machine and taught us two things:
- The invisible-window warning no longer fires on
ClickThrough. Cross-checking two machines' diags against a livevvs.s3dbproved the runtimeHudView.ClickThroughproperty reads True on healthy, un-pinned windows whose persistedStoredViewInfo.ClickThroughis 0 -- it does not mirror the user's click-through toggle, so flagging it was a false positive. It is still reported, just not alarmed on; the authoritative flag lives only in vvs.s3db. /mag diagnow reports the main window's active THEME (reflected from the underlying view). With backend, wireup, ghost, and alpha all verified good, the per-window theme -- persisted per-machine in vvs.s3db (ThemeID2/IsCustomTheme) and capable of rendering control bodies blank while hover states still draw (cf. the tracker'sghostytabstheme knob) -- is the leading remaining suspect for "controls only visible under the mouse"./mag diagruns a texture-pipeline self-test (DxTexture create -> Fill -> ACImage from portal.dat, each step isolated). Screenshots from the affected machine showed the true fingerprint: text and line drawing fine (tabs, coords, the whole dungeon map) while every image-backed element was missing -- window background, buttons, edit/list bodies, and the magenta missing-texture box where the title-bar icon belongs. That is the D3DX/texture-load layer, not core D3D: the usual fix is installing the legacy DirectX End-User Runtime (June 2010) and re-running the Virindi Bundle installer, and the self-test names the first broken step in one chat line.
A diagnostics-and-visibility release, driven by one field report: "the dungeon map draws but the main window draws nothing (unless I hover it)". Both windows render through the same VVS -> Direct3D pipeline, so a working map exonerates the machine's DirectX stack -- the causes live in the windowing layer, and none of them were observable in-game before this release:
- The login banner and
/mag diagnow name the main window's renderer.ViewSystemSelector's auto-detect is a point-in-time snapshot at Startup (char-select): VVS must be loaded andService.Runningat that instant, or the window silently falls back to the legacy Decal-injected renderer. The automap overlay hard-references VVS and skips the check -- so a bad snapshot produces the machine-specific "map fine, main window broken" split. Worse, a legacy-renderer window is subject to Decal's "Disable View Rendering" option (common advice for VVS users): with that on, the fallen-back window draws NOTHING while the plugin runs normally. The banner reports the chosen backend plus the VVS state seen at startup vs now, so the fallback can never be silent again. - Automatic backend upgrade at login. If Startup picked the legacy renderer but VVS is running by first login, the main window is rebuilt on VVS (one shot, fully guarded; control caches cleared and wireup re-run).
- New
/mag reset. Restores both windows to a known-visible, clickable state: on-screen positions, un-pinned, click-through off, full alpha. VVS persists per-window presentation state outside the plugin -- the title-bar thumbtack pins ("hudifies") a window, stripping its border; pinned windows can be made click-through; un-pinning requires holding LEFT-CTRL while clicking the thumbtack (virindi.net wiki). A window pinned or faded months ago therefore looks dead through every update; the login banner now warns when that state is detected, and/mag resetclears it from chat -- the only recovery path that works on a click-through window. Reset restores window size too: VVS persists user-resized dimensions (vvs.s3dbUserW/UserH), so a window once shrunk to its title bar stays that way until reset./mag diagprints Magellan's exact vvs.s3db row keys for out-of-game repair (see README-RELEASE's troubleshooting section). - The map overlay no longer force-moves itself on first show. It only rescues a window that is actually unplaced/off-screen, so a user's saved position is respected -- and the overlay can't park itself on top of the main window every session.
Routing was rebuilt after a forensic audit against the original 2003 installers, an original feature came back, and a batch of polish landed:
- Route planning is correct now. It had been geometrically wrong since the feature first shipped:
the old
places_2.0.0.2.xmldestination fields are axis-transposed and drop the north/south hemisphere entirely (verified against both 2003 MSIs — 132 of 133 cross-checkable portals). Routing now builds from the signedEXITLOCATIONdata in the mainplaces.xml: correct destinations and a bigger graph — 169 deterministic portal edges, up from 149. Random portals are excluded (their in-game exit isn't predictable), andplaces_2.0.0.2.xmlis retired. - Restored: "Show overland relative co-ordinates." Recovered to its true 2003 behaviour — check
it, click any place in Search or Nearby, and the top readout becomes a live
Distance to <place>: 2.3N, 1.1Etracker that updates as you move and ticks toward zero on arrival. - The coordinate readout and About title render yellow as intended (the old colour value was in the wrong byte order and displayed cyan), and the About tab no longer truncates mid-sentence.
- Search and Nearby report their result count in chat ("7 places for 'holt'" / "No places match…"), so an empty search is never mistaken for a dead button, and the login banner shows the version — a quick check that you're on the new build.
Magellan3.sln
├── src/
│ ├── Magellan3.Core/ netstandard2.0 — PURE logic, zero dependencies, fully tested
│ │ ├── World/Coords.cs landcell <-> Dereth coordinates (verified to a half-cell)
│ │ ├── Data/PlacesDb.cs places.xml loader: search + radius query + errata
│ │ ├── Data/DungeonNames.cs 653 landblock -> dungeon-name lookups
│ │ ├── Mapping/OutlineBuilder landblock-scoped floor-outline extraction (the seam fix)
│ │ ├── Mapping/AutomapRenderer heading-up projection + Z-slice (the rotation fix)
│ │ └── Config/Settings.cs the 2003 config.xml format, round-tripped
│ └── Magellan3.Plugin/ net48, x86 — the Decal glue (Windows-only)
│ ├── PluginCore.cs PluginBase; events, /mag command, view control wiring
│ ├── Mapping/DatSource.cs FileService + offline DAT access (+ the phase check)
│ ├── Mapping/DungeonMapper the recovered algorithm, driving OutlineBuilder
│ ├── Ui/DxCanvas.cs IMapCanvas over VVS DxTexture
│ ├── Ui/MapOverlay.cs borderless heading-up HUD, bake-once/blit-per-frame
│ ├── VirindiViews/ MetaViewWrappers shim (MIT, from Mag-nus/DecalPluginTemplates)
│ └── Resources/mainView.xml the RECOVERED view, verbatim, embedded
├── tests/Magellan3.Tests/ net8.0 — 73 tests, no packages, runs anywhere
├── data/ places.xml · dungeon_names.tsv · mainView.xml
└── run-tests.sh offline test runner (no NuGet feed needed)
The dependency arrow points one way: Core knows nothing about Decal, VVS, or DatReaderWriter.
Everything that can be tested without a game is in Core, and it is.
./run-tests.sh # 73/73, no NuGet feed requiredOr, with a feed available:
dotnet test # once tests/Magellan3.Tests is restored normallyThe suite pins the things that were wrong or unknowable before, to ground truth that has nothing to
do with Magellan: the coordinate transform against the four <LOC> records and the Aphus Lassel
landblock; the COORD_X/COORD_Y axes against a 2002 third-party location list; the automap's
heading rotation against a "face east, a point due east must render ahead" check; and the
floor-outline seam-cancellation against a two-cell room that must read as one outline, not two boxes.
Prerequisites (install these first — Magellan does not bundle them):
- Asheron's Call, an End-of-Retail client (the automap reads its
client_cell_1.dat). - Decal 3 — the plugin framework.
- VirindiViewService (VVS) — the UI/drawing toolkit the map and window use.
Then install Magellan 3:
- Download the latest release archive from the Releases page and unzip it. It
contains everything you need:
Magellan3.dll— the pluginMagellan3.Core.dll— its logic libraryDatReaderWriter.dll— the DAT reader (for the automap)places.xml,dungeon_names.tsv— the places and dungeon-name data (routing builds fromplaces.xmltoo)
- Put all of those files together in one folder (e.g.
C:\Games\Magellan3\). They must sit side by side — the plugin loads the data files from beside the DLL, and won't work with just the DLL. - Register the plugin with the 32-bit RegAsm, run from that folder as Administrator:
(You must have
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase Magellan3.dllDecal.Adapter.dll,Decal.FileService.dll, andVirindiViewService.dllreachable — the simplest way is to copy those three next toMagellan3.dllbefore registering.) - Enable Magellan 3 in Decal's plugin list, then launch AC.
- The Magellan window opens from its icon in the VVS bar. Search a place, enter a dungeon to see
the automap, or run
/mag diagto check status.
Settings you change (Show map, footsteps, lock rotation, relative co-ordinates) are saved automatically to
%AppData%\Magellan3\config.xml and persist across logins.
Requires Visual Studio / dotnet on Windows, an installed Decal 3 and VVS, and an EoR client.
- Edit the three
HintPaths insrc/Magellan3.Plugin/Magellan3.Plugin.csprojto point at your installedDecal.Adapter.dll,Decal.FileService.dll, andVirindiViewService.dll. dotnet build src\Magellan3.Plugin\Magellan3.Plugin.csproj -c Release(or build the solution in VS; the plugin isRelease|x86).Chorizite.DatReaderWriterrestores from NuGet. The build copies the two data files (places.xml,dungeon_names.tsv) next to the DLL (routing builds fromplaces.xml).- Copy
Decal.Adapter.dll,Decal.FileService.dll, andVirindiViewService.dllnext to the builtMagellan3.dll, then register with the 32-bit RegAsm as Administrator, frombin\Release:C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase Magellan3.dll - Enable Magellan 3 in Decal's Manage Plugins UI, then launch AC.
- In-game, run
/mag diagfor status, or/mag phaseto verify the DAT read (see below).
The automap is on by default (MAGELLAN_AUTOMAP in <DefineConstants>); the logic layer is covered
by run-tests.sh (73 tests), which runs on any platform without Decal, VVS, or NuGet.
DatReaderWriter's Unpack reads a leading id DWORD for HasId records (EnvCell, Environment,
LandBlockInfo all qualify). Whether Decal's FileService.GetCellFile returns that header or strips
it decides a 4-byte parse phase. On first run, confirm and set:
byte[] b = CoreManager.Current.FileService.GetCellFile(knownCellId);
DecalDatSource.FileServiceIncludesIdHeader = DecalDatSource.HeaderPresent(b, (uint)knownCellId);If it comes back wrong, geometry silently decodes into plausible garbage — so prove it once. See the
note in Mapping/DatSource.cs.
| Feature | State |
|---|---|
| Places database + search (3,307 entries) | done, working in-game |
| Click a result → coordinates in chat | done, working in-game |
| Dungeon identification (653 names) | done, working in-game |
| Always-on coordinate readout (top of window) | done, working in-game |
| "Relative co-ordinates" distance tracker (Options tab) | done, working in-game — live distance-to-selected-place readout |
| Route finding (169-portal Dijkstra) | done, working in-game |
| Automatic dungeon mapping (the automap) | done, working in-game — reads client_cell_1.dat at runtime |
| Footstep trail (Z-sliced by floor) | done, working in-game |
| Settings persist across logins | done — saved to %AppData%\Magellan3\config.xml |
Every original Magellan 2 feature is present, plus a 653-name dungeon database (vs the original's
118), Z-sliced trails, the restored "relative co-ordinates" distance tracker, and an About tab. The
full logic layer is unit-tested (run-tests.sh, 73 tests). The one thing that differs from the
original by necessity: the on-screen coordinate readout lives at the top of the plugin window rather
than as a separate floating overlay (a second VVS window proved unstable on the current client).
- Adam Wright — Magellan 2 (2003): the original places database, window, and automap algorithm.
- Immortalbob — the 2026 resurrection: reverse-engineering the 2003 binary and rebuilding the whole plugin on the modern Decal 3 / End-of-Retail managed stack.
- Chorizite —
DatReaderWriter(MIT): the DAT parsing. - DungeonViewer authors —
dungeons.dvp(653 dungeon names) and the DM→ToD format deltas, used as documentation. - Virindi Plugins / Mag-nus — VirindiViewService and the MetaViewWrappers template.
Released under the MIT License.
DatReaderWriter (bundled at runtime) is also MIT-licensed by Chorizite. Decal and VirindiViewService
are separate installs with their own terms and are not distributed here.
