| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "cpudetect.h"
- #include "wwstring.h"
- #include "wwdebug.h"
- #include "thread.h"
- #include "mpu.h"
- #pragma warning (disable : 4201) // Nonstandard extension - nameless struct
- #include <windows.h>
- #include "systimer.h"
- struct OSInfoStruct {
- const char* Code;
- const char* SubCode;
- const char* VersionString;
- unsigned char VersionMajor;
- unsigned char VersionMinor;
- unsigned short VersionSub;
- unsigned char BuildMajor;
- unsigned char BuildMinor;
- unsigned short BuildSub;
- /* OSInfoStruct() {}
- OSInfoStruct(
- const char* code,
- const char* subcode,
- const char* versionstring,
- unsigned char versionmajor,
- unsigned char versionminor,
- unsigned short versionsub,
- unsigned char buildmajor,
- unsigned char buildminor,
- unsigned short buildsub) :
- Code(code),
- SubCode(subcode),
- VersionString(versionstring),
- VersionMajor(versionmajor),
- VersionMinor(versionminor),
- VersionSub(versionsub),
- BuildMajor(buildmajor),
- BuildMinor(buildminor),
- BuildSub(buildsub)
- {
- }
- */
- };
- static void Get_OS_Info(
- OSInfoStruct& os_info,
- unsigned OSVersionPlatformId,
- unsigned OSVersionNumberMajor,
- unsigned OSVersionNumberMinor,
- unsigned OSVersionBuildNumber);
- StringClass CPUDetectClass::ProcessorLog;
- StringClass CPUDetectClass::CompactLog;
- int CPUDetectClass::ProcessorType;
- int CPUDetectClass::ProcessorFamily;
- int CPUDetectClass::ProcessorModel;
- int CPUDetectClass::ProcessorRevision;
- int CPUDetectClass::ProcessorSpeed;
- __int64 CPUDetectClass::ProcessorTicksPerSecond; // Ticks per second
- double CPUDetectClass::InvProcessorTicksPerSecond; // 1.0 / Ticks per second
- unsigned CPUDetectClass::FeatureBits;
- unsigned CPUDetectClass::ExtendedFeatureBits;
- unsigned CPUDetectClass::L2CacheSize;
- unsigned CPUDetectClass::L2CacheLineSize;
- unsigned CPUDetectClass::L2CacheSetAssociative;
- unsigned CPUDetectClass::L1DataCacheSize;
- unsigned CPUDetectClass::L1DataCacheLineSize;
- unsigned CPUDetectClass::L1DataCacheSetAssociative;
- unsigned CPUDetectClass::L1InstructionCacheSize;
- unsigned CPUDetectClass::L1InstructionCacheLineSize;
- unsigned CPUDetectClass::L1InstructionCacheSetAssociative;
- unsigned CPUDetectClass::L1InstructionTraceCacheSize;
- unsigned CPUDetectClass::L1InstructionTraceCacheSetAssociative;
- unsigned CPUDetectClass::TotalPhysicalMemory;
- unsigned CPUDetectClass::AvailablePhysicalMemory;
- unsigned CPUDetectClass::TotalPageMemory;
- unsigned CPUDetectClass::AvailablePageMemory;
- unsigned CPUDetectClass::TotalVirtualMemory;
- unsigned CPUDetectClass::AvailableVirtualMemory;
- unsigned CPUDetectClass::OSVersionNumberMajor;
- unsigned CPUDetectClass::OSVersionNumberMinor;
- unsigned CPUDetectClass::OSVersionBuildNumber;
- unsigned CPUDetectClass::OSVersionPlatformId;
- StringClass CPUDetectClass::OSVersionExtraInfo;
- bool CPUDetectClass::HasCPUIDInstruction=false;
- bool CPUDetectClass::HasRDTSCInstruction=false;
- bool CPUDetectClass::HasSSESupport=false;
- bool CPUDetectClass::HasSSE2Support=false;
- bool CPUDetectClass::HasCMOVSupport=false;
- bool CPUDetectClass::HasMMXSupport=false;
- bool CPUDetectClass::Has3DNowSupport=false;
- bool CPUDetectClass::HasExtended3DNowSupport=false;
- CPUDetectClass::ProcessorManufacturerType CPUDetectClass::ProcessorManufacturer = CPUDetectClass::MANUFACTURER_UNKNOWN;
- CPUDetectClass::IntelProcessorType CPUDetectClass::IntelProcessor;
- CPUDetectClass::AMDProcessorType CPUDetectClass::AMDProcessor;
- CPUDetectClass::VIAProcessorType CPUDetectClass::VIAProcessor;
- CPUDetectClass::RiseProcessorType CPUDetectClass::RiseProcessor;
- char CPUDetectClass::VendorID[20];
- char CPUDetectClass::ProcessorString[48];
- const char* CPUDetectClass::Get_Processor_Manufacturer_Name()
- {
- static const char* ManufacturerNames[] = {
- "<Unknown>",
- "Intel",
- "UMC",
- "AMD",
- "Cyrix",
- "NextGen",
- "VIA",
- "Rise",
- "Transmeta"
- };
- return ManufacturerNames[ProcessorManufacturer];
- }
- #define ASM_RDTSC _asm _emit 0x0f _asm _emit 0x31
- static unsigned Calculate_Processor_Speed(__int64& ticks_per_second)
- {
- struct {
- unsigned timer0_h;
- unsigned timer0_l;
- unsigned timer1_h;
- unsigned timer1_l;
- } Time;
- __asm {
- ASM_RDTSC;
- mov Time.timer0_h,eax
- mov Time.timer0_l,edx
- }
- unsigned start=TIMEGETTIME();
- unsigned elapsed;
- while ((elapsed=TIMEGETTIME()-start)<200) {
- __asm {
- ASM_RDTSC;
- mov Time.timer1_h,eax
- mov Time.timer1_l,edx
- }
- }
- __int64 t=*(__int64*)&Time.timer1_h-*(__int64*)&Time.timer0_h;
- ticks_per_second=(1000/200)*t; // Ticks per second
- return unsigned(t/(elapsed*1000));
- }
- void CPUDetectClass::Init_Processor_Speed()
- {
- if (!Has_RDTSC_Instruction()) {
- ProcessorSpeed=0;
- return;
- }
- // Loop until two subsequent samples are within 5% of each other (max 5 iterations).
- unsigned speed1=Calculate_Processor_Speed(ProcessorTicksPerSecond);
- unsigned total_speed=speed1;
- for (int i=0;i<5;++i) {
- unsigned speed2=Calculate_Processor_Speed(ProcessorTicksPerSecond);
- float rel=float(speed1)/float(speed2);
- if (rel>=0.95f && rel<=1.05f) {
- ProcessorSpeed=(speed1+speed2)/2;
- InvProcessorTicksPerSecond=1.0/double(ProcessorTicksPerSecond);
- return;
- }
- speed1=speed2;
- total_speed+=speed2;
- }
- // If no two subsequent samples where close enough, use intermediate
- ProcessorSpeed=total_speed/6;
- InvProcessorTicksPerSecond=1.0/double(ProcessorTicksPerSecond);
- }
- void CPUDetectClass::Init_Processor_Manufacturer()
- {
- VendorID[0] = 0;
- unsigned max_cpuid;
- CPUID(
- max_cpuid,
- (unsigned&)VendorID[0],
- (unsigned&)VendorID[8],
- (unsigned&)VendorID[4],
- 0);
- ProcessorManufacturer = MANUFACTURER_UNKNOWN;
- if (stricmp(VendorID, "GenuineIntel") == 0) ProcessorManufacturer = MANUFACTURER_INTEL;
- else if (stricmp(VendorID, "AuthenticAMD") == 0) ProcessorManufacturer = MANUFACTURER_AMD;
- else if (stricmp(VendorID, "AMD ISBETTER") == 0) ProcessorManufacturer = MANUFACTURER_AMD;
- else if (stricmp(VendorID, "UMC UMC UMC") == 0) ProcessorManufacturer = MANUFACTURER_UMC;
- else if (stricmp(VendorID, "CyrixInstead") == 0) ProcessorManufacturer = MANUFACTURER_CYRIX;
- else if (stricmp(VendorID, "NexGenDriven") == 0) ProcessorManufacturer = MANUFACTURER_NEXTGEN;
- else if (stricmp(VendorID, "CentaurHauls") == 0) ProcessorManufacturer = MANUFACTURER_VIA;
- else if (stricmp(VendorID, "RiseRiseRise") == 0) ProcessorManufacturer = MANUFACTURER_RISE;
- else if (stricmp(VendorID, "GenuineTMx86") == 0) ProcessorManufacturer = MANUFACTURER_TRANSMETA;
- }
- void CPUDetectClass::Process_Cache_Info(unsigned value)
- {
- switch (value) {
- case 0x00: // Null
- break;
- case 0x01: // Instruction TLB, 4K pages, 4-way set associative, 32 entries
- break;
- case 0x02: // Instruction TLB, 4M pages, fully associative, 2 entries
- break;
- case 0x03: // Data TLB, 4K pages, 4-way set associative, 64 entries
- break;
- case 0x04: // Data TLB, 4M pages, 4-way set associative, 8 entries
- break;
- case 0x06: // Instruction cache, 8K, 4-way set associative, 32 byte line size
- L1InstructionCacheSize=8*1024;
- L1InstructionCacheLineSize=32;
- L1InstructionCacheSetAssociative=4;
- break;
- case 0x08: // Instruction cache 16K, 4-way set associative, 32 byte line size
- L1InstructionCacheSize=16*1024;
- L1InstructionCacheLineSize=32;
- L1InstructionCacheSetAssociative=4;
- break;
- case 0x0A: // Data cache, 8K, 2-way set associative, 32 byte line size
- L1DataCacheSize=8*1024;
- L1DataCacheLineSize=32;
- L1DataCacheSetAssociative=2;
- break;
- case 0x0C: // Data cache, 16K, 4-way set associative, 32 byte line size
- L1DataCacheSize=16*1024;
- L1DataCacheLineSize=32;
- L1DataCacheSetAssociative=4;
- break;
- case 0x40: // No L2 cache (P6 family), or No L3 cache (Pentium 4 processor)
- // Nice of Intel, Pentium4 has an exception and this field is defined as "no L3 cache"
- if (ProcessorManufacturer==MANUFACTURER_INTEL && ProcessorFamily==0xf) {
- }
- else {
- L2CacheSize=0;
- L2CacheLineSize=0;
- L2CacheSetAssociative=0;
- }
- break;
- case 0x41: // Unified cache, 32 byte cache line,4-way set associative, 128K
- L2CacheSize=128*1024;
- L2CacheLineSize=32;
- L2CacheSetAssociative=4;
- break;
- case 0x42: // Unified cache, 32 byte cache line, 4-way set associative, 256K
- L2CacheSize=256*1024;
- L2CacheLineSize=32;
- L2CacheSetAssociative=4;
- break;
- case 0x43: // Unified cache, 32 byte cache line, 4-way set associative, 512K
- L2CacheSize=512*1024;
- L2CacheLineSize=32;
- L2CacheSetAssociative=4;
- break;
- case 0x44: // Unified cache, 32 byte cache line, 4-way set associative, 1M
- L2CacheSize=1024*1024;
- L2CacheLineSize=32;
- L2CacheSetAssociative=4;
- break;
- case 0x45: // Unified cache, 32 byte cache line, 4-way set associative, 2M
- L2CacheSize=2048*1024;
- L2CacheLineSize=32;
- L2CacheSetAssociative=4;
- break;
- case 0x50: // Instruction TLB, 4K, 2M or 4M pages, fully associative, 64 entries
- break;
- case 0x51: // Instruction TLB, 4K, 2M or 4M pages, fully associative, 128 entries
- break;
- case 0x52: // Instruction TLB, 4K, 2M or 4M pages, fully associative, 256 entries
- break;
- case 0x5B: // Data TLB, 4K or 4M pages, fully associative, 64 entries
- break;
- case 0x5C: // Data TLB, 4K or 4M pages, fully associative, 128 entries
- break;
- case 0x5D: // Data TLB, 4K or 4M pages, fully associative, 256 entries
- break;
- case 0x66: // Data cache, sectored, 64 byte cache line, 4 way set associative, 8K
- L1DataCacheSize=8*1024;
- L1DataCacheLineSize=64;
- L1DataCacheSetAssociative=4;
- break;
- case 0x67: // Data cache, sectored, 64 byte cache line, 4 way set associative, 16K
- L1DataCacheSize=16*1024;
- L1DataCacheLineSize=64;
- L1DataCacheSetAssociative=4;
- break;
- case 0x68: // Data cache, sectored, 64 byte cache line, 4 way set associative, 32K
- L1DataCacheSize=32*1024;
- L1DataCacheLineSize=64;
- L1DataCacheSetAssociative=4;
- break;
- case 0x70: // Instruction Trace cache, 8 way set associative, 12K uOps
- L1InstructionTraceCacheSize=12*1024;
- L1InstructionTraceCacheSetAssociative=8;
- break;
- case 0x71: // Instruction Trace cache, 8 way set associative, 16K uOps
- L1InstructionTraceCacheSize=16*1024;
- L1InstructionTraceCacheSetAssociative=8;
- break;
- case 0x72: // Instruction Trace cache, 8 way set associative, 32K uOps
- L1InstructionTraceCacheSize=32*1024;
- L1InstructionTraceCacheSetAssociative=8;
- break;
- case 0x79: // Unified cache, sectored, 64 byte cache line, 8 way set associative, 128K
- L2CacheSize=128*1024;
- L2CacheLineSize=64;
- L2CacheSetAssociative=8;
- break;
- case 0x7A: // Unified cache, sectored, 64 byte cache line, 8 way set associative, 256K
- L2CacheSize=256*1024;
- L2CacheLineSize=64;
- L2CacheSetAssociative=8;
- break;
- case 0x7B: // Unified cache, sectored, 64 byte cache line, 8 way set associative, 512K
- L2CacheSize=512*1024;
- L2CacheLineSize=64;
- L2CacheSetAssociative=8;
- break;
- case 0x7C: // Unified cache, sectored, 64 byte cache line, 8 way set associative, 1M
- L2CacheSize=1024*1024;
- L2CacheLineSize=64;
- L2CacheSetAssociative=8;
- break;
- case 0x82: // Unified cache, 32 byte cache line, 8 way set associative, 256K
- L2CacheSize=256*1024;
- L2CacheLineSize=32;
- L2CacheSetAssociative=8;
- break;
- case 0x83: // Unified cache, 32 byte cache line, 8 way set associative, 512K
- L2CacheSize=512*1024;
- L2CacheLineSize=32;
- L2CacheSetAssociative=8;
- break;
- case 0x84: // Unified cache, 32 byte cache line, 8 way set associative, 1M
- L2CacheSize=1024*1024;
- L2CacheLineSize=32;
- L2CacheSetAssociative=8;
- break;
- case 0x85: // Unified cache, 32 byte cache line, 8 way set associative, 2M
- L2CacheSize=2048*1024;
- L2CacheLineSize=32;
- L2CacheSetAssociative=8;
- break;
- }
- }
- void CPUDetectClass::Process_Extended_Cache_Info()
- {
- CPUIDStruct max_ext(0x80000000);
- if (max_ext.Eax>=0x80000006) {
- CPUIDStruct l1info(0x80000005);
- CPUIDStruct l2info(0x80000006);
- // L1 data cache
- L1DataCacheLineSize=l1info.Ecx&0xff;
- L1DataCacheSetAssociative=(l1info.Ecx>>16)&0xff;
- L1DataCacheSize=((l1info.Ecx>>24)&0xff)*1024;
- // L1 instruction cache
- L1InstructionCacheLineSize=l1info.Edx&0xff;
- L1InstructionCacheSetAssociative=(l1info.Edx>>16)&0xff;
- L1InstructionCacheSize=((l1info.Edx>>24)&0xff)*1024;
- // L2 cache
- L2CacheSize=((l2info.Ecx>>16)&0xffff)*1024;
- L2CacheLineSize=l2info.Ecx&0xff;
- switch ((l2info.Ecx>>12)&0xf) {
- case 0: L2CacheSetAssociative=0; break;
- case 1: L2CacheSetAssociative=1; break;
- case 2: L2CacheSetAssociative=2; break;
- case 4: L2CacheSetAssociative=4; break;
- case 6: L2CacheSetAssociative=8; break;
- case 8: L2CacheSetAssociative=16; break;
- case 15: L2CacheSetAssociative=0xff; break;
- }
- }
- }
- void CPUDetectClass::Init_Cache()
- {
- CPUIDStruct cache_id(2);
- // This code can only determine cache sizes for cpuid count 1 (see Intel manuals for more info on the subject)
- if ((cache_id.Eax&0xff)==1) {
- if (!(cache_id.Eax&0x80000000)) {
- Process_Cache_Info((cache_id.Eax>>24)&0xff);
- Process_Cache_Info((cache_id.Eax>>16)&0xff);
- Process_Cache_Info((cache_id.Eax>>8)&0xff);
- }
- if (!(cache_id.Ebx&0x80000000)) {
- Process_Cache_Info((cache_id.Ebx>>24)&0xff);
- Process_Cache_Info((cache_id.Ebx>>16)&0xff);
- Process_Cache_Info((cache_id.Ebx>>8)&0xff);
- Process_Cache_Info((cache_id.Ebx)&0xff);
- }
- if (!(cache_id.Ecx&0x80000000)) {
- Process_Cache_Info((cache_id.Ecx>>24)&0xff);
- Process_Cache_Info((cache_id.Ecx>>16)&0xff);
- Process_Cache_Info((cache_id.Ecx>>8)&0xff);
- Process_Cache_Info((cache_id.Ecx)&0xff);
- }
- if (!(cache_id.Edx&0x80000000)) {
- Process_Cache_Info((cache_id.Edx>>24)&0xff);
- Process_Cache_Info((cache_id.Edx>>16)&0xff);
- Process_Cache_Info((cache_id.Edx>>8)&0xff);
- Process_Cache_Info((cache_id.Edx)&0xff);
- }
- }
- else {
- // If standard (Intel) cache information not found, try extended info.
- Process_Extended_Cache_Info();
- }
- }
- void CPUDetectClass::Init_Intel_Processor_Type()
- {
- switch (ProcessorFamily) {
- case 3:
- IntelProcessor=INTEL_PROCESSOR_80386;
- break;
- case 4:
- switch (ProcessorModel) {
- default:
- case 0:
- case 1:
- IntelProcessor=INTEL_PROCESSOR_80486DX;
- break;
- case 2:
- IntelProcessor=INTEL_PROCESSOR_80486SX;
- break;
- case 3:
- IntelProcessor=INTEL_PROCESSOR_80486DX2;
- break;
- case 4:
- IntelProcessor=INTEL_PROCESSOR_80486SL;
- break;
- case 5:
- IntelProcessor=INTEL_PROCESSOR_80486SX2;
- break;
- case 7:
- IntelProcessor=INTEL_PROCESSOR_80486DX2_WB;
- break;
- case 8:
- IntelProcessor=INTEL_PROCESSOR_80486DX4;
- break;
- case 9:
- IntelProcessor=INTEL_PROCESSOR_80486DX4_WB;
- break;
- }
- break;
- case 5:
- switch (ProcessorModel) {
- default:
- case 0:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM; // Early model
- break;
- case 1:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM; // 60/66, 5V
- break;
- case 2:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM; // 75+, 3.xV
- break;
- case 3:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_OVERDRIVE;
- break;
- case 4:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_MMX;
- break;
- case 5:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_OVERDRIVE;
- break;
- case 6:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_OVERDRIVE;
- break;
- case 7:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM;
- break;
- case 8:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_MMX;
- break;
- }
- case 6:
- switch (ProcessorModel) {
- default:
- case 0:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_PRO_SAMPLE;
- break;
- case 1:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_PRO;
- break;
- case 3:
- if (ProcessorType==0) {
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_II_MODEL_3;
- }
- else {
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_II_OVERDRIVE;
- }
- break;
- case 4:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_II_MODEL_4;
- break;
- case 5:
- // This one is either PII, PIIXeon or Celeron with no L2 cache!
- {
- CPUIDStruct cache_id(2);
- // TODO: Check for cache to determine processor type!
- if (L2CacheSize==0) {
- IntelProcessor=INTEL_PROCESSOR_CELERON_MODEL_5;
- }
- else if (L2CacheSize<=512*1024) { // If Xeon has 512k L2 cache we will assume a PII - tough luck!
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_II_MODEL_5;
- }
- else {
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_II_XEON_MODEL_5;
- }
- }
- break;
- case 6:
- IntelProcessor=INTEL_PROCESSOR_CELERON_MODEL_6;
- break;
- case 7:
- if (L2CacheSize<=512*1024) { // If Xeon has 512k L2 cache we will assume a PIII - tough luck!
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_III_MODEL_7;
- }
- else {
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_7;
- }
- break;
- case 8:
- // This could be PentiumIII Coppermine or Celeron with SSE, or a Xeon
- {
- CPUIDStruct brand(1);
- switch (brand.Ebx&0xff) {
- case 0x1: IntelProcessor=INTEL_PROCESSOR_CELERON_MODEL_8; break;
- case 0x2:
- case 0x4: IntelProcessor=INTEL_PROCESSOR_PENTIUM_III_MODEL_8; break;
- case 0x3:
- case 0xe: IntelProcessor=INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_8; break;
- }
- }
- break;
- case 0xa:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_A;
- break;
- case 0xb:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM_III_MODEL_B;
- break;
- }
- break;
- case 0xf:
- IntelProcessor=INTEL_PROCESSOR_PENTIUM4;
- break;
- }
- }
- void CPUDetectClass::Init_AMD_Processor_Type()
- {
- switch (ProcessorFamily) {
- case 4:
- switch (ProcessorModel) {
- case 3:
- AMDProcessor=AMD_PROCESSOR_486DX2;
- break;
- case 7:
- AMDProcessor=AMD_PROCESSOR_486DX4;
- break;
- case 8:
- AMDProcessor=AMD_PROCESSOR_486DX4;
- break;
- case 9:
- AMDProcessor=AMD_PROCESSOR_486DX4;
- break;
- case 0xe:
- AMDProcessor=AMD_PROCESSOR_5x86;
- break;
- case 0xf:
- AMDProcessor=AMD_PROCESSOR_5x86;
- break;
- default:
- AMDProcessor=AMD_PROCESSOR_486;
- }
- break;
- case 5:
- switch (ProcessorModel) {
- case 0:
- AMDProcessor=AMD_PROCESSOR_K5_MODEL0;
- break;
- case 1:
- AMDProcessor=AMD_PROCESSOR_K5_MODEL1;
- break;
- case 2:
- AMDProcessor=AMD_PROCESSOR_K5_MODEL2;
- break;
- case 3:
- AMDProcessor=AMD_PROCESSOR_K5_MODEL3;
- break;
- case 6:
- AMDProcessor=AMD_PROCESSOR_K6_MODEL6;
- break;
- case 7:
- AMDProcessor=AMD_PROCESSOR_K6_MODEL7;
- break;
- case 8:
- AMDProcessor=AMD_PROCESSOR_K6_2_3DNOW_MODEL8;
- break;
- case 9:
- AMDProcessor=AMD_PROCESSOR_K6_3_3DNOW_MODEL9;
- break;
- case 0xd:
- AMDProcessor=AMD_PROCESSOR_K6_3_PLUS;
- break;
- default:
- AMDProcessor=AMD_PROCESSOR_K6;
- }
- case 6:
- switch (ProcessorModel) {
- case 1:
- AMDProcessor=AMD_PROCESSOR_ATHLON_025;
- break;
- case 2:
- AMDProcessor=AMD_PROCESSOR_ATHLON_018;
- break;
- case 3:
- AMDProcessor=AMD_PROCESSOR_DURON;
- break;
- case 4:
- AMDProcessor=AMD_PROCESSOR_ATHLON_018_IL2;
- break;
- default:
- AMDProcessor=AMD_PROCESSOR_ATHLON;
- break;
- }
- }
- }
- void CPUDetectClass::Init_VIA_Processor_Type()
- {
- switch (ProcessorFamily) {
- case 5:
- switch (ProcessorModel) {
- case 4:
- VIAProcessor=VIA_PROCESSOR_IDT_C6_WINCHIP;
- break;
- case 8:
- VIAProcessor=VIA_PROCESSOR_IDT_C6_WINCHIP2;
- break;
- case 9:
- VIAProcessor=VIA_PROCESSOR_IDT_C6_WINCHIP3;
- break;
- }
- case 6:
- switch (ProcessorModel) {
- case 4:
- VIAProcessor=VIA_PROCESSOR_CYRIX_III_SAMUEL;
- break;
- }
- }
- }
- void CPUDetectClass::Init_Rise_Processor_Type()
- {
- switch (ProcessorFamily) {
- case 5:
- switch (ProcessorModel) {
- case 0:
- RiseProcessor=RISE_PROCESSOR_DRAGON_025;
- break;
- case 2:
- RiseProcessor=RISE_PROCESSOR_DRAGON_018;
- break;
- case 8:
- RiseProcessor=RISE_PROCESSOR_DRAGON2_025;
- break;
- case 9:
- RiseProcessor=RISE_PROCESSOR_DRAGON2_018;
- break;
- }
- }
- }
- void CPUDetectClass::Init_Processor_Family()
- {
- unsigned signature=0;
- unsigned notneeded1;
- unsigned notneeded2;
- unsigned features;
- CPUID(
- signature,
- notneeded1,
- notneeded2,
- features,
- 1);
- ProcessorType=(signature>>12)&0x0f;
- ProcessorFamily=(signature>>8)&0x0f;
- ProcessorModel=(signature>>4)&0x0f;
- ProcessorRevision=(signature)&0x0f;
- IntelProcessor=INTEL_PROCESSOR_UNKNOWN;
- AMDProcessor=AMD_PROCESSOR_UNKNOWN;
- VIAProcessor=VIA_PROCESSOR_UNKNOWN;
- RiseProcessor=RISE_PROCESSOR_UNKNOWN;
- Init_Cache();
- switch (ProcessorManufacturer) {
- case MANUFACTURER_INTEL:
- Init_Intel_Processor_Type();
- break;
- case MANUFACTURER_AMD:
- Init_AMD_Processor_Type();
- break;
- case MANUFACTURER_VIA:
- Init_VIA_Processor_Type();
- break;
- case MANUFACTURER_RISE:
- Init_Rise_Processor_Type();
- break;
- }
- }
- void CPUDetectClass::Init_Processor_String()
- {
- if (!Has_CPUID_Instruction()) {
- ProcessorString[0]='\0';
- }
- CPUIDStruct ext_id(0x80000000); // Check maximum extended cpuid level
- // if (ProcessorManufacturer==MANUFACTURER_INTEL && IntelProcessor<INTEL_PROCESSOR_PENTIUM4) {
- // ext_id.Eax=0; // No support for extended cpuid in Intel cpus prior to Pentium4
- // }
- // If extended cpuid level's highest bit is set, we'll get the cpu string from 2/3/4
- if (ext_id.Eax&0x80000000) {
- CPUDetectClass::CPUID(
- (unsigned&)ProcessorString[0],
- (unsigned&)ProcessorString[4],
- (unsigned&)ProcessorString[8],
- (unsigned&)ProcessorString[12],
- 0x80000002);
- CPUDetectClass::CPUID(
- (unsigned&)ProcessorString[16],
- (unsigned&)ProcessorString[20],
- (unsigned&)ProcessorString[24],
- (unsigned&)ProcessorString[28],
- 0x80000003);
- CPUDetectClass::CPUID(
- (unsigned&)ProcessorString[32],
- (unsigned&)ProcessorString[36],
- (unsigned&)ProcessorString[40],
- (unsigned&)ProcessorString[44],
- 0x80000004);
- }
- // If no extended cpuid available (Intel processors prior to P4), compose the string
- else {
- StringClass str(0,true);
- str=Get_Processor_Manufacturer_Name();
- if (ProcessorManufacturer==MANUFACTURER_INTEL) {
- str+=" ";
- switch (IntelProcessor) {
- default:
- case INTEL_PROCESSOR_UNKNOWN: str+="<UNKNOWN>"; break;
- case INTEL_PROCESSOR_80386: str+="80386"; break;
- case INTEL_PROCESSOR_80486DX: str+="80486DX"; break;
- case INTEL_PROCESSOR_80486SX: str+="80486SX"; break;
- case INTEL_PROCESSOR_80486DX2: str+="80486DX2"; break;
- case INTEL_PROCESSOR_80486SL: str+="80486SL"; break;
- case INTEL_PROCESSOR_80486SX2: str+="80486SX2"; break;
- case INTEL_PROCESSOR_80486DX2_WB: str+="80486DX2(WB)"; break;
- case INTEL_PROCESSOR_80486DX4: str+="80486DX4"; break;
- case INTEL_PROCESSOR_80486DX4_WB: str+="80486DX4(WB)"; break;
- case INTEL_PROCESSOR_PENTIUM: str+="Pentium"; break;
- case INTEL_PROCESSOR_PENTIUM_OVERDRIVE: str+="Pentium Overdrive"; break;
- case INTEL_PROCESSOR_PENTIUM_MMX: str+="Pentium MMX"; break;
- case INTEL_PROCESSOR_PENTIUM_PRO_SAMPLE: str+="Pentium Pro (Engineering Sample)"; break;
- case INTEL_PROCESSOR_PENTIUM_PRO: str+="Pentium Pro"; break;
- case INTEL_PROCESSOR_PENTIUM_II_OVERDRIVE: str+="Pentium II Overdrive"; break;
- case INTEL_PROCESSOR_PENTIUM_II_MODEL_3: str+="Pentium II, model 3"; break;
- case INTEL_PROCESSOR_PENTIUM_II_MODEL_4: str+="Pentium II, model 4"; break;
- case INTEL_PROCESSOR_CELERON_MODEL_5: str+="Celeron, model 5"; break;
- case INTEL_PROCESSOR_PENTIUM_II_MODEL_5: str+="Pentium II, model 5"; break;
- case INTEL_PROCESSOR_PENTIUM_II_XEON_MODEL_5: str+="Pentium II Xeon, model 5"; break;
- case INTEL_PROCESSOR_CELERON_MODEL_6: str+="Celeron, model 6"; break;
- case INTEL_PROCESSOR_PENTIUM_III_MODEL_7: str+="Pentium III, model 7"; break;
- case INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_7: str+="Pentium III Xeon, model 7"; break;
- case INTEL_PROCESSOR_CELERON_MODEL_8: str+="Celeron, model 8"; break;
- case INTEL_PROCESSOR_PENTIUM_III_MODEL_8: str+="Pentium III, model 8"; break;
- case INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_8: str+="Pentium III Xeon, model 8"; break;
- case INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_A: str+="Pentium III Xeon, model A"; break;
- case INTEL_PROCESSOR_PENTIUM_III_MODEL_B: str+="Pentium III, model B"; break;
- case INTEL_PROCESSOR_PENTIUM4: str+="Pentium4"; break;
- }
- }
- strncpy(ProcessorString,str.Peek_Buffer(),sizeof(ProcessorString));
- }
- }
- void CPUDetectClass::Init_CPUID_Instruction()
- {
- unsigned long cpuid_available=0;
- // The pushfd/popfd commands are done using emits
- // because CodeWarrior seems to have problems with
- // the command (huh?)
- __asm
- {
- mov cpuid_available,0 // clear flag
- push ebx
- pushfd
- pop eax
- mov ebx,eax
- xor eax,0x00200000
- push eax
- popfd
- pushfd
- pop eax
- xor eax,ebx
- je done
- mov cpuid_available,1
- done:
- push ebx
- popfd
- pop ebx
- }
- HasCPUIDInstruction=!!cpuid_available;
- }
- void CPUDetectClass::Init_Processor_Features()
- {
- if (!CPUDetectClass::Has_CPUID_Instruction()) return;
- CPUIDStruct id(1);
- FeatureBits=id.Edx;
- HasRDTSCInstruction=(!!(FeatureBits&(1<<4)));
- HasCMOVSupport=(!!(FeatureBits&(1<<15)));
- HasMMXSupport=(!!(FeatureBits&(1<<23)));
- HasSSESupport=!!(FeatureBits&(1<<25));
- HasSSE2Support=!!(FeatureBits&(1<<26));
- Has3DNowSupport=false;
- ExtendedFeatureBits=0;
- if (ProcessorManufacturer==MANUFACTURER_AMD) {
- if (Has_CPUID_Instruction()) {
- CPUIDStruct max_ext_id(0x80000000);
- if (max_ext_id.Eax>=0x80000001) { // Signature & features field available?
- CPUIDStruct ext_signature(0x80000001);
- ExtendedFeatureBits=ext_signature.Edx;
- Has3DNowSupport=!!(ExtendedFeatureBits&0x80000000);
- HasExtended3DNowSupport=!!(ExtendedFeatureBits&0x40000000);
- }
- }
- }
- }
- void CPUDetectClass::Init_Memory()
- {
- MEMORYSTATUS mem;
- GlobalMemoryStatus(&mem);
- TotalPhysicalMemory=mem.dwTotalPhys;
- AvailablePhysicalMemory=mem.dwAvailPhys;
- TotalPageMemory=mem.dwTotalPageFile;
- AvailablePageMemory=mem.dwAvailPageFile;
- TotalVirtualMemory=mem.dwTotalVirtual;
- AvailableVirtualMemory=mem.dwAvailVirtual;
- }
- void CPUDetectClass::Init_OS()
- {
- OSVERSIONINFO os;
- os.dwOSVersionInfoSize=sizeof(os);
- GetVersionEx(&os);
- OSVersionNumberMajor=os.dwMajorVersion;
- OSVersionNumberMinor=os.dwMinorVersion;
- OSVersionBuildNumber=os.dwBuildNumber;
- OSVersionPlatformId=os.dwPlatformId;
- OSVersionExtraInfo=os.szCSDVersion;
- }
- bool CPUDetectClass::CPUID(
- unsigned& u_eax_,
- unsigned& u_ebx_,
- unsigned& u_ecx_,
- unsigned& u_edx_,
- unsigned cpuid_type)
- {
- if (!Has_CPUID_Instruction()) return false; // Most processors since 486 have CPUID...
- unsigned u_eax;
- unsigned u_ebx;
- unsigned u_ecx;
- unsigned u_edx;
- __asm
- {
- pushad
- mov eax,[cpuid_type]
- xor ebx,ebx
- xor ecx,ecx
- xor edx,edx
- cpuid
- mov [u_eax],eax
- mov [u_ebx],ebx
- mov [u_ecx],ecx
- mov [u_edx],edx
- popad
- }
- u_eax_=u_eax;
- u_ebx_=u_ebx;
- u_ecx_=u_ecx;
- u_edx_=u_edx;
- return true;
- }
- #define SYSLOG(n) work.Format n ; CPUDetectClass::ProcessorLog+=work;
- void CPUDetectClass::Init_Processor_Log()
- {
- StringClass work(0,true);
- SYSLOG(("Operating System: "));
- switch (OSVersionPlatformId) {
- case VER_PLATFORM_WIN32s: SYSLOG(("Windows 3.1")); break;
- case VER_PLATFORM_WIN32_WINDOWS: SYSLOG(("Windows 9x")); break;
- case VER_PLATFORM_WIN32_NT: SYSLOG(("Windows NT")); break;
- }
- SYSLOG(("\r\n"));
- SYSLOG(("Operating system version %d.%d\r\n",OSVersionNumberMajor,OSVersionNumberMinor));
- SYSLOG(("Operating system build: %d.%d.%d\r\n",
- (OSVersionBuildNumber&0xff000000)>>24,
- (OSVersionBuildNumber&0xff0000)>>16,
- (OSVersionBuildNumber&0xffff)));
- SYSLOG(("OS-Info: %s\r\n",OSVersionExtraInfo));
- SYSLOG(("Processor: %s\r\n",CPUDetectClass::Get_Processor_String()));
- SYSLOG(("Clock speed: ~%dMHz\r\n",CPUDetectClass::Get_Processor_Speed()));
- StringClass cpu_type(0,true);
- switch (CPUDetectClass::Get_Processor_Type()) {
- case 0: cpu_type="Original OEM"; break;
- case 1: cpu_type="Overdrive"; break;
- case 2: cpu_type="Dual"; break;
- case 3: cpu_type="*Intel Reserved*"; break;
- }
- SYSLOG(("Processor type: %s\r\n",cpu_type));
- SYSLOG(("\r\n"));
- SYSLOG(("Total physical memory: %dMb\r\n",Get_Total_Physical_Memory()/(1024*1024)));
- SYSLOG(("Available physical memory: %dMb\r\n",Get_Available_Physical_Memory()/(1024*1024)));
- SYSLOG(("Total page file size: %dMb\r\n",Get_Total_Page_File_Size()/(1024*1024)));
- SYSLOG(("Total available page file size: %dMb\r\n",Get_Available_Page_File_Size()/(1024*1024)));
- SYSLOG(("Total virtual memory: %dMb\r\n",Get_Total_Virtual_Memory()/(1024*1024)));
- SYSLOG(("Available virtual memory: %dMb\r\n",Get_Available_Virtual_Memory()/(1024*1024)));
- SYSLOG(("\r\n"));
- SYSLOG(("CPUID: %s\r\n",CPUDetectClass::Has_CPUID_Instruction() ? "Yes" : "No"));
- SYSLOG(("RDTSC: %s\r\n",CPUDetectClass::Has_RDTSC_Instruction() ? "Yes" : "No"));
- SYSLOG(("CMOV: %s\r\n",CPUDetectClass::Has_CMOV_Instruction() ? "Yes" : "No"));
- SYSLOG(("MMX: %s\r\n",CPUDetectClass::Has_MMX_Instruction_Set() ? "Yes" : "No"));
- SYSLOG(("SSE: %s\r\n",CPUDetectClass::Has_SSE_Instruction_Set() ? "Yes" : "No"));
- SYSLOG(("SSE2: %s\r\n",CPUDetectClass::Has_SSE2_Instruction_Set() ? "Yes" : "No"));
- SYSLOG(("3DNow!: %s\r\n",CPUDetectClass::Has_3DNow_Instruction_Set() ? "Yes" : "No"));
- SYSLOG(("Extended 3DNow!: %s\r\n",CPUDetectClass::Has_Extended_3DNow_Instruction_Set() ? "Yes" : "No"));
- SYSLOG(("CPU Feature bits: 0x%x\r\n",CPUDetectClass::Get_Feature_Bits()));
- SYSLOG(("Ext. CPU Feature bits: 0x%x\r\n",CPUDetectClass::Get_Extended_Feature_Bits()));
- SYSLOG(("\r\n"));
- if (CPUDetectClass::Get_L1_Data_Cache_Size()) {
- SYSLOG(("L1 Data Cache: %d byte cache lines, %d way set associative, %dk\r\n",
- CPUDetectClass::Get_L1_Data_Cache_Line_Size(),
- CPUDetectClass::Get_L1_Data_Cache_Set_Associative(),
- CPUDetectClass::Get_L1_Data_Cache_Size()/1024));
- }
- else {
- SYSLOG(("L1 Data Cache: None\r\n"));
- }
- if (CPUDetectClass::Get_L1_Instruction_Cache_Size()) {
- SYSLOG(("L1 Instruction Cache: %d byte cache lines, %d way set associative, %dk\r\n",
- CPUDetectClass::Get_L1_Instruction_Cache_Line_Size(),
- CPUDetectClass::Get_L1_Instruction_Cache_Set_Associative(),
- CPUDetectClass::Get_L1_Instruction_Cache_Size()/1024));
- }
- else {
- SYSLOG(("L1 Instruction Cache: None\r\n"));
- }
- if (CPUDetectClass::Get_L1_Instruction_Trace_Cache_Size()) {
- SYSLOG(("L1 Instruction Trace Cache: %d way set associative, %dk µOPs\r\n",
- CPUDetectClass::Get_L1_Instruction_Cache_Set_Associative(),
- CPUDetectClass::Get_L1_Instruction_Cache_Size()/1024));
- }
- else {
- SYSLOG(("L1 Instruction Trace Cache: None\r\n"));
- }
- if (CPUDetectClass::Get_L2_Cache_Size()) {
- SYSLOG(("L2 Cache: %d byte cache lines, %d way set associative, %dk\r\n",
- CPUDetectClass::Get_L2_Cache_Line_Size(),
- CPUDetectClass::Get_L2_Cache_Set_Associative(),
- CPUDetectClass::Get_L2_Cache_Size()/1024));
- }
- else {
- SYSLOG(("L2 cache: None\r\n"));
- }
- SYSLOG(("\r\n"));
- }
- // OSCODE OSSUBCODE CPUMANUFACTURER CPUSPEED MEMORY CPUBITS EXTCPUBITS
- #define COMPACTLOG(n) work.Format n ; CPUDetectClass::CompactLog+=work;
- void CPUDetectClass::Init_Compact_Log()
- {
- StringClass work(0,true);
- TIME_ZONE_INFORMATION time_zone;
- GetTimeZoneInformation(&time_zone);
- COMPACTLOG(("%d\t",time_zone.Bias));
- OSInfoStruct os_info;
- Get_OS_Info(os_info,OSVersionPlatformId,OSVersionNumberMajor,OSVersionNumberMinor,OSVersionBuildNumber);
- COMPACTLOG(("%s\t",os_info.Code));
- if (!stricmp(os_info.SubCode,"UNKNOWN")) {
- COMPACTLOG(("%d\t",OSVersionBuildNumber&0xffff));
- }
- else {
- COMPACTLOG(("%s\t",os_info.SubCode));
- }
- COMPACTLOG(("%s\t%d\t",Get_Processor_Manufacturer_Name(),Get_Processor_Speed()));
- COMPACTLOG(("%d\t",Get_Total_Physical_Memory()/(1024*1024)+1));
- COMPACTLOG(("%x\t%x\t",Get_Feature_Bits(),Get_Extended_Feature_Bits()));
- }
- static class CPUDetectInitClass
- {
- public:
- CPUDetectInitClass::CPUDetectInitClass()
- {
- CPUDetectClass::Init_CPUID_Instruction();
- // We pretty much need CPUID, but let's not crash if it doesn't exist.
- // Every processor our games run should have CPUID so it would be extremely unlikely for it not to be present.
- // One can never be sure about the clones though...
- if (CPUDetectClass::Has_CPUID_Instruction()) {
- CPUDetectClass::Init_Processor_Manufacturer();
- CPUDetectClass::Init_Processor_Family();
- CPUDetectClass::Init_Processor_String();
- CPUDetectClass::Init_Processor_Features();
- CPUDetectClass::Init_Memory();
- CPUDetectClass::Init_OS();
- }
- CPUDetectClass::Init_Processor_Speed();
- CPUDetectClass::Init_Processor_Log();
- CPUDetectClass::Init_Compact_Log();
- }
- } _CPU_Detect_Init;
- OSInfoStruct Windows9xVersionTable[]={
- {"WIN95", "FINAL", "Windows 95", 4,0,950, 4,0,950 },
- {"WIN95", "A", "Windows 95a OSR1 final Update", 4,0,950, 4,0,951 },
- {"WIN95", "B20OEM", "Windows 95B OSR 2.0 final OEM", 4,0,950, 4,0,1111 },
- {"WIN95", "B20UPD", "Windows 95B OSR 2.1 final Update", 4,0,950, 4,3,1212 },
- {"WIN95", "B21OEM", "Windows 95B OSR 2.1 final OEM", 4,1,971, 4,1,971 },
- {"WIN95", "C25OEM", "Windows 95C OSR 2.5 final OEM", 4,0,950, 4,3,1214 },
- {"WIN98", "BETAPRD", "Windows 98 Beta pre-DR", 4,10,1351, 4,10,1351 },
- {"WIN98", "BETADR", "Windows 98 Beta DR", 4,10,1358, 4,10,1358 },
- {"WIN98", "BETAE", "Windows 98 early Beta", 4,10,1378, 4,10,1378 },
- {"WIN98", "BETAE", "Windows 98 early Beta", 4,10,1410, 4,10,1410 },
- {"WIN98", "BETAE", "Windows 98 early Beta", 4,10,1423, 4,10,1423 },
- {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1500, 4,10,1500 },
- {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1508, 4,10,1508 },
- {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1511, 4,10,1511 },
- {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1525, 4,10,1525 },
- {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1535, 4,10,1535 },
- {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1538, 4,10,1538 },
- {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1543, 4,10,1543 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1544, 4,10,1544 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1546, 4,10,1546 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1550, 4,10,1550 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1559, 4,10,1559 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1564, 4,10,1564 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1569, 4,10,1569 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1577, 4,10,1577 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1581, 4,10,1581 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1593, 4,10,1593 },
- {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1599, 4,10,1599 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1602, 4,10,1602 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1605, 4,10,1605 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1614, 4,10,1614 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1619, 4,10,1619 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1624, 4,10,1624 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1629, 4,10,1629 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1633, 4,10,1633 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1650, 4,10,1650 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1650,/*,3*/4,10,1650/*,3*/ },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1650,/*,8*/4,10,1650/*,8*/ },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1666, 4,10,1666 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1671, 4,10,1671 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1677, 4,10,1677 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1681, 4,10,1681 },
- {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1687, 4,10,1687 },
- {"WIN98", "RC0", "Windows 98 RC0", 4,10,1691, 4,10,1691 },
- {"WIN98", "RC0", "Windows 98 RC0", 4,10,1702, 4,10,1702 },
- {"WIN98", "RC0", "Windows 98 RC0", 4,10,1708, 4,10,1708 },
- {"WIN98", "RC0", "Windows 98 RC0", 4,10,1713, 4,10,1713 },
- {"WIN98", "RC1", "Windows 98 RC1", 4,10,1721,/*,3*/4,10,1721/*,3*/ },
- {"WIN98", "RC2", "Windows 98 RC2", 4,10,1723,/*,4*/4,10,1723/*,4*/ },
- {"WIN98", "RC2", "Windows 98 RC2", 4,10,1726, 4,10,1726 },
- {"WIN98", "RC3", "Windows 98 RC3", 4,10,1900,/*,5*/4,10,1900/*,5*/ },
- {"WIN98", "RC4", "Windows 98 RC4", 4,10,1900,/*,8*/4,10,1900/*,8*/ },
- {"WIN98", "RC5", "Windows 98 RC5", 4,10,1998, 4,10,1998 },
- {"WIN98", "FINAL", "Windows 98", 4,10,1998,/*,6*/4,10,1998/*,6*/ },
- {"WIN98", "SP1B1", "Windows 98 SP1 Beta 1", 4,10,2088, 4,10,2088 },
- {"WIN98", "OSR1B1", "Windows 98 OSR1 Beta 1", 4,10,2106, 4,10,2106 },
- {"WIN98", "OSR1B1", "Windows 98 OSR1 Beta 1", 4,10,2120, 4,10,2120 },
- {"WIN98", "OSR1B1", "Windows 98 OSR1 Beta 1", 4,10,2126, 4,10,2126 },
- {"WIN98", "OSR1B1", "Windows 98 OSR1 Beta 1", 4,10,2131, 4,10,2131 },
- {"WIN98", "SP1B2", "Windows 98 SP1 Beta 2", 4,10,2150,/*,0*/4,10,2150/*,0*/ },
- {"WIN98", "SP1B2", "Windows 98 SP1 Beta 2", 4,10,2150,/*,4*/4,10,2150/*,4*/ },
- {"WIN98", "SP1", "Windows 98 SP1 final Update", 4,10,2000, 4,10,2000 },
- {"WIN98", "OSR1B2", "Windows 98 OSR1 Beta 2", 4,10,2174, 4,10,2174 },
- {"WIN98", "SERC1", "Windows 98 SE RC1", 4,10,2183, 4,10,2183 },
- {"WIN98", "SERC2", "Windows 98 SE RC2", 4,10,2185, 4,10,2185 },
- {"WIN98", "SE", "Windows 98 SE", 4,10,2222, 4,10,2222/*,3*/ },
- {"WINME", "MEBDR1", "Windows ME Beta DR1", 4,90,2332, 4,90,2332 },
- {"WINME", "MEBDR2", "Windows ME Beta DR2", 4,90,2348, 4,90,2348 },
- {"WINME", "MEBDR3", "Windows ME Beta DR3", 4,90,2358, 4,90,2358 },
- {"WINME", "MEBDR4", "Windows ME Beta DR4", 4,90,2363, 4,90,2363 },
- {"WINME", "MEEB", "Windows ME early Beta", 4,90,2368, 4,90,2368 },
- {"WINME", "MEEB", "Windows ME early Beta", 4,90,2374, 4,90,2374 },
- {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2380, 4,90,2380 },
- {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2394, 4,90,2394 },
- {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2399, 4,90,2399 },
- {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2404, 4,90,2404 },
- {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2410, 4,90,2410 },
- {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2416, 4,90,2416 },
- {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2419,/*,4*/4,90,2419/*,4*/ },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2429, 4,90,2429 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2434, 4,90,2434 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2443, 4,90,2443 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2447, 4,90,2447 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2455, 4,90,2455 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2460, 4,90,2460 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2465, 4,90,2465 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2470, 4,90,2470 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2474, 4,90,2474 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2481, 4,90,2481 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2487, 4,90,2487 },
- {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2491, 4,90,2491 },
- {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2499, 4,90,2499 },
- {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2499,/*,3*/4,90,2499/*,3*/ },
- {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2509, 4,90,2509 },
- {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2513, 4,90,2513 },
- {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2516, 4,90,2516 },
- {"WINME", "RC0", "Windows ME RC0", 4,90,2525, 4,90,2525 },
- {"WINME", "RC1", "Windows ME RC1", 4,90,2525,/*,6*/4,90,2525/*,6*/ },
- {"WINME", "RC2", "Windows ME RC2", 4,90,2535, 4,90,2535 },
- {"WINME", "FINAL", "Windows ME", 4,90,3000,/*,2*/4,90,3000/*,2*/ },
- };
- void Get_OS_Info(
- OSInfoStruct& os_info,
- unsigned OSVersionPlatformId,
- unsigned OSVersionNumberMajor,
- unsigned OSVersionNumberMinor,
- unsigned OSVersionBuildNumber)
- {
- unsigned build_major=(OSVersionBuildNumber&0xff000000)>>24;
- unsigned build_minor=(OSVersionBuildNumber&0xff0000)>>16;
- unsigned build_sub=(OSVersionBuildNumber&0xffff);
- switch (OSVersionPlatformId) {
- default:
- memset(&os_info,0,sizeof(os_info));
- os_info.Code="UNKNOWN";
- os_info.SubCode="UNKNOWN";
- os_info.VersionString="UNKNOWN";
- break;
- case VER_PLATFORM_WIN32_WINDOWS:
- {
- for(int i=0;i<sizeof(Windows9xVersionTable)/sizeof(os_info);++i) {
- if (
- Windows9xVersionTable[i].VersionMajor==OSVersionNumberMajor &&
- Windows9xVersionTable[i].VersionMinor==OSVersionNumberMinor &&
- Windows9xVersionTable[i].BuildMajor==build_major &&
- Windows9xVersionTable[i].BuildMinor==build_minor &&
- Windows9xVersionTable[i].BuildSub==build_sub) {
- os_info=Windows9xVersionTable[i];
- return;
- }
- }
- os_info.BuildMajor=build_major;
- os_info.BuildMinor=build_minor;
- os_info.BuildSub=build_sub;
- if (OSVersionNumberMajor==4) {
- // os_info.SubCode.Format("%d",build_sub);
- os_info.SubCode="UNKNOWN";
- if (OSVersionNumberMinor==0) {
- os_info.Code="WIN95";
- return;
- }
- if (OSVersionNumberMinor==10) {
- os_info.Code="WIN98";
- return;
- }
- if (OSVersionNumberMinor==90) {
- os_info.Code="WINME";
- return;
- }
- os_info.Code="WIN9X";
- return;
- }
- }
- break;
- case VER_PLATFORM_WIN32_NT:
- // os_info.SubCode.Format("%d",build_sub);
- os_info.SubCode="UNKNOWN";
- if (OSVersionNumberMajor==4) {
- os_info.Code="WINNT";
- return;
- }
- if (OSVersionNumberMajor==5) {
- if (OSVersionNumberMinor==0) {
- os_info.Code="WIN2K";
- return;
- }
- if (OSVersionNumberMinor==1) {
- os_info.Code="WINXP";
- return;
- }
- os_info.Code="WINXX";
- return;
- }
- }
- }
|