tge/engine/platformMacCarb/macCarbCPUInfo.cc
2017-04-17 06:17:10 -06:00

298 lines
11 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platformMacCarb/platformMacCarb.h"
#include "console/console.h"
#include "core/stringTable.h"
#include <sys/sysctl.h>
#include <mach/machine.h>
#include <math.h>
// The Gestalt() API will no longer be updated, so this code should migrate to
// the unix sysctl() and sysctlbyname() API. This is the current doctrine from Apple, dec 2005.
// Thanks to Gary "ChunkyKs" Briggs for contributing the sysctl() code patch.
Platform::SystemInfo_struct Platform::SystemInfo;
static char* _MacCarbGetMachineName();
static void _MacCarbGetCpuTypeAndFeatures(U32 *type, char **typeString, U32 *features);
static void _MacCarbGetBasicHWInfo(U32 *osVersion, U64 *cpuMhz, U32 *numCpus, U64 *memMbSize);
void Processor::init()
{
U32 osVersion;
U64 cpuMhz;
U32 numCpus;
U64 memMbSize;
U32 cpuType;
char* cpuTypeString;
U32 cpuFeatures;
Con::printf("System & Processor Information:");
// Get the mac model identifier, just for fun...
char *machineName = _MacCarbGetMachineName();
// get data about the machine out of sysctl and Gestalt ...
_MacCarbGetBasicHWInfo(&osVersion, &cpuMhz, &numCpus, &memMbSize);
_MacCarbGetCpuTypeAndFeatures(&cpuType, &cpuTypeString, &cpuFeatures);
// Set Torque's processor mhz var. This is reported to master servers.
Platform::SystemInfo.processor.mhz = cpuMhz;
// Set Torque's processor type var.
// Don't use special code paths based on this var, instead you should use the
// processor properties bits: Platform::SystemInfo.processor.properties
Platform::SystemInfo.processor.type = cpuType;
// Set Torque's processor name var.
Platform::SystemInfo.processor.name = StringTable->insert(cpuTypeString);
// Set Torques processor properties.
// These should determine what special code paths we use.
Platform::SystemInfo.processor.properties = cpuFeatures;
// Make pretty strings...
char freqString[32];
if(cpuMhz >= 1000)
dSprintf(freqString, 32, "%2.3g GHz", cpuMhz / 1000.0f);
else
dSprintf(freqString, 32, "%i MHz", cpuMhz);
char coresString[32] = "single core";
if(numCpus > 1)
dSprintf(coresString, 32, "%i cores", numCpus);
char memString[32];
if(memMbSize >= 1024)
dSprintf(memString, 32, "%2.1f GB", memMbSize / 1024.0f);
else
dSprintf(memString, 32, "%i MB", memMbSize);
// Dump info to console
Con::printf(" Mac OS X %x.%x.%x", (osVersion>>8), (osVersion&0xFF)>>4, (osVersion&0x0F));
Con::printf(" %s RAM", memString);
Con::printf(" %s %s (%s)", freqString, machineName, coresString);
Con::printf(" %s Architecture", cpuTypeString);
if(Platform::SystemInfo.processor.properties & CPU_PROP_MMX)
Con::printf(" MMX detected");
if(Platform::SystemInfo.processor.properties & CPU_PROP_SSE)
Con::printf(" SSE detected");
if(Platform::SystemInfo.processor.properties & CPU_PROP_ALTIVEC)
Con::printf(" Altivec detected");
Con::printf(" ");
}
static char* _MacCarbGetMachineName()
{
// data from: http://www.cocoadev.com/index.pl?MacintoshModels
// and http://www.theapplemuseum.com/index.php?id=36#
// and 10.4.8's /System/Library/SystemProfiler/SPPlatformReporter.spreporter/Contents/Resources/SPMachineTypes.plist
char* _unknownMac = "unknown Mac model";
char* _macNames[][2] = {
{ "AAPL,Gossamer", "PowerMacG3Series" },
{ "AAPL,PowerBook1998", "PowerBookG3Series" },
{ "AAPL,PowerMac G3", "PowerMacG3" },
{ "ADP2,1" , "Developer Transition Kit" },
{ "iMac,1" , "iMac" },
{ "iMac4,1" , "iMac Core Duo" },
{ "iMac4,2" , "iMac (Core Duo, mid 2006)" },
{ "iMac5,1" , "iMac (Core 2 Duo)" },
{ "iMac6,1" , "iMac (24-inch Core 2 Duo)" },
{ "MacBook1,1" , "MacBook (Core Duo)" },
{ "MacBook2,1" , "MacBook (Core 2 Duo)" },
{ "MacBookPro1,1" , "MacBook Pro (15-inch Core Duo)" },
{ "MacBookPro1,2" , "MacBook Pro (17-inch Core Duo)" },
{ "MacBookPro2,1" , "MacBook Pro (17-inch Core 2 Duo)" },
{ "MacBookPro2,2" , "MacBook Pro (15-inch Core 2 Duo)" },
{ "Macmini1,1" , "Mac mini (Core Duo/Solo)" },
{ "MacPro1,1" , "Mac Pro (Quad Xeon)" },
{ "MacPro1,1,Quad" , "Mac Pro (Quad Xeon)" },
{ "PowerBook1,1" , "PowerBook G3" },
{ "PowerBook2,1" , "iBook" },
{ "PowerBook2,2" , "iBook (FireWire)" },
{ "PowerBook3,1" , "PowerBook G3 (FireWire)" },
{ "PowerBook3,2" , "PowerBook G4" },
{ "PowerBook3,3" , "PowerBook G4 (Gigabit Ethernet)" },
{ "PowerBook3,4" , "PowerBook G4 (DVI)" },
{ "PowerBook3,5" , "PowerBook G4 (867, 1 GHz)" },
{ "PowerBook4,1" , "iBook G3" },
{ "PowerBook4,2" , "iBook G3" },
{ "PowerBook4,3" , "iBook G3" },
{ "PowerBook4,4" , "iBook" },
{ "PowerBook5,1" , "PowerBook G4 (17-inch)" },
{ "PowerBook5,2" , "PowerBook G4 (15-inch FW800)" },
{ "PowerBook5,3" , "PowerBook G4 (17-inch 1.33 GHz)" },
{ "PowerBook5,4" , "PowerBook G4 (15-inch 1.5/1.33 GHz)" },
{ "PowerBook5,5" , "PowerBook G4 (17-inch 1.5 GHz)" },
{ "PowerBook5,6" , "PowerBook G4 (15-inch 1.67/1.5 GHz)" },
{ "PowerBook5,7" , "PowerBook G4 (17-inch 1.67 GHz)" },
{ "PowerBook5,8" , "PowerBook G4 (Double-Layer SD, 15-inch)" },
{ "PowerBook5,9" , "PowerBook G4 (Double-Layer SD, 17-inch)" },
{ "PowerBook6,1" , "PowerBook G4 (12-inch)" },
{ "PowerBook6,2" , "PowerBook G4 (12-inch DVI)" },
{ "PowerBook6,3" , "iBook G4" },
{ "PowerBook6,4" , "PowerBook G4 (12-inch 1.33 GHz)" },
{ "PowerBook6,5" , "iBook G4" },
{ "PowerBook6,7" , "iBook G4" },
{ "PowerBook6,8" , "PowerBook G4 (12-inch 1.5 GHz)" },
{ "PowerMac1,1" , "Power Macintosh G3 (B&W)" },
{ "PowerMac1,2" , "Power Macintosh G4 (PCI-Graphics)" },
{ "PowerMac2,1" , "iMac (Slot-Loading)" },
{ "PowerMac2,2" , "iMac (2000)" },
{ "PowerMac3,1" , "Power Macintosh G4 (AGP-Graphics)" },
{ "PowerMac3,2" , "Power Macintosh G4 (AGP-Graphics)" },
{ "PowerMac3,3" , "Power Macintosh G4 (Gigabit Ethernet)" },
{ "PowerMac3,4" , "Power Macintosh G4 (Digital Audio)" },
{ "PowerMac3,5" , "Power Macintosh G4 (Quick Silver)" },
{ "PowerMac3,6" , "Power Macintosh G4 (Mirrored Drive Doors)" },
{ "PowerMac4,1" , "iMac (2001)" },
{ "PowerMac4,2" , "iMac (Flat Panel)" },
{ "PowerMac4,4" , "eMac G3" },
{ "PowerMac4,5" , "iMac (17-inch Flat Panel)" },
{ "PowerMac5,1" , "Power Macintosh G4 Cube" },
{ "PowerMac5,2" , "Power Macintosh G4 Cube" },
{ "PowerMac6,1" , "iMac (USB 2.0)" },
{ "PowerMac6,3" , "iMac (20-inch Flat Panel)" },
{ "PowerMac6,4" , "eMac (USB 2.0)" },
{ "PowerMac7,2" , "Power Macintosh G5" },
{ "PowerMac7,3" , "Power Macintosh G5" },
{ "PowerMac8,1" , "iMac G5" },
{ "PowerMac8,2" , "iMac G5 (Ambient Light Sensor)" },
{ "PowerMac9,1" , "Power Macintosh G5 (Late 2004)" },
{ "PowerMac10,1" , "Mac mini" },
{ "PowerMac10,2" , "Mac mini (Late 2005)" },
{ "PowerMac11,2" , "Power Macintosh G5 (PCIe)" },
{ "PowerMac11,2,Quad", "Power Macintosh G5 Quad" },
{ "PowerMac12,1" , "iMac G5 (iSight)" },
{ "RackMac1,1" , "Xserve G4" },
{ "RackMac1,2" , "Xserve G4 (Slot-Loading)" },
{ "RackMac3,1" , "Xserve G5" },
{ NULL , NULL }
};
char macModel[MAXPATHLEN];
U32 macModelLen = MAXPATHLEN;
macModel[macModelLen-1] = '\0';
sysctlbyname("hw.model", &macModel, &macModelLen, NULL, 0);
for(int i=0; _macNames[i][0] != NULL; i++)
{
if(!strcmp(_macNames[i][0], macModel))
return _macNames[i][1];
}
#if defined(TORQUE_DEBUG)
Con::warnf("Unknown mac model. Add a definition to _MacCarbGetMachineName() for %s.", macModel);
#endif
return _unknownMac;
}
void _MacCarbGetBasicHWInfo(U32 *osVersion, U64 *cpuMhz, U32 *numCpus, U64 *memMbSize)
{
U32 u64size = sizeof(U64);
U32 u32size = sizeof(U32);
// Get MacOSX version #
// Gestalt is still the only simple way to get the system version number, as of Jan 2007
Gestalt(gestaltSystemVersion, osVersion);
// Get system mem
sysctlbyname("hw.memsize", memMbSize, &u64size, NULL, 0);
*memMbSize /= 1024 * 1024;
// Get cpu clock speed
sysctlbyname("hw.cpufrequency", cpuMhz, &u64size, NULL, 0);
// sometimes the frequency is not a pretty number, so round it.
*cpuMhz = mCeil((float)(*cpuMhz)/(1000*1000));
// Get the # of processors or cores we have available
sysctlbyname("hw.ncpu", numCpus, &u32size, NULL, 0);
}
void _MacCarbGetCpuTypeAndFeatures(U32 *type, char **typeString, U32 *features)
{
int err;
U32 cputype;
U32 cpusubtype;
U32 cpufeature;
U32 u64size = sizeof(U64);
U32 u32size = sizeof(U32);
char *torqueCpuString;
U32 torqueCpuType;
U32 torqueCpuFeatures;
// Identify the cpu
err = sysctlbyname("hw.cputype", &cputype, &u32size, NULL, 0);
err |= sysctlbyname("hw.cpusubtype", &cpusubtype, &u32size, NULL, 0);
AssertWarn(err == 0, "Couldn't detect CPU type. Assuming generic x86.");
// determine the processor type & name
switch(cputype) {
case CPU_TYPE_X86:
case CPU_TYPE_X86_64:
torqueCpuString = "x86";
torqueCpuType = CPU_X86Compatible;
break;
case CPU_TYPE_POWERPC64:
case CPU_TYPE_POWERPC:
switch(cpusubtype)
{
case CPU_SUBTYPE_POWERPC_970:
torqueCpuString = "G5";
torqueCpuType = CPU_PowerPC_G5;
break;
case CPU_SUBTYPE_POWERPC_7400:
case CPU_SUBTYPE_POWERPC_7450:
torqueCpuString = "G4";
torqueCpuType = CPU_PowerPC_G4;
break;
case CPU_SUBTYPE_POWERPC_750:
torqueCpuString = "G3";
torqueCpuType = CPU_PowerPC_G3;
break;
default:
torqueCpuString = "PowerPC";
torqueCpuType = CPU_PowerPC_Unknown;
}
break;
default:
torqueCpuString = "unknown";
torqueCpuType = CPU_X86Compatible;
}
// Get CPU features. These should determine what special code paths we use.
torqueCpuFeatures = 0;
switch(torqueCpuType) {
case CPU_X86Compatible:
err = sysctlbyname("hw.optional.mmx", &cpufeature, &u32size, NULL, 0);
if(!err && cpufeature)
torqueCpuFeatures |= CPU_PROP_MMX;
err = sysctlbyname("hw.optional.sse", &cpufeature, &u32size, NULL, 0);
if(!err && cpufeature)
torqueCpuFeatures |= CPU_PROP_SSE;
break;
case CPU_PowerPC_G5:
case CPU_PowerPC_G4:
err = sysctlbyname("hw.optional.altivec", &cpufeature, &u32size, NULL, 0);
if(!err && cpufeature)
torqueCpuFeatures |= CPU_PROP_ALTIVEC;
break;
}
// return data
*type = torqueCpuType;
*typeString = torqueCpuString;
*features = torqueCpuFeatures;
}