{
 What the heck is it?
 --------------------
 With the magic of Delphi,
 Everything is quite nice and easy to arranged. Writing
 code is much simpler and easy to understood than before.

 You might also check my other code: Absolute Read/Write
 Disk in WIN32 Platform (Win95/NT/2000).

 comments:

 CPUID instruction
 -----------------
 Starting from i486 intel built a new insruction
 (which could be executed at any privilege level)
 to extract CPU's information. This instruction
 (CPUID) will queries information about CPU, such as
 type, family, model and stepping. In more recent CPU,
 this information also includes features supported by
 CPU and cache descriptor.

 This quite useful regarding to identify specific
 capabilties you expect to be existed in CPU, so your
 application will run properly.

 This instruction may also used to queries processor
 about it's Serial Number (a relative unique number
 burnt in Pentium III class processor), but it usages
 then depreciated in IA-64 (Itanium doesn't support
 this feature anymore, some privacy concern -maybe).
 On the contrary of that, I think this features might be useful
 as a complement to Network Card ID's, I even think
 to build -or someone more capable will- some (experiment)
 network protocol based on this processor's unique ID.

 ACPUID Component
 ----------------
 note: I've built and tested this with Delphi 3,
       no hints and warning was produced.
       In Delphi 4 and up (which more restrictive)
       some exceptions may occur.

 Class: Tacpuid
   public and published members:
   properties:
   -----------
     CPUInfo: TCPUInfo
     TCPUInfo = Class(TPersistent)
       published members: properties:

         cpuClass:TcpuClass, Read-write
           TCPUClass = (x000, x086, x286, x386, x486, x586, x586p)
             Class of CPU which indicates the presence of CPUID
             instruction (supported on x486 and up).

         cpuType:TcpuType, Read-only
           TcpuType = (cpu_primary, cpu_overdrive, cpu_secondary, cpu_reserved)
             Type Of CPU based on information retrieved after
             CPUID instruction succesfully executed.

         cpuFamily:String, Read-only
         cpuModel:String, Read-only
         cpuStepping:Integer, Read-only
           Describe CPU's Family/Model/Stepping.

     CPUSerialNo: TCPUSerialNo
     TCPUSerialNo = Class(TPersistent)
       published members: properties:

         property PentiumIII:Boolean, Read-only
           Indicating support for Processor Serial Number Feature.

         PSN_ax:Integer, Read-only
         PSN_Hi:Integer, Read-only
         PSN_Lo:Integer, Read-only
         PSN_String:String, Read-only
           CPU's Processor Serial Number (if PSN is enabled).

     Registers:Tregisters
       TRegisters = Class(TPersistent)
       published members: properties:
       
           eax, ebx, ecx, edx :Integer; Read-write
           CPU's register contents after CPUID execution,
           Corresponding to x486 CPU's registers: EAX, EBX, ECX, EDX.
           It can also set to some values for the next CPUID execution.
           See also property BulkData.

     Auto:Boolean, Read-write
       Default is FALSE, if it set to TRUE then all properties
       will be populated with appropriate information.
       note: Auto is temporarily activated (regardless of current
       state) on RefereshInfo method execution, and then turned
       back to the last state after that.

     Vendor:TVendor, Read-write
       TVendor = (vn_none, vnIntel, vnAMD, vnCyrix, vnIDT,
         vnNexGen, vnUMC, vnRise);
       The CPU's vendor, currently contains only 7 major vendor.

     VendorSign:String, Read-only
       Vaguely hardcoded string in CPU.

     Level:Integer, Read-write
       Last level called by application.
       You can set this property to any value for the next CPUID execution

     MaxLevel:Integer, Read-only
       Maximum CPUID level call supported by CPU.

     Featured:Integer
       Double word representation of CPU's features.

     Features:TFeatureSet
       TFeatureSet = set of TFeature;
         TFeature = ( fe00_FPU, fe01_VME, fe02_DE, fe03_PSE,
           fe04_TSC, fe05_MSR, fe06_PAE, fe07_MCE,
           fe08_CX8, fe09_APIC, fe10_resv, fe11_SEP,
           fe12_MTRR, fe13_PGE, fe14_MCA, fe15_CMOV,
           fe16_PAT, fe17_PSE36, fe18_PPN, fe19_CLFLSH,
           fe20_resv, fe21_DTES, fe22_ACPI, fe23_MMX,
           fe24_FXSR, fe25_XMM, fe26_ISSE2, fe27_SSNOOP,
           fe28_resv, fe29_ACC, fe30_JMPE, fe31_resv )
       Provides information of the features supported by CPU.
       note: fe18_PPN stands for Physical Processor Number (new Intel's term),
       while on some descriptions and names such as PSN_Enabled or PSN_Hi/Lo,
       I used the old term of PSN (Processor Serial Number).
       Dont be confused, they're exactly refers to the same thing.

     CacheInfo:TStrings
       List of CPU's Cache Description.
       Since it has TStrings property, it can be extracted later as text.

     BulkData:pointer;
       Actually it points to 32 bytes of data resulted by the last CPUID
       instruction, in case of an application needs to retrieve them at once.
       Note that only 16 bytes of them filled with data.
       Those data could also be accesed sequentially via Registers
       published members (eax, ebx, ecx, edx).

     Property GlobalInfo:
       (see also GlobalInfoText method)
       Shows Global windows Information, see mine below for example.
       You'll see that some information (Processor Type, Level and
       Revision) are in corellation with CPUInfo's Class members.
       note that on NT Platform you must have an admin account to
       get the correct Hardware Profile Info.

         Hardware Profile Info
         ================
         Docking Info: 7 (00000007H)
         GUID: #$7BD485C050-A982-11D4-8A5E-00E07D87AF61#$7D
         Name:  aa@bitsmart.com

         System Info
         ================
         OEM ID: 0
         Page Size: 4096 (00001000H)
         Minimum Application Address: 00010000H
         Maximum Application Address: 7FFEFFFFH
         Active Processor Mask: 1
         Number Of Processors: 1
         Processor Type: 586
         Allocation Granularity: 65536 (00010000H)
         Processor Level: 6
         Processor Revision: 2051 (8038H)

         OS Version Info
         ================
         Major Version: 4 (00000004H)
         Minor Version: 0 (00000000H)
         Build Number: 1381 (00000565H)
         Platform ID: 2 (00000002H)
         CSD Version: Service Pack 6

         Memory Status
         ================
         Length: 32 (00000020H)
         Memory Load: 0 (00000000H)
         Total Physical: 133603328 (07F6A000H)
         Avail Physical: 65228800 (03E35000H)
         Total Page File: 389099520 (17313000H)
         Avail Page File: 351047680 (14EC9000H)
         Total Virtual: 2147352576 (7FFE0000H)
         Avail Virtual: 2087247872 (7C68E000H)

   methods:
   --------
     Constructor Create(Whoever:TComponent); override
     Destructor Destroy; override;
       Honestly, I want to eliminate both methods above, but I just couldn't ;)

     procedure About;
       Hi, it's me!

     procedure DoNothing(Sender:TObject)
       as it expressed, it does none thing ;-)

     OK, that's enough...

     function Execute:Integer;
       Execute CPUID instruction for current level.
       make sure that you have specified a value for Level property
       to avoid unexpected result.

     function ExecuteLevel(const nLevel:Integer):Integer
       Another way to execute CPUID instruction,
       this one will force you to enter the specified level call.

     function ExecuteCPUID(const nLevel:Integer; var eax,
       ebx, ecx, edx: Integer):Integer
       This way you have even more control of CPUID instruction flow.
       This method is merely a wrapper of the assembly form of instruction
       to a more convenient one.

     procedure ExecuteLevel0; virtual;
     procedure ExecuteLevel1; virtual;
     procedure ExecuteLevel2; virtual;
     procedure ExecuteLevel3; virtual;
       a group of methods for commonly used level call.

     procedure RefereshInfo; virtual;
       Re-enumerate all information in current state.
       It rarely needed except you had changed manually
       some of read-write properties.

     function FeaturesAvailable(fs:TFeatureSet):String;
     function FeaturesNotAvailable(fs:TFeatureSet):String;
       List of available / not available features supported by
       CPU, simply give an empty set [] as argumen, this method then
       will use current feature set as default value.

     function CacheInfoText(const datadword:Integer):String;
       Plain text representation of CPU Cache

     function GlobalInfoText:String;
     // removed: procedure ShowGlobalInfo;
       This method added (later) for additional info.
       Its a kind of greedy method, I added unit Windows, SysUtils //and Dialogs
       just for this single method alone, no kidding.
       The function itself is quite independent, you may even copy-paste it
       to your code without anymore constraint.

   events:
   -------
     OnLevelChange
       property Level Changed

     OnAutoChange
       property Auto Changed


. (this point was intended as such, since Borland's auto indent throws me apart from BOL)


notes:
  I'm running out of time!
  I just only have Intel processor (& some old cyrix also),
  never really test this code with other.

  This version can not detect Extended (or is it Extension?) Level $8XXX-XXXX.
  Actually it can, but the descriptor mechanism hasn't been prepared yet.
  You are always welcome to extend the capabilities of this component in any way.

  Look also the commented properties in this source code to see the
  Features information that can be retrieved in Extended Level
  (it appears to be applied and customized only by non-Intel's CPU),
  such as 3DNow!'s AMD and MMXX's Cyrix.
  for more details, see Christian Ludloff's http://www.sandpile.org

Final notes:
  Sorry for the mess,
  My time is up.
  my big-boss seems not too happy,
  and the salespersons btw, need to sell something.

  I've got to do my-'real-life' works now.

  Well, We'll see next month,
  If I had some time for doing some fun again.
}

{
  ===========================================================
  DISCLAIMER
  I HEREBY DISCLAIM ANY... BLAH 3x
  .....

  comments:
    If you find this code is useful for you or your company,
    please contribute US $10 (at least) or equivalent,
    for any of kidney charity/funds/organization/etc.
    in poor country to help poor people with kidney
    handicap/malfunction.

    Yes, they will otherways die indeed, but they might
    lived a little longer with your help.
  ============================================================
  CopyRight (DeleteWrong) 2000, Dadang Sofyan,
  mailto:aa@bitsmart.com   ...hope it still working ;)
}