darling-IOGraphics/tools/modesuck.c
2020-07-03 22:03:44 -04:00

305 lines
9.7 KiB
C

// cc -o /tmp/modesuck -g modesuck.c -framework ApplicationServices -framework IOKit -Wall
#include <mach/mach.h>
#include <mach/thread_switch.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <math.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/graphics/IOGraphicsTypesPrivate.h>
#include <ApplicationServices/ApplicationServices.h>
__private_extern__ IOReturn
readFile(const char *path, vm_offset_t * objAddr, vm_size_t * objSize)
{
int fd;
int err;
struct stat stat_buf;
*objAddr = 0;
*objSize = 0;
if((fd = open(path, O_RDONLY)) == -1)
return errno;
do {
if(fstat(fd, &stat_buf) == -1) {
err = errno;
continue;
}
if (0 == (stat_buf.st_mode & S_IFREG))
{
*objAddr = 0;
*objSize = 0;
err = kIOReturnNotReadable;
continue;
}
*objSize = stat_buf.st_size;
if( KERN_SUCCESS != map_fd(fd, 0, objAddr, TRUE, *objSize)) {
*objAddr = 0;
*objSize = 0;
err = errno;
continue;
}
err = kIOReturnSuccess;
} while( false );
close(fd);
return( err );
}
__private_extern__ CFMutableDictionaryRef
readPlist( const char * path, UInt32 key )
{
IOReturn err;
vm_offset_t bytes;
vm_size_t byteLen;
CFDataRef data;
CFMutableDictionaryRef obj = 0;
err = readFile( path, &bytes, &byteLen );
if( kIOReturnSuccess != err)
return (0);
data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault,
(const UInt8 *) bytes, byteLen, kCFAllocatorNull );
if( data) {
obj = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, data,
kCFPropertyListMutableContainers,
(CFStringRef *) NULL );
CFRelease( data );
}
vm_deallocate( mach_task_self(), bytes, byteLen );
return (obj);
}
int main(int argc, char * argv[])
{
io_service_t framebuffer;
CGError err;
int i;
CGDisplayCount max;
CGDirectDisplayID displayIDs[8];
IODisplayModeInformation * modeInfo;
IODetailedTimingInformationV2 *timingInfo;
CFDictionaryRef dict;
CFArrayRef modes;
CFIndex count;
CFDictionaryRef mode;
CFMutableDictionaryRef result, stdModes, timingIDs;
CFDataRef data;
CFNumberRef num;
CFStringRef cfStr;
char key[64];
const void * keys[2];
const void * values[2];
err = CGGetOnlineDisplayList(8, displayIDs, &max);
if(err != kCGErrorSuccess)
exit(1);
if(max > 8)
max = 8;
for(i = 0; i < max; i++ ) {
framebuffer = CGDisplayIOServicePort(displayIDs[i]);
dict = IORegistryEntryCreateCFProperty(framebuffer, CFSTR(kIOFBConfigKey),
kCFAllocatorDefault, kNilOptions);
assert(dict);
modes = CFDictionaryGetValue(dict, CFSTR(kIOFBModesKey));
assert(modes);
result = readPlist("/System/Library/Frameworks/IOKit.framework/"
"Resources/IOGraphicsProperties.plist", 0);
if (result)
{
stdModes = (CFMutableDictionaryRef) CFDictionaryGetValue(result, CFSTR("std-modes"));
assert(stdModes);
timingIDs = (CFMutableDictionaryRef) CFDictionaryGetValue(result, CFSTR("timing-ids"));
assert(timingIDs);
data = CFDictionaryGetValue(result, CFSTR("apple-edid"));
if (data)
{
UInt32 ids[24] = { 0 };
UInt32 * p = (UInt32 *) CFDataGetBytePtr(data);
int i;
for( i = 0; i < (CFDataGetLength(data)/4); i+=2)
{
UInt32 bit, id;
id = p[i];
bit = p[i + 1] >> 16;
if( bit < 24)
{
bit = (0x10 - (bit & 0xf8)) | (bit & 7);
if( ids[bit])
printf("bit %ld, id %ld dup\n", bit, id);
else
ids[bit] = id;
}
}
data = CFDataCreate( kCFAllocatorDefault,
(const UInt8 *) ids, sizeof(ids) );
CFDictionarySetValue( result, CFSTR("established-ids"), data);
CFRelease(data);
}
}
else
{
result = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
assert(result);
stdModes = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
assert(stdModes);
timingIDs = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
assert(timingIDs);
}
count = CFArrayGetCount(modes);
for (i = 0; i < count; i++)
{
SInt32 aid;
mode = CFArrayGetValueAtIndex(modes, i);
num = CFDictionaryGetValue(mode, CFSTR(kIOFBModeAIDKey));
if (num)
CFNumberGetValue( num, kCFNumberSInt32Type, &aid );
else
aid = timingInvalid;
data = CFDictionaryGetValue(mode, CFSTR(kIOFBModeDMKey));
if (!data)
continue;
modeInfo = (IODisplayModeInformation *) CFDataGetBytePtr(data);
data = CFDictionaryGetValue(mode, CFSTR(kIOFBModeTMKey));
if (!data)
continue;
timingInfo = (IODetailedTimingInformationV2 *) CFDataGetBytePtr(data);
printf("%ldx%ld@%ld, %ld\n", modeInfo->nominalWidth, modeInfo->nominalHeight, ((modeInfo->refreshRate + 0x8000) >> 16), aid);
if( timingInfo->horizontalActive & 7) printf("horizontalActive & 7\n");
if( timingInfo->horizontalBlanking & 7) printf("horizontalBlanking & 7\n");
if( timingInfo->horizontalSyncOffset & 7) printf("horizontalSyncOffset & 7\n");
if( timingInfo->horizontalSyncPulseWidth & 7) printf("horizontalSyncPulseWidth & 7\n");
if( (aid == timingInvalid)
|| (aid == timingInvalid_SM_T24)
|| (aid == timingApple_FixedRateLCD)
|| (aid == timingGTF_640x480_120hz)
|| (aid == timingAppleNTSC_ST)
|| (aid == timingAppleNTSC_FF)
|| (aid == timingAppleNTSC_STconv)
|| (aid == timingAppleNTSC_FFconv)
|| (aid == timingApplePAL_ST)
|| (aid == timingApplePAL_FF)
|| (aid == timingApplePAL_STconv)
|| (aid == timingApplePAL_FFconv)
|| (aid == timingSMPTE240M_60hz)
|| (aid == timingFilmRate_48hz)
|| (aid == timingApple_0x0_0hz_Offline))
continue;
if(modeInfo->flags & (1<<kModeShowNever))
{
printf("nv!\n");
continue;
}
if( true
&& (aid != timingApple_1024x768_75hz)
)
{
if( aid == timingVESA_640x480_72hz)
modeInfo->refreshRate = 72 << 16; // from 72.8
sprintf(key, "%ld", ((modeInfo->nominalWidth << 20) | (modeInfo->nominalHeight << 8) | ((modeInfo->refreshRate + 0x8000) >> 16)));
cfStr = CFStringCreateWithCString( kCFAllocatorDefault, key,
kCFStringEncodingMacRoman );
if (CFDictionaryGetValue( timingIDs, cfStr ))
printf("%ld timing id dup\n", aid);
else
{
printf("ADDING\n");
CFDictionarySetValue( timingIDs, cfStr, num );
}
}
sprintf(key, "%ld", aid);
cfStr = CFStringCreateWithCString( kCFAllocatorDefault, key,
kCFStringEncodingMacRoman );
keys [0] = CFSTR(kIOFBModeTMKey);
values[0] = data;
keys [1] = CFSTR(kIOFBModeAIDKey);
values[1] = num;
dict = CFDictionaryCreate( kCFAllocatorDefault, keys, values, 1,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
assert(dict);
if (CFDictionaryGetValue( stdModes, cfStr ))
printf("%ld timing id dup\n", aid);
else
{
printf("ADDING\n");
CFDictionarySetValue( stdModes, cfStr, dict );
}
CFRelease(dict);
}
CFDictionarySetValue(result, CFSTR("std-modes"), stdModes);
CFDictionarySetValue(result, CFSTR("timing-ids"), timingIDs);
data = CFPropertyListCreateXMLData( kCFAllocatorDefault, result );
if (data)
{
char * str = (char *) CFDataGetBytePtr(data);
str[CFDataGetLength(data)] = 0;
printf( str );
}
}
exit(0);
return(0);
}