Skip to content

Add Windows Mono scanner: readMtgaCardsMono + readMtgaInventoryMono#5

Open
dan-blanchard wants to merge 3 commits intomtgatool:mainfrom
dan-blanchard:feat/windows-mono-scanner
Open

Add Windows Mono scanner: readMtgaCardsMono + readMtgaInventoryMono#5
dan-blanchard wants to merge 3 commits intomtgatool:mainfrom
dan-blanchard:feat/windows-mono-scanner

Conversation

@dan-blanchard
Copy link
Copy Markdown

@dan-blanchard dan-blanchard commented Apr 13, 2026

Ports the card collection and inventory readers to work against Arena's Mono runtime on Windows. Verified against a live Windows Arena install in a Parallels VM, with output matching the macOS IL2CPP results exactly (same account, cloud-synced).

Depends on #3 and #6 for the macOS scanner infrastructure and napi dispatch pattern.

What works

Function Result Time
`readMtgaCardsMono("MTGA.exe")` 4300 cards ~4s
`readMtgaInventoryMono("MTGA.exe", 0, 0)` Correct wildcards, gold, gems, vault ~5s

Key differences from the IL2CPP scanners

Card collection: Uses direct Entry[] pattern scan at stride 16 (scanning for consecutive `hash==key` entries) instead of finding the Dictionary wrapper object. More robust when Dictionary field offsets are uncertain.

Inventory: Gold+gems-anchored search with a vault f64 roundness filter. Real vault percentages from C# have IEEE 754 representation error ~1e-13 when multiplied by 10. Random bytes that happen to decode as floats in [5, 100] have errors orders of magnitude larger.

Mono object headers: Standalone heap objects (Dictionary, Array) have the same 16-byte header as IL2CPP. But embedded value-type structs (like `ClientPlayerInventory` inside the wrapper) have NO header, so their fields start 8 bytes earlier.

Platform support

  • `VirtualQueryEx`-based heap region enumeration for Windows
  • Bulk `ReadProcessMemory` via cached process handle
  • Wider pointer bounds for Windows x64 address space
  • New winapi features: `memoryapi`, `errhandlingapi`

Testing

  • 8 tests for scanner error handling and return shape validation (`npm test` passes)
  • `readMtgaCardsMono("MTGA.exe")` returns 4300 cards matching macOS output
  • `readMtgaInventoryMono("MTGA.exe", 0, 0)` returns wcCommon=26, gold=1825, gems=610, vault=58.9 (verified against Arena UI)
  • Cross-check: Mono inventory values match IL2CPP inventory values for the same account

🤖 Generated with Claude Code

dan-blanchard and others added 3 commits April 12, 2026 23:22
Bypasses the broken PAPA walker by scanning Arena's heap directly for
the card-collection Dictionary<int,int>. Identifies it via the hash==key
invariant for DefaultEqualityComparer<int>.

Returns ~4300 cards in <1s. Requires sudo for task_for_pid.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scans for ClientPlayerInventory using class-pointer-set pre-filter
plus value plausibility and activity-score ranking. Returns wildcards,
gold, gems, and vault progress.

Key discovery: vaultProgress is an 8-byte double (not int32), storing
the UI percentage directly (e.g. 58.9%). Ground-truth verified against
Arena's UI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ports collection and inventory readers to Mono runtime on Windows.
Verified against Windows Arena in Parallels VM: 4300 cards and
inventory values match macOS IL2CPP output exactly.

Card collection uses direct Entry[] pattern scan at stride 16.
Inventory uses gold+gems-anchored search with vault f64 roundness
filter (1e-10 tolerance). Includes VirtualQueryEx heap enumeration
and bulk ReadProcessMemory for performance.

8 tests included.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@dan-blanchard dan-blanchard force-pushed the feat/windows-mono-scanner branch from 964b93b to c5e19eb Compare April 13, 2026 03:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant