Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#!/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
Copy link

GetVladimir commented Feb 10, 2022

@hagarj Indeed, it's still an active conversion. You will need to look into an USB-C to DisplayPort cable otherwise, but your TV can't accept that input.

The benefit is that cables which are specifically designed to do the function of converting USB-C to HDMI have a much better chance to work properly.

Compared to docks which have multiple ports, they have a lot more things to worry about and the main priority becomes to output an image. They usually can't test too much whether that image is 4:2:2 or 4:4:4 with a specific TV, and it's ok for them as long as it works.

@hanoii
Copy link

hanoii commented Mar 23, 2022

Hi All, I got myself a new Dell s2721dgf monitor mostly for coding, I am coming from an P2715Q (4 years old) that worked perfectly. The former is 2k@165hz and the later is 4k@60k. I am having bad looking text.. The resolution I use is 2k for both monitors but on this new one the text looks bad... it is a bit blurry. The color format reported on the display is RGB, but I don't understand the odd looking text vs my 4k display (at 2k), it's a huge noticeable difference. Is anything in here that you think might help?

@GetVladimir
Copy link

GetVladimir commented Mar 23, 2022

@hanoii If the monitor already outputs RGB color and the text still doesn't look sharp, the options are a bit limited on what you can do to improve it.

First, make sure you're on the latest version on macOS 12.3, since older versions are know to have blurry text issues (which aren't fully resolved yet).

Second, make a backup and delete any displays plist files in /Library/Preferences/ that might be leftover from the older monitor.

Finally, if nothing else works, you can look into apps that create a fake second monitor that allows you to set HiDPI resolution on your current monitor. Something like this for example: https://github.com/waydabber/BetterDummy

@hanoii
Copy link

hanoii commented Mar 23, 2022

@GetVladimir thanks! I was trying BetterDummy but couldn't make it a difference. I wonder if I am just asking something that's not possible, so maybe you can share some advise there. Based on my previous comment I am having a second monitor for a second setup at home. I use my 4k P2715Q at 2560x1440 resolution which is my sweet spot of real estate and test size.

I now got my DELL D2721DGF which is 2K (2560x1440) but was looking for a different experience in terms of refresh rates. I expected the text to look just as good, but it's not. It's not super blurry, just kind of oldschool looking and not what I'd expect to be.

As for BetterDummy I am not sure what combinations of resolutions I should be using, but I always end up looking at the display as if there was no dummy on top. I didn't see any plist files, but will double check.

EDIT: NOTE that this is a 2017 MBP

@GetVladimir
Copy link

GetVladimir commented Mar 23, 2022

@hanoii thank you for the additional details.

From what you explained, the 4K monitor seems that it's actually running in HiDPI mode. This means that it uses its native 4K resolution, but macOS makes it zoomed in like it's on 1440p regarding the size.

If you go to System Preferences > Displays and click on "Scaled" and they select "Show all resolutions", you might see some entries showing as (low resolution) next to them.

My guess is that the 4K P2715Q is running at 2560x1440 HiDPI mode, while the D2721DFG is running at 2560x1440 (low resolution) mode.

There is a good explanation on HiDPI if you want to read more about it here: https://www.eizo.com/library/basics/hidpi/

If you don't use an M1 based Mac, you can also try apps such as SwitchResX to generate a custom override file with the display resolutions that you need: https://www.madrau.com/support/support/faq_files/ns_How_can_I_define_a_new_HiDPI_re.html

Let us know how it goes.

@hanoii
Copy link

hanoii commented Mar 23, 2022

@GetVladimir great info, thanks. I am also close to having a new M1 based MBP. So do you think I should be able to to run 2560x1440 at HiDPI mode on my new monitor and get the same text sharpness as with the 4k monitor at the same resolution. If so, how :)? I will read on all of that.

EDIT: Also, should I bi able to run hiDPI mode on the new monitor at 2560x1440 even though the pixel density is not as high?

@GetVladimir
Copy link

GetVladimir commented Mar 23, 2022

@hanoii No, actually the support for HiDPI on M1 based Macs is even more restricted, and the workarounds that worked on older x86 Macs for HiDPI no longer work on M1.

The limitation seems to be intentional. You can also read more details about it here: https://www.madrau.com/support/support/faq_files/ns_Why_isnt_there_any_HiDPI_resolu.html

@the1010boy
Copy link

the1010boy commented Apr 4, 2022

I applied this workaround / mod ...and yet, the image & text on my Dell U3014 still look "scratchy" and harsh on the eyes.

Screen Shot 2022-04-04 at 2 42 56 PM

I have a Mac Pro 5,1 running Mojave (10.14.6).

Screen Shot 2022-04-04 at 3 56 14 PM

Interestingly enough, when I replace the HDMI 2.0b HDCP 2.2 compatible HDIM cable with a DisplayPort cable the image looks GREAT! just as I would expect it too. However, because I'm driving 3 displays (all Dell U3014) at once I have to use HDMI for one of the monitors since my graphics card (Saphire Radeon RX580) only has 2x DisplayPort outputs. And it's the always the monitor connected to the HDMI cable that has the "scratchy" rendering.

Screen Shot 2022-04-04 at 3 56 00 PM

FYI, I had this working successfully for 4 years before I needed to rebuild my machine (reinstall the OS anew) and I forgot to take notes of how I got it all working last time (or I forgot where I put my notes 😅). ...and so far all my searches on the interweb haven't lead me to a solution that resolves this issue for me. So any help I could get would be greatly appreciated.

Lastly, as this might not be the right place to ask for such help let me know & I'll delete my post, as I know this goes beyond what this code is intended to do.

Also, for what it's worth, here's the contents of the "override file" this script created for me that I am using. At the time I ran the script to generate this file, I had only 1 dell monitor connected via HDMI.

<?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>DisplayProductName</key>
  <string>DELL U3014 - forced RGB mode (EDID override)</string>
  <key>IODisplayEDID</key>
  <data>AP///////wAQrINATDYwMgkYAQOAQCh44h31rk81syUNUFSlSwCBALMA0QBx
T6lAgYDRwAEB4mgAoKBALmAwIDYAgZEhAAAaAAAA/wBQMVY2TjQyUDIwNkwK
AAAA/ABERUxMIFUzMDE0CiAgAAAA/QAxVh1xHAAKICAgICAgAHg=
</data>
  <key>DisplayVendorID</key>
  <integer>4268</integer>
  <key>DisplayProductID</key>
  <integer>16515</integer>
</dict>
</plist>

@mfaughn
Copy link

mfaughn commented Apr 13, 2022

I've got something working on an M1 Mac. I'm not messing with RGB settings but I have been able to use a (rather sloppy) modification of the script to semi-successfully alter the name of the display as it is displayed in the MacOS 15.3.1 System Settings for displays. I really wanted it renamed in the Sound settings, which it sadly doesn't do. I'm using two Dell U3023e monitors and there is no way to distinguish which one to select for my sound output. I don't know much about plist files. Maybe there is a way to do conditionals in them or something?

Also referenced this to know where to put the generated files.

@GetVladimir
Copy link

GetVladimir commented Apr 13, 2022

@mfaughn Thank you for creating the modification and for sharing it. Every little bit helps.

This is useful to generate the correct displays override file on M1 based Macs, even if the EDID override doesn't work.

Perhaps this script can be used to add the DisplayIsTV key in the override file:

<key>DisplayIsTV</key>
<false/>

So that the generated example file looks something like this:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>DisplayProductName</key>
  <string>DELL U2415 (RGB)</string>
  <key>DisplayIsTV</key>
  <false/>
  <key>IODisplayEDID</key>
  <data>AP///////wAQrLigTEY0MCUYAQSlNCB4IgSVqVVNnSYQUFSlSwBxT4GAqUDR
wNEAAQEBAQEBKDyAoHCwI0AwIDYABkQhAAAeAAAA/wAwOERYRDQ5NzA0RkwK
AAAA/ABERUxMIFUyNDE1CiAgAAAA/QAxPR5TEQAKICAgICAgAGo=
</data>
  <key>DisplayVendorID</key>
  <integer>4268</integer>
  <key>DisplayProductID</key>
  <integer>41144</integer>
</dict>
</plist>

This seems to help some M1 Macs that incorrectly detect the monitor as a TV. However, more testing with more models is needed in order to confirm that the DisplayIsTV still makes a difference in those situations.

@nvcken
Copy link

nvcken commented Apr 14, 2022

Hi @GetVladimir
My problem is when connect MacBook Pro M1 to LG TV, the color on LG TV is washed out like very high contrast. I don't get this trouble when connect MBP Intel though.
So this plist would fix for it, is it? and can I know how to use that file plist?
THanks

@nvcken
Copy link

nvcken commented Apr 14, 2022

and does have anyway to revert patch script or overrides?

@mfaughn
Copy link

mfaughn commented Apr 14, 2022

and does have anyway to revert patch script or overrides?

On an M1, just deleting the plist file from /Library/Displays/Contents/Resources/Overrides/ and restarting should revert the patch.

@ibehnam
Copy link

ibehnam commented May 5, 2022

Folks I have a problem. Since ioreg -l | grep "DisplayVendorID" doesn't work on M1 mac, I don't know how to extract the DisplayProductID and DisplayVendorID. I tried using Switchresx which outputs EDID. In the EDID file, I was able to find DisplayProductID, but not the DisplayVendorID. The closest thing I found was Manufacturer ID, which is "SAM" (hex: 4C2D). However, "SAM" is not an integer and I don't know how to insert it in the fake plist file to force HiDPI. Can anyone please help?
image

@GetVladimir
Copy link

GetVladimir commented May 5, 2022

@ibehnam perhaps you can check if you can use the script from @mfaughn to help you generate just the DisplayVendorID and DisplayProductID here: https://gist.github.com/adaugherity/7435890?permalink_comment_id=4132166#gistcomment-4132166

@joevt
Copy link

joevt commented May 6, 2022

@ibehnam manufacturer is the vendor ID. 4C2D hex = 19501 decimal
The number comes from using each letter as a 5 bit number ('A' = 1).

vendor=SAM
bytes=$(printf "$vendor" | xxd -p)
echo $(((0x${bytes:0:2} & 31) << 10 | (0x${bytes:2:2} & 31) << 5 | (0x${bytes:4:2} & 31)))

@ibehnam
Copy link

ibehnam commented May 6, 2022

@GetVladimir So I used that script on M1 and unfortunately it didn’t work. After running the script, putting the plist file in the said directory, and restarting, RDM still doesn’t show the HiDPI resolution.

@ibehnam
Copy link

ibehnam commented May 6, 2022

@ibehnam manufacturer is the vendor ID. 4C2D hex = 19501 decimal The number comes from using each letter as a 5 bit number ('A' = 1).

vendor=SAM
bytes=$(printf "$vendor" | xxd -p)
echo $(((0x${bytes:0:2} & 31) << 10 | (0x${bytes:2:2} & 31) << 5 | (0x${bytes:4:2} & 31)))

Oh this is useful! The script also gives the same number 19501, but it’s good to know how it’s calculated.

@ibehnam
Copy link

ibehnam commented May 6, 2022

I’ve seen in comments on other forums that HiDPI is disabled for external monitors. So it seems like futile to even try…

That said, Better Dummy and Switchresx have been helpful.

@aseevlx
Copy link

aseevlx commented May 10, 2022

I used this script to fix color issues on my Xiaomi Mi Curved display (connected to MacBook Pro 15 2018), but it's also removed extension block from original EDID and macOS stuck at the default refresh rate - 50Hz. It was a really painful experience after 100Hz or 144Hz.

I spent several days trying to fix this, and finally found a solution to increase refresh rate and have normal color at the same time.

You need to decode the base64-encoded data string from the patched EDID to binary data, pass that data to AW EDID Editor, add an extension block with desired resolution and refresh rate, then encode that binary to base64 and put it back into patched EDID.

I also wrote a blog post with detailed instructions, but it's only in my native language. Mention me if you need help, I will translate it.

@GetVladimir
Copy link

GetVladimir commented May 10, 2022

@aseevlx This is a pretty awesome solution, thank you for the heads-up and the workaround.

I've found your blog post (hopefully it's the correct one) and used Google Translate for a quick translation: https://blog-aseev-im.translate.goog/nastraivaiem-xiaomi-mi-curved-gaming-monitor-pod-macos/?_x_tr_sl=ru&_x_tr_tl=en&_x_tr_hl=en-US&_x_tr_pto=wapp

This process might be useful for setting other custom resolutions and workarounds too (on x86 based macs). Thanks again for sharing the solution

@xeroxoid
Copy link

xeroxoid commented May 12, 2022

@GetVladimir @shageevan awesome solution indeed.
As I was also stuck at 50Hz when using the custom EDID, I gave it a shot, but for some reason the edid.bin can not be read by AW EDID Editor, it said the file is corrupted.

for some reason the decoding did not work correctly (probably because I use a newer Ruby version ruby 2.7.4p191 so I just saved the edid string to a file i.e. base64.txt and run base64 --decode base64.txt > edid.bin instead. That worked and I could then read the file in AW EDID Editor.

All good, RGB mode on and 100Hz over HDMI working! Thanks.

@ibehnam
Copy link

ibehnam commented May 12, 2022

@aseevlx does this method also solve the problem of HIDPI on external monitors?

@aseevlx
Copy link

aseevlx commented May 12, 2022

@ibehnam I don't know about the HiDPI problem, sorry. The resolution of my main display is 3440x1440 and I don't have the problem of blurry fonts. But I think you can try to create another extension block with "supported" resolution in EW EDID Editor, but that's just my thoughts.

@aseevlx
Copy link

aseevlx commented May 12, 2022

@xeroxoid excellent, I'm very glad you also find this useful.

I also tried to decode the data using system base64 lib, but I saw that it cuts off some of the encoded binary data. So the size of the resulting file is also different: 532 bytes for the file created by the ruby script, and 128 bytes for the file resulting from decoding with system base64. So I haven't tested this approach, but it's very interesting that it works too.

@GetVladimir
Copy link

GetVladimir commented May 23, 2022

Hey team, just wanted to update you that with macOS 12.4, there seems to be native support for HiDPI on external monitors as well now, without additional modifications:

HiDPI

Source for the news: https://www.reddit.com/r/MacOS/comments/uvsdv8/did_apple_solve_the_hidpi_problem/

Ping @hanoii and @ibehnam who were asking about these issues

@ibehnam
Copy link

ibehnam commented May 24, 2022

Thanks @GetVladimir, this is good news coming from Apple. Although, as the reddit comments mentioned, Apple has only put ≤720p HiDPI resolutions (at least for my 2K monitor with 2560x1440). So, I still use BetterDummy to get by.

There's also a flickering issue with external displays which happens when the M1 mac wakes up from sleep. The solution is to re-plug the HDMI cable, or turn the monitor off and on again.

@GetVladimir
Copy link

GetVladimir commented May 24, 2022

@ibehnam thank you for the reply and for the confirmation.

The screenshot on the original Reddit post seems to show HiDPI resolutions higher than 720p, but they might be based on a 4K monitor.

Also, good to know regarding the flickering issue workaround, thanks!

@GetVladimir
Copy link

GetVladimir commented Jun 20, 2022

How to enable HiDPI on M1 based Macs on any resolution

I have some interesting news: I found a solution to enable HiDPI on M1 based Macs on any resolution, even on 1080p screens, without the need to use mirroring or other workarounds.

Here is an example of HiDPI running on a Dell U2415 monitor that only supports a maximum resolution of 1920x1200:
1200p HiDPI

What you need to do is to edit the com.apple.windowserver.displays.plist file located in
/Library/Preferences/com.apple.windowserver.displays.plist

and change the key <key>Scale</key> to have a value of 2.

This is an example of how the section in the displays plist file should look like after the change:

					<key>CurrentInfo</key>
					<dict>
						<key>Depth</key>
						<integer>8</integer>
						<key>High</key>
						<real>1200</real>
						<key>Hz</key>
						<real>60</real>
						<key>IsLink</key>
						<false/>
						<key>OriginX</key>
						<real>0.0</real>
						<key>OriginY</key>
						<real>0.0</real>
						<key>Rotation</key>
						<integer>0</integer>
						<key>Scale</key>
						<real>2</real>
						<key>Wide</key>
						<real>1920</real>
					</dict>

Make sure that you change only the Scale key for the monitor that you need, and nothing else.

You can follow the step-by-step video tutorial on how to make the changes in the displays plist file here:
https://www.youtube.com/watch?v=Z1EqH3fd0V4

After that, restart your Mac and you should get HiDPI and noticeably more crisp and anti-aliased text, and the high resolution macOS icons.

An easy way to confirm that the HiDPI changes work is by looking at the Safari icon on the dock. If the HiDPI version of the icon is enabled, it will have a lot more sections in the compass than the low resolution icon. It should look something like this:
Safari HiDPI

Please note that while this might make the image look better even on 1080p screens, they will still be running at 1080p resolution, so the change might not be as drastic as running on a higher resolution screen.

If you have any questions about the procedure, please feel free to contact me or comment below.

@MajorVanBloodnok
Copy link

MajorVanBloodnok commented Jul 25, 2022

Can confirm this patch work to fix my magenta coloured extended display.
Colours now display correctly.
However, the display is now shifted 15% to the right, so that the right edge is cropped off screen.
The only way to regain the lost portion is to adjust overscan in display preferences, to shrink down the overall screen, but this obviously leaves a smaller display with a border around the sides.

What is the script doing, that alters horizontal image shift?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment