mirror of
https://github.com/darlinghq/darling-IOGraphics.git
synced 2024-11-27 06:10:33 +00:00
305 lines
9.7 KiB
C
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);
|
||
|
}
|