Fixing iOS Simulator Black Screen on NVidia Kepler Macs with OCLP
Tags: macos, ios
Published: 2023-10-10 16:52:43

## Background

I've previously shared [how to develop and debug iOS 16 apps](ios-debug-catalina.md) on macOS catalina. While that workaround allowed compiling code with a newer toolchain than officially supported, Catalina proved to be too old of a system to effectively support modern iOS development. A huge limitation is its limit to Xcode 12.4.

I've finally made the decision to use [Opencore Legacy Patcher](https://dortania.github.io/OpenCore-Legacy-Patcher/) to install newer macOS on my iMac late 2013. Although OCLP officially supports macOS 14, there are still quite a few outstanding bugs. That calls for being more conservative when considering upgrading macOS on legacy Macs. So I picked MacOS 12 as the base for my iMac late 2013.

The way OCLP works is by extracting kexts (or in more common terminology - drivers) from older macOS releases and install them in the new macOS version. Because this combination (older kexts from old OS on a new OS) is not supported, you can run into bugs that does not exist on supported configurations.

## Problem

My particular iMac has an NVidia Kepler graphics card. NVidia had a row with Apple causing Apple to switch to AMD in later Macs (despite NVidia being superior in energy efficiency for much of the 2014-2020 period). 

The conflict between the two companies shows in the quality of the NVidia Metal driver. The NVidia driver has trouble running the iOS 16.2 simulator that comes with XCode 14.2 (the last XCode version supported by macOS 12). When the simulator is started, the screen remains black, although the log shows the simulator processes are running fine.

This problem is only relevant to people with NVidia Kepler graphics cards. NVidia GPUs before Kepler do not support metal. Later Macs use AMD. And Macs of the same generation using Intel Haswell processors integrated graphics is also free of this problem. This is one peculiar bug that affect a very small subset of people. 

Through experimentation, I determined the last release of iOS simulator that works with Kepler driver is the iOS 15.2 simulator bundled with XCode 13.2.1. If you do not mind the extra disk space, and do not mind testing with iOS 15 rather than iOS 16, then simply download the iOS 15.2 runtime in Xcode and everything should work.

Here is the workaround I discovered after some experimentation to get 16.2 simulator working. (I've tested it on macOS 12 and XCode 14.2. It should also work on macOS 13 with XCode 14.x. I have not tested this on XCode 15 / iOS 17 Simulator, or on macOS 14.)

## Obtaining iOS 15.2 Simulator

To start, you need to download the iOS 15.2 simulator. There are two ways to do it:

### Download iOS 15.2 Simulator in XCode

In XCode -> Preferences -> Platforms -> ➕ -> iOS -> iOS 15.2 Simulator.

Then, show package content of the simulator runtime. It is in `/Library/Developer/CoreSimulator/Profiles/Runtimes` if you installed Simulator through XCode.

### Obtain iOS 15.2 Simulator from Apple Developer Website

If you do not want to download the runtime inside XCode, which is much smaller, you can also download XCode 13.2.1 from the Apple Developer website.

After you extract the package, show package content and find the runtime in `Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes`.

## After Obtaining iOS 15.2 Simulator

Also open up the content of XCode 14.2, navigate to `Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes` to find the iOS 16.2 runtime.

The magic files you need from iOS 15.2 runtime is `Resources/RuntimeRoot/System/Library/PrivateFrameworks/MTLSimDriver.framework`. Copy and replace the folder in the same path from the iOS 15.2 runtime to the iOS 16.2 runtime.

After this, quit iOS 16.2 Simulator if you have it open, and start it up again. This time, the screen should no longer be black, because by replacing this private library, iOS 16.2 Simulator can now draw using the older API.