Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
cpudetect.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include "cpudetect.h"
20#include "wwstring.h"
21#include "wwdebug.h"
22#include "thread.h"
23#include "mpu.h"
24#pragma warning (disable : 4201) // Nonstandard extension - nameless struct
25#include <windows.h>
26#include "systimer.h"
27
28#ifdef _UNIX
29# include <time.h> // for time(), localtime() and timezone variable.
30#endif
31
33 const char* Code;
34 const char* SubCode;
35 const char* VersionString;
36 unsigned char VersionMajor;
37 unsigned char VersionMinor;
38 unsigned short VersionSub;
39 unsigned char BuildMajor;
40 unsigned char BuildMinor;
41 unsigned short BuildSub;
42};
43
44static void Get_OS_Info(
45 OSInfoStruct& os_info,
46 unsigned OSVersionPlatformId,
47 unsigned OSVersionNumberMajor,
48 unsigned OSVersionNumberMinor,
49 unsigned OSVersionBuildNumber);
50
51
52StringClass CPUDetectClass::ProcessorLog;
53StringClass CPUDetectClass::CompactLog;
54
55int CPUDetectClass::ProcessorType;
56int CPUDetectClass::ProcessorFamily;
57int CPUDetectClass::ProcessorModel;
58int CPUDetectClass::ProcessorRevision;
59int CPUDetectClass::ProcessorSpeed;
60__int64 CPUDetectClass::ProcessorTicksPerSecond; // Ticks per second
61double CPUDetectClass::InvProcessorTicksPerSecond; // 1.0 / Ticks per second
62
63unsigned CPUDetectClass::FeatureBits;
64unsigned CPUDetectClass::ExtendedFeatureBits;
65
66unsigned CPUDetectClass::L2CacheSize;
67unsigned CPUDetectClass::L2CacheLineSize;
68unsigned CPUDetectClass::L2CacheSetAssociative;
69unsigned CPUDetectClass::L1DataCacheSize;
70unsigned CPUDetectClass::L1DataCacheLineSize;
71unsigned CPUDetectClass::L1DataCacheSetAssociative;
72unsigned CPUDetectClass::L1InstructionCacheSize;
73unsigned CPUDetectClass::L1InstructionCacheLineSize;
74unsigned CPUDetectClass::L1InstructionCacheSetAssociative;
75unsigned CPUDetectClass::L1InstructionTraceCacheSize;
76unsigned CPUDetectClass::L1InstructionTraceCacheSetAssociative;
77
78unsigned CPUDetectClass::TotalPhysicalMemory;
79unsigned CPUDetectClass::AvailablePhysicalMemory;
80unsigned CPUDetectClass::TotalPageMemory;
81unsigned CPUDetectClass::AvailablePageMemory;
82unsigned CPUDetectClass::TotalVirtualMemory;
83unsigned CPUDetectClass::AvailableVirtualMemory;
84
85unsigned CPUDetectClass::OSVersionNumberMajor;
86unsigned CPUDetectClass::OSVersionNumberMinor;
87unsigned CPUDetectClass::OSVersionBuildNumber;
88unsigned CPUDetectClass::OSVersionPlatformId;
89StringClass CPUDetectClass::OSVersionExtraInfo;
90
91bool CPUDetectClass::HasCPUIDInstruction=false;
92bool CPUDetectClass::HasRDTSCInstruction=false;
93bool CPUDetectClass::HasSSESupport=false;
94bool CPUDetectClass::HasSSE2Support=false;
95bool CPUDetectClass::HasCMOVSupport=false;
96bool CPUDetectClass::HasMMXSupport=false;
97bool CPUDetectClass::Has3DNowSupport=false;
98bool CPUDetectClass::HasExtended3DNowSupport=false;
99
101CPUDetectClass::IntelProcessorType CPUDetectClass::IntelProcessor;
102CPUDetectClass::AMDProcessorType CPUDetectClass::AMDProcessor;
103CPUDetectClass::VIAProcessorType CPUDetectClass::VIAProcessor;
104CPUDetectClass::RiseProcessorType CPUDetectClass::RiseProcessor;
105
106char CPUDetectClass::VendorID[20];
107char CPUDetectClass::ProcessorString[48];
108
110{
111 static const char* ManufacturerNames[] = {
112 "<Unknown>",
113 "Intel",
114 "UMC",
115 "AMD",
116 "Cyrix",
117 "NextGen",
118 "VIA",
119 "Rise",
120 "Transmeta"
121 };
122
123 return ManufacturerNames[ProcessorManufacturer];
124}
125
126#define ASM_RDTSC _asm _emit 0x0f _asm _emit 0x31
127
128static unsigned Calculate_Processor_Speed(__int64& ticks_per_second)
129{
130 struct {
131 unsigned timer0_h;
132 unsigned timer0_l;
133 unsigned timer1_h;
134 unsigned timer1_l;
135 } Time;
136
137#ifdef WIN32
138 __asm {
139 ASM_RDTSC;
140 mov Time.timer0_h, eax
141 mov Time.timer0_l, edx
142 }
143#elif defined(_UNIX)
144 __asm__("rdtsc");
145 __asm__("mov %eax, __Time.timer1_h");
146 __asm__("mov %edx, __Time.timer1_l");
147#endif
148
149 unsigned start=TIMEGETTIME();
150 unsigned elapsed;
151 while ((elapsed=TIMEGETTIME()-start)<200) {
152#ifdef WIN32
153 __asm {
154 ASM_RDTSC;
155 mov Time.timer1_h, eax
156 mov Time.timer1_l, edx
157 }
158#elif defined(_UNIX)
159 __asm__ ("rdtsc");
160 __asm__("mov %eax, __Time.timer1_h");
161 __asm__("mov %edx, __Time.timer1_l");
162#endif
163 }
164
165 __int64 t=*(__int64*)&Time.timer1_h-*(__int64*)&Time.timer0_h;
166 ticks_per_second=(__int64)((1000.0/(double)elapsed)*(double)t); // Ticks per second
167 return unsigned((double)t/(double)(elapsed*1000));
168}
169
170void CPUDetectClass::Init_Processor_Speed()
171{
172 if (!Has_RDTSC_Instruction()) {
173 ProcessorSpeed=0;
174 return;
175 }
176
177 // Loop until two subsequent samples are within 5% of each other (max 5 iterations).
178 unsigned speed1=Calculate_Processor_Speed(ProcessorTicksPerSecond);
179 unsigned total_speed=speed1;
180 for (int i=0;i<5;++i) {
181 unsigned speed2=Calculate_Processor_Speed(ProcessorTicksPerSecond);
182 float rel=float(speed1)/float(speed2);
183 if (rel>=0.95f && rel<=1.05f) {
184 ProcessorSpeed=(speed1+speed2)/2;
185 InvProcessorTicksPerSecond=1.0/double(ProcessorTicksPerSecond);
186 return;
187 }
188 speed1=speed2;
189 total_speed+=speed2;
190 }
191 // If no two subsequent samples where close enough, use intermediate
192 ProcessorSpeed=total_speed/6;
193 InvProcessorTicksPerSecond=1.0/double(ProcessorTicksPerSecond);
194}
195
196void CPUDetectClass::Init_Processor_Manufacturer()
197{
198 VendorID[0] = 0;
199 unsigned max_cpuid;
200 CPUID(
201 max_cpuid,
202 (unsigned&)VendorID[0],
203 (unsigned&)VendorID[8],
204 (unsigned&)VendorID[4],
205 0);
206
207 ProcessorManufacturer = MANUFACTURER_UNKNOWN;
208
209 if (stricmp(VendorID, "GenuineIntel") == 0) ProcessorManufacturer = MANUFACTURER_INTEL;
210 else if (stricmp(VendorID, "AuthenticAMD") == 0) ProcessorManufacturer = MANUFACTURER_AMD;
211 else if (stricmp(VendorID, "AMD ISBETTER") == 0) ProcessorManufacturer = MANUFACTURER_AMD;
212 else if (stricmp(VendorID, "UMC UMC UMC") == 0) ProcessorManufacturer = MANUFACTURER_UMC;
213 else if (stricmp(VendorID, "CyrixInstead") == 0) ProcessorManufacturer = MANUFACTURER_CYRIX;
214 else if (stricmp(VendorID, "NexGenDriven") == 0) ProcessorManufacturer = MANUFACTURER_NEXTGEN;
215 else if (stricmp(VendorID, "CentaurHauls") == 0) ProcessorManufacturer = MANUFACTURER_VIA;
216 else if (stricmp(VendorID, "RiseRiseRise") == 0) ProcessorManufacturer = MANUFACTURER_RISE;
217 else if (stricmp(VendorID, "GenuineTMx86") == 0) ProcessorManufacturer = MANUFACTURER_TRANSMETA;
218}
219
220void CPUDetectClass::Process_Cache_Info(unsigned value)
221{
222 switch (value) {
223 case 0x00: // Null
224 break;
225 case 0x01: // Instruction TLB, 4K pages, 4-way set associative, 32 entries
226 break;
227 case 0x02: // Instruction TLB, 4M pages, fully associative, 2 entries
228 break;
229 case 0x03: // Data TLB, 4K pages, 4-way set associative, 64 entries
230 break;
231 case 0x04: // Data TLB, 4M pages, 4-way set associative, 8 entries
232 break;
233 case 0x06: // Instruction cache, 8K, 4-way set associative, 32 byte line size
234 L1InstructionCacheSize=8*1024;
235 L1InstructionCacheLineSize=32;
236 L1InstructionCacheSetAssociative=4;
237 break;
238 case 0x08: // Instruction cache 16K, 4-way set associative, 32 byte line size
239 L1InstructionCacheSize=16*1024;
240 L1InstructionCacheLineSize=32;
241 L1InstructionCacheSetAssociative=4;
242 break;
243 case 0x0A: // Data cache, 8K, 2-way set associative, 32 byte line size
244 L1DataCacheSize=8*1024;
245 L1DataCacheLineSize=32;
246 L1DataCacheSetAssociative=2;
247 break;
248 case 0x0C: // Data cache, 16K, 4-way set associative, 32 byte line size
249 L1DataCacheSize=16*1024;
250 L1DataCacheLineSize=32;
251 L1DataCacheSetAssociative=4;
252 break;
253 case 0x40: // No L2 cache (P6 family), or No L3 cache (Pentium 4 processor)
254 // Nice of Intel, Pentium4 has an exception and this field is defined as "no L3 cache"
255 if (ProcessorManufacturer==MANUFACTURER_INTEL && ProcessorFamily==0xf) {
256 }
257 else {
258 L2CacheSize=0;
259 L2CacheLineSize=0;
260 L2CacheSetAssociative=0;
261 }
262 break;
263 case 0x41: // Unified cache, 32 byte cache line,4-way set associative, 128K
264 L2CacheSize=128*1024;
265 L2CacheLineSize=32;
266 L2CacheSetAssociative=4;
267 break;
268 case 0x42: // Unified cache, 32 byte cache line, 4-way set associative, 256K
269 L2CacheSize=256*1024;
270 L2CacheLineSize=32;
271 L2CacheSetAssociative=4;
272 break;
273 case 0x43: // Unified cache, 32 byte cache line, 4-way set associative, 512K
274 L2CacheSize=512*1024;
275 L2CacheLineSize=32;
276 L2CacheSetAssociative=4;
277 break;
278 case 0x44: // Unified cache, 32 byte cache line, 4-way set associative, 1M
279 L2CacheSize=1024*1024;
280 L2CacheLineSize=32;
281 L2CacheSetAssociative=4;
282 break;
283 case 0x45: // Unified cache, 32 byte cache line, 4-way set associative, 2M
284 L2CacheSize=2048*1024;
285 L2CacheLineSize=32;
286 L2CacheSetAssociative=4;
287 break;
288 case 0x50: // Instruction TLB, 4K, 2M or 4M pages, fully associative, 64 entries
289 break;
290 case 0x51: // Instruction TLB, 4K, 2M or 4M pages, fully associative, 128 entries
291 break;
292 case 0x52: // Instruction TLB, 4K, 2M or 4M pages, fully associative, 256 entries
293 break;
294 case 0x5B: // Data TLB, 4K or 4M pages, fully associative, 64 entries
295 break;
296 case 0x5C: // Data TLB, 4K or 4M pages, fully associative, 128 entries
297 break;
298 case 0x5D: // Data TLB, 4K or 4M pages, fully associative, 256 entries
299 break;
300 case 0x66: // Data cache, sectored, 64 byte cache line, 4 way set associative, 8K
301 L1DataCacheSize=8*1024;
302 L1DataCacheLineSize=64;
303 L1DataCacheSetAssociative=4;
304 break;
305 case 0x67: // Data cache, sectored, 64 byte cache line, 4 way set associative, 16K
306 L1DataCacheSize=16*1024;
307 L1DataCacheLineSize=64;
308 L1DataCacheSetAssociative=4;
309 break;
310 case 0x68: // Data cache, sectored, 64 byte cache line, 4 way set associative, 32K
311 L1DataCacheSize=32*1024;
312 L1DataCacheLineSize=64;
313 L1DataCacheSetAssociative=4;
314 break;
315 case 0x70: // Instruction Trace cache, 8 way set associative, 12K uOps
316 L1InstructionTraceCacheSize=12*1024;
317 L1InstructionTraceCacheSetAssociative=8;
318 break;
319 case 0x71: // Instruction Trace cache, 8 way set associative, 16K uOps
320 L1InstructionTraceCacheSize=16*1024;
321 L1InstructionTraceCacheSetAssociative=8;
322 break;
323 case 0x72: // Instruction Trace cache, 8 way set associative, 32K uOps
324 L1InstructionTraceCacheSize=32*1024;
325 L1InstructionTraceCacheSetAssociative=8;
326 break;
327 case 0x79: // Unified cache, sectored, 64 byte cache line, 8 way set associative, 128K
328 L2CacheSize=128*1024;
329 L2CacheLineSize=64;
330 L2CacheSetAssociative=8;
331 break;
332 case 0x7A: // Unified cache, sectored, 64 byte cache line, 8 way set associative, 256K
333 L2CacheSize=256*1024;
334 L2CacheLineSize=64;
335 L2CacheSetAssociative=8;
336 break;
337 case 0x7B: // Unified cache, sectored, 64 byte cache line, 8 way set associative, 512K
338 L2CacheSize=512*1024;
339 L2CacheLineSize=64;
340 L2CacheSetAssociative=8;
341 break;
342 case 0x7C: // Unified cache, sectored, 64 byte cache line, 8 way set associative, 1M
343 L2CacheSize=1024*1024;
344 L2CacheLineSize=64;
345 L2CacheSetAssociative=8;
346 break;
347 case 0x82: // Unified cache, 32 byte cache line, 8 way set associative, 256K
348 L2CacheSize=256*1024;
349 L2CacheLineSize=32;
350 L2CacheSetAssociative=8;
351 break;
352 case 0x83: // Unified cache, 32 byte cache line, 8 way set associative, 512K
353 L2CacheSize=512*1024;
354 L2CacheLineSize=32;
355 L2CacheSetAssociative=8;
356 break;
357 case 0x84: // Unified cache, 32 byte cache line, 8 way set associative, 1M
358 L2CacheSize=1024*1024;
359 L2CacheLineSize=32;
360 L2CacheSetAssociative=8;
361 break;
362 case 0x85: // Unified cache, 32 byte cache line, 8 way set associative, 2M
363 L2CacheSize=2048*1024;
364 L2CacheLineSize=32;
365 L2CacheSetAssociative=8;
366 break;
367 }
368}
369
370void CPUDetectClass::Process_Extended_Cache_Info()
371{
372 CPUIDStruct max_ext(0x80000000);
373 if (max_ext.Eax>=0x80000006) {
374 CPUIDStruct l1info(0x80000005);
375 CPUIDStruct l2info(0x80000006);
376
377 // L1 data cache
378 L1DataCacheLineSize=l1info.Ecx&0xff;
379 L1DataCacheSetAssociative=(l1info.Ecx>>16)&0xff;
380 L1DataCacheSize=((l1info.Ecx>>24)&0xff)*1024;
381
382 // L1 instruction cache
383 L1InstructionCacheLineSize=l1info.Edx&0xff;
384 L1InstructionCacheSetAssociative=(l1info.Edx>>16)&0xff;
385 L1InstructionCacheSize=((l1info.Edx>>24)&0xff)*1024;
386
387 // L2 cache
388 L2CacheSize=((l2info.Ecx>>16)&0xffff)*1024;
389 L2CacheLineSize=l2info.Ecx&0xff;
390 switch ((l2info.Ecx>>12)&0xf) {
391 case 0: L2CacheSetAssociative=0; break;
392 case 1: L2CacheSetAssociative=1; break;
393 case 2: L2CacheSetAssociative=2; break;
394 case 4: L2CacheSetAssociative=4; break;
395 case 6: L2CacheSetAssociative=8; break;
396 case 8: L2CacheSetAssociative=16; break;
397 case 15: L2CacheSetAssociative=0xff; break;
398 }
399
400 }
401}
402
403void CPUDetectClass::Init_Cache()
404{
405 CPUIDStruct cache_id(2);
406 // This code can only determine cache sizes for cpuid count 1 (see Intel manuals for more info on the subject)
407 if ((cache_id.Eax&0xff)==1) {
408 if (!(cache_id.Eax&0x80000000)) {
409 Process_Cache_Info((cache_id.Eax>>24)&0xff);
410 Process_Cache_Info((cache_id.Eax>>16)&0xff);
411 Process_Cache_Info((cache_id.Eax>>8)&0xff);
412 }
413 if (!(cache_id.Ebx&0x80000000)) {
414 Process_Cache_Info((cache_id.Ebx>>24)&0xff);
415 Process_Cache_Info((cache_id.Ebx>>16)&0xff);
416 Process_Cache_Info((cache_id.Ebx>>8)&0xff);
417 Process_Cache_Info((cache_id.Ebx)&0xff);
418 }
419 if (!(cache_id.Ecx&0x80000000)) {
420 Process_Cache_Info((cache_id.Ecx>>24)&0xff);
421 Process_Cache_Info((cache_id.Ecx>>16)&0xff);
422 Process_Cache_Info((cache_id.Ecx>>8)&0xff);
423 Process_Cache_Info((cache_id.Ecx)&0xff);
424 }
425 if (!(cache_id.Edx&0x80000000)) {
426 Process_Cache_Info((cache_id.Edx>>24)&0xff);
427 Process_Cache_Info((cache_id.Edx>>16)&0xff);
428 Process_Cache_Info((cache_id.Edx>>8)&0xff);
429 Process_Cache_Info((cache_id.Edx)&0xff);
430 }
431 }
432 else {
433 // If standard (Intel) cache information not found, try extended info.
434 Process_Extended_Cache_Info();
435 }
436}
437
438void CPUDetectClass::Init_Intel_Processor_Type()
439{
440 switch (ProcessorFamily) {
441 case 3:
442 IntelProcessor=INTEL_PROCESSOR_80386;
443 break;
444 case 4:
445 switch (ProcessorModel) {
446 default:
447 case 0:
448 case 1:
449 IntelProcessor=INTEL_PROCESSOR_80486DX;
450 break;
451 case 2:
452 IntelProcessor=INTEL_PROCESSOR_80486SX;
453 break;
454 case 3:
455 IntelProcessor=INTEL_PROCESSOR_80486DX2;
456 break;
457 case 4:
458 IntelProcessor=INTEL_PROCESSOR_80486SL;
459 break;
460 case 5:
461 IntelProcessor=INTEL_PROCESSOR_80486SX2;
462 break;
463 case 7:
464 IntelProcessor=INTEL_PROCESSOR_80486DX2_WB;
465 break;
466 case 8:
467 IntelProcessor=INTEL_PROCESSOR_80486DX4;
468 break;
469 case 9:
470 IntelProcessor=INTEL_PROCESSOR_80486DX4_WB;
471 break;
472 }
473 break;
474 case 5:
475 switch (ProcessorModel) {
476 default:
477 case 0:
478 IntelProcessor=INTEL_PROCESSOR_PENTIUM; // Early model
479 break;
480 case 1:
481 IntelProcessor=INTEL_PROCESSOR_PENTIUM; // 60/66, 5V
482 break;
483 case 2:
484 IntelProcessor=INTEL_PROCESSOR_PENTIUM; // 75+, 3.xV
485 break;
486 case 3:
488 break;
489 case 4:
490 IntelProcessor=INTEL_PROCESSOR_PENTIUM_MMX;
491 break;
492 case 5:
494 break;
495 case 6:
497 break;
498 case 7:
499 IntelProcessor=INTEL_PROCESSOR_PENTIUM;
500 break;
501 case 8:
502 IntelProcessor=INTEL_PROCESSOR_PENTIUM_MMX;
503 break;
504 }
505 case 6:
506 switch (ProcessorModel) {
507 default:
508 case 0:
510 break;
511 case 1:
512 IntelProcessor=INTEL_PROCESSOR_PENTIUM_PRO;
513 break;
514 case 3:
515 if (ProcessorType==0) {
517 }
518 else {
520 }
521 break;
522 case 4:
524 break;
525 case 5:
526 // This one is either PII, PIIXeon or Celeron with no L2 cache!
527 {
528 CPUIDStruct cache_id(2);
529 // TODO: Check for cache to determine processor type!
530 if (L2CacheSize==0) {
531 IntelProcessor=INTEL_PROCESSOR_CELERON_MODEL_5;
532 }
533 else if (L2CacheSize<=512*1024) { // If Xeon has 512k L2 cache we will assume a PII - tough luck!
535 }
536 else {
538 }
539 }
540 break;
541 case 6:
542 IntelProcessor=INTEL_PROCESSOR_CELERON_MODEL_6;
543 break;
544 case 7:
545 if (L2CacheSize<=512*1024) { // If Xeon has 512k L2 cache we will assume a PIII - tough luck!
547 }
548 else {
550 }
551 break;
552 case 8:
553 // This could be PentiumIII Coppermine or Celeron with SSE, or a Xeon
554 {
555 CPUIDStruct brand(1);
556 switch (brand.Ebx&0xff) {
557 case 0x1: IntelProcessor=INTEL_PROCESSOR_CELERON_MODEL_8; break;
558 case 0x2:
559 case 0x4: IntelProcessor=INTEL_PROCESSOR_PENTIUM_III_MODEL_8; break;
560 case 0x3:
561 case 0xe: IntelProcessor=INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_8; break;
562 }
563 }
564 break;
565 case 0xa:
567 break;
568 case 0xb:
570 break;
571 }
572 break;
573 case 0xf:
574 IntelProcessor=INTEL_PROCESSOR_PENTIUM4;
575 break;
576 }
577}
578
579void CPUDetectClass::Init_AMD_Processor_Type()
580{
581 switch (ProcessorFamily) {
582 case 4:
583 switch (ProcessorModel) {
584 case 3:
585 AMDProcessor=AMD_PROCESSOR_486DX2;
586 break;
587 case 7:
588 AMDProcessor=AMD_PROCESSOR_486DX4;
589 break;
590 case 8:
591 AMDProcessor=AMD_PROCESSOR_486DX4;
592 break;
593 case 9:
594 AMDProcessor=AMD_PROCESSOR_486DX4;
595 break;
596 case 0xe:
597 AMDProcessor=AMD_PROCESSOR_5x86;
598 break;
599 case 0xf:
600 AMDProcessor=AMD_PROCESSOR_5x86;
601 break;
602 default:
603 AMDProcessor=AMD_PROCESSOR_486;
604 }
605 break;
606 case 5:
607 switch (ProcessorModel) {
608 case 0:
609 AMDProcessor=AMD_PROCESSOR_K5_MODEL0;
610 break;
611 case 1:
612 AMDProcessor=AMD_PROCESSOR_K5_MODEL1;
613 break;
614 case 2:
615 AMDProcessor=AMD_PROCESSOR_K5_MODEL2;
616 break;
617 case 3:
618 AMDProcessor=AMD_PROCESSOR_K5_MODEL3;
619 break;
620 case 6:
621 AMDProcessor=AMD_PROCESSOR_K6_MODEL6;
622 break;
623 case 7:
624 AMDProcessor=AMD_PROCESSOR_K6_MODEL7;
625 break;
626 case 8:
628 break;
629 case 9:
631 break;
632 case 0xd:
633 AMDProcessor=AMD_PROCESSOR_K6_3_PLUS;
634 break;
635 default:
636 AMDProcessor=AMD_PROCESSOR_K6;
637 }
638 case 6:
639 switch (ProcessorModel) {
640 case 1:
641 AMDProcessor=AMD_PROCESSOR_ATHLON_025;
642 break;
643 case 2:
644 AMDProcessor=AMD_PROCESSOR_ATHLON_018;
645 break;
646 case 3:
647 AMDProcessor=AMD_PROCESSOR_DURON;
648 break;
649 case 4:
650 AMDProcessor=AMD_PROCESSOR_ATHLON_018_IL2;
651 break;
652 default:
653 AMDProcessor=AMD_PROCESSOR_ATHLON;
654 break;
655 }
656 }
657}
658
659void CPUDetectClass::Init_VIA_Processor_Type()
660{
661 switch (ProcessorFamily) {
662 case 5:
663 switch (ProcessorModel) {
664 case 4:
665 VIAProcessor=VIA_PROCESSOR_IDT_C6_WINCHIP;
666 break;
667 case 8:
669 break;
670 case 9:
672 break;
673 }
674 case 6:
675 switch (ProcessorModel) {
676 case 4:
678 break;
679 }
680 }
681}
682
683void CPUDetectClass::Init_Rise_Processor_Type()
684{
685 switch (ProcessorFamily) {
686 case 5:
687 switch (ProcessorModel) {
688 case 0:
689 RiseProcessor=RISE_PROCESSOR_DRAGON_025;
690 break;
691 case 2:
692 RiseProcessor=RISE_PROCESSOR_DRAGON_018;
693 break;
694 case 8:
695 RiseProcessor=RISE_PROCESSOR_DRAGON2_025;
696 break;
697 case 9:
698 RiseProcessor=RISE_PROCESSOR_DRAGON2_018;
699 break;
700 }
701 }
702}
703
704void CPUDetectClass::Init_Processor_Family()
705{
706 unsigned signature=0;
707 unsigned notneeded1;
708 unsigned notneeded2;
709 unsigned features;
710 CPUID(
711 signature,
712 notneeded1,
713 notneeded2,
714 features,
715 1);
716
717 ProcessorType=(signature>>12)&0x0f;
718 ProcessorFamily=(signature>>8)&0x0f;
719 ProcessorModel=(signature>>4)&0x0f;
720 ProcessorRevision=(signature)&0x0f;
721
722 IntelProcessor=INTEL_PROCESSOR_UNKNOWN;
723 AMDProcessor=AMD_PROCESSOR_UNKNOWN;
724 VIAProcessor=VIA_PROCESSOR_UNKNOWN;
725 RiseProcessor=RISE_PROCESSOR_UNKNOWN;
726
727 Init_Cache();
728
729 switch (ProcessorManufacturer) {
731 Init_Intel_Processor_Type();
732 break;
733 case MANUFACTURER_AMD:
734 Init_AMD_Processor_Type();
735 break;
736 case MANUFACTURER_VIA:
737 Init_VIA_Processor_Type();
738 break;
740 Init_Rise_Processor_Type();
741 break;
742 }
743}
744
745void CPUDetectClass::Init_Processor_String()
746{
747 if (!Has_CPUID_Instruction()) {
748 ProcessorString[0]='\0';
749 }
750
751 CPUIDStruct ext_id(0x80000000); // Check maximum extended cpuid level
752// if (ProcessorManufacturer==MANUFACTURER_INTEL && IntelProcessor<INTEL_PROCESSOR_PENTIUM4) {
753// ext_id.Eax=0; // No support for extended cpuid in Intel cpus prior to Pentium4
754// }
755 // If extended cpuid level's highest bit is set, we'll get the cpu string from 2/3/4
756 if (ext_id.Eax&0x80000000) {
758 (unsigned&)ProcessorString[0],
759 (unsigned&)ProcessorString[4],
760 (unsigned&)ProcessorString[8],
761 (unsigned&)ProcessorString[12],
762 0x80000002);
764 (unsigned&)ProcessorString[16],
765 (unsigned&)ProcessorString[20],
766 (unsigned&)ProcessorString[24],
767 (unsigned&)ProcessorString[28],
768 0x80000003);
770 (unsigned&)ProcessorString[32],
771 (unsigned&)ProcessorString[36],
772 (unsigned&)ProcessorString[40],
773 (unsigned&)ProcessorString[44],
774 0x80000004);
775 }
776 // If no extended cpuid available (Intel processors prior to P4), compose the string
777 else {
778 StringClass str(0,true);
780 if (ProcessorManufacturer==MANUFACTURER_INTEL) {
781 str+=" ";
782 switch (IntelProcessor) {
783 default:
784 case INTEL_PROCESSOR_UNKNOWN: str+="<UNKNOWN>"; break;
785 case INTEL_PROCESSOR_80386: str+="80386"; break;
786 case INTEL_PROCESSOR_80486DX: str+="80486DX"; break;
787 case INTEL_PROCESSOR_80486SX: str+="80486SX"; break;
788 case INTEL_PROCESSOR_80486DX2: str+="80486DX2"; break;
789 case INTEL_PROCESSOR_80486SL: str+="80486SL"; break;
790 case INTEL_PROCESSOR_80486SX2: str+="80486SX2"; break;
791 case INTEL_PROCESSOR_80486DX2_WB: str+="80486DX2(WB)"; break;
792 case INTEL_PROCESSOR_80486DX4: str+="80486DX4"; break;
793 case INTEL_PROCESSOR_80486DX4_WB: str+="80486DX4(WB)"; break;
794 case INTEL_PROCESSOR_PENTIUM: str+="Pentium"; break;
795 case INTEL_PROCESSOR_PENTIUM_OVERDRIVE: str+="Pentium Overdrive"; break;
796 case INTEL_PROCESSOR_PENTIUM_MMX: str+="Pentium MMX"; break;
797 case INTEL_PROCESSOR_PENTIUM_PRO_SAMPLE: str+="Pentium Pro (Engineering Sample)"; break;
798 case INTEL_PROCESSOR_PENTIUM_PRO: str+="Pentium Pro"; break;
799 case INTEL_PROCESSOR_PENTIUM_II_OVERDRIVE: str+="Pentium II Overdrive"; break;
800 case INTEL_PROCESSOR_PENTIUM_II_MODEL_3: str+="Pentium II, model 3"; break;
801 case INTEL_PROCESSOR_PENTIUM_II_MODEL_4: str+="Pentium II, model 4"; break;
802 case INTEL_PROCESSOR_CELERON_MODEL_5: str+="Celeron, model 5"; break;
803 case INTEL_PROCESSOR_PENTIUM_II_MODEL_5: str+="Pentium II, model 5"; break;
804 case INTEL_PROCESSOR_PENTIUM_II_XEON_MODEL_5: str+="Pentium II Xeon, model 5"; break;
805 case INTEL_PROCESSOR_CELERON_MODEL_6: str+="Celeron, model 6"; break;
806 case INTEL_PROCESSOR_PENTIUM_III_MODEL_7: str+="Pentium III, model 7"; break;
807 case INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_7: str+="Pentium III Xeon, model 7"; break;
808 case INTEL_PROCESSOR_CELERON_MODEL_8: str+="Celeron, model 8"; break;
809 case INTEL_PROCESSOR_PENTIUM_III_MODEL_8: str+="Pentium III, model 8"; break;
810 case INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_8: str+="Pentium III Xeon, model 8"; break;
811 case INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_A: str+="Pentium III Xeon, model A"; break;
812 case INTEL_PROCESSOR_PENTIUM_III_MODEL_B: str+="Pentium III, model B"; break;
813 case INTEL_PROCESSOR_PENTIUM4: str+="Pentium4"; break;
814 }
815 }
816 strncpy(ProcessorString,str.Peek_Buffer(),sizeof(ProcessorString));
817 }
818
819}
820
821void CPUDetectClass::Init_CPUID_Instruction()
822{
823 unsigned long cpuid_available=0;
824
825 // The pushfd/popfd commands are done using emits
826 // because CodeWarrior seems to have problems with
827 // the command (huh?)
828
829#ifdef WIN32
830 __asm
831 {
832 mov cpuid_available, 0 // clear flag
833 push ebx
834 pushfd
835 pop eax
836 mov ebx, eax
837 xor eax, 0x00200000
838 push eax
839 popfd
840 pushfd
841 pop eax
842 xor eax, ebx
843 je done
844 mov cpuid_available, 1
845 done:
846 push ebx
847 popfd
848 pop ebx
849 }
850#elif defined(_UNIX)
851 __asm__(" mov $0, __cpuid_available"); // clear flag
852 __asm__(" push %ebx");
853 __asm__(" pushfd");
854 __asm__(" pop %eax");
855 __asm__(" mov %eax, %ebx");
856 __asm__(" xor 0x00200000, %eax");
857 __asm__(" push %eax");
858 __asm__(" popfd");
859 __asm__(" pushfd");
860 __asm__(" pop %eax");
861 __asm__(" xor %ebx, %eax");
862 __asm__(" je done");
863 __asm__(" mov $1, __cpuid_available");
864 goto done; // just to shut the compiler up
865 done:
866 __asm__(" push %ebx");
867 __asm__(" popfd");
868 __asm__(" pop %ebx");
869#endif
870 HasCPUIDInstruction=!!cpuid_available;
871}
872
873void CPUDetectClass::Init_Processor_Features()
874{
876
877 CPUIDStruct id(1);
878 FeatureBits=id.Edx;
879 HasRDTSCInstruction=(!!(FeatureBits&(1<<4)));
880 HasCMOVSupport=(!!(FeatureBits&(1<<15)));
881 HasMMXSupport=(!!(FeatureBits&(1<<23)));
882 HasSSESupport=!!(FeatureBits&(1<<25));
883 HasSSE2Support=!!(FeatureBits&(1<<26));
884
885 Has3DNowSupport=false;
886 ExtendedFeatureBits=0;
887 if (ProcessorManufacturer==MANUFACTURER_AMD) {
888 if (Has_CPUID_Instruction()) {
889 CPUIDStruct max_ext_id(0x80000000);
890 if (max_ext_id.Eax>=0x80000001) { // Signature & features field available?
891 CPUIDStruct ext_signature(0x80000001);
892 ExtendedFeatureBits=ext_signature.Edx;
893 Has3DNowSupport=!!(ExtendedFeatureBits&0x80000000);
894 HasExtended3DNowSupport=!!(ExtendedFeatureBits&0x40000000);
895 }
896 }
897 }
898}
899
900void CPUDetectClass::Init_Memory()
901{
902#ifdef WIN32
903
904 MEMORYSTATUS mem;
905 GlobalMemoryStatus(&mem);
906
907 TotalPhysicalMemory = mem.dwTotalPhys;
908 AvailablePhysicalMemory = mem.dwAvailPhys;
909 TotalPageMemory = mem.dwTotalPageFile;
910 AvailablePageMemory = mem.dwAvailPageFile;
911 TotalVirtualMemory = mem.dwTotalVirtual;
912 AvailableVirtualMemory = mem.dwAvailVirtual;
913#elif defined(_UNIX)
914#warning FIX Init_Memory()
915#endif
916}
917
918void CPUDetectClass::Init_OS()
919{
920 OSVERSIONINFO os;
921#ifdef WIN32
922 os.dwOSVersionInfoSize = sizeof(os);
923 GetVersionEx(&os);
924
925 OSVersionNumberMajor = os.dwMajorVersion;
926 OSVersionNumberMinor = os.dwMinorVersion;
927 OSVersionBuildNumber = os.dwBuildNumber;
928 OSVersionPlatformId = os.dwPlatformId;
929 OSVersionExtraInfo = os.szCSDVersion;
930#elif defined(_UNIX)
931#warning FIX Init_OS()
932#endif
933}
934
936 unsigned& u_eax_,
937 unsigned& u_ebx_,
938 unsigned& u_ecx_,
939 unsigned& u_edx_,
940 unsigned cpuid_type)
941{
942 if (!Has_CPUID_Instruction()) return false; // Most processors since 486 have CPUID...
943
944 unsigned u_eax;
945 unsigned u_ebx;
946 unsigned u_ecx;
947 unsigned u_edx;
948
949#ifdef WIN32
950 __asm
951 {
952 pushad
953 mov eax, [cpuid_type]
954 xor ebx, ebx
955 xor ecx, ecx
956 xor edx, edx
957 cpuid
958 mov [u_eax], eax
959 mov [u_ebx], ebx
960 mov [u_ecx], ecx
961 mov [u_edx], edx
962 popad
963 }
964#elif defined(_UNIX)
965 __asm__("pusha");
966 __asm__("mov __cpuid_type, %eax");
967 __asm__("xor %ebx, %ebx");
968 __asm__("xor %ecx, %ecx");
969 __asm__("xor %edx, %edx");
970 __asm__("cpuid");
971 __asm__("mov %eax, __u_eax");
972 __asm__("mov %ebx, __u_ebx");
973 __asm__("mov %ecx, __u_ecx");
974 __asm__("mov %edx, __u_edx");
975 __asm__("popa");
976#endif
977
978 u_eax_=u_eax;
979 u_ebx_=u_ebx;
980 u_ecx_=u_ecx;
981 u_edx_=u_edx;
982
983 return true;
984}
985
986#define SYSLOG(n) work.Format n ; CPUDetectClass::ProcessorLog+=work;
987
988void CPUDetectClass::Init_Processor_Log()
989{
990 StringClass work(0,true);
991
992 SYSLOG(("Operating System: "));
993 switch (OSVersionPlatformId) {
994 case VER_PLATFORM_WIN32s: SYSLOG(("Windows 3.1")); break;
995 case VER_PLATFORM_WIN32_WINDOWS: SYSLOG(("Windows 9x")); break;
996 case VER_PLATFORM_WIN32_NT: SYSLOG(("Windows NT")); break;
997 }
998 SYSLOG(("\r\n"));
999
1000 SYSLOG(("Operating system version %d.%d\r\n",OSVersionNumberMajor,OSVersionNumberMinor));
1001 SYSLOG(("Operating system build: %d.%d.%d\r\n",
1002 (OSVersionBuildNumber&0xff000000)>>24,
1003 (OSVersionBuildNumber&0xff0000)>>16,
1004 (OSVersionBuildNumber&0xffff)));
1005#ifdef WIN32
1006 SYSLOG(("OS-Info: %s\r\n", OSVersionExtraInfo));
1007#elif defined(_UNIX)
1008 SYSLOG(("OS-Info: %s\r\n", OSVersionExtraInfo.Peek_Buffer()));
1009#endif
1010
1011 SYSLOG(("Processor: %s\r\n",CPUDetectClass::Get_Processor_String()));
1012 SYSLOG(("Clock speed: ~%dMHz\r\n",CPUDetectClass::Get_Processor_Speed()));
1013 StringClass cpu_type(0,true);
1015 case 0: cpu_type="Original OEM"; break;
1016 case 1: cpu_type="Overdrive"; break;
1017 case 2: cpu_type="Dual"; break;
1018 case 3: cpu_type="*Intel Reserved*"; break;
1019 }
1020#ifdef WIN32
1021 SYSLOG(("Processor type: %s\r\n", cpu_type));
1022#elif defined(_UNIX)
1023 SYSLOG(("Processor type: %s\r\n", cpu_type.Peek_Buffer()));
1024#endif
1025
1026 SYSLOG(("\r\n"));
1027
1028 SYSLOG(("Total physical memory: %dMb\r\n",Get_Total_Physical_Memory()/(1024*1024)));
1029 SYSLOG(("Available physical memory: %dMb\r\n",Get_Available_Physical_Memory()/(1024*1024)));
1030 SYSLOG(("Total page file size: %dMb\r\n",Get_Total_Page_File_Size()/(1024*1024)));
1031 SYSLOG(("Total available page file size: %dMb\r\n",Get_Available_Page_File_Size()/(1024*1024)));
1032 SYSLOG(("Total virtual memory: %dMb\r\n",Get_Total_Virtual_Memory()/(1024*1024)));
1033 SYSLOG(("Available virtual memory: %dMb\r\n",Get_Available_Virtual_Memory()/(1024*1024)));
1034
1035 SYSLOG(("\r\n"));
1036
1037 SYSLOG(("CPUID: %s\r\n",CPUDetectClass::Has_CPUID_Instruction() ? "Yes" : "No"));
1038 SYSLOG(("RDTSC: %s\r\n",CPUDetectClass::Has_RDTSC_Instruction() ? "Yes" : "No"));
1039 SYSLOG(("CMOV: %s\r\n",CPUDetectClass::Has_CMOV_Instruction() ? "Yes" : "No"));
1040 SYSLOG(("MMX: %s\r\n",CPUDetectClass::Has_MMX_Instruction_Set() ? "Yes" : "No"));
1041 SYSLOG(("SSE: %s\r\n",CPUDetectClass::Has_SSE_Instruction_Set() ? "Yes" : "No"));
1042 SYSLOG(("SSE2: %s\r\n",CPUDetectClass::Has_SSE2_Instruction_Set() ? "Yes" : "No"));
1043 SYSLOG(("3DNow!: %s\r\n",CPUDetectClass::Has_3DNow_Instruction_Set() ? "Yes" : "No"));
1044 SYSLOG(("Extended 3DNow!: %s\r\n",CPUDetectClass::Has_Extended_3DNow_Instruction_Set() ? "Yes" : "No"));
1045 SYSLOG(("CPU Feature bits: 0x%x\r\n",CPUDetectClass::Get_Feature_Bits()));
1046 SYSLOG(("Ext. CPU Feature bits: 0x%x\r\n",CPUDetectClass::Get_Extended_Feature_Bits()));
1047
1048 SYSLOG(("\r\n"));
1049
1051 SYSLOG(("L1 Data Cache: %d byte cache lines, %d way set associative, %dk\r\n",
1055 }
1056 else {
1057 SYSLOG(("L1 Data Cache: None\r\n"));
1058 }
1059
1061 SYSLOG(("L1 Instruction Cache: %d byte cache lines, %d way set associative, %dk\r\n",
1065 }
1066 else {
1067 SYSLOG(("L1 Instruction Cache: None\r\n"));
1068 }
1069
1071 SYSLOG(("L1 Instruction Trace Cache: %d way set associative, %dk µOPs\r\n",
1074 }
1075 else {
1076 SYSLOG(("L1 Instruction Trace Cache: None\r\n"));
1077 }
1078
1079
1081 SYSLOG(("L2 Cache: %d byte cache lines, %d way set associative, %dk\r\n",
1085 }
1086 else {
1087 SYSLOG(("L2 cache: None\r\n"));
1088 }
1089 SYSLOG(("\r\n"));
1090
1091
1092}
1093
1094// OSCODE OSSUBCODE CPUMANUFACTURER CPUSPEED MEMORY CPUBITS EXTCPUBITS
1095#define COMPACTLOG(n) work.Format n ; CPUDetectClass::CompactLog+=work;
1096
1097void CPUDetectClass::Init_Compact_Log()
1098{
1099 StringClass work(0,true);
1100
1101#ifdef WIN32
1102 TIME_ZONE_INFORMATION time_zone;
1103 GetTimeZoneInformation(&time_zone);
1104 COMPACTLOG(("%d\t", time_zone.Bias)); // get diff between local time and UTC
1105#elif defined(_UNIX)
1106 time_t t = time(NULL);
1107 localtime(&t);
1108 COMPACTLOG(("%d\t", timezone));
1109#endif
1110
1111 OSInfoStruct os_info;
1112 Get_OS_Info(os_info,OSVersionPlatformId,OSVersionNumberMajor,OSVersionNumberMinor,OSVersionBuildNumber);
1113 COMPACTLOG(("%s\t",os_info.Code));
1114
1115 if (!stricmp(os_info.SubCode,"UNKNOWN")) {
1116 COMPACTLOG(("%d\t",OSVersionBuildNumber&0xffff));
1117 }
1118 else {
1119 COMPACTLOG(("%s\t",os_info.SubCode));
1120 }
1121
1123
1124 COMPACTLOG(("%d\t",Get_Total_Physical_Memory()/(1024*1024)+1));
1125
1127}
1128
1129static class CPUDetectInitClass
1130{
1131public:
1132 CPUDetectInitClass::CPUDetectInitClass()
1133 {
1134 CPUDetectClass::Init_CPUID_Instruction();
1135 // We pretty much need CPUID, but let's not crash if it doesn't exist.
1136 // Every processor our games run should have CPUID so it would be extremely unlikely for it not to be present.
1137 // One can never be sure about the clones though...
1139 CPUDetectClass::Init_Processor_Manufacturer();
1140 CPUDetectClass::Init_Processor_Family();
1141 CPUDetectClass::Init_Processor_String();
1142 CPUDetectClass::Init_Processor_Features();
1143 CPUDetectClass::Init_Memory();
1144 CPUDetectClass::Init_OS();
1145 }
1146 CPUDetectClass::Init_Processor_Speed();
1147
1148 CPUDetectClass::Init_Processor_Log();
1149 CPUDetectClass::Init_Compact_Log();
1150 }
1151} _CPU_Detect_Init;
1152
1153
1155 {"WIN95", "FINAL", "Windows 95", 4,0,950, 4,0,950 },
1156 {"WIN95", "A", "Windows 95a OSR1 final Update", 4,0,950, 4,0,951 },
1157 {"WIN95", "B20OEM", "Windows 95B OSR 2.0 final OEM", 4,0,950, 4,0,1111 },
1158 {"WIN95", "B20UPD", "Windows 95B OSR 2.1 final Update", 4,0,950, 4,3,1212 },
1159 {"WIN95", "B21OEM", "Windows 95B OSR 2.1 final OEM", 4,1,971, 4,1,971 },
1160 {"WIN95", "C25OEM", "Windows 95C OSR 2.5 final OEM", 4,0,950, 4,3,1214 },
1161 {"WIN98", "BETAPRD", "Windows 98 Beta pre-DR", 4,10,1351, 4,10,1351 },
1162 {"WIN98", "BETADR", "Windows 98 Beta DR", 4,10,1358, 4,10,1358 },
1163 {"WIN98", "BETAE", "Windows 98 early Beta", 4,10,1378, 4,10,1378 },
1164 {"WIN98", "BETAE", "Windows 98 early Beta", 4,10,1410, 4,10,1410 },
1165 {"WIN98", "BETAE", "Windows 98 early Beta", 4,10,1423, 4,10,1423 },
1166 {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1500, 4,10,1500 },
1167 {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1508, 4,10,1508 },
1168 {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1511, 4,10,1511 },
1169 {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1525, 4,10,1525 },
1170 {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1535, 4,10,1535 },
1171 {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1538, 4,10,1538 },
1172 {"WIN98", "BETA1", "Windows 98 Beta 1", 4,10,1543, 4,10,1543 },
1173 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1544, 4,10,1544 },
1174 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1546, 4,10,1546 },
1175 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1550, 4,10,1550 },
1176 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1559, 4,10,1559 },
1177 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1564, 4,10,1564 },
1178 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1569, 4,10,1569 },
1179 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1577, 4,10,1577 },
1180 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1581, 4,10,1581 },
1181 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1593, 4,10,1593 },
1182 {"WIN98", "BETA2", "Windows 98 Beta 2", 4,10,1599, 4,10,1599 },
1183 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1602, 4,10,1602 },
1184 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1605, 4,10,1605 },
1185 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1614, 4,10,1614 },
1186 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1619, 4,10,1619 },
1187 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1624, 4,10,1624 },
1188 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1629, 4,10,1629 },
1189 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1633, 4,10,1633 },
1190 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1650, 4,10,1650 },
1191 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1650,/*,3*/4,10,1650/*,3*/ },
1192 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1650,/*,8*/4,10,1650/*,8*/ },
1193 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1666, 4,10,1666 },
1194 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1671, 4,10,1671 },
1195 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1677, 4,10,1677 },
1196 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1681, 4,10,1681 },
1197 {"WIN98", "BETA3", "Windows 98 Beta 3", 4,10,1687, 4,10,1687 },
1198 {"WIN98", "RC0", "Windows 98 RC0", 4,10,1691, 4,10,1691 },
1199 {"WIN98", "RC0", "Windows 98 RC0", 4,10,1702, 4,10,1702 },
1200 {"WIN98", "RC0", "Windows 98 RC0", 4,10,1708, 4,10,1708 },
1201 {"WIN98", "RC0", "Windows 98 RC0", 4,10,1713, 4,10,1713 },
1202 {"WIN98", "RC1", "Windows 98 RC1", 4,10,1721,/*,3*/4,10,1721/*,3*/ },
1203 {"WIN98", "RC2", "Windows 98 RC2", 4,10,1723,/*,4*/4,10,1723/*,4*/ },
1204 {"WIN98", "RC2", "Windows 98 RC2", 4,10,1726, 4,10,1726 },
1205 {"WIN98", "RC3", "Windows 98 RC3", 4,10,1900,/*,5*/4,10,1900/*,5*/ },
1206 {"WIN98", "RC4", "Windows 98 RC4", 4,10,1900,/*,8*/4,10,1900/*,8*/ },
1207 {"WIN98", "RC5", "Windows 98 RC5", 4,10,1998, 4,10,1998 },
1208 {"WIN98", "FINAL", "Windows 98", 4,10,1998,/*,6*/4,10,1998/*,6*/ },
1209 {"WIN98", "SP1B1", "Windows 98 SP1 Beta 1", 4,10,2088, 4,10,2088 },
1210 {"WIN98", "OSR1B1", "Windows 98 OSR1 Beta 1", 4,10,2106, 4,10,2106 },
1211 {"WIN98", "OSR1B1", "Windows 98 OSR1 Beta 1", 4,10,2120, 4,10,2120 },
1212 {"WIN98", "OSR1B1", "Windows 98 OSR1 Beta 1", 4,10,2126, 4,10,2126 },
1213 {"WIN98", "OSR1B1", "Windows 98 OSR1 Beta 1", 4,10,2131, 4,10,2131 },
1214 {"WIN98", "SP1B2", "Windows 98 SP1 Beta 2", 4,10,2150,/*,0*/4,10,2150/*,0*/ },
1215 {"WIN98", "SP1B2", "Windows 98 SP1 Beta 2", 4,10,2150,/*,4*/4,10,2150/*,4*/ },
1216 {"WIN98", "SP1", "Windows 98 SP1 final Update", 4,10,2000, 4,10,2000 },
1217 {"WIN98", "OSR1B2", "Windows 98 OSR1 Beta 2", 4,10,2174, 4,10,2174 },
1218 {"WIN98", "SERC1", "Windows 98 SE RC1", 4,10,2183, 4,10,2183 },
1219 {"WIN98", "SERC2", "Windows 98 SE RC2", 4,10,2185, 4,10,2185 },
1220 {"WIN98", "SE", "Windows 98 SE", 4,10,2222, 4,10,2222/*,3*/ },
1221 {"WINME", "MEBDR1", "Windows ME Beta DR1", 4,90,2332, 4,90,2332 },
1222 {"WINME", "MEBDR2", "Windows ME Beta DR2", 4,90,2348, 4,90,2348 },
1223 {"WINME", "MEBDR3", "Windows ME Beta DR3", 4,90,2358, 4,90,2358 },
1224 {"WINME", "MEBDR4", "Windows ME Beta DR4", 4,90,2363, 4,90,2363 },
1225 {"WINME", "MEEB", "Windows ME early Beta", 4,90,2368, 4,90,2368 },
1226 {"WINME", "MEEB", "Windows ME early Beta", 4,90,2374, 4,90,2374 },
1227 {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2380, 4,90,2380 },
1228 {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2394, 4,90,2394 },
1229 {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2399, 4,90,2399 },
1230 {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2404, 4,90,2404 },
1231 {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2410, 4,90,2410 },
1232 {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2416, 4,90,2416 },
1233 {"WINME", "MEB1", "Windows ME Beta 1", 4,90,2419,/*,4*/4,90,2419/*,4*/ },
1234 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2429, 4,90,2429 },
1235 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2434, 4,90,2434 },
1236 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2443, 4,90,2443 },
1237 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2447, 4,90,2447 },
1238 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2455, 4,90,2455 },
1239 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2460, 4,90,2460 },
1240 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2465, 4,90,2465 },
1241 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2470, 4,90,2470 },
1242 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2474, 4,90,2474 },
1243 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2481, 4,90,2481 },
1244 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2487, 4,90,2487 },
1245 {"WINME", "MEB2", "Windows ME Beta 2", 4,90,2491, 4,90,2491 },
1246 {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2499, 4,90,2499 },
1247 {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2499,/*,3*/4,90,2499/*,3*/ },
1248 {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2509, 4,90,2509 },
1249 {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2513, 4,90,2513 },
1250 {"WINME", "MEB3", "Windows ME Beta 3", 4,90,2516, 4,90,2516 },
1251 {"WINME", "RC0", "Windows ME RC0", 4,90,2525, 4,90,2525 },
1252 {"WINME", "RC1", "Windows ME RC1", 4,90,2525,/*,6*/4,90,2525/*,6*/ },
1253 {"WINME", "RC2", "Windows ME RC2", 4,90,2535, 4,90,2535 },
1254 {"WINME", "FINAL", "Windows ME", 4,90,3000,/*,2*/4,90,3000/*,2*/ },
1255};
1256
1257void Get_OS_Info(
1258 OSInfoStruct& os_info,
1259 unsigned OSVersionPlatformId,
1260 unsigned OSVersionNumberMajor,
1261 unsigned OSVersionNumberMinor,
1262 unsigned OSVersionBuildNumber)
1263{
1264 unsigned build_major=(OSVersionBuildNumber&0xff000000)>>24;
1265 unsigned build_minor=(OSVersionBuildNumber&0xff0000)>>16;
1266 unsigned build_sub=(OSVersionBuildNumber&0xffff);
1267
1268 switch (OSVersionPlatformId) {
1269 default:
1270 memset(&os_info,0,sizeof(os_info));
1271 os_info.Code="UNKNOWN";
1272 os_info.SubCode="UNKNOWN";
1273 os_info.VersionString="UNKNOWN";
1274 break;
1275 case VER_PLATFORM_WIN32_WINDOWS:
1276 {
1277 for(int i=0;i<sizeof(Windows9xVersionTable)/sizeof(os_info);++i) {
1278 if (
1279 Windows9xVersionTable[i].VersionMajor==OSVersionNumberMajor &&
1280 Windows9xVersionTable[i].VersionMinor==OSVersionNumberMinor &&
1281 Windows9xVersionTable[i].BuildMajor==build_major &&
1282 Windows9xVersionTable[i].BuildMinor==build_minor &&
1283 Windows9xVersionTable[i].BuildSub==build_sub) {
1284 os_info=Windows9xVersionTable[i];
1285 return;
1286 }
1287 }
1288
1289 os_info.BuildMajor=build_major;
1290 os_info.BuildMinor=build_minor;
1291 os_info.BuildSub=build_sub;
1292 if (OSVersionNumberMajor==4) {
1293// os_info.SubCode.Format("%d",build_sub);
1294 os_info.SubCode="UNKNOWN";
1295 if (OSVersionNumberMinor==0) {
1296 os_info.Code="WIN95";
1297 return;
1298 }
1299 if (OSVersionNumberMinor==10) {
1300 os_info.Code="WIN98";
1301 return;
1302 }
1303 if (OSVersionNumberMinor==90) {
1304 os_info.Code="WINME";
1305 return;
1306 }
1307 os_info.Code="WIN9X";
1308 return;
1309 }
1310 }
1311 break;
1312 case VER_PLATFORM_WIN32_NT:
1313// os_info.SubCode.Format("%d",build_sub);
1314 os_info.SubCode="UNKNOWN";
1315 if (OSVersionNumberMajor==4) {
1316 os_info.Code="WINNT";
1317 return;
1318 }
1319 if (OSVersionNumberMajor==5) {
1320 if (OSVersionNumberMinor==0) {
1321 os_info.Code="WIN2K";
1322 return;
1323 }
1324 if (OSVersionNumberMinor==1) {
1325 os_info.Code="WINXP";
1326 return;
1327 }
1328 os_info.Code="WINXX";
1329 return;
1330 }
1331 }
1332}
#define NULL
Definition BaseType.h:92
void const char * value
@ INTEL_PROCESSOR_80486SX
Definition cpudetect.h:78
@ INTEL_PROCESSOR_80486DX2_WB
Definition cpudetect.h:82
@ INTEL_PROCESSOR_CELERON_MODEL_8
Definition cpudetect.h:99
@ INTEL_PROCESSOR_PENTIUM_MMX
Definition cpudetect.h:87
@ INTEL_PROCESSOR_UNKNOWN
Definition cpudetect.h:75
@ INTEL_PROCESSOR_80486DX4_WB
Definition cpudetect.h:84
@ INTEL_PROCESSOR_80486SX2
Definition cpudetect.h:81
@ INTEL_PROCESSOR_80386
Definition cpudetect.h:76
@ INTEL_PROCESSOR_PENTIUM_II_MODEL_5
Definition cpudetect.h:94
@ INTEL_PROCESSOR_PENTIUM_III_MODEL_8
Definition cpudetect.h:100
@ INTEL_PROCESSOR_80486DX
Definition cpudetect.h:77
@ INTEL_PROCESSOR_PENTIUM_III_MODEL_B
Definition cpudetect.h:103
@ INTEL_PROCESSOR_PENTIUM_II_MODEL_3
Definition cpudetect.h:91
@ INTEL_PROCESSOR_80486DX4
Definition cpudetect.h:83
@ INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_7
Definition cpudetect.h:98
@ INTEL_PROCESSOR_80486SL
Definition cpudetect.h:80
@ INTEL_PROCESSOR_CELERON_MODEL_5
Definition cpudetect.h:93
@ INTEL_PROCESSOR_PENTIUM_PRO_SAMPLE
Definition cpudetect.h:88
@ INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_A
Definition cpudetect.h:102
@ INTEL_PROCESSOR_PENTIUM
Definition cpudetect.h:85
@ INTEL_PROCESSOR_PENTIUM_II_MODEL_4
Definition cpudetect.h:92
@ INTEL_PROCESSOR_PENTIUM_II_OVERDRIVE
Definition cpudetect.h:90
@ INTEL_PROCESSOR_PENTIUM_II_XEON_MODEL_5
Definition cpudetect.h:95
@ INTEL_PROCESSOR_PENTIUM_PRO
Definition cpudetect.h:89
@ INTEL_PROCESSOR_PENTIUM_III_MODEL_7
Definition cpudetect.h:97
@ INTEL_PROCESSOR_PENTIUM_OVERDRIVE
Definition cpudetect.h:86
@ INTEL_PROCESSOR_PENTIUM4
Definition cpudetect.h:104
@ INTEL_PROCESSOR_PENTIUM_III_XEON_MODEL_8
Definition cpudetect.h:101
@ INTEL_PROCESSOR_CELERON_MODEL_6
Definition cpudetect.h:96
@ INTEL_PROCESSOR_80486DX2
Definition cpudetect.h:79
static unsigned Get_Total_Physical_Memory()
Definition cpudetect.h:197
static unsigned Get_Total_Virtual_Memory()
Definition cpudetect.h:201
@ MANUFACTURER_TRANSMETA
Definition cpudetect.h:70
static int Get_Processor_Speed()
Definition cpudetect.h:170
static const char * Get_Processor_Manufacturer_Name()
static bool Has_CPUID_Instruction()
Definition cpudetect.h:152
static bool Has_3DNow_Instruction_Set()
Definition cpudetect.h:158
static unsigned Get_L1_Instruction_Trace_Cache_Size()
Definition cpudetect.h:193
static bool Has_CMOV_Instruction()
Definition cpudetect.h:154
static unsigned Get_L2_Cache_Size()
Definition cpudetect.h:178
static const char * Get_Processor_String()
Definition cpudetect.h:206
static unsigned Get_Available_Page_File_Size()
Definition cpudetect.h:200
static unsigned Get_Total_Page_File_Size()
Definition cpudetect.h:199
static unsigned Get_L1_Data_Cache_Set_Associative()
Definition cpudetect.h:185
@ VIA_PROCESSOR_CYRIX_III_SAMUEL
Definition cpudetect.h:137
@ VIA_PROCESSOR_IDT_C6_WINCHIP2
Definition cpudetect.h:135
@ VIA_PROCESSOR_IDT_C6_WINCHIP3
Definition cpudetect.h:136
@ VIA_PROCESSOR_IDT_C6_WINCHIP
Definition cpudetect.h:134
static unsigned Get_L1_Data_Cache_Size()
Definition cpudetect.h:183
static unsigned Get_Processor_Type()
Definition cpudetect.h:204
static unsigned Get_Available_Physical_Memory()
Definition cpudetect.h:198
static bool Has_Extended_3DNow_Instruction_Set()
Definition cpudetect.h:159
static unsigned Get_Available_Virtual_Memory()
Definition cpudetect.h:202
static unsigned Get_L1_Instruction_Cache_Line_Size()
Definition cpudetect.h:189
static unsigned Get_L2_Cache_Line_Size()
Definition cpudetect.h:179
static unsigned Get_L1_Instruction_Cache_Set_Associative()
Definition cpudetect.h:190
static bool CPUID(unsigned &u_eax_, unsigned &u_ebx_, unsigned &u_ecx_, unsigned &u_edx_, unsigned cpuid_type)
static unsigned Get_Feature_Bits()
Definition cpudetect.h:174
@ AMD_PROCESSOR_ATHLON_025
Definition cpudetect.h:124
@ AMD_PROCESSOR_K6_MODEL7
Definition cpudetect.h:119
@ AMD_PROCESSOR_K6_3_3DNOW_MODEL9
Definition cpudetect.h:121
@ AMD_PROCESSOR_K5_MODEL0
Definition cpudetect.h:114
@ AMD_PROCESSOR_K5_MODEL1
Definition cpudetect.h:115
@ AMD_PROCESSOR_K6_2_3DNOW_MODEL8
Definition cpudetect.h:120
@ AMD_PROCESSOR_ATHLON_018
Definition cpudetect.h:125
@ AMD_PROCESSOR_K5_MODEL2
Definition cpudetect.h:116
@ AMD_PROCESSOR_ATHLON_018_IL2
Definition cpudetect.h:127
@ AMD_PROCESSOR_K6_3_PLUS
Definition cpudetect.h:122
@ AMD_PROCESSOR_K6_MODEL6
Definition cpudetect.h:118
@ AMD_PROCESSOR_K5_MODEL3
Definition cpudetect.h:117
static bool Has_SSE_Instruction_Set()
Definition cpudetect.h:156
static unsigned Get_L2_Cache_Set_Associative()
Definition cpudetect.h:180
static bool Has_SSE2_Instruction_Set()
Definition cpudetect.h:157
@ RISE_PROCESSOR_DRAGON2_025
Definition cpudetect.h:145
@ RISE_PROCESSOR_DRAGON_018
Definition cpudetect.h:144
@ RISE_PROCESSOR_DRAGON_025
Definition cpudetect.h:143
@ RISE_PROCESSOR_DRAGON2_018
Definition cpudetect.h:146
static unsigned Get_Extended_Feature_Bits()
Definition cpudetect.h:175
static unsigned Get_L1_Instruction_Cache_Size()
Definition cpudetect.h:188
static bool Has_RDTSC_Instruction()
Definition cpudetect.h:153
static unsigned Get_L1_Data_Cache_Line_Size()
Definition cpudetect.h:184
static bool Has_MMX_Instruction_Set()
Definition cpudetect.h:155
TCHAR * Peek_Buffer(void)
Definition wwstring.h:560
#define SYSLOG(n)
#define ASM_RDTSC
OSInfoStruct Windows9xVersionTable[]
#define COMPACTLOG(n)
Definition dx8caps.cpp:51
const char * VersionString
Definition cpudetect.cpp:35
unsigned short BuildSub
Definition cpudetect.cpp:41
unsigned char VersionMajor
Definition cpudetect.cpp:36
unsigned char BuildMinor
Definition cpudetect.cpp:40
unsigned char BuildMajor
Definition cpudetect.cpp:39
const char * Code
Definition cpudetect.cpp:33
unsigned short VersionSub
Definition cpudetect.cpp:38
unsigned char VersionMinor
Definition cpudetect.cpp:37
const char * SubCode
Definition cpudetect.cpp:34
#define TIMEGETTIME
Definition systimer.h:44
long time_t
Definition wolapi.h:436