-
-
Save adaugherity/7435890 to your computer and use it in GitHub Desktop.
#!/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?" | |
puts "\nNote: Apple Silicon (arm64) devices are currently unsupported, as the standard" | |
puts "method of retrieving display information does not work." | |
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 |
@GetVladimir Yes, I've thought of this as well. I've tested it with an older dell monitor P2417, side by side to one of the Asus in my current pair. They did not swap after a week of use on the dock.
I should also point out, when I test to plug in the pair to laptop itself, (my current work around), I have to remember the cable and order to do so. Say, if I plugin monitor A to port 1 and then monitor B to port 2, and arrange it in the OS to my liking, next time, I go plug monitor B to port 2 first then monitor A to port 1, it swaps.
@daili0802 that is actually a good find with the workaround you're using.
I don't know of another way to consistently work except for using the separate cables without using a dock. If you find some solution for this, let us know
Sure. @GetVladimir
But, are there ways to us this script to override the EDID without changing the RGB setting?
@daili0802 as far as I know, this specific script only works for x86 based Macs
Ah! that was one important part I missed. Sorry and thank you.
@daili0802 not a problem, you're welcome. It would be great if it gets resolved
Is there any similar way to accomplish this on an Apple Silicon Mac? Thanks :)
@rainyskye you can try modifying the displays plist file to force RGB color output on Apple Silicon based Macs: https://gist.github.com/GetVladimir/c89a26df1806001543bef4c8d90cc2f8#how-to-force-rgb-color-output-instead-of-ypbpr-on-your-m1-apple-silicon-mac-for-an-external-monitor
Here is my issue, I am sending signal from Mac to a monitor via HDbaseT adapter, and I get a display like this: https://i.imgur.com/yO1ArVp.png
Whats strange is if I rotate the picture 90 or 180 degrees it looks completely perfect. But setting it back to Standard it goes back looking like the picture. I tried running this script, but it didnt improve it.
I have a 4k monitor, using a MacBook Pro 13-inch, 2017, Two Thunderbolt 3 ports. Resolution is maxed out at blurry 1440p. Any way to fix this?
@anbarae What display? Is it HDMI or DisplayPort connection? Try SwitchResX? Run AllRez to get a list of display modes.
Works for Sonoma on a 2016 Macbook Pro 👌
I have 2 external HDMI-to-usbc monitors. The override works and I can see it take effect in Settings > Displays, but when i rearrange the monitors in Display settings, one of the monitors gets blurry again. Anyone run into this?
@MikaelDDavidd This solution works on x86 based Macs. It's not meant for M1 based Macs, as they ignore the EDID override.
You can delete the override file you have created, reboot and it should be back to default.
If possible, try using an USB-C to DisplayPort port cable on the M1 Pro
Any way to make this work with BetterDisplay? It also works on Silicon-based Macs.
Based on the current situation, TVs still switch back to YCbCr color in HDR mode, such as LG's C series and G series TVs.
Is it possible to support using RGB in HDR mode as well?
@LeXwDeX Most of the time, TVs will default to YCbCr 4:2:2 whenever you enable HDR, especially if your Mac's HDMI port is version 2.0.
It's usually limited by the bandwidth of the HDMI port and the formats (HDR10, HLG, Dolby Vision) announced during the handshake.
You can check with USB-C/Thunderbolt-to-HDMI adapters to work around this if you really want to, but usually it will just not work reliably or introduce other issues
@daili0802 thank you for the reply and the update.
That might point that the issue is not the monitors being detected the same, but an issue with macOS to remember the display order.
This is usually the case when the Apple Silicon based Macs assign different UUID on each reboot.
If that is indeed what's happening, you might have the same issue even if you connect completely different monitors or TVs.
You can easily test this if you have a TV nearby and connect it with only one monitor.
To resolve this, you might need to connect each monitor directly to your Mac on a different USB-C port, and not use a dock