
#AutoIt3Wrapper_UseX64=y


#include <winapi.au3>

;Code ausführen im 64-Bit-Modus
;in erste Scriptzeile: #AutoIt3Wrapper_UseX64=y
If Not @AutoItX64 Then Exit (MsgBox(0, "n-Body", "64-Bit not available, Program terminated!"))


Global $w = 800                                              ;Fenstergröße
Global $h = $w
Global $ausgleich = 1E-10                                    ;falls mehrere partikel dieselben parameter haben
Global $dt = 0.000015                                        ;Zeit


;***********************************************************************
Global $particles = 30000                                    ;20000                              ;anzahl partikel
Global $cleanflag = 1                                        ;0=weg zeigen, 1= nur pixel
Global $number_Threads = 16
Global $faktor = $particles / 30                             ;Anpassung Rotationsgeschwindigkeit
;***********************************************************************

$particles -= Mod($particles, 4 * $number_Threads)           ;anzahl partikel anpassen

If Mod($particles, 4 * $number_Threads) <> 0 Then Exit (MsgBox(0, "n-Body Simulation", "$particles must be a multiple of 4*$number_Threads!"))


Global $from = 0, $to = $particles                           ; bei mehreren Threads werden die Berechnungen auf die Threads verteilt
Global $steps = 0, $stepspersecond = 0, $stepspersecondmax = 0

Dim $para_struct[$number_Threads]                            ;jeder thread bekommt seine eigene struct
Dim $param[$number_Threads]                                  ;pointer auf die parameter-struct

Dim $Thread[$number_Threads]                                 ;Threads
Dim $Threadexit[$number_Threads]                             ;exit-code der Threads
Global $minest_ticks = 1e22, $maxest_interacts, $maxest_clockticks, $clockticks, $bench, $bench_ticks
Global $bench_Interacts, $clockticks, $time, $bench_time, $benchtime_fastest = 1e22, $cpuspeed, $cpuspeed_max

;CPU-Stuff for Benchmarking, BIG thx to UEZ
Global $iCPUCores = _WinAPI_GetCPUCoreCount(), $sStructPPI, $hDLLPowrProf = DllOpen("PowrProf.dll"), $i
For $i = 1 To $iCPUCores
    $sStructPPI &= "ulong Number                             ;ulong MaxMhz;ulong CurrentMhz;ulong MhzLimit;ulong MaxIdleState;ulong CurrentIdleState;"
Next
Global $tPROCESSOR_POWER_INFORMATION = DllStructCreate($sStructPPI)
Global $aTotalCPUCurInfo, $aCPUsCurInfo, $aPercents
Global $CPU_Name = RegRead("HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0", "ProcessorNameString")
;~ If @error Then Exit ConsoleWrite("Error calling _CPUGetIndividualProcessorTimes():" & @error & ", @extended = " & @extended & @CRLF)
Global $aTotalCPUPrevInfo = _CPUGetTotalProcessorTimes()
If @error Then Exit ConsoleWrite("Error calling _CPUGetTotalProcessorTimes():" & @error & ", @extended = " & @extended & @CRLF)


$gui = GUICreate("n-body", $w, $h, 0, 0)
AutoItSetOption("GUIOnEventMode", 1)
GUISetOnEvent(-3, "Ende")
GUISetState()
$DC_gui = _WinAPI_GetDC($gui)                                ;DeviceContext GUI holen
Global $ptr1, $hbmp1
$DC_bmp = _CreateNewBmp32($w, $h, $ptr1, $hbmp1)             ;leere Bitmap
;~     ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ptr1 = ' & $ptr1 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

$bmp_struct = DllStructCreate("dword[" & $w * $h & "]", $ptr1)
$leer_struct = DllStructCreate("byte[" & $w * $h * 4 & "]", $ptr1)

$leerstring = ""                                             ;string mit w*w*4 chr(0) zum löschen der Bitmap ;o)
Do
    $leerstring &= $leerstring & Chr(0)
Until StringLen($leerstring) > $w * $h * 4
$leerstring = StringLeft($leerstring, $w * $h * 4)


$col_struct = DllStructCreate("int[" & $particles & "]")     ;Farben
;struct of arrays ist wesentlich schneller als array of structs (später mit asm-SIMD oder c++)
$x_struct = DllStructCreate("float [" & $particles & "]")    ;Koordinaten
$y_struct = DllStructCreate("float [" & $particles & "]")    ;
$z_struct = DllStructCreate("float [" & $particles & "]")    ;
$vx_struct = DllStructCreate("float [" & $particles & "]")   ;Geschwindigkeiten
$vy_struct = DllStructCreate("float [" & $particles & "]")   ;
$vz_struct = DllStructCreate("float [" & $particles & "]")   ;


$pi = 4 * ATan(1)                                            ;  zwei Kreisförmige Partikelwolken erstellen
For $i = 1 To $particles
    $a = Random(-$pi, $pi)
    $b = Random(-$pi, $pi)                                   ;    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $b = ' & $b & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    If $a > $b Then                                          ;swap
        $c = $a
        $a = $b
        $b = $c
    EndIf
    ;    $z=random(-1,1)*$w/3*sin($t)
    If Mod($i, 2) Then                                       ;zwei Wolken
        $u = 0.3
        DllStructSetData($col_struct, 1, 0xFF000000 + Random(0, 0x00FFFF, 1), $i) ;zufällige Farben blau
    Else
        $u = 0.7
        DllStructSetData($col_struct, 1, 0xFF000000 + Random(0xFF00FF, 0xFFFF00, 1), $i) ;zufällige Farben rot
    EndIf
    $t = Random($a, $b)
    $x = $u + Random(-1, 1) * 1 / 3 * Sin($t)
    $y = $u + Random(-1, 1) * 1 / 3 * Cos($t)
    DllStructSetData($x_struct, 1, $x, $i)                   ;koordinaten mit zufälligen floats füllen
    DllStructSetData($y_struct, 1, $y, $i)                   ;
    DllStructSetData($z_struct, 1, Random(-0.2, .2), $i)     ;

    $vx = ($y - $u) * $faktor                                ;Geschwindigkeiten der Rotation
    $vy = -($x - $u) * $faktor
    DllStructSetData($vx_struct, 1, $vx, $i)
    DllStructSetData($vy_struct, 1, $vy, $i)
Next

For $i = 0 To $number_Threads - 1
    $para_struct[$i] = DllStructCreate("dword BITMAP;" & _
            "float W; float SIZE; dword PARTICLES;" & _
            "dword XSTRUCT; dword YSTRUCT; dword ZSTRUCT;" & _
            "dword vxSTRUCT ; dword vySTRUCT; dword vzSTRUCT; float AUSGLEICH;" & _
            "float DT; dword FROM; dword TO; uint64 TICKS")

    DllStructSetData($para_struct[$i], "BITMAP", DllStructGetPtr($bmp_struct)) ;eax
    DllStructSetData($para_struct[$i], "W", $w)              ;eax+4
    DllStructSetData($para_struct[$i], "SIZE", $w * $w * 4)  ;eax+8
    DllStructSetData($para_struct[$i], "PARTICLES", $particles) ;eax+12
    DllStructSetData($para_struct[$i], "XSTRUCT", DllStructGetPtr($x_struct));eax+16
    DllStructSetData($para_struct[$i], "YSTRUCT", DllStructGetPtr($y_struct));eax+20
    DllStructSetData($para_struct[$i], "ZSTRUCT", DllStructGetPtr($z_struct));eax+24
    DllStructSetData($para_struct[$i], "vxSTRUCT", DllStructGetPtr($vx_struct));eax+28
    DllStructSetData($para_struct[$i], "vySTRUCT", DllStructGetPtr($vy_struct));eax+32
    DllStructSetData($para_struct[$i], "vzSTRUCT", DllStructGetPtr($vz_struct));eax+36
    DllStructSetData($para_struct[$i], "AUSGLEICH", 1E-3)    ;eax+40
    DllStructSetData($para_struct[$i], "DT", $dt)            ;eax+44
    DllStructSetData($para_struct[$i], "FROM", $from)        ;eax+48
    DllStructSetData($para_struct[$i], "TO", $to)            ;eax+52
    DllStructSetData($para_struct[$i], "TICKS", 0)           ;eax+56  int64

    $param[$i] = DllStructGetPtr($para_struct[$i])
Next

$binarycode = "0x4883EC040FAE1C2431C0810C24408900000FAE14248B04244883C404575653554831F64831C05052510FA2595A580F3189D64848C1E620484809C64189C867418B483467458B780C67458B481067458B501467458B581867458B601C67458B682067458B702467418B5028660F6EE2660F70E40067418B502C660F6EDA660F70DB0083E90190909090909090909090906766450F6E1C8966450F70DB006766450F6E248A66450F70E4006766450F6E2C8B66450F70ED00BB00000000450F57C0450F57C9450F57D2909090909090909067410F282C9967410F28349A67410F283C9B410F5CEB410F5CF4410F5CFD660F6FC5660F6FCE660F6FD70F59ED0F59F60F59FF0F58EE0F58EF0F58EC0F52ED660F6FF50F59ED0F59EE0F59C50F59CD0F59D5440F58C0440F58C9440F58D283C3044439FB759A440F59C3440F59CB440F59D36766410F6E2C8C6766410F6E748D006766410F6E3C8E440F58C5440F58CE440F58D7F2450F7CC0F2450F7CC9F2450F7CD2F2450F7CC0F2450F7CC9F2450F7CD26766450F7E048C6766450F7E4C8D006766450F7E148E83E90167413B48300F8DEAFEFFFF67418B583483EB04909067410F282C9967410F28349A67410F283C9B67410F28049C67410F284C9D0067410F28149E0F59C30F59CB0F59D30F58E80F58F10F58FA6766410FE72C996766410FE7349A6766410FE73C9B83EB0467413B58307DA84831C05052510FA2595A580F3189D74848C1E720484809C7484829F74867498978385D5B5E5FC3" ;code in Speicher schreiben
Global $tCodeBuffer = _dllstructcreate16("byte[" & StringLen($binarycode) * 2 + 2 & "]") ;reserve Memory for opcodes
DllStructSetData($tCodeBuffer, 1, $binarycode)               ;write opcodes into memory
;msgbox(0,0,dllstructgetptr($tCodeBuffer))
$binarycode = "0x5756535531C04189C84189D667458B680C67458B481067458B501467458B1867458B6004B8000080BF660F6ED8660F70DB00B80000803F660F6EE0660F70E40066410F6EC4F30F5BC0660F7EC0F7E0C1E0024189C748C7C70000000048C7C200000000909090909090909090909090904183ED0467430F2804A90F28E8660F66EB0F28F0660F66F40F55F00F28C60F54C567430F280CAA66410F6ED4660F70D2000F59C20F59CAF30F5BC0F30F5BC9F30F5BD2660F6FD9660FF4DA660F70C9F5660FF4CA660F70C991660FFECB660FFEC1660F72F00248C7C104000000660F7EC783FF007E164439FF7D114401DF4489EB01CB83EB0167418B049EAB660F70C093E2DA4183FD000F8F63FFFFFF5D5B5E5FC3" ;code in Speicher schreiben
Global $tCodeBuffer_plot = _dllstructcreate16("byte[" & StringLen($binarycode) * 2 + 2 & "]") ;reserve Memory for opcodes
DllStructSetData($tCodeBuffer_plot, 1, $binarycode)          ;write opcodes into memory

$ptr_asm = DllStructGetPtr($tCodeBuffer)                     ;pointer auf den assemblercode

$sum_Threadnumber = 0
$sum_Threadnumber += 0                                       ;summe aller Threadnummern
For $i = 1 To $number_Threads
    $sum_Threadnumber += $i
Next

Global $bench_Interacts = 0, $bench_ticks = 0, $bench = 0
Global $steps = 0, $stepspersecond = 0, $stepspersecondmax = 0

$ret = DllCall("kernel32.dll", "uint", "SetPriorityClass", "hwnd", _WinAPI_GetCurrentProcess(), "dword", 0x00000080)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret = ' & $ret[0] & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

$overall_time = TimerInit()

While 1                                                      ;Hauptschleife, Threads erstellen und assemblercode zum Berechnen und Anzeigen aufrufen
    $steps += 1
    $t = TimerInit()
    For $i = 0 To $number_Threads - 1                        ;anzahl threads starten
        $teiler = Int($particles / $number_Threads)
        $from = $i * $teiler                                 ;jeder thread bekommt nur einen teil der partikel aber berechnet
        $to = $from + $teiler                                ;die kräfte zu jedem vorhandenen Partikel
        If $i = $number_Threads - 1 Then $to = $particles
        DllStructSetData($para_struct[$i], "FROM", $from)    ;eax+48
        DllStructSetData($para_struct[$i], "TO", $to)        ;eax+52
        $ret = DllCall("kernel32.dll", "hwnd", "CreateThread", "ptr", 0, "dword", 0, "int64", $ptr_asm, "int64", $param[$i], "long", 0, "int*", 0)
        $Thread[$i] = $ret[0]
    Next

    $flag = 0
    $sum_Threads = 0
    $loops = 0
    $test = 0
    Do                                                       ;threads are running
        For $i = 0 To $number_Threads - 1
            $Return = DllCall("Kernel32.dll", "uint64", "GetExitCodeThread", "ptr", $Thread[$i], "dword*", 0) ;Rückgabe (EAX) aus den Threads
            If ($Return[2] <> 259) And $Threadexit[$i] = "" Then ;ist Thread bereits fertig?
                $Threadexit[$i] = DllStructGetData($para_struct[$i], "TICKS");Anzahl Clockticks, da TerminateProcess und GetexitCodeThread  nur 32-Bit-Werte zurück gibt!
                $sum_Threads += $i + 1                       ;summe aller Threads
                If $sum_Threadnumber = $sum_Threads Then
                    $flag = 1
                    ExitLoop                                 ;alle Threads fertig
                EndIf
            EndIf
        Next
    Until $flag = 1                                          ;so lange, wie noch keine "alle fertig"- Rückgabe aus den Threads erfolgt

    $ticks = 0
    For $i = 0 To $number_Threads - 1                        ;alle threads terminieren
        $ret = DllCall("Kernel32.dll", "int64", "TerminateProcess", "dword", $Thread[$i], "uint", 999) ;Threads löschen
        $ticks += $Threadexit[$i]                            ;anzahl Clockticks, da TerminateProcess und GetexitCodeThread  nur 32-Bit-Werte zurück gibt!
        $Threadexit[$i] = ""                                 ;feld löschen
    Next

    $m = TimerDiff($t)                                       ;looptime

    $bench += 1                                              ;benchmark-zähler
    If $m < $benchtime_fastest Then $benchtime_fastest = $m  ;schnellste looptime
    $bench_time += $m                                        ;alle looptimes zusammenzählen

    $Ticks_per_Interact = StringFormat("%.2f", $ticks / ($particles ^ 2 / 4))
    If Number($Ticks_per_Interact) < $minest_ticks Then $minest_ticks = Number($Ticks_per_Interact) ;wenigste clockticks

    $bench_ticks += $Ticks_per_Interact                      ;alle ticks/interact
    $Interacts_per_Second = StringFormat("%.2e", $particles ^ 2 / ($m / 1000) * 4)
    If Number($Interacts_per_Second) > $maxest_interacts Then $maxest_interacts = Number($Interacts_per_Second)

    $bench_Interacts += $Interacts_per_Second

    DllCall($hDLLPowrProf, "ulong", "CallNtPowerInformation", _
            "int", 11, _                                     ;http://msdn.microsoft.com/en-us/library/windows/desktop/aa372675(v=vs.85).aspx
            "ptr", 0, _
            "ulong", 0, _
            "ptr", DllStructGetPtr($tPROCESSOR_POWER_INFORMATION), _
            "ulong", DllStructGetSize($tPROCESSOR_POWER_INFORMATION))
    $currentMHZ = DllStructGetData($tPROCESSOR_POWER_INFORMATION, "CurrentMhz")
    $cpuspeed += $currentMHZ

    If $currentMHZ > $cpuspeed_max Then $cpuspeed_max = $currentMHZ

    $stepspersecond += 1 / $m * 1000                         ;vergleichbare Anzahl der Berechnungsschritte pro Sekunde
    If $stepspersecondmax < 1 / $m * 1000 Then $stepspersecondmax = 1 / $m * 1000

    WinSetTitle($gui, "", "n-body  #Particle= " & $particles & "   Interacts/sec= " & $Interacts_per_Second & "  Ticks/Interact= " & $Ticks_per_Interact & "   MaxSteps/sec=" & StringFormat("%.2f", $stepspersecondmax) & "   Threads= " & $number_Threads)
    _pic()                                                   ;pixel anzeigen
WEnd


Func ende()
    _DeleteBitmap32($DC_bmp, $ptr1, $hbmp1)
    _bench($bench, $bench_ticks, $bench_Interacts, $cpuspeed, $minest_ticks, $maxest_interacts, $cpuspeed_max, TimerDiff($overall_time), $bench_time, $benchtime_fastest)
    ShellExecute(@ScriptDir & "\n-Body_bench.txt")
    Exit
EndFunc                                                      ;==>ende

Func _bench($anz, $tick, $inter, $clock, $mintick, $maxinter, $maxclock, $time, $benchtime, $benchtime_fastest)
    $tick = StringFormat("%.2f", $tick / $anz)               ;durchschnitte bilden
    $inter = StringFormat("%.2e", $inter / $anz)
    $clock = StringFormat("%.2f", $clock / $anz)
    $time = StringFormat("%.2f", $time / 1000)
    $benchtime = StringFormat("%.2f", $benchtime / $anz)
    $benchtime_fastest = StringFormat("%.2f", $benchtime_fastest)
    $maxinter = StringFormat("%.2e", $maxinter)
    $stepspersecond = StringFormat("%.2f", $stepspersecond / $steps)
    $stepspersecondmax = StringFormat("%.2f", $stepspersecondmax)
    $text = "Benchmark n-Body-Simulation" & @CRLF & @CRLF & _
            "Number Particles:" & @TAB & @TAB & $particles & @CRLF & _
            "Processor:" & @TAB & @TAB & $CPU_Name & @CRLF & _
            "Number Processors(Cores):" & @TAB & _WinAPI_GetCPUCoreCount() & @CRLF & _
            "Number Threads:" & @TAB & @TAB & $number_Threads & @CRLF & _
            "Overall Time:" & @TAB & @TAB & $time & " Seconds" & @CRLF & _
            "Number Loops benchmarked:" & @TAB & $anz & @CRLF & @CRLF & _
            "Average Interacts/sec:" & @TAB & $inter & @CRLF & _
            "Maximum Interacts/sec:" & @TAB & $maxinter & @CRLF & @CRLF & _
            "Average Steps/sec:" & @TAB & @TAB & $stepspersecond & @CRLF & _
            "Maximum Steps/sec:" & @TAB & $stepspersecondmax & @CRLF & @CRLF & _
            "Average Ticks/Interact:" & @TAB & $tick & "    CAUTION! Depends on real Clockticks!" & @CRLF & _
            "Minimum Ticks/Interact:" & @TAB & $mintick & "    CAUTION! Depends on real Clockticks!" & @CRLF & @CRLF & _
            "Average Clockticks[Mhz]:" & @TAB & Int($clock) & "    CAUTION! Clockticks may NOT match if over/underclocked! Please insert the real Clockticks!" & @CRLF & _
            "Maximum Clockticks[Mhz]:" & @TAB & Int($maxclock) & "    CAUTION! Clockticks may NOT match if over/underclocked! Please insert the real Clockticks!" & @CRLF & @CRLF & _
            "Average Looptime:" & @TAB & @TAB & $benchtime & " Milliseconds" & @CRLF & _
            "Fastest Looptime:" & @TAB & @TAB & $benchtime_fastest & " Milliseconds" & @CRLF & @CRLF
    ConsoleWrite($text)
    FileDelete(@ScriptDir & "\n-Body_bench.txt")
    FileWrite(@ScriptDir & "\n-Body_bench.txt", $text)
EndFunc                                                      ;==>_bench

Func _pic()                                                  ;schreibt die koordinaten in die Bitmap
    If $cleanflag Then DllStructSetData($leer_struct, 1, $leerstring) ;hintergrund leeren
    $Return = DllCallAddress("uint", DllStructGetPtr($tCodeBuffer_plot), "int64", DllStructGetPtr($para_struct[0]), "int64", DllStructGetPtr($col_struct))
    _WinAPI_BitBlt($DC_gui, 0, 0, $w, $h, $DC_bmp, 0, 0, 0xCC0020);bitmap in DC blitten
EndFunc                                                      ;==>_pic





Func _dllstructcreate16($struct)                             ;align auf 16-byte adresse
    $temp = DllStructCreate($struct)
    $tempsize = DllStructGetSize($temp) + 16
    $ptr = DllStructGetPtr($struct)
    $a = Mod(Number($ptr), 16)
    $temp = 0
    $mem = DllCall("kernel32.dll", "ptr", "VirtualAlloc", "ptr", $ptr + $a, "ulong_ptr", $tempsize, "dword", 0x00003000, "dword", 0x00000040)
    $a = Mod(Number($mem[0]), 16)                            ;rest div 16 adresse = offset
    Return DllStructCreate($struct, (Number($mem[0]) - $a + 16)) ;auf 16 alingned pointer
EndFunc                                                      ;==>_dllstructcreate16

Func _CreateNewBmp32_test($iwidth, $iheight, ByRef $ptr, ByRef $hbmp) ;erstellt leere 32-bit-Bitmap; Rückgabe DC und ptr und handle auf die Bitmapdaten
    ;by Andy
    Local $aResult = DllCall("gdi32.dll", "handle", "CreateCompatibleDC", "handle", 0)
    If @error Then Return SetError(@error, @extended, 0)
    Local $hcdc = $aResult[0]                                ;Desktop-Kompatiblen DeviceContext erstellen lassen
    Local $tBMI = DllStructCreate($tagBITMAPINFO)            ;Struktur der Bitmapinfo erstellen und Daten eintragen
    DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4) ;Structgröße abzüglich der Daten für die Palette
    DllStructSetData($tBMI, "Width", $iwidth)
    DllStructSetData($tBMI, "Height", -$iheight)             ;minus =standard = bottomup
    DllStructSetData($tBMI, "Planes", 1)
    DllStructSetData($tBMI, "BitCount", 32)                  ;32 Bit = 4 Bytes => AABBGGRR
    Local $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'uint', 0)
    $hbmp = $adib[0]                                         ;hbitmap handle auf die Bitmap, auch per GDI+ zu verwenden
    $ptr = $adib[4]                                          ;pointer auf den Anfang der Bitmapdaten, vom Assembler verwendet
    Local $aResult = DllCall("gdi32.dll", "handle", "SelectObject", "handle", $hcdc, "handle", $hbmp);objekt hbitmap in DC
    If @error Then Return SetError(@error, @extended, False)
    Return $hcdc                                             ;DC der Bitmap zurückgeben
EndFunc                                                      ;==>_CreateNewBmp32_test


Func _CreateNewBmp32($iwidth, $iheight, ByRef $ptr, ByRef $hbmp) ;erstellt leere 32-bit-Bitmap; Rückgabe $HDC und $ptr und handle auf die Bitmapdaten
    $hcdc = _WinAPI_CreateCompatibleDC(0)                    ;Desktop-Kompatiblen DeviceContext erstellen lassen
    $tBMI = DllStructCreate($tagBITMAPINFO)                  ;Struktur der Bitmapinfo erstellen und Daten eintragen
    DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4);Structgröße abzüglich der Daten für die Palette
    DllStructSetData($tBMI, "Width", $iwidth)
    DllStructSetData($tBMI, "Height", -$iheight)             ;minus =standard = bottomup
    DllStructSetData($tBMI, "Planes", 1)
    DllStructSetData($tBMI, "BitCount", 32)                  ;32 Bit = 4 Bytes => AABBGGRR
    $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'uint', 0)
    $hbmp = $adib[0]                                         ;hbitmap handle auf die Bitmap, auch per GDI+ zu verwenden
    $ptr = $adib[4]                                          ;pointer auf den Anfang der Bitmapdaten, vom Assembler verwendet
    _WinAPI_SelectObject($hcdc, $hbmp)                       ;objekt hbitmap in DC
    Return $hcdc                                             ;DC der Bitmap zurückgeben
EndFunc                                                      ;==>_CreateNewBmp32

Func _DeleteBitmap32($DC, $ptr, $hbmp)
    _WinAPI_DeleteDC($DC)
    _WinAPI_DeleteObject($hbmp)
    $ptr = 0
EndFunc                                                      ;==>_DeleteBitmap32


Func _WinAPI_GetCPUCoreCount()
    Local $tSYSTEM_INFO = DllStructCreate( _
            "ushort dwOemId;" & _
            "short wProcessorArchitecture;" & _
            "dword dwPageSize;" & _
            "ptr lpMinimumApplicationAddress;" & _
            "ptr lpMaximumApplicationAddress;" & _
            "long_ptr dwActiveProcessorMask;" & _
            "dword dwNumberOfProcessors;" & _
            "dword dwProcessorType;" & _
            "dword dwAllocationGranularity;" & _
            "short wProcessorLevel;" & _
            "short wProcessorRevision")
    Local $aRes = DllCall("Kernel32.dll", "none", "GetSystemInfo", "struct*", $tSYSTEM_INFO)
    If @error Or Not IsArray($aRes) Then Return -1
    Return DllStructGetData($tSYSTEM_INFO, "dwNumberOfProcessors")
EndFunc                                                      ;==>_WinAPI_GetCPUCoreCount


Func _CPU_speed()

    DllCall($hDLLPowrProf, "ulong", "CallNtPowerInformation", _
            "int", 11, _                                     ;http://msdn.microsoft.com/en-us/library/windows/desktop/aa372675(v=vs.85).aspx
            "ptr", 0, _
            "ulong", 0, _
            "ptr", DllStructGetPtr($tPROCESSOR_POWER_INFORMATION), _
            "ulong", DllStructGetSize($tPROCESSOR_POWER_INFORMATION))
    $iCPUSpeed_Current = DllStructGetData($tPROCESSOR_POWER_INFORMATION, "CurrentMhz")

    Return $iCPUSpeed_Current
EndFunc                                                      ;==>_CPU_speed



; Author: Ascend4nt
; ==============================================================================================
Func _CPUGetTotalProcessorTimes()
    Local $aRet, $stSystemTimes

    $stSystemTimes = DllStructCreate("int64 IdleTime;int64 KernelTime;int64 UserTime;")

    $aRet = DllCall("kernel32.dll", "bool", "GetSystemTimes", "ptr", DllStructGetPtr($stSystemTimes, 1), _
            "ptr", DllStructGetPtr($stSystemTimes, 2), "ptr", DllStructGetPtr($stSystemTimes, 3))

    If @error Then Return SetError(2, @error, "")
    If Not $aRet[0] Then Return SetError(3, 0, "")

    Dim $aRet[3] = [ _
            DllStructGetData($stSystemTimes, 1), _
            DllStructGetData($stSystemTimes, 2), _
            DllStructGetData($stSystemTimes, 3)]

    Return $aRet
EndFunc                                                      ;==>_CPUGetTotalProcessorTimes












































































