AMD Custom Timing Converter v0.3
By T. Sosnow.

3 Arguments are required:
- The input text file.
- A registry path point to DAL2_DATA__2_0\Common\EDID_0_0 (the last numbers can be different for EDID monitors)
- A name of the node (REG_BINARY) which starts with ModeTimingOverrides_ and has the name followed with the ID of the connector

This originally started out as an migration utility for WinModelines.
So the input text file follows the same XFree86 based format:
Modeline "XXXxYYY_RR hfreq vfreq" PixelClock ActivePixels HSyncStart HSyncStop HTotal ActiveLines VSyncStart VSyncStop VTotal Flags

The starting word "MODELINE" is required for the line to be recognized, lines not following that are IGNORED!
The description string gets parsed to define the reported resolution and refreshrate values (can be different/fake to trick certain software)
The pixel clock is in Mhz and will the parsed to an float and should have an period '.' as decimal point.
The four horizontal numbers shall ascend (the next number MUST be bigger than the previous ones).
Same applies to the vertical numbers as well.
The flags MUST specifiy both sync polarities, also an optional interlace flag is supported (the last 3 vertical numbers MUST BE ODD for this).

Here's an example:
Modeline "1600x1200_160 105,4KHz 159,9Hz" 231.970 1600 1723 1899 2200 1200 1203 1209 1319 interlace -hsync -vsync
This is my favorite modeline, looks damn crisp and smooth on my Sony GDM-5403.

To figure out your node name it might be necessary to use AMDCustomTimingTool or ADLutil to inject a 'dummy' modeline.
The program will print out all parsed lines like this:
>640x400_140hz   (640x400  | -60.76kHz:-140.00Hz  856x 434 total)
>1024x768_85hz   (1024x768 | +68.68kHz: +85.00Hz 1376x 808 total)
>2048x1536_100hz (2048x1536| -81.40kHz: -99.94Hz 2784x1629 total interlaced)
>640x480_59hz    (640x480  | -15.75kHz: -60.00Hz  779x 525 total interlaced)

Each mode starts with an > telling the reported values (will default to the actual values if not defined).
Then followed with more info such as actual resolution, frequency prefixed with syncpolarity, total pixels and lines (also with blanking).
Lastly if it's interlaced.
The point of this printout serves as feedback to see how the program interpreted the line.

Also the program will stop parsing at the first error. It will tell you exactly what's wrong and which line it is.
The following (read) errors could occour and what exactly to check for:
- HSync polarity not defined.
- VSync polarity not defined.
H/VSync flags were found but no - or + was detected.
- VSync not found.
- HSync not found.
- Width is below 16 pixels!
- Height is below 32 lines!
- Refresh is below 12hz!
- Pixelclock is below 500khz!
These six ones should be selfexplainatory.
- Active pixels exceeds HSyncStart!
The 1st number after the pixel clock is larger than the 2nd number.
- HSync time is negative!
The 2nd number after the pixel clock is larger than the 3rd number.
- Total amount of pixels is wrong!
The 3rd number after the pixel clock is larger than the 4th number.
- Active lines exceeds VSyncStart!
The 5th number after the pixel clock is larger than the 6th number.
- VSync lines is negative!
The 6th number after the pixel clock is larger than the 7th number.
- Total amount of lines is wrong!
The 7th number after the pixel clock is larger than the 8th number.
- Interlaced VSyncStart must be odd!
The 6th number is even on a line with the interlace flag.
- Interlaced VSyncStop must be odd!
The 7th number is even on a line with the interlace flag.
- Interlaced total lines must be odd!
The 8th number is even on a line with the interlace flag.


Supported cards so far:
AMD Radeon HD6970 with hacked FirePro 8.911.3.4 or Catalyst 12.1 running under Windows XP 32-bit.


For other (newer) drivers you may need to change the source to output 4 bytes more, and wedge a 0x00000000 before or after the "mark as interlaced" entry. 
This could be easily done in these two sections:
// Modeline parsing done, create data
Wedge in another "putValueInBuf(buffer, 0, 5);" OR "putValueInBuf(buffer, 0, 6);" and increment the index numbers of the following putValueInBuf.
// Write data to .reg file
Change "while(i<104){" to "while(i<108){"

I can't tell you what works, all data I've seen on the net was progressive. If you don't care about interlacing then either one should work fine.
Otherwise just try it and tell me what worked (and if driver reported the correct refreshrate). 
I might offer an alternative version for newer drivers/cards if someone would tell me.


T. Sosnow. <t-sosnow@posteo.com>
Visit QWERTZ-tek at http://qwertz.w10.site/ for my other stuff
June 7, 2026
