Running Adobe Products and rectifying Discord’s voice chat crash on a Ryzentosh

P.S. If you ever modify an application bundle and it doesn’t behave, there’s a possibility it’s due to failing codesigning checks, fix that by using chmod +x /Applications/ApplicationBundle.app/Contents/MacOS/* && sudo codesign -fs - /Applications/ApplicationBundle.app
When it comes to getting Adobe products to work on non-Intel CPUs, back then you only had XLNC’s original patch and while it did do the job, there were some edge cases where the original patches weren’t enough. Taking what I can from the comments section and noting down what worked, I tried my hand at making a script and it did the job for me, though since then, a better patch has come along and I’d recommend using that instead.
Though I’ll still keep mine for reference for those who might need it (also because there’s a bit of sentimental value attached to it as it’s my first patch variant! Small victories and all that!)
Additional Resources⌗
- Adobe Crash Fix XLNC by @naveenkrdy - Github Gist (use this script to patch Adobe software, only use my variant if it doesn’t work)
u/neoney_'s
comment on “Discord keeps crashing every time i join a voice channel/call” on the r/Hackintosh subreddit (which served as the basis for my Discord patching script)u/nedflanders1976
's post “How-To force Matlab to use a fast codepath on AMD Ryzen/TR CPUs - up to 250% performance gains” on the r/matlab subreddit
How to get Discord to behave on macOS⌗
UPDATE: 3rd January 2022, the original blogpost did not include this method as I personally was weary with setting global environment variables but
it hadn’t dawned on me at the time that Discord updates itself… rather frequently, which overwrites the patch, rather frequently, which is annoying; and
as I’m a zsh
user, dropping into a bash
prompt and pasting my own script by visitng my own article to the point where I bookmarked my own post felt
ridiculous.
Also, entering voice chat only for the app to crash causing a misunderstanding, was very annoying. So here’s a new way.
# This is a fork of https://gist.github.com/naveenkrdy/26760ac5135deed6d0bb8902f6ceb6bd
#
# I actually use the above script as now I'm back to using Adobe products
# but my install resulted using the fakeintel library patch, which
# doesn't work for Discord.
#
# It's quite possible that what this does is already done by the above
# patch, this script should only be used if you
# a) Aren't using Adobe products; or
# b) Use Adobe products but the fakeintel patch was applied by the above script
agent_dir="${HOME}/Library/LaunchAgents"
env_file="${agent_dir}/environment_mkl.plist"
mkl_value=$(
sysctl -n machdep.cpu.brand_string | grep FX >/dev/null 2>&1
echo $(($? != 0 ? 5 : 4))
)
[[ ! -d $agent_dir ]] && mkdir $agent_dir
cat >$env_file <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>mkl-debugenv</string>
<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>-c</string>
<string>launchctl setenv MKL_DEBUG_CPU_TYPE $mkl_value;</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
EOF
# Courtesy of https://developer.apple.com/forums/thread/665661
launchctl unload ${AGENT} >/dev/null 2>&1
launchctl load -w ${AGENT} >/dev/null 2>&1
launchctl start ${AGENT} >/dev/null 2>&1
Ordinarily I’d delete the old method but I figure the explanation of how it works might be useful to someone, so I’ve kept it here.
#!/usr/bin/env bash
# DO NOT USE ME, I NOT A PERSISTENT PATCH AND EVERY DISCORD UPDATE
# WILL REVERT ME, DO NOT USE THIS PATCH!!!!
function _mkldebug_patch {
BUNDLE_ROOT=$1
BUNDLE_NAME=$(echo "$1" | sed 's@.*/@@' | sed 's/.app//g')
echo "MKL_DEBUG_CPU_TYPE=5 ./$BUNDLE_NAME" > "$BUNDLE_ROOT"/Contents/MacOS/dLauncher && chmod +x "$BUNDLE_ROOT"/Contents/MacOS/dLauncher
plutil -replace CFBundleExecutable -string "dLauncher" "$BUNDLE_ROOT"/Contents/Info.plist
}
export -f _mkldebug_patch
find /Applications -type d -iname "*Discord*.app" -depth 1 | xargs -I {} bash -c '_mkldebug_patch "$@"' _ {}
Let’s break this script down, shall we?
It’s a simple script.
It’s essentially an automation of u/neoney's
method (see “Additional Resources”) that extends to
all variants of Discord (including Canary, which I use because I love Powercord and Public Test Builds)
#!/usr/bin/env bash
The #!
(also known as a shebang or hash-bang) tells the program loader to use a particular interpreter to parse and execute our shell script.
A lot of scripts (including some of my older ones), tend to use the Bash interpreter located at /bin/
instead of /usr/local/bin
(where Homebrew installs packages on macOS) and while that
might do the job (as long as the version disparity between the two versions isn’t too large and you’re not attempting to use the latest Bash features),
I’d still prefer to invoke a version of bash
that’s preferred by the user.
For example, I update my version of bash
using Homebrew as macOS no longer ships with updated versions for legal reasons
and using the interpreter defined through /usr/bin/env
will execute my script using GNU bash, version 5.1.8(1)-release (x86_64-apple-darwin18.7.0)
(the latest version of Bash as of this writing), while using the interpreter in /bin/
will run with the version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
which was last updated in 2007.
function _mkldebug_patch {
BUNDLE_ROOT=$1
We are defining a function _mkldebug_patch
that will accept one argument. Unlike programming languages like C++, you don’t
explicitly specify the type of argument or its name, you only get a number, $0
referencing itself, $1
representing the
first argument and so on….
To keep things easier to track, I assign $1
's value to a variable named BUNDLE_ROOT
so it’s easier for me to keep track
of what that argument is used for.
BUNDLE_NAME=$(echo "$BUNDLE_ROOT" | sed 's@.*/@@' | sed 's/.app//g')
This variable takes the first argument (which is the location of the Discord application bundle, usually /Applications/Discord.app
and pipes it through a program called sed
, the first call everything before (and including) the last forward slash and the second
sed
call simply replaces all instances of .app
(which we can safely presume to be 1) with nothing, effectively removing it.
So, if BUNDLE_ROOT
is set to /Applications/Discord Canary.app
, then BUNDLE_NAME will be Discord Canary
.
echo "MKL_DEBUG_CPU_TYPE=5 ./$BUNDLE_NAME" > "$BUNDLE_ROOT"/Contents/MacOS/dLauncher && chmod +x "$BUNDLE_ROOT"/Contents/MacOS/dLauncher
The magic sauce to XLNC’s patches are the usage of an undocumented environment variable (specifically MKL_DEBUG_CPU_TYPE
)
that allows non-Intel CPUs to use optimised code paths that are otherwise artificially restricted to Intel CPUs (the fact that
we can run them on non-Intel systems show that there isn’t a technical reason as to why they can’t run on non-Intel x86_64 processors)
Normally, this should give you only a speed improvement, it shouldn’t be a prerequisite to an application functioning at all but in macOS-land, where Intel-only processors are the norm, there’s no reason for the binary to account for non-Intel processors.
So it tries to run under the presumption that it’s an Intel-based machine and it crashes, by using this flag it skips over the crash-inducing check and then we’re golden! We basically create a small script setting this magic variable before running the actual Discord binary and mark it as executable using chmod
plutil -replace CFBundleExecutable -string "dLauncher" "$BUNDLE_ROOT"/Contents/Info.plist
}
Let me let you in on a little secret, /Applications/Discord Canary.app
isn’t actually an application, it’s a folder… more
specifically called an Application Bundle, double-click-to-execute-folders-as-bundles are a thing macOS has inherited from
NeXTStep and the binary that’s actually executed is defined by an XML file
called Info.plist
located within Contents
By default, macOS will launch the binary located within the MacOS
directory within Contents
, so when you launch
open /Applications/Discord Canary.app
, macOS is guided to open the binary /Applications/Discord Canary.app/Contents/MacOS/Discord Canary
which is all good but we don’t want that behaviour here.
We want it to open our script, which will open Discord with the set variable, so by using a Property List manipulation
tool that comes with macOS, we change the value of CFBundleExecutable
, a key that dictates what should be launched from
the MacOS
directory when executing the bundle from Discord Canary
to dLauncher
(the script we just created)
export -f _mkldebug_patch
Since we are planning to use this function on every Discord application bundle found (which will be done using find
, we will
be spinning up new instances of the Bash interpreter, so we need to ensure that our function is globally accessible, hence the export
.
find /Applications -type d -iname "*Discord*.app" -depth 1 | xargs -I {} bash -c '_mkldebug_patch "$@"' _ {}
Let’s break this command down even further…
find /Applications
, search in the Applications directory at the root of the volume-type d
, only list directories-iname "*Discord*.app"
, that contain the word Discord before or after it, excluding the extension and…-depth 1
, to go only one level deep, we don’t need a thorough recursive search. This is to avoid false positives.
This command alone would print on my computer
bash-5.1$ find /Applications -type d -iname "*Discord*.app" -depth 1
/Applications/Discord Canary.app
/Applications/Discord.app
Okay, we found our Discord appbundles but now we must run the patch on it, since our patch cannot accept multiple variables (it only expects one), we have to run the function twice, once for each bundle found.
We pipe the output of find
using the |
operator and then run xargs -I {} bash -c '_mkldebug_patch "$@"' _ {}
which
runs a new Bash instance that’ll run the patch function, accepting the contents of each line as the first argument.
How to get Adobe products to behave on macOS⌗
Use the naveenkrdy patch but if that doesn’t work, here’s mine which is also a Github Gist!
#!/usr/bin/env bash
cpuname=$(sysctl -n machdep.cpu.brand_string)
# Patch Lightroom Classic first
sudo perl -i -pe 's|\x90\x90\x90\x90\x56\xE8\x3A\x00|\x90\x90\x90\x90\x56\xE8\x1A\x00|sg' /Applications/Adobe\ Lightroom\ Classic/Adobe\ Lightroom\ Classic.app/Contents/Frameworks/CameraRaw.lrtoolkit/CameraRaw
sudo perl -i -pe 's|\x90\x90\x90\x90\x56\xE8\x5A\x00|\x90\x90\x90\x90\x56\xE8\x3A\x00|sg' /Applications/Adobe\ Lightroom\ Classic/Adobe\ Lightroom\ Classic.app/Contents/Frameworks/CameraRaw.lrtoolkit/CameraRaw
# Patch MMXCore and FastCore instances in all other applications
find /Applications/Adobe* -type f -name "MMXCore" -print0 | sudo xargs -0 -I "{}" perl -i -pe 's|\x90\x90\x90\x90\x56\xE8\x5A\x00|\x90\x90\x90\x90\x56\xE8\x3A\x00|sg' "{}"
find /Applications/Adobe* -type f -name "MMXCore" -print0 | sudo xargs -0 -I "{}" perl -i -pe 's|\x90\x90\x90\x90\x56\xE8\x6A\x00|\x90\x90\x90\x90\x56\xE8\x3A\x00|sg' "{}"
find /Applications/Adobe* -type f -name "FastCore" -print0 | sudo xargs -0 -I "{}" perl -i -pe 's|\x90\x90\x90\x90\x56\xE8\x5A\x00|\x90\x90\x90\x90\x56\xE8\x3A\x00|sg' "{}"
find /Applications/Adobe* -type f -name "FastCore" -print0 | sudo xargs -0 -I "{}" perl -i -pe 's|\x90\x90\x90\x90\x56\xE8\x6A\x00|\x90\x90\x90\x90\x56\xE8\x3A\x00|sg' "{}"
#Patch Camera Raw
sudo perl -i -pe 's|\x90\x90\x90\x90\x56\xE8\x3A\x00|\x90\x90\x90\x90\x56\xE8\x1A\x00|sg' /Library/Application\ Support/Adobe/Plug-Ins/CC/File\ Formats/Camera\ Raw.plugin/Contents/MacOS/Camera\ Raw
sudo perl -i -pe 's|\x90\x90\x90\x90\x56\xE8\x5A\x00|\x90\x90\x90\x90\x56\xE8\x3A\x00|sg' /Library/Application\ Support/Adobe/Plug-Ins/CC/File\ Formats/Camera\ Raw.plugin/Contents/MacOS/Camera\ Raw
# Delete Camera Raw
#sudo rm -rf /Library/Application\ Support/Adobe/Plug-Ins/CC/File\ Formats/Camera\ Raw.plugin
# Photoshop and Illustrator specific fix
sudo rm -rf /Applications/Adobe\ Photoshop*/Adobe\ Photoshop*/Contents/Required/Deep_Font
sudo rm -rf /Applications/Adobe\ Illustrator*/Adobe\ Illustrator*/Contents/Required/Plug-ins/Text\ Filters/TextModel.aip
# Re-sign the binary (this may break activation, can't really get around that)
sudo codesign -fs - /Applications/Adobe*/Adobe*.app
sudo codesign -fs - /Library/Application\ Support/Adobe/Plug-Ins/CC/File\ Formats/Camera\ Raw.plugin
# Generate environment variable plist from base64
echo "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8ZGljdD4KIDxrZXk+TGFiZWw8L2tleT4KIDxzdHJpbmc+bXkuc3RhcnR1cDwvc3RyaW5nPgogPGtleT5Qcm9ncmFtQXJndW1lbnRzPC9rZXk+CiA8YXJyYXk+CiA8c3RyaW5nPnNoPC9zdHJpbmc+CiA8c3RyaW5nPi1jPC9zdHJpbmc+CiA8c3RyaW5nPmxhdW5jaGN0bCBzZXRlbnYgTUtMX0RFQlVHX0NQVV9UWVBFPTQ8L3N0cmluZz4KIDwvYXJyYXk+CiA8a2V5PlJ1bkF0TG9hZDwva2V5PgogPHRydWUvPgo8L2RpY3Q+CjwvcGxpc3Q+" | base64 --decode > onemomentplease.plist
# Upgrade version if necessary and copy to launchdaemons folder
if [[ $cpuname == *"Ryzen"* ]]; then
cat onemomentplease.plist | tr '4' '5' > onemomentplease2.plist
sudo cp onemomentplease2.plist /Library/LaunchDaemons/startupadobepatch.plist
else
sudo cp onemomentplease.plist /Library/LaunchDaemons/startupadobepatch.plist
fi
# Run for current instance
launchctl load /Library/LaunchDaemons/startupadobepatch.plist
launchctl start /Library/LaunchDaemons/startupadobepatch.plist
# Cleanup
rm onemomentplease*.plist