-
-
Save jrjhealey/9d3476cf13b4d52593251ad683f9af1c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
# Create display override file to force Mac OS X to use RGB mode for Display | |
# see http://embdev.net/topic/284710 | |
require 'base64' | |
data=`ioreg -l -d0 -w 0 -r -c AppleDisplay` | |
edids=data.scan(/IODisplayEDID.*?<([a-z0-9]+)>/i).flatten | |
vendorids=data.scan(/DisplayVendorID.*?([0-9]+)/i).flatten | |
productids=data.scan(/DisplayProductID.*?([0-9]+)/i).flatten | |
displays = [] | |
edids.each_with_index do |edid, i| | |
disp = { "edid_hex"=>edid, "vendorid"=>vendorids[i].to_i, "productid"=>productids[i].to_i } | |
displays.push(disp) | |
end | |
# Process all displays | |
if displays.length > 1 | |
puts "Found %d displays! You should only install the override file for the one which" % displays.length | |
puts "is giving you problems.","\n" | |
elsif displays.length == 0 | |
puts "No display data found! Are any external displays connected?" | |
end | |
displays.each do |disp| | |
# Retrieve monitor model from EDID display descriptor | |
i = disp["edid_hex"].index('000000fc00') | |
if i.nil? | |
monitor_name = "Display" | |
else | |
# The monitor name is stored in (up to) 13 bytes of text following 00 00 00 fc 00. | |
# If the name is shorter than 13 bytes, it is terminated with a newline (0a) and then padded with spaces. | |
monitor_name = [disp["edid_hex"][i + 10, 26].to_s].pack("H*") | |
monitor_name.rstrip! # remove trailing newline/spaces | |
end | |
puts "Found display '#{monitor_name}': vendor ID=#{disp["vendorid"]} (0x%x), product ID=#{disp["productid"]} (0x%x)" % | |
[disp["vendorid"], disp["productid"]] | |
puts "Raw EDID data:\n#{disp["edid_hex"]}" | |
bytes=disp["edid_hex"].scan(/../).map{|x|Integer("0x#{x}")}.flatten | |
puts "Setting color support to RGB 4:4:4 only" | |
bytes[24] &= ~(0b11000) | |
puts "Number of extension blocks: #{bytes[126]}" | |
puts "removing extension block" | |
bytes = bytes[0..127] | |
bytes[126] = 0 | |
bytes[127] = (0x100-(bytes[0..126].reduce(:+) % 256)) % 256 | |
puts | |
puts "Recalculated checksum: 0x%x" % bytes[127] | |
puts "new EDID:\n#{bytes.map{|b|"%02X"%b}.join}" | |
Dir.mkdir("DisplayVendorID-%x" % disp["vendorid"]) rescue nil | |
filename = "DisplayVendorID-%x/DisplayProductID-%x" % [disp["vendorid"], disp["productid"]] | |
puts "Output file: #{Dir.pwd}/#{filename}" | |
f = File.open(filename, 'w') | |
f.write '<?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">' | |
f.write " | |
<dict> | |
<key>DisplayProductName</key> | |
<string>#{monitor_name} - forced RGB mode (EDID override)</string> | |
<key>IODisplayEDID</key> | |
<data>#{Base64.encode64(bytes.pack('C*'))}</data> | |
<key>DisplayVendorID</key> | |
<integer>#{disp["vendorid"]}</integer> | |
<key>DisplayProductID</key> | |
<integer>#{disp["productid"]}</integer> | |
</dict> | |
</plist>" | |
f.close | |
puts "\n" | |
end # displays.each |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A fix for weird behaviour between MacOS and some monitors. If a picture is produced, and resolutions etc all appear correct, yet text is fuzzy - this might solve the problem.
Worked for me on OSX 10.15.1.
This fix will essentially force the Mac to output an RGB colourspace to the monitor instead of the YPbPr one, which is generally used for TVs.
1. Run the above script.
patch-edid.rb
, then:ruby patch-edid.rb
.2. A folder with a name of the form
DisplayVendorID-xxxx
will be created in your home directory.3. Reboot into recovery mode.
Cmd+R
while powering it on, until the Apple logo and a progress bar appears.4. Inside recovery mode, open a terminal window (
Utilities > Terminal
on the top menu bar).5. Copy the directory to the relevant path (change
username
appropriately):cp -r /Volumes/Macintosh\ HD/Users/username/DisplayVendorID-xxxx /Volumes/Macintosh\ HD/System/Library/Displays/Contents/Resources/Overrides/
If
/Volumes/Macintosh\ HD/System/Library/Displays/Contents/Resources/Overrides/
doesn't exist (/Resources/Overrides
may not) you can make them without issue.If a folder matching the
DisplayVendorID-xxxx
already exists, consider copying it/backing it up somewhere first.6. Reboot
UPDATE 08.12.2020
It appears that on Big Sur and Catalina, it is no longer necessary to use the above approach and try to edit system partitions. The OS protections will stop this. Instead, the process can all be done within OSX, as follows:
1. Run the script as before
2. Make the filestructure if it doesn't already exist
sudo mkdir -p /Library/Displays/Contents/Resources/Overrides/
3. Copy the directory produced by the
ruby
script as before, to this newly created destination:sudo cp -r ~/DisplayVendorID-xxxx/ /Library/Displays/Contents/Resources/Overrides/
This also means you do not need to reboot in to recovery mode or attempt to bypass the SIP (
csrutil
).4. Unplug and replug the offending monitor, and the changes should apply
Useful further reading about the latter approach here: https://gist.github.com/ejdyksen/8302862#gistcomment-3460110