;CPU-Y, developed by Mat Quasar (aka fliermate), 2025/2
;
;Reference:
; - https://board.flatassembler.net/topic.php?t=15628
; - https://codeby.net/threads/cpuid-identifikacija-processora.78279/
; - https://board.flatassembler.net/topic.php?t=23697
; - https://learn.microsoft.com/en-us/windows/win32/controls/create-a-simple-list-box
;
; Update: 11 Apr 2025 - XP style
;
format PE GUI 4.0
include 'win32a.inc'

IDD_MAIN        = 100
IDC_CPUNAME     = 101
IDC_CORES       = 102
IDC_FEATURES    = 103
IDC_OK          = 104
IDM_MAIN        = 200

PF_MMX_INSTRUCTIONS_AVAILABLE = 3
PF_SSE3_INSTRUCTIONS_AVAILABLE= 13
PF_SSSE3_INSTRUCTIONS_AVAILABLE =36
PF_SSE4_1_INSTRUCTIONS_AVAILABLE =37
PF_SSE4_2_INSTRUCTIONS_AVAILABLE =38
PF_AVX_INSTRUCTIONS_AVAILABLE =39
PF_AVX2_INSTRUCTIONS_AVAILABLE = 40
PF_AVX512F_INSTRUCTIONS_AVAILABLE =41

section '.text' code readable executable

  entry $

        mov     eax, 0x80000002
        cpuid
        mov     dword [_name], eax
        mov     dword [_name + 4], ebx
        mov     dword [_name + 8], ecx
        mov     dword [_name + 12], edx
        mov     eax, 0x80000003
        cpuid
        mov     dword [_name + 16], eax
        mov     dword [_name + 20], ebx
        mov     dword [_name + 24], ecx
        mov     dword [_name + 28], edx
        mov     eax, 0x80000004
        cpuid
        mov     dword [_name + 32], eax
        mov     dword [_name + 36], ebx
        mov     dword [_name + 40], ecx
        mov     dword [_name + 44], edx

        mov     eax,1
        cpuid
        movzx   ecx,bl
        movzx   edx,bh
        shl     edx,3
        shr     ebx,16
        movzx   esi,bl
        movzx   edi,bh

        mov     [_core], esi
        mov     eax, [_core]
        call    itoa
        mov     [_len], ebx

 ;       cinvoke  printf,<10,' ***** EAX=1 ****************',\
 ;                        10,'   Family & Model.:  0x%x',\
 ;                        10,'   Brand index....:  0x%02x',\
 ;                        10,'   Cache line.....:  %d byte',\
 ;                        10,'   CPU cores......:  %d',\
 ;                        10,'   APIC id........:  %d',\
 ;                        10,'   Feature flags..:  ',0>, eax,ecx,edx,esi,edi

        invoke  IsProcessorFeaturePresent, PF_MMX_INSTRUCTIONS_AVAILABLE
        or      eax, eax
        cmovne  ebx, dword [_yes]
        cmove   ebx, dword [_no]
        mov     dword [_mmx + 11], ebx

        invoke  IsProcessorFeaturePresent, PF_SSE3_INSTRUCTIONS_AVAILABLE
        or      eax, eax
        cmovne  ebx, dword [_yes]
        cmove   ebx, dword [_no]
        mov     dword [_sse3 + 11], ebx

        invoke  IsProcessorFeaturePresent, PF_SSSE3_INSTRUCTIONS_AVAILABLE
        or      eax, eax
        cmovne  ebx, dword [_yes]
        cmove   ebx, dword [_no]
        mov     dword [_ssse3 + 11], ebx

        invoke  IsProcessorFeaturePresent, PF_SSE4_1_INSTRUCTIONS_AVAILABLE
        or      eax, eax
        cmovne  ebx, dword [_yes]
        cmove   ebx, dword [_no]
        mov     dword [_sse41 + 11], ebx

        invoke  IsProcessorFeaturePresent, PF_SSE4_2_INSTRUCTIONS_AVAILABLE
        or      eax, eax
        cmovne  ebx, dword [_yes]
        cmove   ebx, dword [_no]
        mov     dword [_sse42 + 11], ebx

        invoke  IsProcessorFeaturePresent, PF_AVX_INSTRUCTIONS_AVAILABLE
        or      eax, eax
        cmovne  ebx, dword [_yes]
        cmove   ebx, dword [_no]
        mov     dword [_avx + 11], ebx

        invoke  IsProcessorFeaturePresent, PF_AVX2_INSTRUCTIONS_AVAILABLE
        or      eax, eax
        cmovne  ebx, dword [_yes]
        cmove   ebx, dword [_no]
        mov     dword [_avx2 + 11], ebx

        invoke  IsProcessorFeaturePresent, PF_AVX512F_INSTRUCTIONS_AVAILABLE
        or      eax, eax
        cmovne  ebx, dword [_yes]
        cmove   ebx, dword [_no]
        mov     dword [_avx512f + 11], ebx

        invoke  GetModuleHandle,0
        invoke  DialogBoxParam,eax,IDD_MAIN,HWND_DESKTOP,DialogProc,0
        or      eax,eax
        jz      exit
  exit:
        invoke  ExitProcess,0

itoa:                      ;-) Nice code snippet by Pauli Lindgren  (https://pkl.paldex.fi/)
; INPUT:  EAX
; OUTPUT: _number
; LEN OF OUTPUT: EBX
         mov     ecx, 10
         xor     ebx, ebx

.divide:
         xor     edx, edx
         div     ecx
         push    edx
         inc     ebx
         test    eax, eax
         jnz     .divide

         mov     ecx, ebx
         lea     esi, [_number]
.next:
         pop     eax
         add     al, '0'
         mov     [esi], al
         inc     esi
         loop    .next
         ret

proc DialogProc hwnddlg,msg,wparam,lparam
        push    ebx esi edi
        cmp     [msg],WM_INITDIALOG
        je      .wminitdialog
        cmp     [msg],WM_CLOSE
        je      .wmclose
        xor     eax,eax
        jmp     .finish
  .wminitdialog:
        ;invoke  GetDlgItem,[hwnddlg],IDC_CPUNAME
        ;mov     [hwndcpuname],eax
        ;invoke  GetDlgItem,[hwnddlg],IDC_CORES
        ;mov     [hwndcores],eax
        invoke  GetDlgItem,[hwnddlg],IDC_FEATURES
        mov     [hwndfeatures],eax

        invoke  SetDlgItemText,[hwnddlg],IDC_CPUNAME,_name
        invoke  SetDlgItemText,[hwnddlg],IDC_CORES,_number
        invoke  SendMessage, [hwndfeatures], LB_ADDSTRING,0, _mmx
        invoke  SendMessage, [hwndfeatures], LB_ADDSTRING,0,_sse3
        invoke  SendMessage, [hwndfeatures], LB_ADDSTRING,0,_ssse3
        invoke  SendMessage, [hwndfeatures], LB_ADDSTRING,0,_sse41
        invoke  SendMessage, [hwndfeatures], LB_ADDSTRING,0,_sse42
        invoke  SendMessage, [hwndfeatures], LB_ADDSTRING,0,_avx
        invoke  SendMessage, [hwndfeatures], LB_ADDSTRING,0,_avx2
        invoke  SendMessage, [hwndfeatures], LB_ADDSTRING,0,_avx512f
;        invoke  SendMessage[hwndfeatures], LB_SETITEMDATA,1,0

        ;invoke  SendMessage,[hwndcpuname],EM_SETSEL,0,-1
        ;invoke  SetFocus,[hwndcpuname]
        jmp     .processed
  .wmclose:
        invoke  EndDialog,[hwnddlg],0
  .processed:
        mov     eax,1
  .finish:
        pop     edi esi ebx
        ret
endp

section '.data' data readable writeable

  _mmx        db 'MMX    ',9,'-       ',0
  _sse3       db 'SSE3   ',9,'-       ',0
  _ssse3      db 'SSSE3  ',9,'-       ',0
  _sse41      db 'SSE4.1 ',9,'-       ',0
  _sse42      db 'SSE4.2 ',9,'-       ',0
  _avx        db 'AVX    ',9,'-       ',0
  _avx2       db 'AVX2   ',9,'-       ',0
  _avx512f    db 'AVX512F',9,'-       ',0  ;11th pos
  _yes        db 'Yes '
  _no         db 'No  '
  _core       dd ?
  _len        dd ?
  hwndcpuname dd ?
  hwndcores   dd ?
  hwndfeatures dd ?
  _number     rb 10
  _name       rb 48


section '.idata' import readable

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL'

  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         IsProcessorFeaturePresent, 'IsProcessorFeaturePresent',\
         ExitProcess,'ExitProcess'

  import user,\
         DialogBoxParam,'DialogBoxParamA',\
         EndDialog,'EndDialog' ,\
         SetDlgItemText,'SetDlgItemTextA',\
         GetDlgItemText,'GetDlgItemTextA',\
         GetDlgItem,'GetDlgItem',\
         SendMessage,'SendMessageA',\
         SetFocus,'SetFocus'

section '.rsrc' resource data readable

  directory RT_DIALOG,dialogs,\
            24,manifest

  resource dialogs,\
           IDD_MAIN,LANG_ENGLISH+SUBLANG_DEFAULT,main_dialog

  dialog main_dialog,'CPU-Y',0,0,400,250,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
     dialogitem 'STATIC','CPU Name',-1,10,10,70,15,WS_VISIBLE
     dialogitem 'EDIT','0',IDC_CPUNAME,80,10,250,15,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_AUTOHSCROLL+ES_READONLY
     dialogitem 'STATIC','CPU Cores',-1,10,30,70,15,WS_VISIBLE
     dialogitem 'EDIT','0',IDC_CORES,80,30,50,15,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_AUTOHSCROLL+ES_READONLY
     dialogitem 'STATIC','Processor Features',-1,10,60,70,15,WS_VISIBLE
     dialogitem 'LISTBOX','0',IDC_FEATURES,10,75,330,120,WS_VISIBLE+WS_TABSTOP+WS_BORDER+LBS_USETABSTOPS
  enddialog

  resource  manifest,\
            1, LANG_NEUTRAL, winxp

resdata winxp
      ;  file 'manifest.xml'
db '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',13,10
db '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">',13,10
db '<assemblyIdentity',13,10
    db 'version="1.0.0.0"',13,10
    db 'processorArchitecture="X86"',13,10
    db 'name="CompanyName.ProductName.Application"',13,10
    db 'type="win32"',13,10
db  '/>',13,10
db '<description>Your application description here.</description>',13,10
db '<dependency>',13,10
    db '<dependentAssembly>',13,10
        db '<assemblyIdentity',13,10
            db 'type="win32"',13,10
            db  'name="Microsoft.Windows.Common-Controls"',13,10
            db 'version="6.0.0.0"',13,10
            db 'processorArchitecture="X86"',13,10
            db 'publicKeyToken="6595b64144ccf1df"',13,10
            db 'language="*"',13,10
       db  '/>',13,10
    db '</dependentAssembly>',13,10
db '</dependency>',13,10
db '</assembly>'
endres
