Feature Request: Add a built-in pre-configuration profile for legacy 32-bit strategy games (e.g., Medieval II: Total War massive mods)

Hello Lutris Development Team,

After extensive testing (over 40+ hours) on modern Linux distributions (specifically Zorin OS/Ubuntu layouts) with low-to-mid specs (8GB RAM, AMD/Intel integrated and discrete graphics), we discovered a highly stable configuration formula for legacy 32-bit strategy engines running massive community modifications (such as Divide & Conquer or Tsardoms for Medieval II: Total War).

Currently, these mods are completely unplayable on modern Windows 10/11 due to rigid OS memory management structures and broken DirectX 9 allocations, leading to constant “Out of Memory” runtime errors and graphic crashes. Linux via Lutris handles these games beautifully, but only if very specific, non-standard variables are manually applied.

We kindly request the integration of a toggle or a pre-configured profile inside Lutris tailored for “Legacy 32-bit / Heavy Modded Strategy Games” that automatically applies or suggests the following runtime parameters:

  1. Core Environmental Variables to Automate:
    • WINE_LARGE_ADDRESS_AWARE=1 — Absolutely critical. While the 4GB patch executable bit is modified manually, Wine frequently ignores the memory extension unless this exact flag forces a true 4GB virtual memory address space.
    • PULSE_LATENCY_MSEC=256 — Legacy engines suffer from massive audio buffer overflows on modern Linux audio servers during battles with thousands of units firing projectiles and triggering simultaneous sound effects. Forcing a safe buffer window between 128 and 256 completely stops the hard crashes caused by the audio subsystem. Our tests show that with this variable, whenever the AI triggers sudden heavy voice lines (like general deaths or army status updates), it only results in a minor, harmless audio stutter instead of an instant desktop crash.

• STAGING_SHARED_MEMORY=1 — Crucial for smooth texture and asset streaming between the Wine layer and Linux subsystem, removing micro-stutters during heavy computational frames (like AI “End Turn” processing cycles).
• LC_ALL=C — Prevents localized decimal/string formatting errors within older game engines that cause unintended string read crashes.

  1. Recommended Runner Defaults:
    • DXVK: Enabled (Stable v1.10.3 preferred for DX9 wrappers).
    • VKD3D: Disabled by default for DX9 profiles to save sub-allocator overhead.
    • Esync / Fsync: Disabled or optional. Surprisingly, our practical tests showed that modern synchronization protocols conflict with these specific unoptimized legacy engines, leading to engine lockups. Keeping them OFF yields 100% stability.

Implementing an easy-to-use profile template like this within Lutris would make Linux the ultimate, definitive refuge for retro PC strategy gaming communities who are currently being locked out of their favorite games by Windows updates.

Thank you for your incredible work on Lutris!

:video_game: Universal Stability Blueprint for Heavy Modded 32-bit Engines (Lutris / Linux)

Verified deployment layout for the Medieval II: Total War engine (tested extensively across Tsardoms 3.0, Divide & Conquer, GoT, and DCI: Last Alliance 2.0).

:hammer_and_wrench: 1. Environmental Variables Table (Lutris System Options)

Inject the following keys and values into your Lutris Environment Variables table to stabilize the Wine/DXVK runtime translation layer:

:brain: Core Memory Management & Throughput

  • WINE_LARGE_ADDRESS_AWARE=1 — Absolutely critical. Forces a true 4GB virtual memory address space. This prevents Wine from ignoring manual 4GB executable patches, neutralizing “Out of Memory” crashes during heavy computational cycles.
  • STAGING_SHARED_MEMORY=1 — Crucial for smooth texture and asset streaming between the Wine layer and the Linux subsystem. This completely removes micro-stutters during heavy inter-turn processing phases.
  • LC_ALL=C — Prevents localized decimal/string formatting parsing errors within older game engines that cause unintended crashes when reading configuration files.

:computer: Low-to-Mid Specs & Integrated GPU Safeguards (iGPU - e.g., AMD Ryzen / Intel Iris Xe with 8GB RAM)

If running on shared system RAM architectures, these explicit tokens block the aggressive allocation nature of Vulkan from oversaturating host memory and triggering VK_ERROR_MEMORY_MAP_FAILED allocation errors:

  • Key: DXVK_CONFIG | Value: dxvk.maxChunkSize = 64; dxvk.vramBudget = 2048
    • Why it works: It forces the translation layer to fragment high-fidelity graphical assets into safe 64MB processing blocks and hard-caps the VRAM budget at 2GB, preventing the Linux host from triggering Out-Of-Memory (OOM) routine panics.
  • Key: dxvk.enableGraphicsPipelineLibrary | Value: False
    • Why it works: Mandatory for older integrated chipsets under Linux; leaving this active causes a severe thread deadlock inside the Vulkan driver, trapping the game engine in an infinite loading hourglass freeze on boot.
  • Key: dxvk.gplCache | Value: False
    • Why it works: Completely disables the generation of complex pipeline caches that trigger internal resource leaks and compiler hangs during heavy mid-turn script evaluations on integrated hardware.

:lock: 2. Frame-Pacing & Thread Synchronization (The Esync Breakthrough)

  • Key: DXVK_FRAME_RATE | Value: 60 (or your native monitor refresh rate)
  • Key: d3d9.maxFrameLatency | Value: 1
    • Why it works: Forcing a strict frame latency limit of 1 blocks DXVK from buffering frames ahead. This keeps the GPU perfectly synced with heavy CPU script threads, preventing the notorious post-battle data-dump crash (Runtime Error R6025).
  • The Esync Sync Shift: For advanced, heavy script-driven LUA modification frameworks (like Tsardoms 3.0+), enabling Esync (PROTON_EARLY_SYNC) inside Lutris is mandatory for modern frame fluidity. Esync completely bypasses standard Wine thread synchronization bottlenecks by leveraging native Linux kernel eventfd descriptors, eliminating camera stuttering and stabilizing micro-frames during AI end-turn calculation loops. (Note: For older, basic mods lacking external engine patches, keeping Esync/Fsync OFF may yield better stability.)

:wrench: 3. The Garrison Manager Desync Fix (Siege Battles, Tsardoms 3.0+)

When running Tsardoms 3.0+ on low-to-mid specs or integrated AMD hardware, real-time siege battles that trigger the M2TWEOP Garrison Manager script (spawning/de-spawning defensive troops) can create a rendering deadlock during post-battle transitions, flooding the logs with Garrison for Draw.settlementName loops whenever custom unit types are completely wiped out.

  • The Fix: Applying the Frame-Pacing table above (DXVK_FRAME_RATE=60, d3d9.maxFrameLatency=1) resolves the rendering deadlock by keeping the GPU tightly synced with the Garrison Manager’s script threads, preventing the post-battle log flood and the associated freeze.

:loud_sound: 4. Comprehensive Audio Fail-Safe

  • PULSE_LATENCY_MSEC=256 — Expands the modern Linux audio server buffer window. This entirely eliminates hard desktop crashes when thousands of combat units fire projectiles and trigger parallel voice triggers simultaneously.
  • The ALSA Passthrough Safety Net: If your system layout still experiences dropouts or thread hangs under PulseAudio/PipeWire pipelines, add WINEAUDIODRIVER=alsa to your Lutris environment to establish a direct hardware audio driver bypass.

:gear: 5. Recommended Runner Defaults

  • DXVK: Enabled (Stable v1.10.3 is highly preferred as the definitive wrapper for legacy DX9 titles).
  • VKD3D: Disabled by default for DX9 profile trees to completely eliminate unnecessary sub-allocator memory overhead.
  • Runner Choice: Modern high-throughput runners such as Proton 10-34+ are excellent for heavy graphical throughput. However, script-heavy total overhauls requiring strict legacy stability run best on the Wine-GE 8-26 line (now merged into the GE-Proton naming — look for GE-Proton8-26 if wine-ge-8-26-x86_64 no longer shows as installable).

:open_file_folder: 6. In-Game Engine Configuration Overrides (.cfg adjustments)

Open your mod’s primary engine configuration file (e.g., tsardoms.cfg or TATW.cfg) and append or modify the following distinct blocks:

[sound]
max_channels = 32       ; Caps the simultaneous audio pool to stop server-side mixer overflow crashes
use_3d_sound = 0         ; Strips away obsolete 2006 software 3D positional calculations that overflow buffers
provider = Miles Fast 2D Positional Audio  ; Anchors the engine to its fastest, most compatible legacy decoder block
music_volume = 0.7
sfx_volume = 0.8
voice_volume = 0.9
sound_quality = 1

[game]
auto_management = 0              ; Explicitly instructs the retail framework that the player intends to govern manually
micromanage_all_settlements = 1  ; Overrides profile layers at boot, forcing manual settlement control on Turn 1

[ai]
bypass_ai_automanager = 1        ; Runtime shield blocking background AI from modifying player values during reloads

[video]
windowed = 0     ; Forces exclusive native fullscreen to prevent focus loss on shared memory rigs
borderless = 0   ; Prevents resolution desync loops often triggered on modern Wayland/X11 compositors

[log]
level = * error  ; Restricts log verbosity, cutting file size from 320MB+ down to a clean 3MB

(Note: Limiting the log footprint to errors completely removes heavy camera lag on the strategic map caused by continuous disk I/O log spamming.)

:computer: 7. Command-Line Fixes & Mod-Side Scripting Resolutions

:link: Resolving “Steam Not Found” and Missing Executable Launch Loops

Digital re-releases, GOG binaries, or standalone non-Steam installers often trigger broken launch wrappers under modern Proton layers. First, inject SteamAppId = 21690 and SteamGameId = 21690 into your Lutris Environment table to force Proton to bypass the verification layer.

Next, to satisfy mod launch scripts requiring a specific .exe name without duplicating physical files (which breaks applied 4GB memory patches), open a terminal inside your main game installation root directory and deploy a clean Linux symbolic link:

ln -sf medieval2.exe kingdoms.exe

This maps a 0KB virtual mirror that perfectly satisfies the mod launcher scripts while retaining 100% data integrity.

:bug: Fixing the Fatal Lua Faction-Heir Turn Freeze (luaPluginScript.lua)

When a faction leader dies unexpectedly on the exact turn a new heir is evaluated, the M2TWEOP Lua framework can throw a fatal ‘nil value’ error when executing eventData.faction.leader, permanently freezing the end-turn state. Open luaPluginScript.lua around line 235 and insert a safety barrier check:

if leader ~= nil then

This forces the scripting subsystem to safely bypass the thread execution if the leader object is missing, guaranteeing flawless turn transitions.

:boom: The M2TWEOP Save-Reload Crash (campaign_script.txt)

A minor syntax typo in the AI condition checks for the Hungary/Croatia event monitor (around line 36681) causes the M2TWEOP parser to choke and crash with an “Oh no…” fatal error whenever you attempt to reload a save game directly from inside an active match. The script uses a non-existent token instead of the correct one.

  • The Fix: Replace the broken variant manually with the clean, native commands: and I_FactionIsAIControlled croatia and and I_FactionIsAIControlled hungary. This allows the parser to read the faction states correctly during mid-match reloads.

:brick: Hardcoded Database Structure Gaps (export_descr_buildings.txt)

Logic gaps in unique landmark building trees create extreme I/O log spam and thread stalls when specific factions conquer target provinces.

  • The Issue: A Level 0 base structure blocks a specific culture pool (e.g., suceava_citadel requires not factions { middle_eastern, }), but its subsequent upgrade tier allows everyone (kruje_castle requires factions { all, }).
  • The Fix: Change the Level 0 restriction to requires factions { all, } and handle actual strategic building limitations exclusively through hidden resource flags.
  • Empty Brackets: Search for empty faction constraint parameters (e.g., requires factions { }). Empty hooks trigger endless engine validation loops. Overwrite empty brackets manually to { all, }.

:crown: The Three Golden Rules of Core Gameplay

  1. Enforce Clean Session Loads (VRAM Cache Purge): The heavy, cumulative background scripting generates unavoidable 32-bit memory leaks. NEVER reload a save file or use the “Load Game” feature directly from inside an active 3D match or a running campaign session. You must always Quit to Desktop and launch the game completely fresh to enforce a complete VRAM and script cache flush.
  2. The Geographic Matrix Rebuild: If you experience an improper system shutdown, power loss, or a hard engine lockup, the active campaign map files can get poisoned. Manually delete the map cache file inside your mod directory before launching to force a clean, uncorrupted rebuild:
    • Action: Delete .../mods/[Your-Mod-Folder]/data/world/maps/base/map.rwm.
  3. Strict Log Discipline: Ensure your configuration file’s log level is hard-locked to error blocks only (level = * error). Allowing the retail engine to track routine structural database warnings will result in massive log files that cause severe, artificial stuttering on modern hardware.

:gear: ADDENDUM: Hardware-Specific Optimization for AMD Ryzen iGPUs & Steam Client Bypass

If you are deploying this blueprint on an AMD Ryzen APU with Integrated Radeon Graphics (iGPU) sharing system RAM (e.g., Ryzen 3 4300G / Vega 8 setups) under Wayland environments, two critical anomalies must be resolved: Steam Client Hijacking and Vulkan Memory Map Deadlocks (VK_ERROR_MEMORY_MAP_FAILED).

1. Overcoming the Steam AppID Hijack Loop (The “Trojan Horse” Bypass)

When launching modified engines natively or via custom shortcuts, the Steam client frequently intercepts the execution, forcing a 10–12 second delay before overriding the parameters and executing the retail 32-bit vanilla branch. To completely sever this hardcoded redirection loop:

  1. Navigate to your installation directory: …/SteamLibrary/steamapps/common/Medieval II Total War/
  2. Rename the retail binary medieval2.exe to medieval2_original.exe.
  3. Create a copy of the modern 64-bit engine executable (M2EX.exe) and rename it exactly to medieval2.exe.
  4. Launch your mods cleanly directly from the standard green PLAY button in Steam by passing your parameters cleanly inside Steam’s native LAUNCH OPTIONS: --features.mod=mods/your_exact_mod_folder_name

2. Memory & Frame-Pacing Constraints for Shared RAM (iGPU Vega/Radeon)

Because integrated graphics dynamically allocate memory from the global system pools, unconstrained 64-bit translation can trigger sudden host memory starvation. Implement these precise system caps:

  • Linux Environment Cache Constraint: Open a terminal and bind your global Mesa shader cache to a safe 2GB ceiling to keep host background tasks breathing:

sudo nano /etc/environment# Append this line at the bottom:
MESA_SHADER_CACHE_MAX_SIZE=2G

  • Targeted DXVK VRAM Budgeting (Launch Options): Prefix your Steam LAUNCH OPTIONS syntax to manually fragment processing cycles and strictly enforce a virtual VRAM limit, preventing system-wide rendering deadlocks on shared 16GB system RAM configurations:

DXVK_CONFIG=“dxvk.maxChunkSize=64; dxvk.vramBudget=2048” %command% --features.mod=mods/your_exact_mod_folder_name


:loudspeaker: Feature Request to Lutris Developers: Native Environment Integration for 64-bit Engines

A Call to Action for the Lutris Development Team:
Based on my intensive benchmarking on modern Linux distributions (Zorin OS), Lutris vastly outperforms Steam when it comes to system optimization, custom runners, and micro-stutter reduction. If I were to rate the gaming performance and runtime optimization, Lutris easily scores a 9.5/10 (or a solid 10), while Steam lags behind at a 7/8. The frame pacing and resource allocation controls inside Lutris are vastly superior.
However, we are currently forced into this Steam “Trojan Horse” file-replacement workaround because the steam_api64.dll embedded in the modern M2EX engine aggressively triggers hardcoded Steam client hooks, trapping Lutris in a silent boot loop (Exit Code 13568).
The Request:
We kindly ask the Lutris developers to investigate a native bypass or a pre-configuration layout within the UMU/Wine runner subsystem. If Lutris can find a way to gracefully intercept or satisfy these modern 64-bit Steam API calls without crashing the prefix container, users will finally be able to ditch Steam entirely and run these massive total conversions natively inside Lutris—where the performance actually belongs.
Adding a native “64-bit Legacy Strategy Bypass” profile or toggle would permanently solve retro-compatibility for thousands of players on Linux!