Repository navigation
Releases: MathiasKowoll/RaccoonBot
Release list
RaccoonBot 0.3.9
Download RaccoonBot-0.3.9.zip, unzip it, right-click the application and choose Open (it is signed ad hoc, not notarised).
This replaces 0.3.8. It carries MacGameVideoFix 5.3.1, which includes 5.3.0. The controller set and the codec payload are unchanged.
Marvel's Spider-Man 2: no T-pose, the symbiote renders correctly
This is macprotips' fix, plus one improvement of ours. On M1-M4 Macs, D3DMetal returns 0 for typed buffer reads past element 2^28 and drops typed writes past it. Characters stay in a T-pose, and the symbiote shows up as spikes, a flat black sheet, or not at all. macprotips found the cause and fixed it. Their fix rebuilds four shaders raw, on your Mac, from your own copy of the game.
What MGVF adds:
- No DLL override. It works with nothing set in the bottle.
- A barrier after the volumetric fog copy. It removes the brief black blocks in the sandstorm stage. One clean session, so it is evidence rather than proof.
The first install downloads macprotips' release once, sha256 pinned, to take Microsoft's shader tools from it.
God of War: no white specks on the characters
The game tests depth with EQUAL against a depth prepass. The translated shaders do not match the prepass to the last bit, so specks appear on Kratos in dim light. The fix creates that one depth test as GREATER_EQUAL. Measured on DXMT, under Rosetta and under FEX. Picking the game recommends DXMT, the only backend it was measured on.
The Witcher 3: DLSS is offered again
The game's 2026-10-08 update moved one register in the Wine check the fix answers, so the menu said DLSS was unsupported again. The fix now accepts any register. A title already patched shows "A newer version of this fix is available". Updating it replaces the old DLL.
Tests
1087 unit tests pass. The frame-cap tests no longer depend on the attached display. The build was made from a clean checkout of this tag.
Engine patches and sources: https://github.com/MathiasKowoll/MacGameVideoFix
RaccoonBot 0.3.8
Download RaccoonBot-0.3.8.zip, unzip it, right-click the application and choose Open (it is signed ad hoc, not notarised).
This replaces 0.3.7. It carries MacGameVideoFix 5.2.1. Only the CONTROL Resonant fix changes. The controller set and the codec payload are unchanged.
CONTROL Resonant: the window fix works again after the game's update
The game's 2026-10-01 update recompiled the shader that draws the lit rooms behind the windows. The fix recognised that shader by a hash of its bytes, so after the update it matched nothing, and the coloured windows came back. The fix now recognises the shader by its name, which survives a recompile. Measured on the updated game: it hid all four of the new pipelines, and no coloured window was seen.
A title already patched shows "A newer version of this fix is available". Updating it removes the old DLL and installs the new one.
Tests
1087 unit tests pass. The build was made from a clean checkout of this tag.
Engine patches and sources: https://github.com/MathiasKowoll/MacGameVideoFix
RaccoonBot 0.3.7
Download RaccoonBot-0.3.7.zip, unzip it, right-click the application and choose Open (it is signed ad hoc, not notarised).
This replaces 0.3.6. It carries MacGameVideoFix 5.2.0. The controller set and the codec payload are unchanged.
The Witcher 3: Wild Hunt starts, and offers DLSS
Patch 5.00b stopped on a black screen under D3DMetal. The bundled fix (install-w3-fix.sh) does three things:
- The black screen. It refuses the one pipeline that crashed D3DMetal's shader converter.
- DLSS. The game switches NVIDIA Streamline off when it finds Wine, which is why the menu said DLSS was not supported. The fix tells only that one check that there is no Wine. DLSS then runs through MetalFX and looks right. Frame generation does not work.
bin/x64. It linksbin/x64tox64_dx12, because the launch can still ask for the old DX11 path.
Measured on an M4 Max with D3DMetal 4 and Metal 4 on: 60 fps and smooth, with DLSS and ray tracing on. Run the fix again after a game update or a file verification.
A frame-rate cap holds the rate it says
D3DMetal 4 holds a cap by showing each frame no sooner than 1/cap after the last one, and a ProMotion display only shows frames on 1/240 s slots. A cap of 60 therefore held 48: anything from 48 to 60 did. A cap of 70 held exactly 60.
- The slider offers only rates the display can hold. On a 120 Hz MacBook that is 80, 60, 48, 40… The top stop, "No limit", is the same as the switch off.
- D3DMetal is handed the value that holds the chosen rate. 60 is written as 69.
- A value saved with the old slider snaps to the nearest held rate. One at or above the display's maximum reads as no limit.
This was checked by the user on the built-in display. A 240 Hz and a fixed 144 Hz display are covered by tests only; on 144 Hz there is no 60, and 60 holds 48.
Tests
1087 unit tests pass. The build was made from a clean checkout of this tag.
Engine patches and sources: https://github.com/MathiasKowoll/MacGameVideoFix
RaccoonBot 0.3.6
Download RaccoonBot-0.3.6.zip, unzip it, right-click the application and choose Open (it is signed ad hoc, not notarised).
This replaces 0.3.5. It carries MacGameVideoFix 5.1.0. All ten controller binaries are rebuilt, from mgvf-0002 to mgvf-0035. The codec payload is byte-identical.
CONTROL Resonant: the window fix
On D3DMetal the lit rooms behind the city's windows showed as flat violet, cyan and yellow, and the colours spread from window to window. The bundled fix (install-ctl-fix.sh) keeps the one shader that draws them from drawing, so the windows show as dark glass and the rest of the frame is unchanged. Play it with Metal 4 off; with it on, faces and hair render as black boxes. Keep ray tracing and path tracing off in the game.
Ray tracing (DXR) per title
A new row under a D3DMetal title's options. Off writes D3DM_SUPPORT_DXR=0, so the game sees no ray-tracing support; checked in a trace, where the reported tier was 0. On writes nothing, and that is the toolkit's default. The setting was stored before but never reached the launch.
Unreal's Visual C++ dialog
Unreal 5.6 games (Silent Hill: Townfall, for one) asked for the Visual C++ runtime on every launch, because the engine's builtin runtime reported a version five builds short. An engine copy made by this version applies MGVF's install-engine-vcruntime.sh, which rewrites only those version numbers. The engine copy's progress bar no longer runs past its end.
The DualSense is shared with macOS by default
The engine opens a DualSense shared with macOS unless the pad's SeizeDevice setting asks for the seize (mgvf-0034). macOS repaints a shared pad's lightbar, so the lights you chose are sent again every two seconds (mgvf-0035). Tested in Mortal Shell 2: the pad was opened shared, 174 resends with none failing, and the chosen colour held throughout. The macOS idle-disconnect line in the console no longer appears for an engine that shares the pad.
Quitting with a bottle still up
Quitting RaccoonBot while Steam or the Epic launcher is open now closes them first, in order (game, save sync, launcher, bottle), and the window says so while it waits. Before, macOS's quit reached every wine process at once and left Steam frozen with its window up. Confirmed live with Steam open: everything closed and nothing was left behind.
Engine.ini only for Unreal games
A Steam title whose cloud saves are laid out like Unreal's (<name>/Saved/SaveGames) got an Engine.ini written on every launch, even when it is not Unreal (Granblue Fantasy: Relink). Now only a folder with Unreal's Binaries/Win64 gets one.
Tests
1071 unit tests pass. The build was made from a clean checkout of this tag.
Engine patches and sources: https://github.com/MathiasKowoll/MacGameVideoFix
RaccoonBot 0.3.5
Download RaccoonBot-0.3.5.zip, unzip it, right-click the application and choose Open (it is signed ad hoc, not notarised).
This replaces 0.3.4. Two of the ten controller binaries change, winebus.sys and winebus.so. The codec payload is byte-identical.
A DualSense nobody is using turns itself off
A new setting under Options, Turn off an idle DualSense after: Off, 10, 20, 30 or 60 minutes (20 unless you change it). A pad with no stick, trigger or button input for that long is asked to turn itself off; the PS button turns it back on. Moving only the gyro or the touchpad does not count.
- While RaccoonBot is open and no game is running, RaccoonBot does it. It opens the pad shared, never takes it, and lets it go the moment you press Play.
- During a game the engine does it (
mgvf-0033), for a pad the bottle holds. - Measured: the request turned off a DualSense Edge and a plain DualSense within about 63 ms with no wine running. RaccoonBot's own watcher was seen doing it once, at the 10-minute setting, without an Input Monitoring prompt.
- Not measured yet: the engine doing it inside a game.
This addresses 0.3.4's known issue, a pad left on after walking away from a running game.
The Play-time notice is gone
Play no longer stops to warn about macOS cutting the pad. The same check is kept as a line in the console.
Stop ends everything, in order
Stop, on a card, the list or the title's page, now:
- asks the game to close, and ends it after 5 seconds if it has not (a game that hangs no longer keeps Steam and the bottle up);
- waits for Steam's (or the Epic launcher's) save sync of that game;
- asks Steam or the Epic launcher to leave, only if it is running;
- closes the bottle.
A launch starts from a clean bottle
- If Steam or the Epic launcher was left open with no game running, a launch closes that session first and starts fresh. Steam therefore starts again on every launch; a download in progress there is interrupted.
- If a game is running in the bottle, nothing is closed.
- If a short wine command (a fix's status check, for instance) has just left the bottle up, the launch waits up to 20 seconds for it to go. The title's controller settings are then written, and a HID trace captures the driver's own lines.
Steam closes after a short session even when it started the game late
When Steam took more than 90 seconds to start a title (a dialog waiting on screen, for example), RaccoonBot lost track of the game and waited two minutes after it exited before closing Steam. It now keeps watching for a game Steam starts late, so that Steam can be closed right after the game's save sync, as it is when Steam starts the game promptly.
Leftover wine processes are cleared when RaccoonBot quits
Wine's services and controller driver can outlive their server. One was seen reading the pad for about ten minutes after its session ended. They are now cleared when RaccoonBot quits, not only when it next starts. A running game or bottle is never touched.
Fix status checks no longer start wine
The NINJA GAIDEN 3, NieR and Kingdom Hearts fixes read the bottle's registry file to report their status while the bottle is not running. The NINJA GAIDEN 3 card no longer brings the Steam bottle up for a few seconds every time RaccoonBot opens.
RaccoonBot's own look
A grey background instead of Procyon's indigo, the raccoon's mint on the tags, green buttons, and a grey icon.
Not exercised live yet
Stop on a game that hangs, closing a session left open, a late Steam start, and the sweep when RaccoonBot quits. They are covered by unit tests (1049 passing) and were reviewed, but none of them has had a live session yet.
Engine patches and sources: https://github.com/MathiasKowoll/MacGameVideoFix
RaccoonBot 0.3.4
Download RaccoonBot-0.3.4.zip, unzip it, right-click the application and choose Open (it is signed ad hoc, not notarised).
This replaces 0.3.3. Two of the ten controller binaries change, winebus.sys and winebus.so. The other eight, and the codec payload, are byte-identical.
Choose what the DualSense's lights show, per title
Two new rows under Controller: Lightbar (a colour, or off) and Player lights (player 1 to 4, or off). They reach the engine as mgvf-0031.
The engine does not add a light writer. It puts your choice into the light changes the game or Steam Input already sends to the pad. On Bluetooth it also sends one lightbar release before the first colour, because a Bluetooth DualSense ignores a new colour until it gets one. As the game asks changes nothing, so a game that drives the pad itself keeps its own lights.
- Measured: a red bar and player 1 held in two titles under Steam Input, and a Sony-library title left at As the game asks kept the lights the game sets.
- Not yet: a title that never sends a light change gets nothing from this.
Wine's own SDL no longer holds on to the pad
Wine's SDL bus opened a DualSense that the raw route already owned, kept the handle, and wrote a keep-alive into it twice a second. The seize refused every one of those writes. mgvf-0032 tells SDL to leave such a pad alone, and its failed-write counter now stays at zero.
Why a DualSense on Bluetooth drops, and a notice for the one you can avoid
Holding PS for about five seconds disconnects the pad. That is the pad itself, and it happens under macOS alone too. To open Steam's menu, tap PS instead.
macOS disconnects the pad about fifteen minutes into play if it was connected before the game started. macOS's own controller plugin cuts a Bluetooth pad that has sent it no input for 900 s. While the game holds the pad, that plugin sees none of your play. Turning the pad off and on once the game's window is up avoids it: macOS then leaves that connection alone. Pressing Play with a pad in that state now shows a notice saying so. It can be switched off, and brought back from Tools.
Known issue
A pad reconnected while a game is running is not disconnected by anything. If you walk away from a running game, it can stay on until its battery is flat. This is being worked on.
The options sheet, reorganised
- Generic options keeps only what you type.
- Advanced graphics options holds everything else, in two columns: the backend with what only it reads, Vulkan, the Metal HUD, and what Rosetta and wine are told.
- Three things were wrong and are fixed:
- DXMT's rows showed internal key names instead of labels.
- The HUD's settings only appeared for D3DMetal 4.
- A controller could land on D3DMetal settings that were not on screen.
- The controller section is in two columns as well.
Library cards
Every card has the name and its tags on one line and one row of actions under it.
- Installed: Play or Stop, options, folder, Uninstall and the title's page. Changing a setting no longer means opening the page first.
- Not installed: Install, the title's page, and Hide.
Also, Play on a title that needs its video fix used to do nothing unless the title had been added by hand. It now says why.
Engine patches and sources: https://github.com/MathiasKowoll/MacGameVideoFix
RaccoonBot 0.3.3
Download RaccoonBot-0.3.3.zip, unzip it, right-click the application and choose Open (it is signed ad hoc, not notarised).
This replaces 0.3.2. The engine payload is byte-identical — all seventeen binaries, including the whole controller set. What changed is three installer scripts, the fixes catalogue, and the application.
One title was being told to change its display for nothing
The installer for RESONANCE: A PLAGUE TALE LEGACY said the game needs a 16:9 display and told you to go and set one, in its own notes and in the catalogue entry the application reads. That was retracted on 2026-09-03 and the retraction never reached either.
The cause is HDR10, which the title turns on by itself on a display it reads as HDR, and then draws into a window that stays black. Set HDR10 0 in its ENGINESETTINGS file and it starts at the desktop resolution — no 16:9, no 1920x1080, no virtual desktop.
The reasoning that led to the wrong answer is kept rather than deleted, because somebody will arrive at it again: 1920x1080 really does cure the black screen. It cures it by changing which display mode is picked, which takes HDR with it.
The catalogue finally lists the controller set
engineOptional — the entry that tells a launcher the controller set exists and which files it installs — has been absent from every catalogue this project ever generated, while the application shipped all ten of its files. A Perl precedence bug: grep BLOCK LIST swallowed the condition that followed it, so the guard in front of the entry was always false. Nothing failed and nothing warned; the catalogue simply never mentioned it.
The catalogue says which Mac it was verified on
A configuration that makes a game playable is a claim, and a claim without the machine behind it is what makes a catalogue of them worthless. The manifest now carries the machine every entry was verified on, and every per-game configuration you save records the Mac it was written on.
It is on the catalogue rather than on each entry because every entry was measured on the same Mac — one fact, not nineteen. And it is bookkeeping rather than guidance: that machine is the top of the range, so "verified here" puts no floor under anything. It answers the first question anybody asks when a fix works for one person and not another.
Also
The controller installer reported "restored 10 of 4" after a complete, successful restore. It counts now.
And the claim that a DualSense on Bluetooth never rumbles was too strong wherever it appeared — some titles did and others did not, and the adaptive triggers were the same lottery. That unpredictability is the clue rather than a footnote: every client asks the pad's parent device whether it is Bluetooth, under Wine the answer was always no, so clients built the wrong report and the pad ignores the wrong one in silence.
And the library opens on what is installed
It used to reopen on whichever list you last had open, so closing it while browsing what you own handed you that list again the next time you came to play. It starts on what is installed now, every time. How you like to view and sort the library is still remembered, because those are preferences; which list you were on is not.
Unchanged from 0.3.2
Everything the controller work added: rumble over Bluetooth in games that only speak XInput at no cost in frames, the Modern and Legacy vibration paths per title, the strength bar, the per-game HID trace.
Engine patches and sources: https://github.com/MathiasKowoll/MacGameVideoFix
RaccoonBot 0.2.1
Six commits on 0.2.0, and every one of them is about the same thing: a report
that did not match the disk.
A patch run blamed a game that was not running
Applying a fix refuses while a Windows game is open, which is right — the
installers rename a DLL the game may have mapped. The refusal decided that by
asking whether any command line contained .exe, and reported the answer as
"A Windows game is running". That is a claim about a program's purpose made
from evidence that only ever showed a suffix.
Wine's own services carry that suffix — services.exe, winedevice.exe,
plugplay.exe — and a patch run creates them itself: three of the installers
write their per-application overrides by running reg.exe through wine, and
the wineserver that starts lingers afterwards. So a sweep patched titles until
it reached one of those three, then reported every title after it as blocked
by a game that did not exist. Nine refusals, six of which that same run had
just patched.
The refusal now names what it found. Wine's furniture reads as an open bottle,
a game or a launcher is named rather than classified, and a pgrep that could
not be run reports as not knowing rather than as finding a game. It still
refuses in every one of those cases: refusing was never the defect.
A sweep now waits for the bottle to settle and offers the title again, because
what it is waiting for is usually its own doing. If it is still busy after
that it stops and says where it reached, rather than listing the rest of the
library as failures. And refusals are logged — nothing logged them before,
which is why that run had to be reconstructed from the installers' source
rather than read.
The engine that patched a bottle was the wrong one
This is the one worth reading even if nothing else here matters to you.
Writing a DLL override means running reg.exe inside the bottle, and the
installers chose which CrossOver to run it with by searching a list of names.
Those names had gone stale: one was a bundle that project stopped making, and
the other was a glob that never matched our engine's name, because sh
compares globs case-sensitively even where the filesystem does not. So they
fell through to stock /Applications/CrossOver.app and ran reg.exe against
a bottle a patched engine had built.
Wine does what it always does when a bottle meets an unfamiliar engine: it
updates it. On 2026-08-31 at 08:19 that rewrote 1,475 files under
drive_c/windows of this application's Steam bottle, put back three of the
four DLLs the NINJA GAIDEN 3 fix had installed, and left the registry override
naming all four. Nothing failed. The install had reported success.
The danger there is not the DLLs, it is the update. A fix that writes into the
bottle can be reverted by any bottle update — so patching KINGDOM HEARTS could
revert NINJA GAIDEN 3 in the same bottle. The title that loses its fix is
not the title being patched.
MacGameVideoFix 5.0.4 fixed the cause by asking the bottle which engine owns
it, and 5.0.5 lets the caller say outright. Both are in this build, and this
application now names the engine it built rather than letting a script infer.
Measured with the copy that ships here:
our bottle -> Crossover_MGVF.app (was stock)
CrossOver's own -> /Applications/CrossOver.app
the old name search, for both -> stock
A fix in an updated bottle is no longer vouched for
The cause is fixed; the class is not. Any bottle update can revert a fix that
writes into the bottle, and until now this application would have kept saying
the fix was there — because the only evidence such a fix leaves is the record
we keep, and a fix beside the game is checked on disk while a fix inside a
bottle was not.
Wine stamps .update-timestamp in a bottle every time it updates one. That
stamp is now recorded beside the applied fix, and one that has moved makes the
row say the record is stale — never that the fix is gone. Those are different
claims and only the installer can make the second, which is why it is asked
before installing rather than while drawing a list.
Where nothing was recorded, nothing is claimed. A title patched by an earlier
build reads as unchanged rather than as an alarm.
The codecs are verified in the copy that installs
0.2.0 carried the twelve decoder libraries twice: a folder of our own with a
SHA-256 table and verification, and the copy inside MacGameVideoFix. Only the
second ever reached an engine, so the payload being verified was the one
nobody used and the one that ran was unverified. The duplicate is gone — 21 MB
of it — and the verification now reads the copy that ships, before the engine
build starts rather than after a gigabyte has been copied and signed.
The 0.2.0 notes said this was already true. It was true of the code and false
of the product, and that sentence was corrected within the hour of publishing.
The panel was reading its own source out loud
The fix row showed this, literally:
^[4 installed title](inflect: true) needs its video fix
^[...](inflect: true) is automatic grammar agreement, resolved by the
localisation system. This application ships no localisation resources at all —
no .lproj, no .xcstrings, no .stringsdict — so there was nothing to
resolve against and the markup went through untouched. It had never worked, at
any of the four places that used it; one of them assigned to a plain string,
where it never could have.
The plurals are written out now, verbs included, which agreement would have had
to handle anyway: "1 installed title needs its video fix" against "4 installed
titles need their video fix".
It also offered to install something nothing reads
The same panel offered "Install GStreamer…" whenever the framework was missing:
roughly 200 MB, and an admin password, for a thing no path this application
takes has read since 0.2.0.
That was traced rather than assumed. RaccoonBot runs make-engine-copy.sh and
the per-title installers named in the manifest, and none of them reads
/Library/Frameworks/GStreamer.framework. The button is gone, and so is
everything that existed only to serve it.
The line beside it used to say which GStreamer was installed and which version
would be imported at the next patch. Neither is true any more, and naming a
version there invited somebody to go and change a thing that changes nothing.
It now answers what the panel is for: whether this engine has the decoders, and
what it costs if it does not.
Smaller
A title patched with an older fix was already described that way rather
than as unpatched. The summary now counts all three states instead of deriving
the second from the first, which was right only while there were two.
MacGameVideoFix 5.0.5 replaces 5.0.2. Its --status used to count
displaced originals, so a bottle with no d3d9.dll of its own reported the fix
as absent while all four files were installed. This application renders that
answer, so it arrived as our error.
Installing
Ad-hoc signed. macOS will quarantine it after download and call it damaged,
which is a statement about the signature and not about the file:
xattr -dr com.apple.quarantine /Applications/RaccoonBot.app
Apple Silicon only. GStreamer is still not required — the decoders travel
inside.
RaccoonBot 0.2.0
Fourth pre-release, and the first where a working install is one download.
Sixty-five commits since 0.1.2. Two of them change what the application is,
and the rest are mostly the consequence of watching real games fail.
GStreamer is no longer something you have to install
The last release ended by saying that GStreamer 1.24.13 was required, and
that the exact version was part of the requirement rather than a series. That
is no longer true.
The twelve libraries the video path needs — three GStreamer plugins and the
nine FFmpeg and support libraries they load — now travel inside the
application. They are copied into the patched engine while it is being built:
the plugins where GStreamer scans for them, the support libraries where each
plugin's @rpath will find them. Nothing to install, nothing to match a
version against, and no way to end up with a decoder built against a different
series than the plugin loading it.
They live in the engine rather than staged beside each bottle, which means one
copy instead of one per bottle, no GST_PLUGIN_PATH to write, and no second
GStreamer core on the search path — that last one being the crash the old
staging arrangement existed to avoid.
MacGameVideoFix travels inside too, and now owns the engine
There is no fixes archive to download and no second application to keep in
step. MacGameVideoFix 5.0.2 is inside this build.
It has also taken over the work of making the patched CrossOver copy. That
copy is now called Crossover_MGVF.app, and it is MacGameVideoFix that
creates it, patches it and records what it placed. RaccoonBot passes it the
settings from the configuration panel and shows the progress; it no longer
carries a patcher of its own.
The reason is narrow and practical: both applications are worked on together,
and there was one engine-patching path in each of them. Now there is one, so
there is one thing to validate rather than two agreeing by luck.
A game could refuse to start, and nothing anywhere said why
Kingdom Hearts installed correctly, launched, and then sat there. No error, no
crash, nothing in any log — Steam's main loop simply waited "without event
signalled" forever. About twenty plausible causes were measured and every one
of them was wrong.
The cause was macOS privacy, not the engine. A Windows game launched through
this application asks the system for the microphone under this application's
identity. RaccoonBot never declared why it might want a microphone, so macOS
could not even show the request — and the client waiting for an answer waited
for one that could never come.
The application now says why a game might want the microphone and the camera.
Both are declared, and — this was the second half of the defect — the hardened
runtime is on, so the matching entitlements had to be carried as well or the
fix would have worked in development and died in the first signed release.
This is that release, and they are verified present in it.
The settings you saved were not always the settings used
Games were launching with settings nobody had chosen. Five separate faults
chained into that:
A title that had never had its panel opened had no saved configuration, so the
launch read defaults from wherever it could find them. Three of the Metal HUD
fields were dropped every time a configuration was written. One graphics
backend could be produced by the code but never chosen in the interface. The
legacy backend was read as a different toolkit in different places. And a
second launch path existed that did not consult the saved options at all.
The saved configuration is now the single source for building a launch
environment, always. A title that has none gets one written the moment it is
found or its panel is opened — Metal HUD on showing frame rate, and the newest
graphics toolkit the build carries — and from then on that file is respected
and nothing else is consulted.
Closing a game no longer risks your save data
Shutting down used to kill Steam while it was still uploading saves. It now
asks Steam to go, waits for the upload to finish — recognised either by what
Steam writes or by its silence — and ends only the processes belonging to that
bottle.
A game that starts through a launcher is no longer mistaken for a game that
has finished when the launcher exits, a launcher that restarts itself is not
read as a shutdown, and a bottle is never torn down while a game is running in
it. When the game cannot be recognised, the answer is to wait and ask again
rather than to loosen what counts as a game.
Fixes install only into the bottles you configure
A fix used to be installed wherever a bottle could be found, including bottles
belonging to other applications. It now installs only into the bottles
RaccoonBot itself defines — however many that is, one today and two once Epic
is integrated. The refusal lives in the write path rather than in a check that
had to be remembered, and the installer is told which bottle to use instead of
being left to look for one.
You can also choose where bottles live. They are kept under their own root so
they are not mixed with anything else's.
Game Mode
The application declares itself a games application and declares
LSSupportsGameMode, which Apple has said will become required. macOS turns
Game Mode on for RaccoonBot itself.
It does not reach the Windows game inside the bottle — those processes are not
visible to the system as games, and that is macOS's design rather than
something left undone here.
Smaller, and still worth saying
The Metal HUD has three levels, can be told which rows to draw, and
defaults to frame rate alone. It follows Apple's documentation rather than a
wrapper's guess at it.
CrossOver 27 is refused for now, deliberately, until it settles. An engine
that will not say which version it is, is refused too.
The x87 engine is gone, along with the patcher that built it. So is the
"Use DX9" switch, which did the opposite of what its name said.
A title patched with an older fix is now described that way, instead of
being reported as needing a fix it already has.
Installing
This build is ad-hoc signed. macOS will quarantine it after download and say
it is damaged, which is a statement about the signature and not about the
file. Remove the quarantine attribute after moving it to Applications:
xattr -dr com.apple.quarantine /Applications/RaccoonBot.app
Apple Silicon only.
RaccoonBot 0.1.2
Third pre-release. Still a pre-release.
Almost everything here came out of one crash that would not explain itself,
and out of the tooling built to make it explain itself.
Games that start through a launcher were being killed
Nioh died on every launch. It was not the engine, the codecs or the graphics
backend — it was RaccoonBot destroying the bottle while the game was still
coming up.
A game is known by a list of executable names, and that list is every .exe
found anywhere under the game's directory -- the game, its launcher, and
whatever else ships beside them: crash handlers, redistributable installers,
uninstallers. Any one of those exiting was read as the game closing.
A launcher makes that happen every single time, because a launcher exits the
moment it has handed off to the game; that is its whole job. So Steam and
explorer.exe were terminated seconds before the game finished starting. The
log of a crashing run reads:
nioh_launcher.exe terminated -> closing steam...
terminating explorer.exe, steam.exe, steamwebhelper.exe
found game nioh.exe, loading...
force terminating steam.exe
attempting to put your game in the foreground
The game was starting perfectly — Direct3D up, feature level 11_0, its window
associated — and we tore the bottle down around it, then tried to bring to the
front something we had just destroyed.
The game is now the one executable Steam reports as started, and nothing is
torn down before that is known. Where there is no Steam to ask, at least the
other known names are checked for still being alive.
This affected any title that starts through a launcher, not only Nioh.
Shutting a game down never actually reached Steam
The selected bottle is held as a file:// URL, and CrossOver's --bottle
wants a bare name. Nobody translated between them, so every shutdown failed
with invalid 'file:///.../CXPBottles/Steam/' bottle name behind a Fatal Error
dialog. The polite request to Steam never arrived, and the code fell through to
killing processes instead — which is why the fault above was as violent as it
was.
Bottles are now read wherever they came from — a name, a path, or a URL — and
the engine is told which bottle root to resolve the name under, because there
are bottles of the same name under two roots and macOS does not tell them
apart by case.
Both of these are inherited from upstream unchanged.
Turning the log on no longer needs a terminal
Debug logging was decided once, at startup, from an environment variable. To
get a log you had to quit the application and relaunch it from a terminal —
too much to ask of somebody who has just hit a bug, and too much to ask of
anyone trying to help them.
There is now a switch in Tools, the Debug section is always visible rather than
appearing only when the variable was set beforehand, and the panel says what it
is doing in each state. The environment variable still wins where it is set,
because it is the only way to record from the first line, before any window
exists — and the switch says so instead of silently doing nothing.
Debug mode also used to freeze the application it was meant to explain; that is
fixed.
One backend, one family of variables
Choosing a graphics backend set the variables for all of them. D3DMetal's
variables were exported for a game drawing through DXMT, and DXMT's for a game
drawing through D3DMetal. Each family is now written only for the toolkit that
reads it, and D3DMetal is no longer installed into a bottle for a backend that
does not draw with it.
Still true
GStreamer 1.24.13 is still required, and the version is part of the
requirement rather than a series.