btparser/cparser/EDIDTemplate.bt

731 lines
32 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//--------------------------------------
//--- 010 Editor v3.2.2 Binary Template
//
// File: EDIDTemplate.bt
// Author: Rafael Vuijk
// Revision: 2012-03-02
// Purpose: EDID structure parser
//--------------------------------------
//
// NOTE: This template uses variable-size/unoptimized structure arrays.
// Information source: https://en.wikipedia.org/wiki/Extended_display_identification_data
// Modeline calculator: http://www.epanorama.net/faq/vga2rgb/calc.html
//
//--------------------------------------
typedef uint16 EISAId <read=EISAIdToString, write=StringToEISAId>;
string EISAIdToString(EISAId x)
{
uint16 sw = SwapBytes(x);
string s;
SPrintf(s, "%c%c%c", '@' + (sw>>10 & 0x1F), '@' + (sw>>5 & 0x1F), '@' + (sw>>0 & 0x1F));
return s;
}
void StringToEISAId(EISAId &x, string s)
{
char c[3];
SScan(s, "%c%c%c", c[0], c[1], c2[2]);
x = (c[0] - '@')<<10 | (c[1] - '@')<<5 | (c[2] - '@')<<0;
x = SwapBytes(x);
}
//--------------------------------------
typedef struct
{
ubyte x_resolution;
ubyte vFrequency : 6;
ubyte pixelRatio : 2;
} Timing <read=TimingToString>;
string TimingToString(Timing &t)
{
if (t.x_resolution == 1 && t.vFrequency == 1 && t.pixelRatio == 0) return "-";
int x = (t.x_resolution + 31) * 8;
int y;
switch (t.pixelRatio)
{
case 0: y = x*10/16; break;
case 1: y = x*3/4; break;
case 2: y = x*4/5; break;
case 3: y = x*9/16; break;
}
string s;
SPrintf(s, "%ux%u, %uHz", x, y, t.vFrequency + 60);
return s;
}
//--------------------------------------
enum <ubyte> DescriptorType
{
TIMINGS = 0xFA, // Additional standard timing identifiers. 6- 2-byte descriptors, padded with 0A.
WHITE_POINT = 0xFB, // Additional white point data. 2- 5-byte descriptors, padded with 0A 20 20.
MONITOR_NAME = 0xFC, // Monitor name (text)
RANGE_LIMITS = 0xFD, // Monitor range limits. 6- or 13-byte binary descriptor.
UNSPECIFIED_TEXT = 0xFE, // Unspecified text (text)
SERIAL_NUMBER = 0xFF, // Monitor serial number (text)
};
//--------------------------------------
enum <ubyte> FormatCode
{
RESERVED = 0,
LPCM = 1,
AC_3 = 2,
MPEG1 = 3,
MP3 = 4,
MPEG2 = 5,
AAC = 6,
DTS = 7,
ATRAC = 8,
SACD = 9,
DD_PLUS = 10,
DTS_HD = 11,
MLP_TRUEHD = 12,
DST = 13,
WMA_PRO = 14,
RESERVED2 = 15,
};
//--------------------------------------
enum <ubyte> BlockType
{
AUDIO = 1,
VIDEO = 2,
VENDOR_SPECIFIC = 3,
SPEAKER = 4,
};
//--------------------------------------
enum <ubyte> SVDIndex
{
_DMT0659 = 1, // 4:3 640x480p @ 59.94/60Hz
_480p = 2, // 4:3 720x480p @ 59.94/60Hz
_480pH = 3, // 16:9 720x480p @ 59.94/60Hz
_720p = 4, // 16:9 1280x720p @ 59.94/60Hz
_1080i = 5, // 16:9 1920x1080i @ 59.94/60Hz
_480i = 6, // 4:3 720(1440)x480i @ 59.94/60Hz
_480iH = 7, // 16:9 720(1440)x480i @ 59.94/60Hz
_240p = 8, // 4:3 720(1440)x240p @ 59.94/60Hz
_240pH = 9, // 16:9 720(1440)x240p @ 59.94/60Hz
_480i4x = 10, // 4:3 (2880)x480i @ 59.94/60Hz
_480i4xH = 11, // 16:9 (2880)x480i @ 59.94/60Hz
_240p4x = 12, // 4:3 (2880)x240p @ 59.94/60Hz
_240p4xH = 13, // 16:9 (2880)x240p @ 59.94/60Hz
_480p2x = 14, // 4:3 1440x480p @ 59.94/60Hz
_480p2xH = 15, // 16:9 1440x480p @ 59.94/60Hz
_1080p = 16, // 16:9 1920x1080p @ 59.94/60Hz
_576p = 17, // 4:3 720x576p @ 50Hz
_576pH = 18, // 16:9 720x576p @ 50Hz
_720p50 = 19, // 16:9 1280x720p @ 50Hz
_1080i25 = 20, // 16:9 1920x1080i @ 50Hz*
_576i = 21, // 4:3 720(1440)x576i @ 50Hz
_576iH = 22, // 16:9 720(1440)x576i @ 50Hz
_288p = 23, // 4:3 720(1440)x288p @ 50Hz
_288pH = 24, // 16:9 720(1440)x288p @ 50Hz
_576i4x = 25, // 4:3 (2880)x576i @ 50Hz
_576i4xH = 26, // 16:9 (2880)x576i @ 50Hz
_288p4x = 27, // 4:3 (2880)x288p @ 50Hz
_288p4xH = 28, // 16:9 (2880)x288p @ 50Hz
_576p2x = 29, // 4:3 1440x576p @ 50Hz
_576p2xH = 30, // 16:9 1440x576p @ 50Hz
_1080p50 = 31, // 16:9 1920x1080p @ 50Hz
_1080p24 = 32, // 16:9 1920x1080p @ 23.98/24Hz
_1080p25 = 33, // 16:9 1920x1080p @ 25Hz
_1080p30 = 34, // 16:9 1920x1080p @ 29.97/30Hz
_480p4x = 35, // 4:3 (2880)x480p @ 59.94/60Hz
_480p4xH = 36, // 16:9 (2880)x480p @ 59.94/60Hz
_576p4x = 37, // 4:3 (2880)x576p @ 50Hz
_576p4xH = 38, // 16:9 (2880)x576p @ 50Hz
_1080i25b = 39, // 16:9 1920x1080i(1250 Total) @ 50Hz*
_1080i50 = 40, // 16:9 1920x1080i @ 100Hz
_720p100 = 41, // 16:9 1280x720p @ 100Hz
_576p100 = 42, // 4:3 720x576p @ 100Hz
_576p100H = 43, // 16:9 720x576p @ 100Hz
_576i50 = 44, // 4:3 720(1440)x576i @ 100Hz
_576i50H = 45, // 16:9 720(1440)x576i @ 100Hz
_1080i60 = 46, // 16:9 1920x1080i @ 119.88/120Hz
_720p120 = 47, // 16:9 1280x720p @ 119.88/120Hz
_480p119 = 48, // 4:3 720x480p @ 119.88/120Hz
_480p119H = 49, // 16:9 720x480p @ 119.88/120Hz
_480i59 = 50, // 4:3 720(1440)x480i @ 119.88/120Hz
_480i59H = 51, // 16:9 720(1440)x480i @ 119.88/120Hz
_576p200 = 52, // 4:3 720x576p @ 200Hz
_576p200H = 53, // 16:9 720x576p @ 200Hz
_576i100 = 54, // 4:3 720(1440)x576i @ 200Hz
_576i100H = 55, // 16:9 720(1440)x576i @ 200Hz
_480p239 = 56, // 4:3 720x480p @ 239.76/240Hz
_480p239H = 57, // 16:9 720x480p @ 239.76/240Hz
_480i119 = 58, // 4:3 720(1440)x480i @ 239.76/240Hz
_480i119H = 59, // 16:9 720(1440)x480i @ 239.76/240Hz
_720p24 = 60, // 16:9 1280x720p @ 23.98/24Hz
_720p25 = 61, // 16:9 1280x720p @ 25Hz
_720p30 = 62, // 16:9 1280x720p @ 29.97/30Hz
_1080p120 = 63, // 16:9 1920x1080p @ 119.88/120Hz
};
typedef struct
{
SVDIndex index : 7 <comment="index value to a table of standard resolutions/timings from CEA/EIA-861E">;
ubyte native : 1 <comment="1 to designate that this should be considered a \"native\" resolution, 0 for non-native">;
} SVD <read=SVDToString, comment="Short Video Descriptor">;
string SVDToString(SVD &svd)
{
string s;
SPrintf(s, "%s%s (%u)", (svd.native ? "*" : ""), EnumToString(svd.index), svd.index);
return s;
}
//--------------------------------------
string SPAToString(uint16 spa)
{
string s;
SPrintf(s, "%u.%u.%u.%u", spa>>4&15, spa>>0&15, spa>>12&15, spa>>8&15);
return s;
}
//--------------------------------------
string TDMSFreqToString(ubyte f)
{
string s;
SPrintf(s, "%u MHz", (uint)f * 5);
return s;
}
//--------------------------------------
string PixelClockToString(uint16 f)
{
string s;
SPrintf(s, "%.2lf MHz", (double)f / 100);
return s;
}
void StringToPixelClock(uint16 &f, string s)
{
f = Atof(s) * 100;
}
//--------------------------------------
typedef ubyte PixelRate <read=PixelRateToString, write=StringToPixelRate>;
string PixelRateToString(PixelRate f)
{
string s;
SPrintf(s, "%u MHz", (uint)f * 10);
return s;
}
void StringToPixelRate(PixelRate &f, string s)
{
f = Atof(s) / 10;
}
//--------------------------------------
typedef ubyte BitRate <read=BitRateToString, write=StringToBitRate, comment="maximum supported bitrate divided by 8 kbit/s">;
string BitRateToString(BitRate b)
{
string s;
SPrintf(s, "%u kHz", (uint)b * 8);
return s;
}
void StringToBitRate(BitRate &b, string s)
{
b = Atof(s) / 8;
}
//--------------------------------------
typedef ubyte Latency <read=LatencyToString, write=StringToLatency, comment="Latency (value=1+ms/2 with a max of 251 meaning 500ms)">;
string LatencyToString(Latency l)
{
if (l == 0) return "-";
string s;
SPrintf(s, "%u ms", ((uint)l - 1) * 2);
return s;
}
void StringToLatency(Latency &l, string s)
{
if (s == "-") l = 0; else l = (uint)(Atof(s) / 2) + 1;
}
//--------------------------------------
typedef struct
{
ubyte size : 5 <comment="Total number of bytes in this block following this byte">;
BlockType typeTag : 3 <comment="Block Type Tag (1 is audio, 2 is video, 3 is vendor specific, 4 is speaker allocation, all other values Reserved)">;
// local int64 dataStart <hidden=true> = FTell();
switch (typeTag)
{
case AUDIO:
{
ubyte channelCount : 3 <comment="number of channels minus 1">;
FormatCode formatCode : 4 <comment="Audio format code">;
ubyte reserved1 : 1;
struct SampleRates
{
ubyte _32kHz : 1;
ubyte _44kHz : 1;
ubyte _48kHz : 1;
ubyte _88kHz : 1;
ubyte _96kHz : 1;
ubyte _176kHz : 1;
ubyte _192kHz : 1;
ubyte reserved : 1;
} sampleRates <comment="sampling frequencies supported">;
if (formatCode == 1) // LPCM
{
ubyte _16bits : 1;
ubyte _20bits : 1;
ubyte _24bits : 1;
ubyte reserved : 5;
}
else
{
BitRate bitrate;
}
break;
}
case VIDEO:
{
SVD svds[size] <bgcolor=cLtGreen, comment="Short Video Descriptors">;
break;
}
case VENDOR_SPECIFIC:
{
ubyte oui[3] <format=hex, comment="IEEE Registration Identifier">;
uint16 spa <read=SPAToString, comment="Source Physical Address">;
if (size >= 3)
{
ubyte DVI_Dual : 1 <comment="sink supports DVI Dual Link Operation">;
ubyte reserved : 1;
ubyte reserved : 1;
ubyte dc_Y444 : 1 <comment="sink supports 4:4:4 in deep color modes">;
ubyte dc_30bit : 1 <comment="sink supports 10-bit-per-channel deep color">;
ubyte dc_36bit : 1 <comment="sink supports 12-bit-per-channel deep color">;
ubyte dc_48bit : 1 <comment="sink supports 16-bit-per-channel deep color">;
ubyte supports_AI : 1 <comment="sink supports a function that needs info from ACP or ISRC packets">;
}
if (size >= 4)
ubyte max_TMDS_Frequency <read=TDMSFreqToString, comment="Maximum TMDS frequency">;
if (size >= 5)
{
ubyte reserved : 6;
ubyte i_latency_fields : 1 <comment="set if interlaced latency fields are present; if set four latency fields will be present">;
ubyte latency_fields : 1 <comment="set if latency fields are present">;
if (latency_fields)
{
Latency videoLatency <comment="Video Latency (value=1+ms/2 with a max of 251 meaning 500ms)">;
Latency audioLatency <comment="Audio Latency (value=1+ms/2 with a max of 251 meaning 500ms)">;
}
if (i_latency_fields)
{
Latency interlacedVideoLatency <comment="Interlaced Video Latency (value=1+ms/2 with a max of 251 meaning 500ms)">;
Latency interlacedAudioLatency <comment="Interlaced Audio Latency (value=1+ms/2 with a max of 251 meaning 500ms)">;
}
}
break;
}
case SPEAKER:
{
ubyte frontLeftRight : 1 <comment="Front Left / Front Right present for 1, absent for 0">;
ubyte LFE : 1 <comment="LFE present for 1, absent for 0">;
ubyte frontCenter : 1 <comment="Front Center present for 1, absent for 0">;
ubyte rearLeftRight : 1 <comment="Rear Left / Rear Right present for 1, absent for 0">;
ubyte rearCenter : 1 <comment="Rear Center present for 1, absent for 0">;
ubyte frontLeftRightCenter : 1 <comment="Front Left Center / Front Right Center present for 1, absent for 0">;
ubyte rearLeftRightCenter : 1 <comment="Rear Left Center / Rear Right Center present for 1, absent for 0">;
ubyte reserved : 1;
ubyte reserved[2];
break;
}
} // switch
// local int64 dataEnd <hidden=true> = FTell();
// Printf("block size: %u %lu\n", size, dataEnd - dataStart);
/* Assert(dataEnd - dataStart <= size, "Data block size error");
if (dataEnd - dataStart < size)
{
ubyte extraData[size - (dataEnd - dataStart)];
}*/
} DataBlock <size=DataBlockSize, optimize=false, open=true, comment="Data block">;
int DataBlockSize(DataBlock &b)
{
return (ReadUByte(startof(b)) & 0x1F);
}
//--------------------------------------
typedef struct
{
uint16 pixelClock <read=PixelClockToString, write=StringToPixelClock, comment="Pixel clock in 10 kHz units. (0.01-655.35 MHz, little-endian)">;
ubyte hActive_lsb <comment="Horizontal active pixels 8 lsbits (0-4095)">;
ubyte hBlanking_lsb <comment="Horizontal blanking pixels 8 lsbits (0-4095) End of active to start of next active.">;
ubyte hBlanking_msb : 4 <comment="Horizontal blanking pixels 4 msbits">;
ubyte hActive_msb : 4 <comment="Horizontal active pixels 4 msbits">;
ubyte vActive_lsb <comment="Vertical active lines 8 lsbits (0-4095)">;
ubyte vBlanking_lsb <comment="Vertical blanking lines 8 lsbits (0-4095)">;
ubyte vBlanking_msb : 4 <comment="Vertical blanking lines 4 msbits">;
ubyte vActive_msb : 4 <comment="Vertical active lines 4 msbits">;
ubyte hSyncOffset_lsb <comment="Horizontal sync offset pixels 8 lsbits (0-1023) From blanking start">;
ubyte hSync_lsb <comment="Horizontal sync pulse width pixels 8 lsbits (0-1023)">;
ubyte vSync_lsb : 4 <comment="Vertical sync pulse width lines 4 lsbits (0-63)">;
ubyte vSyncOffset_lsb : 4 <comment="Vertical sync offset lines 4 lsbits (0-63)">;
ubyte vSync_msb : 2 <comment="Vertical sync pulse width lines 2 msbits">;
ubyte vSyncOffset_msb : 2 <comment="Vertical sync offset lines 2 msbits">;
ubyte hSync_msb : 2 <comment="Horizontal sync pulse width pixels 2 msbits">;
ubyte hSyncOffset_msb : 2 <comment="Horizontal sync offset pixels 2 msbits">;
ubyte hSize_lsb <comment="Horizontal display size, mm, 8 lsbits (0-4095 mm, 161 in)">;
ubyte vSize_lsb <comment="Vertical display size, mm, 8 lsbits (0-4095 mm, 161 in)">;
ubyte vSize_msb : 4 <comment="Vertical display size, mm, 4 msbits">;
ubyte hSize_msb : 4 <comment="Horizontal display size, mm, 4 msbits">;
ubyte hBorder <comment="Horizontal border pixels (each side; total is twice this)">;
ubyte vBorder <comment="Vertical border lines (each side; total is twice this)">;
ubyte _f0 : 1 <comment="2-way line-interleaved stereo, if bits 4-3 are not 00.">;
ubyte _f1 : 1 <comment="If analog sync: Sync on all 3 RGB lines (else green only). Digital: HSync polarity (1=positive)">;
ubyte _f2 : 1 <comment="If digital separate: Vertical sync polarity (1=positive). Other types: VSync serrated (HSync during VSync)">;
ubyte _f34 : 2 <comment="Sync type: 00=Analog composite; 01=Bipolar analog composite; 10=Digital composite (on HSync); 11=Digital separate">;
ubyte _f56 : 2 <comment="Stereo mode: 00=No stereo; other values depend on bit 0: Bit 0=0: 01=Field sequential, sync=1 during right; 10=similar, sync=1 during left; 11=4-way interleaved stereo. Bit 0=1 2-way interleaved stereo: 01=Right image on even lines; 10=Left image on even lines; 11=side-by-side">;
ubyte interlaced : 1 <comment="Interlaced">;
//if (_f34 >> 1 & 1) Printf("Digital sync: "); else Printf("Analog sync: ");
//if (_f34 >> 0 & 1) Printf("Bipolar/separate\n"); else Printf("Composite\n");
} ModeLine <read=ModeLineToString, write=StringToModeLine, comment="Xfree86 modeline">;
string ModeLineToString(ModeLine &n)
{
uint hActive = (uint)n.hActive_msb<<8 | n.hActive_lsb;
uint hSyncOffset = (uint)n.hSyncOffset_msb<<8 | n.hSyncOffset_lsb;
uint hSync = (uint)n.hSync_msb<<8 | n.hSync_lsb;
uint hBlanking = (uint)n.hBlanking_msb<<8 | n.hBlanking_lsb;
uint vActive = (uint)n.vActive_msb<<8 | n.vActive_lsb;
uint vSyncOffset = (uint)n.vSyncOffset_msb<<8 | n.vSyncOffset_lsb;
uint vSync = (uint)n.vSync_msb<<8 | n.vSync_lsb;
uint vBlanking = (uint)n.vBlanking_msb<<8 | n.vBlanking_lsb;
uint im = n.interlaced ? 2 : 1;
string s;
SPrintf(s, "Modeline \"%ux%u\" %.2lf %4u %4u %4u %4u %4u %4u %4u %4u %chsync %cvsync %s ; %u %u", // relative to absolute
hActive, vActive*im, (double)n.pixelClock / 100,
hActive, hActive + hSyncOffset, hActive + hSyncOffset + hSync, hActive + hBlanking,
vActive*im, (vActive + vSyncOffset)*im, (vActive + vSyncOffset + vSync)*im, (vActive + vBlanking)*im,
n._f1 ? '+' : '-', n._f2 ? '+' : '-',
n.interlaced ? "Interlace" : "",
n.hBorder, n.vBorder
);
return s;
}
void StringToModeLine(ModeLine &n, string s)
{
uint dummy;
uint hActive, hActive_hSyncOffset, hActive_hSyncOffset_hSync, hActive_hBlanking;
uint vActive, vActive_vSyncOffset, vActive_vSyncOffset_vSync, vActive_vBlanking;
char hsync, vsync;
string interlaced;
double f;
SScanf(s, "Modeline \"%ux%u\" %lf %u %u %u %u %u %u %u %u %chsync %cvsync %[^0-9;]",
dummy, dummy, f,
hActive, hActive_hSyncOffset, hActive_hSyncOffset_hSync, hActive_hBlanking,
vActive, vActive_vSyncOffset, vActive_vSyncOffset_vSync, vActive_vBlanking,
hsync, vsync,
interlaced
);
int p = Strchr(s, ';');
if (p >= 0) SScanf(SubStr(s, p), "; %u %u", n.hBorder, n.vBorder);
n.interlaced = (interlaced[0] == 'I');
uint im = n.interlaced ? 2 : 1;
uint hBlanking = hActive_hBlanking - hActive;
uint hSync = hActive_hSyncOffset_hSync - hActive_hSyncOffset;
uint hSyncOffset = hActive_hSyncOffset - hActive;
n.hActive_msb = hActive>>8; n.hActive_lsb = (ubyte)hActive;
n.hSyncOffset_msb = hSyncOffset>>8; n.hSyncOffset_lsb = (ubyte)hSyncOffset;
n.hSync_msb = hSync>>8; n.hSync_lsb = (ubyte)hSync;
n.hBlanking_msb = hBlanking>>8; n.hBlanking_lsb = (ubyte)hBlanking;
uint vBlanking = (vActive_vBlanking - vActive)/im;
uint vSync = (vActive_vSyncOffset_vSync - vActive_vSyncOffset)/im;
uint vSyncOffset = (vActive_vSyncOffset - vActive)/im;
vActive /= im;
n.vActive_msb = vActive>>8; n.vActive_lsb = (ubyte)vActive;
n.vSyncOffset_msb = vSyncOffset>>8; n.vSyncOffset_lsb = (ubyte)vSyncOffset;
n.vSync_msb = vSync>>8; n.vSync_lsb = (ubyte)vSync;
n.vBlanking_msb = vBlanking>>8; n.vBlanking_lsb = (ubyte)vBlanking;
n._f1 = hsync == '+' ? 1 : 0;
n._f2 = vsync == '+' ? 1 : 0;
n.pixelClock = f * 100;
}
//--------------------------------------
struct File
{
struct Header
{
ubyte pattern[8] <format=hex, comment="Fixed header pattern: 00 FF FF FF FF FF FF 00">;
EISAId eisaId <comment="EISA ID. Encoded as 3 5-bit letters (1=A, 26=Z), big-endian, with msbit reserved.">;
uint16 mfgProductId <comment="Manufacturer product code. 16-bit number, little-endian.">;
uint32 serial <comment="Serial number. 32 bits, little endian.">;
ubyte mfgWeek <comment="Week of manufacture. Week numbering is not consistent between manufacturers.">;
ubyte mfgYear <comment="Year of manufacture, less 1990. (1990-2245). If week=255, it is the model year instead.">;
ubyte edidVersion <comment="EDID version, usually 1 (for 1.3)">;
ubyte edidRevision <comment="EDID revision, usually 3 (for 1.3)">;
} header <open=false, comment="Header information">;
struct Basic
{
union Bitmap
{
ubyte hmz;
if (hmz & 0x80)
{
struct Digital
{
ubyte vesa : 1 <comment="Signal is compatible with VESA DFP 1.x TMDS CRGB, 1 pixel per clock, up to 8 bits per color, MSB aligned,">;
ubyte reserved : 6 <comment="Reserved, must be 0">;
ubyte digital : 1 <comment="1=Digital input">;
} digital;
}
else
{
struct Analog
{
ubyte vSeparate : 1 <comment="VSync pulse must be separated when composite or sync-on-green is used">;
ubyte syncOnGreen : 1 <comment="Sync on green supported">;
ubyte compositeSync : 1 <comment="Composite sync (on HSync) supported">;
ubyte separateSync : 1 <comment="Separate sync supported">;
ubyte blankToBlack : 1 <comment="Blank-to-black setup (pedestal) expected">;
ubyte level : 2 <comment="Video white and sync levels, relative to blank: 00=+0.7/0.3 V; 01=+0.714/0.286 V; 10=+1.0/0.4 V; 11=+0.7/0 V">;
ubyte analog : 1 <comment="0=Analog input">;
} analog;
}
} bitmap <comment="Video input parameters bitmap">;
ubyte width <comment="Maximum horizontal image size, in centimetres (max 292 cm/115 in at 16:9 aspect ratio)">;
ubyte height <comment="Maximum vertical image size, in centimetres. If either byte is 0, undefined (e.g. projector)">;
ubyte gamma <comment="Display gamma, minus 1, times 100 (range 1.00-3.54)">;
struct Features
{
ubyte gtf : 1 <comment="GTF supported with default parameter values.">;
ubyte prefTimingDesc1 : 1 <comment="Preferred timing mode specified in descriptor block 1.">;
ubyte sRGB : 1 <comment="Standard sRGB colour space. Bytes 25-34 must contain sRGB standard values.">;
if (bitmap.hmz & 0x80)
ubyte displayType : 2 <comment="Display type (digital): 00 = RGB 4:4:4; 01 = RGB 4:4:4 + YCrCb 4:4:4; 10 = RGB 4:4:4 + YCrCb 4:2:2; 11 = RGB 4:4:4 + YCrCb 4:4:4 + YCrCb 4:2:2">;
else
ubyte displayType : 2 <comment="Display type (analog): 00 = Monochrome or Grayscale; 01 = RGB color; 10 = Non-RGB color; 11 = Undefined">;
ubyte dpmsActiveOff : 1 <comment="DPMS active-off supported">;
ubyte dpmsSusepend : 1 <comment="DPMS suspend supported">;
ubyte dpmsStandby : 1 <comment="DPMS standby supported">;
} features <comment="Supported features bitmap">;
} basic <open=false, comment="Basic display parameters">;
struct Chromaticity
{
ubyte green_y_lsb : 2 <comment="Green y value least-significant 2 bits">;
ubyte green_x_lsb : 2 <comment="Green x value least-significant 2 bits">;
ubyte red_y_lsb : 2 <comment="Red y value least-significant 2 bits">;
ubyte red_x_lsb : 2 <comment="Red x value least-significant 2 bits">;
ubyte bluewhite_lsb : 2 <comment="Blue and white least-significant 2 bits">;
ubyte zero : 6; // Lelouch
ubyte red_x_msb <comment="Red x value most significant 8 bits. 0-255 encodes 0-0.996 (255/256); 0-0.999 (1023/1024) with lsbits">;
ubyte red_y_msb <comment="Red y value most significant 8 bits">;
ubyte green_x_msb <comment="Green x value most significant 8 bits">;
ubyte green_y_msb <comment="Green y value most significant 8 bits">;
ubyte blue_x_msb <comment="Blue x value most significant 8 bits">;
ubyte blue_y_msb <comment="Blue y value most significant 8 bits">;
ubyte white_x_msb <comment="Default white point x value most significant 8 bits">;
ubyte white_y_msb <comment="Default white point y value most significant 8 bits">;
} chromaticity <bgcolor=cLtAqua, comment="Chromaticity coordinates. 10-bit CIE xy coordinates for red, green, blue, and white. [0-1023/1024].">;
struct Timings
{
ubyte _800x600_60 : 1;
ubyte _800x600_56 : 1;
ubyte _640x480_75 : 1;
ubyte _640x480_72 : 1;
ubyte _640x480_67 : 1;
ubyte _640x480_60 : 1;
ubyte _720x400_88 : 1;
ubyte _720x400_70 : 1;
ubyte _1280x1024_75 : 1;
ubyte _1024x768_75 : 1;
ubyte _1024x768_72 : 1;
ubyte _1024x768_60 : 1;
ubyte _1024x768i_87 : 1;
ubyte _832x624_75 : 1;
ubyte _800x600_75 : 1;
ubyte _800x600_72 : 1;
ubyte mfgSpecific : 7;
ubyte _1152x870_75 : 1; // Apple Macintosh II
} timings <bgcolor=cLtGreen, comment="Established timing bitmap. Supported bitmap for very common timing modes.">;
Timing timings2[8] <bgcolor=cLtGreen, comment="Standard timing information. Up to 8 2-byte fields describing standard display modes.">;
struct Descriptor
{
if (ReadUShort(FTell()) != 0)
{
ModeLine numbers;
}
else
{
uint16 zero;
ubyte zero;
DescriptorType descriptorType; // FA-FF currently defined. 00-0F reserved for vendors.
ubyte zero;
switch (descriptorType)
{
case TIMINGS:
Timing timings[6] <comment="Additional standard timing identifiers. 6- 2-byte descriptors, padded with 0A.">;
break;
case MONITOR_NAME:
char name[13] <comment="Monitor name (text)">;
break;
case SERIAL_NUMBER:
char serial[13] <comment="Monitor serial number (text)">;
break;
case UNSPECIFIED_TEXT:
char text[13] <comment="Unspecified text (text)">;
break;
case RANGE_LIMITS: // Monitor range limits. 6- or 13-byte binary descriptor.
{
ubyte vMinRate <comment="Minimum vertical field rate">;
ubyte vMaxRate <comment="Maximum vertical field rate">;
ubyte hMinRate <comment="Minimum horizontal line rate">;
ubyte hMaxRate <comment="Maximum horizontal line rate">;
PixelRate maxPixelRate <comment="Maximum pixel clock rate, rounded up to 10 MHz multiple (10-2550 MHz)">;
ubyte extended <comment="02: Secondary GTF supported, parameters as follows.">;
if (extended == 0x02)
{
ubyte reserved;
ubyte startFreqSecondCurve <comment="Start frequency for secondary curve, divided by 2 kHz (0-510 kHz)">;
ubyte gtf_C <comment="C value, multiplied by 2 (0-127.5)">;
uint16 gtf_M <comment="GTF M value (0-65535, little-endian)">;
ubyte gtf_K <comment="GTF K value (0-255)">;
ubyte gtf_J <comment="GTF J value, multiplied by 2 (0-127.5)">;
}
else
{
ubyte padding[7] <comment="0A 20 20 20 20 20 20">;
}
break;
}
case WHITE_POINT: // Additional white point data. 2- 5-byte descriptors, padded with 0A 20 20.
{
struct
{
ubyte indexNumber <comment="Point index number (1-255) Usually 1; 0 indicates descriptor not used.">;
ubyte white_y_lsb : 2 <comment="White point y value least-significant 2 bits">;
ubyte white_x_lsb : 2 <comment="White point x value least-significant 2 bits">;
ubyte unused : 4; // (C) DarkFader
ubyte white_x_msb <comment="White point x value most significant 8 bits (like EDID byte 27)">;
ubyte white_y_msb <comment="White point y value most significant 8 bits (like EDID byte 28)">;
ubyte gamma <comment="Gamma value, minus 1, time 100 (1.0-3.54, like EDID byte 23)">;
} whitePoints[2] <bgcolor=cLtAqua, comment="Additional white point descriptors">;
ubyte padding[3] <comment="0A 20 20">;
break;
}
default:
{
ubyte unknown[13];
Warning("Unknown descriptor type");
break;
}
}
}
} descriptors[4] <optimize=false, bgcolor=cLtGray, comment="Detailed Timing Descriptor blocks, in decreasing preference order. After all detailed timing descriptors, additional descriptors are permitted.">;
ubyte extensionCount <comment="Number of extensions to follow. 0 if no extensions.">;
ubyte checksum <format=hex, comment="Sum of all 128 bytes should equal 0 (mod 256).">;
//--------------------------------------
struct CEA_EDID
{
local int64 extensionBlockStart <hidden=true> = FTell();
ubyte extensionTag <comment="Extension tag (which kind of extension block this is); 02h for CEA EDID">;
switch (extensionTag)
{
case 0x02: // Additional Timing Data Block (CEA EDID Timing Extension)
{
ubyte revision <comment="Revision number (Version number); 03h for Version 3">;
ubyte dtdStart <comment="Byte number \"d\" within this block where the 18-byte DTDs begin.">;
ubyte dtdCount : 4 <comment="total number of native formats in the DTDs included in this block">;
ubyte YCbCr422 : 1 <comment="1 if display supports YCbCr 4:2:2, 0 if not">;
ubyte YCbCr444 : 1 <comment="1 if display supports YCbCr 4:4:4, 0 if not">;
ubyte basic_audio : 1 <comment="1 if display supports basic audio, 0 if not">;
ubyte underscan : 1 <comment="if display supports underscan, 0 if not">;
while (FTell() < extensionBlockStart + dtdStart)
{
DataBlock dataBlock;
} // while
if (FTell() != extensionBlockStart + dtdStart)
{
Warning("Unexpected DTD start");
}
FSeek(extensionBlockStart + dtdStart);
while (ReadUShort(FTell()) != 0)
{
Descriptor descriptor <optimize=false, bgcolor=cLtGray, comment="Detailed Timing Descriptor block">;
}
ubyte padding[127 - (FTell() - extensionBlockStart)] <format=hex, comment="Post-DTD padding. Should be populated with 00h">;
ubyte checksum <format=hex, comment="This byte should be programmed such that the sum of all 128 bytes equals 00h.">;
if (Checksum(CHECKSUM_SUM8, extensionBlockStart, 128) != 0) Warning("Invalid extension block checksum!");
break;
}
default:
Warning("Unsupported extension block");
break;
}
} extensions[extensionCount] <optimize=false, open=true, comment="EDID Extensions">;
} file <open=true, fgcolor=cBlue>;
//--------------------------------------