UPDATED STATUS: KOTOR 1 on Apple Silicon via CrossOver: Mesa GL-on-D3D12 / zink experiments (four walls mapped, one partial breakthrough)
TLDR: I tried replacing KOTOR's OpenGL path with Mesa (mesa-dist-win) inside a CrossOver bottle on an M3 Max MacBook Pro, to bypass Apple's deprecated OpenGL driver. Current Mesa fails on both backends. But downgrading to Mesa 23.1.9 got zink to create a real Vulkan device (Apple M3 Max via MoltenVK) and a GL context. The game then exits silently right after its first texture calls. This post maps exactly where each attempt dies, so the next person starts where I stopped. Looking for anyone who knows swkotor's renderer init well enough to guess what it checks after context creation.
Setup
M3 Max MacBook Pro, 36GB RAM, macOS (Darwin 25.5.0)
CrossOver, Windows 10 bottle, wine build wine-11.0-8726-g2e2f5fca349
KOTOR 1, GOG Windows version, 32-bit exe
Mods: K1CP, UniWS 1920x1200, ndix UR HR Menus, HQ Skyboxes II, High Quality Blasters
Game runs via Apple's deprecated OpenGL driver. Playable but with low FPS in 3D scenes, worst during camera movement (call-flood pattern: every GL call pays wine + Rosetta + Apple GL translation toll, and camera movement multiplies calls)
Hypothesis
Inspired by the ostriv-macos repo (maksymenkoml): drop Mesa's WGL DLLs next to the game exe inside the CrossOver bottle so KOTOR's OpenGL goes through modern Mesa instead of Apple GL. Two possible chains:
d3d12: Mesa WGL -> gallium d3d12 driver -> D3D12 -> (whatever serves D3D12 in the bottle) -> Metal
zink: Mesa WGL -> Vulkan -> MoltenVK -> Metal
Method
mesa-dist-win prebuilt binaries (pal1000's repo, release-msvc packages)
From the x86 folder (KOTOR is 32-bit): opengl32.dll, libgallium_wgl.dll, dxil.dll (and libglapi.dll on 23.x, which still ships it) copied next to swkotor.exe
Wine Configuration -> Libraries -> opengl32 -> Native then Builtin
Launch from Terminal with GALLIUM_DRIVER set explicitly, output captured via tee
Wall 1: d3d12 backend (current Mesa)
Black fullscreen window, then access violation (c0000005) at null. Key log lines:
vkd3d:err:d3d12_device_init Cannot load DXIL conversion library, DXBC-TPF shaders won't be supported
vkd3d:fixme:d3d12_device_CreateCommandQueue1 ... stub!
Mesa: error: GL User Error: glGetFloatv called without a rendering context
[cascade of GL calls without context]
wine: Unhandled page fault on read access to 00000000
Findings:
D3D12 in this bottle is served by Wine's vkd3d (D3D12-on-Vulkan-on-MoltenVK), not by D3DMetal, at least for this 32-bit exe, regardless of the bottle's Graphics setting.
vkd3d in CrossOver's build cannot load its DXIL conversion library, so it cannot consume the shaders Mesa's d3d12 backend emits. Device init fails, context creation returns null.
KOTOR never checks for a null context. It issues GL calls blind and crashes. The crash is a symptom; the wall is vkd3d's missing DXIL support, which is compiled into CrossOver itself and not fixable by dropping files.
A second wall (CreateCommandQueue1 stub) is already visible queued behind the first.
Verdict: dead at the CrossOver-internals level.
Wall 2: zink backend (current Mesa)
Identical crash signature. No vkd3d lines, and no Vulkan activity logged at all; zink bails during earliest setup, silently. (Note: CrossOver's retail wine ships with WINEDEBUG channels like +loaddll compiled out, so runtime tracing is not available for diagnosis.)
Filesystem check shows 32-bit Vulkan plumbing DOES exist in the bottle (vulkan-1.dll, winevulkan.dll, winevulkan.json in syswow64, and matching DLLs in CrossOver's i386-windows lib dir). So the failure is not a missing loader. See Wall 3 for the explanation.
Partial breakthrough: Mesa 23.1.9 zink
Downgraded to mesa-dist-win 23.1.9 (last of the legacy 23.1 line, October 2023). Same DLL swap. Result:
WARNING: Some incorrect rendering might occur because the selected Vulkan device (Apple M3 Max)
doesn't support base Zink requirements: feats.features.logicOp have_EXT_custom_border_color have_EXT_line_rasterization
Mesa: error: GL_INVALID_VALUE in glTexParameter(param)
This is the breakthrough and Wall 3 in one:
Old zink creates a REAL Vulkan device on the M3 Max through MoltenVK, and a GL context. This explains Wall 2: modern zink hard-requires features MoltenVK doesn't offer (logicOp, EXT_custom_border_color, EXT_line_rasterization) and refuses silently; old zink warns and proceeds.
The game gets a working context, issues its first texture setup calls, one glTexParameter value is rejected, and then swkotor exits silently. No crash, no window, no error dialog. The wine process just returns.
Wall 4: silent exit
Tried against it:
MESA_EXTENSION_MAX_YEAR=2003 (and 2006): no change. The famous extension-string-overflow bug is not the cause.
MESA_GL_VERSION_OVERRIDE=2.1COMPAT + MESA_GLSL_VERSION_OVERRIDE=120: no change.
Remaining suspects, unproven:
zink's compatibility-profile / WGL pixel format handling for pre-2004 games (fixable in Mesa if so)
one of the three missing MoltenVK features being fatal to KOTOR specifically (logicOp is used by old fixed-function games)
swkotor's own init logic rejecting something it queries right after context creation (would need exe-side reverse engineering; this is my question to anyone who knows the binary)
Control run
GALLIUM_DRIVER=llvmpipe (software rendering): the game RUNS. Unusably slow (CPU rendering under Rosetta), but it proves Mesa's WGL layer is fully compatible with KOTOR under CrossOver. Everything above is specifically about GPU device paths.
Summary map
+---------------------+---------------------------------------------+------------------------------------------------------+
| Path | Result | Wall |
+---------------------+---------------------------------------------+------------------------------------------------------+
| Mesa current, d3d12 | crash | vkd3d missing DXIL converter (CrossOver internals) |
| Mesa current, zink | crash | zink hard-requires features MoltenVK lacks |
| Mesa 23.1.9, zink | device + context created, then silent exit | unknown, after first glTexParameter calls |
| Mesa any, llvmpipe | runs (slow) | none; proves WGL layer works |
+---------------------+---------------------------------------------+------------------------------------------------------+
What would change the game
MoltenVK gaining logicOp / custom border color / line rasterization (or zink emulating them on Mac)
CrossOver's vkd3d shipping DXIL conversion
Someone identifying what swkotor checks after context creation (the actionable question right now)
Any of the open engine reimplementation projects reaching playable state on Mac
Rollback
Delete the copied DLLs next to swkotor.exe, remove the opengl32 override in Wine Configuration. Two minutes, fully reversible. (Tip learned the hard way: never edit swkotor.ini while the game runs; it rewrites the file on exit and will revert or mangle your edits. Also, on multi-user Macs with bottles in /Users/Shared, check that no other user session holds a wineserver lock on the bottle; it produces "cannot find the server port" errors.)
Offer
I have full logs of every run and a configured Apple Silicon test bench. Happy to run builds, patches, or instrumented Mesa versions and return results within a day (if available). Find me here or on the OpenKotor Discord.