Cemu
Cemu copied to clipboard
macOS: Apple Silicon support (interpreter only)
Fixes #396(?), supersedes #1211 (I don't own BOTW and haven't been able to reproduce the issue on other games, but this fixes a similar error that only occurred on Apple Silicon)
The re-compiler hasn't been implemented and only the interpreter works. (and there's already an WIP aarch64 recompiler for cemu android, assuming that they plan on merging into this repo)
I'll be honest, it will probably be a while until we have a decent ARM recompiler that will outperform Rosetta so this seems a bit early. But I generally don't want to stand in the way of adding new target platforms. That said, the changes made here are detrimental for other platforms. Just on a quick glance some obvious issues:
- Putting gx2WriteGatherPipe access behind a mutex is absolutely gonna wreck performance. Better to work with atomic pointers or manually insert memory barriers where needed.
mmuRange_HIGHMEMis supposed to match Wii U's memory map. I get that there is a 16KB page size restriction but other platforms don't have this so it should be conditional.- Lots of changes in the h264 decoder, would be nice if you could give an explanation?
Lots of changes in the h264 decoder, would be nice if you could give an explanation?
On OSX, C functions are compiled with a leading underscore and the header files define the ASM functions as a normal C function, resulting in functions being called with a leading underscore but defined without one.
~~Admittedly now I see this could probably be done by just marking them with extern, I'll do that instead~~ This results in the same thing.
Putting gx2WriteGatherPipe access behind a mutex is absolutely gonna wreck performance. Better to work with atomic pointers or manually insert memory barriers where needed.
Makes sense, I'll revert that and try something else
mmuRange_HIGHMEMis supposed to match Wii U's memory map. I get that there is a 16KB page size restriction but other platforms don't have this so it should be conditional.
Ah, I wasn't sure but that's what I somewhat assumed.
@exverge-0 If you're trying to solve this error:
/Users/runner/work/Cemu/Cemu/src/Cafe/HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp:172:16: note: 'jumpStart' declared here
for (auto&& [jumpStart, jumpInfo] : jumps)
^
/Users/runner/work/Cemu/Cemu/src/Cafe/HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp:178:45: error: reference to local binding 'jumpStart' declared in enclosing function 'AArch64GenContext_t::processAllJumps'
sint64 addressOffset = targetAddress - jumpStart;
^
/Users/runner/work/Cemu/Cemu/src/Cafe/HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp:172:16: note: 'jumpStart' declared here
for (auto&& [jumpStart, jumpInfo] : jumps)
^
2 warnings and 6 errors generated
this worked for me: https://github.com/cemu-project/Cemu/blob/d219a192c927d7913ed1f73109e5e55362cfa5c3/.github/workflows/build.yml#L189-L191 build: https://github.com/neebyA/Cemu/actions/runs/15248824548
I found this related StackOverflow post; instead of changing the code, this issue can be fixed by using version 16+ of the Xcode command line tools. The macos-14 runner by default uses Xcode 15.4, so either explicitly selecting a newer version of Xcode or using the macos-15 runner would work.
@neebyA Try changing the start of the loop to this as a workaround:
for (auto&& [_jumpStart, _jumpInfo] : jumps)
{
auto& jumpStart = _jumpStart;
auto& jumpInfo = _jumpInfo;
I am not familiar with macOS development so I am not sure what the best strategy is in regards of which xcode version to target. But in general I am against bumping a compiler version when something can be worked around easily.
I used @Exzap 's workaround in order to avoid said issue, and it seems to compile fine.
Otherwise, with the addition of the aarch64 recompiler, this PR is essentially done. I haven't done much testing, from what I've tested it seems to run smoothly with no new issues and the only real difference I've noticed being that the arm64 seemingly has less lag spikes, whereas under Rosetta it would stutter while compiling shaders, but otherwise it's seemingly the same. (though Rosetta already ran at 60/30 fps on the games I tested, so any performance improvement wouldn't be noticeable) I also reverted the change from https://github.com/cemu-project/Cemu/issues/1255#discussion_r1709465498 so as to separate it from this PR to not have to include the odd workaround (which hadn't prevented any games from running/caused any visible issues in my testing, only console errors)
build-macos:
runs-on: macos-14
steps:
- name: "Checkout repo"
uses: actions/checkout@v4
with:
submodules: "recursive"
- name: "Select Xcode 16.2"
run: sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
- name: "Verify Xcode Version"
run: xcodebuild -version
- name: Setup release mode parameters
run: |
echo "BUILD_MODE=release" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is release"
- name: Setup build flags for version
if: ${{ inputs.next_version_major != '' }}
run: |
echo "[INFO] Version ${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEMULATOR_VERSION_MAJOR=${{ inputs.next_version_major }} -DEMULATOR_VERSION_MINOR=${{ inputs.next_version_minor }}" >> $GITHUB_ENV
- name: "Install system dependencies"
run: |
brew update
brew install ninja nasm automake libtool
- name: "Install molten-vk"
run: |
curl -L -O https://github.com/KhronosGroup/MoltenVK/releases/download/v1.3.0/MoltenVK-macos.tar
tar xf MoltenVK-macos.tar
sudo mkdir -p /usr/local/lib
sudo cp MoltenVK/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib /usr/local/lib
- name: "Setup cmake"
uses: jwlawson/actions-setup-cmake@v2
with:
cmake-version: '3.29.0'
- name: "Bootstrap vcpkg"
run: |
bash ./dependencies/vcpkg/bootstrap-vcpkg.sh
- name: 'Setup NuGet Credentials for vcpkg'
shell: 'bash'
run: |
mono `./dependencies/vcpkg/vcpkg fetch nuget | tail -n 1` \
sources add \
-source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" \
-storepasswordincleartext \
-name "GitHub" \
-username "${{ github.repository_owner }}" \
-password "${{ secrets.GITHUB_TOKEN }}"
mono `./dependencies/vcpkg/vcpkg fetch nuget | tail -n 1` \
setapikey "${{ secrets.GITHUB_TOKEN }}" \
-source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json"
- name: "cmake x64"
run: |
mkdir build
cd build
cmake .. ${{ env.BUILD_FLAGS }} \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DMACOS_BUNDLE=ON \
-G Ninja
- name: "Build Cemu x64"
run: |
cmake --build build
- name: "Move x64 artifact"
run: |
mkdir bin/x64
mv bin/Cemu_release.app bin/x64/Cemu.app
mv bin/x64/Cemu.app/Contents/MacOS/Cemu_release bin/x64/Cemu.app/Contents/MacOS/Cemu
sed -i '' 's/Cemu_release/Cemu/g' bin/x64/Cemu.app/Contents/Info.plist
chmod a+x bin/x64/Cemu.app/Contents/MacOS/{Cemu,update.sh}
codesign --force --deep --sign - bin/x64/Cemu.app
- name: "cmake arm64"
run: |
rm -rf build
mkdir build
cd build
cmake .. ${{ env.BUILD_FLAGS }} \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \
-DCMAKE_OSX_ARCHITECTURES=arm64 \
-DMACOS_BUNDLE=ON \
-G Ninja
- name: "Build Cemu arm64"
run: |
cmake --build build
- name: "Move arm64 artifact"
run: |
mkdir bin/arm64
mkdir bin/universal
mv bin/Cemu_release.app bin/arm64/Cemu.app
cp -R bin/arm64/Cemu.app bin/universal/Cemu.app
mv bin/arm64/Cemu.app/Contents/MacOS/Cemu_release bin/arm64/Cemu.app/Contents/MacOS/Cemu
sed -i '' 's/Cemu_release/Cemu/g' bin/arm64/Cemu.app/Contents/Info.plist
chmod a+x bin/arm64/Cemu.app/Contents/MacOS/{Cemu,update.sh}
codesign --force --deep --sign - bin/arm64/Cemu.app
- name: "Create Universal binary"
run: |
rm bin/universal/Cemu.app/Contents/MacOS/Cemu_release
lipo -create -output bin/universal/Cemu.app/Contents/MacOS/Cemu \
bin/x64/Cemu.app/Contents/MacOS/Cemu \
bin/arm64/Cemu.app/Contents/MacOS/Cemu
rm bin/universal/Cemu.app/Contents/Frameworks/libusb-1.0.0.dylib
lipo -create -output bin/universal/Cemu.app/Contents/Frameworks/libusb-1.0.0.dylib \
bin/x64/Cemu.app/Contents/Frameworks/libusb-1.0.0.dylib \
bin/arm64/Cemu.app/Contents/Frameworks/libusb-1.0.0.dylib
sed -i '' 's/Cemu_release/Cemu/g' bin/universal/Cemu.app/Contents/Info.plist
chmod a+x bin/universal/Cemu.app/Contents/MacOS/{Cemu,update.sh}
codesign --force --deep --sign - bin/universal/Cemu.app
rm -rf bin/x64/Cemu.app bin/arm64/Cemu.app
- name: Prepare artifacts
run: |
mkdir bin/Cemu_app_universal
mv bin/universal/Cemu.app bin/Cemu_app_universal/Cemu.app
ln -s /Applications bin/Cemu_app_universal/Applications
hdiutil create ./bin/tmp.dmg -ov -volname "Cemu" -fs HFS+ -srcfolder "./bin/Cemu_app_universal"
hdiutil convert ./bin/tmp.dmg -format UDZO -o bin/Cemu_universal.dmg
rm bin/tmp.dmg
- name: Upload universal artifact
uses: actions/upload-artifact@v4
with:
name: cemu-bin-macos-universal
path: ./bin/Cemu_universal.dmg
- uses: actions/download-artifact@v4
with:
name: cemu-bin-macos-universal
path: cemu-bin-macos-universal
- name: Create release from macos-bin-universal
run: cp cemu-bin-macos-universal/Cemu_universal.dmg upload/cemu-${{ env.CEMU_VERSION }}-macos-12-universal.dmg
I suggest building a universal version would be better, to avoid distinguishing between x86_64 and arm64 versions. After all, the universal version can run directly on both x86_64 and arm64 platforms. Moreover, on arm64 platforms, the universal version can switch to running the x86_64 version through the Rosetta 2 option.
@hauntek Feel free to open a separate PR for building the universal binary
Individual arch builds have the benefit of being smaller and launching faster. They should be keep, even if universal is regarded as the main distribution