Update 24/03/2010 Etwas Finetuning an den Funktionen, FASM-Assembler(download) integriert, big thx to Ward @ https://autoit.de/www.autoitscript.com
Bitte testen und bei Problemen Betriebssystem 32/64 Bit und auch Info´s zum den Prozessor(!) (übertaktet usw.) mitteilen!
-zzt nur als 32-Bitversion lauffähig....
-ein "Flug" durch das Apfelmännchen (KEIN Video, sondern live berechnet) ist nun möglich! Das Fenster kann während des Fluges geändert werden, sowie auch die Farbpaletten.
-Palettenfarben werden sofort geändert
-Beim Speichern des Bildes werden die Koordinaten in die Datei fractalsave.dat geschrieben, von dort können die "Zielkoordinaten" für einen eigenen Flug in den Quellcode eingetragen werden.
Update 07/03/2010 Farbpalette eingefügt, beliebige Paletten integrierbar, alle Farbwünsche sind möglich ^^, "Bild zurück" funktioniert auch jetzt
Hallo zusammen,
die "alten Zeiten" hatten mich wieder eingeholt, als ich beim Aufräumen einige 5 1/4´´-Disketten fand mit der Aufschrift "Apfelmännchen in Assembler". Leider konnnte der damals aktuelle (und das Viech läuft immer noch!) 8088 "ORGINAL IBM-PC" die Disketten nicht mehr lesen, kein Wunder nach 25 Jahren^^
Damals hatte ich in Basic (erst GW- dann Turbo-bzw. Powerbasic) und Inlineassembler programmiert, die schriftlichen Unterlagen (Handabschriften der Programme, denn Drucker konnte sich kaum ein Normalsterblicher leisten) werden meine Urenkel irgendwann der thermischen Verwertung zuführen.
Jedenfalls konnte ich mich noch daran erinnern, daß ich mir für den 8088 extra einen Co-Prozessor 8087 gekauft hatte, welcher die floating-point Berechnungen extrem (4,77 MHz) beschleunigte. Die Berechnung des Apfelmännchens passte vom Code genau in den 8 Register (a 80-Bit) großen Stack des Coprozessors, welcher PARALLEL zum eigentlichen Prozessor arbeiten konnte und so bei geschickter Programmierung sehr effizient einsetzbar ist.
Naja, daran hat sich nicht viel geändert, der Coprozessorstack ist heutzutage immer noch 8 Register groß (80 Bit) , und weil man heutzutage alles als neu verkaufen kann, was einen neuen Namen hat, hat man diese Register "neu erfunden" und MMX genannt. "Ursprünglich stand das Kürzel MMX für Matrix Math Extensions, wurde allerdings von Intel marketingbedingt in Multi Media Extension umbenannt.[1]"(Zitat Wikipedia)
Naja, das frühere Basic ist heutzutage AutoIt gewichen, und der Inlineassembler.....ja, den gibts bei AutoIt auch (fast jedenfalls^^)
Also hab ich mich wieder in die Bits und Bytes gestürzt, und mit einer Handvoll Assemblerbefehlen (es sind immer noch dieselben wie früher ) AutoIt einen "Turbo" verpasst. Zum "Apfelmännchen" bzw. der Mandelbrotmenge sag ich jetzt weniger, im Anhang findet sich ein simples AutoIt-Script mit der Darstellung (geistert hier auch irgendwo im Forum herum).
Natürlich kann man auch einfach einen C-Compiler anwerfen, eine DLL erstellen und diese aufrufen. Aber einfach kann jeder^^ *******//EDIT Ja, der FASM-Assembler kann auch dll´s erstellen.....//**********
Ausserdem sollte man bemerken, daß sich der Aufwand nur bei langen Berechnungen lohnt, oder wenn es SEHR schnell sein muss, Beispiele finden sich für Verschlüsselung usw...
Nun zum Programm, es ist ziemlich ausführlich dokumentiert, wenn irgendetwas unklar sein sollte, immer Fragen!
Erstellt wird ein Bild der Mandelbrotmenge, die Berechnung der "Farbtiefe" der einzelnen Pixel und der gesamten Bitmap wurde mittels des Assemblerprogramms realisiert. Dabei ist erwähnenswert, daß die eigentliche Berechnung unabhängig von der GUI erfolgt, es ist also ohne weiteres möglich, ein 8000x6000 Pixel großes Bild zu erstellen, ohne daß man eine GUI erstellen muss. Ich bin gerade dabei, das Programm so auszulegen, daß auch Mehrkernprozessoren unterstützt werden. Bei Quadcores sollte eine Geschwindigkeitserhöhung um mindestens Faktor 3 drin sein.
Was bei der Assemblerprogrammierung beachtet werden muß, es gibt KEINERLEI Fehleranzeigen, jeder Fehler führt unweigerlich zum Absturz (des Programms), allerdings ist es möglich, Register- und Speicherinhalte an AutoIt zurückzugeben und dort anzeigen zu lassen. Debugging (und evtl. einen Debugger) setze ich voraus, andererseits lernt man so extrem viel.
Der vom Assembler erstellte Bytecode wird als Datei abgespeichert und kann von jedem Debugger eingelesen werden. Weiterhin ist dieser Bytecode, und das ist ein sehr feiner Nebeneffekt, direkt aus AutoIt OHNE Assembler ausführbar! Das heisst, wenn der Code funktioniert, reichen 5 Zeilen AutoIt-Code, um das Programm ablaufen zu lassen. Der Assemblercode ist etwas seltsam geworden, denn der von mir verwendete (AutoIt-Assembler) erlaubt keine Vorwärtssprünge (rückwärts gehts^^) zu einem Label, das heisst, bei jedem Vorwärtssprung müssen die Bytes der Prozessor-Opcodes gezählt oder ein Debugger angeworfen werden, sehr lästig das ganze, aber leider halten sich die Beteiligten mit Informationen SEHR bedeckt, vieles habe ich durch T&E herausgefunden Man sollte also so wenig wie möglich nach vorne springen.... ********//EDIT Sprünge, Makros und die gesamte moderne Assemblersyntax sind problemlos verwendbar// ************
Die GUI ist sehr bescheiden, die Fenstergröße lässt sich verändern und ein Kontextmenü (rechtsklick in die Grafik) stellt Optionen bereit. Ein Linksklick in die Grafik "zoomt" an der dortigen Position. Weiterhin sollte man beachten, daß, solange der Assemblercode läuft, keine Rückmeldung von AutoIt erfolgt! Aus diesem Grund habe ich mich dazu entschlossen, nach jeder berechneten Zeile in der Grafik aus dem Assemblercode einen Call einer einfachen AutoIt-Funktion aufzurufen, gewissermaßen ein Erlauben von Interrupts. Dieser Call frisst zwar enorm Performance, allerdings ist so gewährleistet, daß das Fenster auf Eingaben reagieren kann. Versucht mal, während der Berechnung zu minimieren....
Eine Bitte hab ich noch an die Pinselquäler, Fachrichtung Farbpaletten. Zur Zeit ist die grafische Ausgabe "bunt", d.h. das Pixel wird einfach aus der berechneten Iterationstiefe bestimmt. Um die aus dem Internet bekannten "schönen" Bilder zu kommen, muß/sollte das Programm mit einer bzw. mehreren Farbpaletten arbeiten. Wer Ideen hat, her damit!
EDIT /Palette eingefügt, weitere folgen....
Die "schönen" Bilder unterscheiden sich nämlich ausschliesslich in dieser Palette, die eigentlichen Bildinformationen sind identisch!
Hier mal Beispielbilder, mit dem Programm erstellt:
[Blockierte Grafik: http://www.abload.de/thumb/test3curq.jpg][Blockierte Grafik: http://www.abload.de/thumb/test1pueo.jpg][Blockierte Grafik: http://www.abload.de/thumb/testtulu.jpg][Blockierte Grafik: http://www.abload.de/thumb/testrcm8.jpg]
Spoiler anzeigen
#include <FASM.au3>
#include <WinAPI.au3>
#include <Memory.au3>
#include <ScreenCapture.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <MemoryConstants.au3>
#include <StructureConstants.au3>
#include <GuiMenu.au3>
#include <MemoryDll.au3>
;#include <GDIConstants.au3>
;Thx to Ward from http://www.AutoIt.com for the great FASM.AU3
;http://www.autoitscript.com/forum/index.ph…ndpost&p=782727
;#include <GDIConstants.au3>
[/autoit] [autoit][/autoit] [autoit]Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 2)
Opt("PixelCoordMode", 2)
Global Const $DIB_RGB_COLORS = 0
[/autoit] [autoit][/autoit] [autoit]Global $winx = 800 ;größe der CLIENT-Fläche!
Global $winy = 600 ;größe der CLIENT-Fläche!
Global $height, $width, $bitmap, $ptr, $pbitmap, $pixelstruct, $zoom
Global $iwidth, $iheight, $hgui, $hdc, $adib, $hcdc, $breite, $tiefe, $maxiter
Global $cx, $cy, $clics, $count = 0, $minimized, $contextflag, $flightflag=0, $newwindowflag=0
global $exitflag=0
Global $wintitle = "Apfelmaennchen by Andy (http://www.AutoIt.de)"
Global $hgui = GUICreate($wintitle, $winx, $winy, -1, -1, $WS_OVERLAPPEDWINDOW); @DesktopWidth, @DesktopHeight)
GUISetOnEvent($GUI_EVENT_CLOSE, "_WindowEvents", $hgui)
GUISetOnEvent($GUI_EVENT_MINIMIZE, "_WindowEvents")
GUISetOnEvent($GUI_EVENT_MAXIMIZE, "_WindowEvents")
GUISetOnEvent($GUI_EVENT_RESTORE, "_WindowEvents")
GUISetOnEvent($GUI_EVENT_RESIZED, "_WindowEvents")
GUISetOnEvent($GUI_EVENT_PRIMARYDown, "_MouseEvents") ;beim UP der linken Maustaste die func aufrufen
$context = GUICtrlCreateContextMenu(-1)
$item1 = GUICtrlCreateMenuItem("Save Picture", $context)
$item2 = GUICtrlCreateMenuItem("Zoom backwards", $context)
;$item3 = GUICtrlCreateMenuItem("Load Picture/File", $context)
$item4 = GUICtrlCreateMenu("Render flight to a nice place....", $context)
$item4_1 = GUICtrlCreateMenuItem("Example 1", $item4)
$item4_2 = GUICtrlCreateMenuItem("Example 2", $item4)
$item4_3 = GUICtrlCreateMenuItem("Example 3", $item4)
$item4_4 = GUICtrlCreateMenuItem("Example 4", $item4)
$item5 = GUICtrlCreateMenu("Zoom", $context)
$item5_1 = GUICtrlCreateMenuItem("Zoom x2", $item5,0,1)
$item5_2 = GUICtrlCreateMenuItem("Zoom x3", $item5,1,1)
$item5_3 = GUICtrlCreateMenuItem("Zoom x4", $item5,2,1)
$item5_4 = GUICtrlCreateMenuItem("Zoom x1.2", $item5,3,1)
$item6 = GUICtrlCreateMenu("Palette", $context)
$item6_1 = GUICtrlCreateMenuItem("Palette1", $item6,0,1)
$item6_2 = GUICtrlCreateMenuItem("Palette2", $item6,1,1)
$item6_3 = GUICtrlCreateMenuItem("Palette3", $item6,2,1)
$item6_4 = GUICtrlCreateMenuItem("Palette4", $item6,3,1)
$item7 = GUICtrlCreateMenuItem("Start new", $context)
GUICtrlSetOnEvent($item1, "_SavePic")
GUICtrlSetOnEvent($item2, "_PicBack")
;GUICtrlSetOnEvent($item3, "_LoadPic")
GUICtrlSetOnEvent($item4_1, "_Flightrender")
GUICtrlSetOnEvent($item4_2, "_Flightrender")
GUICtrlSetOnEvent($item4_3, "_Flightrender")
GUICtrlSetOnEvent($item4_4, "_Flightrender")
GUICtrlSetOnEvent($item5_1, "_zoom")
GUICtrlSetOnEvent($item5_2, "_zoom")
GUICtrlSetOnEvent($item5_3, "_zoom")
GUICtrlSetOnEvent($item5_4, "_zoom")
GUICtrlSetOnEvent($item6_1, "_palette1")
GUICtrlSetOnEvent($item6_2, "_palette2")
GUICtrlSetOnEvent($item6_3, "_palette3")
GUICtrlSetOnEvent($item6_4, "_palette4")
GUICtrlSetOnEvent($item7, "_startnew")
GUICtrlSetState($item5_3,$gui_checked)
GUICtrlSetState($item6_1,$gui_checked)
Global $AsmObj = FAsmInit() ;init assembler
Global $pointer ;pointer auf die Bitmapdaten initialisieren, byref für _createbitmap32()
Global $hbitmap ;hbitmap initialisieren , byref _createbitmap32()
Global $hpicDC = _CreateNewBmp32($winx, $winy, $pointer, $hbitmap) ;neue 32-Bit-Bitmap erstellen, pointer ist nun die Startadresse der Bitmapdaten, hbitmap zum einfachen speichern usw
Global $pointer_palette ;pointer auf die Bitmapdaten initialisieren, byref für _createbitmap32()
Global $hbitmap_palette ;hbitmap initialisieren , byref _createbitmap32()
Global $hpicDC_palette = _CreateNewBmp32($winx, $winy, $pointer_palette, $hbitmap_palette) ;neue 32-Bit-Bitmap für die mit der Farbpalette eingefärbte Bitmap erstellen, pointer ist nun die Startadresse der Bitmapdaten, hbitmap zum einfachen speichern usw
Global $hwinDC = _WinAPI_GetDC($hgui) ;DeviceContext der GUI holen, brauchen wir zum blitten der Bitmaps
[/autoit] [autoit][/autoit] [autoit];Struct erstellen, auf diese Daten greift der Assembler zu
;ich arbeite mit Absicht hier nicht mit den Basepointern, dazu später mehr^^
;Übergabeparameter Name Parameter Größe Adresse(im asm-prog bzw Speicher)
Global $asmstack = DllStructCreate("double startx;" & _;$x0, 8 Byte [EBP]
"double starty;" & _;$y0, 8 Byte [EBP+08]
"double stepx;" & _;$stepx 8 Byte [EBP+10]
"double stepy;" & _;$stepy 8 Byte [EBP+18]
"int tiefe;" & _ ;$tiefe, 4 Byte [EBP+20]
"int maxiter;" & _ ;$maxiter, 4 Byte [EBP+24]
"ptr bmpdata;" & _ ;$bmpdata, 4 Byte [EBP+28]
"int winwidth;" & _ ;$winwidth, 4 Byte [EBP+2C]
"int winheight;" & _ ;winheight) 4 Byte [EBP+30]
"ptr callback;" & _ ;callback 4 Byte [EBP+34]
"ptr bmppalette;" & _ ;2. bitmap 4 Byte [EBP+38]
"ptr palette;" & _ ;Farbpalette 4 Byte [EBP+3C]
"byte [300]"); [EBP+40] platz zum sichern der FPU-Register
Global $data_palette = DllStructCreate("byte[1024]") ;256 colors * 4Byte(32Bitcolor)
;ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $data_palette = ' & DllStructGetPtr($data_palette) & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
Global $showpercentfunc = DllCallbackRegister("showpercent", "int", "") ;aus dem Assemblerprogramm kann man AutoIt-Funktionen aufrufen!
;$a = DllCallbackGetPtr($showpercentfunc)
Global $bytecode = _build_Asmcode() ;erstellt den bytecode aus den Assembleranweisungen
;Bytecode: 0x55DBE38BAC2408000000DD8510000000DD8518000000DD8500000000DD8508000000D9C1D9C18BBD280000008B852C0000008B9D30000000F7E3C1E00203C78BD8C7C000000000C7C1000000008B95200000008BB538000000EB34C7C0000000005253AB33D2C7C3FF000000F7F3C1E2028B853C00000003D08B820100000089065B5A81C6040000003BFB75CC5DC3DDD8DDD8D9C3DEC2C7C0000000003B8D2C0000007C2AC7C100000000DDB540000000608B8534000000FFD061DDA540000000D9C2DEC1DD8500000000D9CADDD841D9C1D9C1D9C1D8C8D9C1D8C8DEE9D8C4D9CADEC9D8C0D8C2D9C0D8C8D9C2D8C8DEC1DB9D200000003995200000000F875DFFFFFF3B85240000000F874BFFFFFF40EBC1
;folgende Zeilen sind nur nötig, wenn man direkt den Bytecode (ohne Assembler) ausführen möchte
; only nessecary if you want to run the bytecode without assembler
Global $pMemory = _MemVirtualAlloc(0, StringLen($bytecode) / 2, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE) ;speicher anfordern für den assemblercode, kann auch ausgelagert werden
Global $tCode = DllStructCreate("byte[" & StringLen($bytecode) / 2 & "]", $pMemory) ;unser Programmcode soll in diesen Speicherbereich
DllStructSetData($tCode, 1, $bytecode) ;Bytecode des Assemblerprogramms in den reservierten Speicherbereich schreiben
AdlibRegister("_ShowPic", 500) ;alle 500ms das Bild darstellen
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]_startnew() ;initialisiere startparameter
GUISetState() ;gui zeigen
_showpic() ;bitblt bitmap into GUI
_palette1() ;palettendaten in die struct schreiben
While 1 ;main loop
Sleep(10) ;OnEventmode....
if $flightflag then flight() ;Menu: Flug ausgewählt
if $newwindowflag then _newwindow() ;size of GUI changed
;tooltip(hex(pixelgetcolor(MouseGetPos(0),MouseGetPos(1),$hgui)/2)&" "&hex($maxiter)&" "&hex($tiefe)) ;anzeige der Pixelfarbe unter dem Mauszeiger
WEnd
Func _NewWindow() ;creates new bitmaps to bitblt into the GUI
$newwindowflag=0
$winsize = WinGetClientSize($hgui);fenstergröße bestimmen
$winx = $winsize[0] ;client-width
$winy = $winsize[1] ;client-height
If $winy < 10 Then
$winy = 10 ;falls das Fenster zu klein wird, bleibt immer noch die Bitmap erhalten
$winx=10
endif
_deletebitmap32($hpicDC, $pointer, $hbitmap);alte bitmap und DC löschen , sets pointer=0, delete hbitmap-object
_deletebitmap32($hpicDC_palette, $pointer_palette, $hbitmap_palette)
$hpicDC = _CreateNewBmp32($winx, $winy, $pointer, $hbitmap) ;neue 32-Bit-Bitmap erstellen mit aktueller Fenster-Client-Größe, pointer ist die Startadresse der Bitmapdaten
$hpicDC_palette = _CreateNewBmp32($winx, $winy, $pointer_palette, $hbitmap_palette) ;neue 32-Bit-Bitmap erstellen mit aktueller Fenster-Client-Größe, pointer ist die Startadresse der Bitmapdaten
_RenderPic() ;Grafik erstellen
EndFunc ;==>_NewWindow
Func _Build_Asmcode()
FAsmReset($AsmObj)
;hier gehts los^^
FasmAdd($AsmObj, " use32 ");
FasmAdd($AsmObj, " push ebp ");Basepointer Register sichern, not really needed, there is no registerpressure^^
FasmAdd($AsmObj, " finit ");copro init
FasmAdd($AsmObj, " mov ebp,dword[ESP+08h] ");lade den Inhalt der 2-Byte-Adresse an der position des 1. Elementes der asmstack-struct ins register EBP (pointer auf die struct)
;EBP ist nun ganz normal zu verwenden und zeigt auf die übergebenen Parameter
FasmAdd($AsmObj, " fld qword[EBP+10h] ");lade die 4 bytes(qword) an der Position Structanfang+10h Bytes in den Coprozessor-Stack st0=stepx
;Damit man nachvollziehen kann, wie die Berechnung vor sich geht, zeige ich immer den aktuellen Copro-Stack
;st0 =stepx
FasmAdd($AsmObj, " fld qword[EBP+18h] ");st0=stepy
;st0 =stepy
;st1 =stepx
FasmAdd($AsmObj, " fld qword[EBP] ");st0=startx=x0 x-position
;st0 =x0
;st1 =stepy
;st2 =stepx
FasmAdd($AsmObj, " fld qword[EBP+08h] ");st0=starty y0
;st0 =y0
;st1 =x0
;st2 =stepy
;st3 =stepx
FasmAdd($AsmObj, " fld st1 ");st0=x
;st0 =x
;st1 =y0
;st2 =x0
;st3 =stepy
;st4 =stepx
FasmAdd($AsmObj, " fld st1 ");st0=y 10
;st0 =y
;st1 =x
;st2 =y0
;st3 =x0
;st4 =stepy
;st5 =stepx
;alle für die Berechnung notwendigen Parameter in die Prozessor-Register eintragen
[/autoit] [autoit][/autoit] [autoit]FasmAdd($AsmObj, " mov edi,dword[EBP+28h] ");startadresse bitmapdaten
FasmAdd($AsmObj, " mov eax,dword[EBP+2Ch] ");eax=winwidth
FasmAdd($AsmObj, " mov ebx,dword[EBP+30h] ");ebx=winheight
FasmAdd($AsmObj, " mul ebx ");eax = winheight*winwidth
FasmAdd($AsmObj, " shl eax,2 ");eax = winheight*winwidth*4 jedes pixel besteht aus 4 Byte
FasmAdd($AsmObj, " add eax,edi ");eax = Adresse letztes pixel der Bitmap
FasmAdd($AsmObj, " mov ebx,eax ");EBX = Adresse letztes pixel der Bitmap
FasmAdd($AsmObj, " mov eax,0 ");EAX = wird die Anzahl der berechneten Iterationen
FasmAdd($AsmObj, " mov ecx,0 ");ECX = counter für Pixelposition in einer Zeile, wenn >width, dann wieder 0
FasmAdd($AsmObj, " mov edx,dword[EBP+20h] ");EDX = tiefe 20
FasmAdd($AsmObj, " mov esi,dword[EBP+38h] ");Pointer auf die 2. Bitmap, diese enthält die durch die Palette umgewandelten Farbpixel
;~ FasmAdd($AsmObj, " mov eax,esi ")
;~ FasmAdd($AsmObj, " pop ebp ");register wiederherstellen
;~ FasmAdd($AsmObj, " ret ");Rücksprung nach AutoIt
FasmAdd($AsmObj, " mainloop: ");Einsprungpunkt für die schleife
FasmAdd($AsmObj, " jmp berechnung ");springe in die Berechnung der Iteration nach @berechnung
FasmAdd($AsmObj, " limit: ");Rücksprungpunkt aus der Berechnung der MAXIteration = EAX, limit erreicht
FasmAdd($AsmObj, " mov eax,0 ");Rücksprungpunkt aus der Berechnung der Iteration = EAX , gewissermassen die "Farbe"
FasmAdd($AsmObj, " ergebnis: ");Rücksprungpunkt aus der Berechnung der Iteration = EAX , gewissermassen die "Farbe"
;Hier ist der Rücksprungpunkt der Berechnungsroutine, in EAX steht die Anzahl der Iterationen also gewissermassen die "Farbe"
;EAX (4 Byte)) wird als "Farbe (AABBGGRR auch 4 Byte)" direkt an die Speicherstelle des Pixels geschrieben
;hier könnte man auch direkt auf eine Farbpalette zugreifen oder den EAX-Wert durch Berechnungen anpassen
;allerdings müssen die Adressen der absoluten Vorwärtssprünge (der jmp nach loop: und vor ergebnis:) von Hand angepasst werden => Debugger hilft
FasmAdd($AsmObj, " push edx ");EDX sichern auf den Stack ACHTUNG! Ergebnis von mul ist EDX:EAX!!!! EDX wird verändert !
FasmAdd($AsmObj, " push ebx ");uuuuhhhh, registerpressure^^
FasmAdd($AsmObj, " mov dword[EDI],eax ");stosd ^^, speichere EAX an adresse ES:EDI (EDI+4) position des pixels in der bitmap
;nun in der zweiten Bitmap die Pixelfarbe aus der Palette holen
FasmAdd($AsmObj, " xor edx,edx ");EDX=0 30
FasmAdd($AsmObj, " mov ebx,0FFh ");EBX=255
FasmAdd($AsmObj, " div ebx ");in EAX steht nun die integerdivision, in EDX steht der Rest! =>edx=modulo(eax,ebx)
FasmAdd($AsmObj, " mov eax,dword[EBP+3Ch] ");anfang der palette
FasmAdd($AsmObj, " shl edx,2 ");edx=edx*4 4 Byte pro Farbe in der palette
FasmAdd($AsmObj, " add edx,eax ");Adresse der Farbe in der palette
FasmAdd($AsmObj, " mov eax,dword[edx+01] ");Farbe in der palette
FasmAdd($AsmObj, " mov dword[ESI],eax ");Farbe aus der palette in die 2. Bitmap schreiben
FasmAdd($AsmObj, " pop ebx ")
FasmAdd($AsmObj, " pop edx ");EDX vom Stack
FasmAdd($AsmObj, " add EDI,4 ");4 Byte dahinter ist die nächste Pixeladresse(Orginaldaten) 40
FasmAdd($AsmObj, " add ESI,4 ");4 Byte dahinter ist die nächste Pixeladresse(2.Bitmap)
FasmAdd($AsmObj, " cmp edi,ebx ");Vergleich aktuelle Pixeladresse mit der letzten Pixeladresse der Bitmap
FasmAdd($AsmObj, " jne mainloop ");springe, wenn nicht gleich (Jump if Not Equal) nach loop: , wenn gleich dann sind alle Pixel berechnet
; FasmAdd($AsmObj, " finit ");copro init
FasmAdd($AsmObj, " pop ebp ");register wiederherstellen
FasmAdd($AsmObj, " ret ");Rücksprung nach AutoIt
FasmAdd($AsmObj, " berechnung: ")
;stack bereinigen, aktuellex x und y auf den stack
FasmAdd($AsmObj, " fstp st0 ");POP stack
;st0 =x
;st1 =y0
;st2 =x0
;st3 =stepy
;st4 =stepx
FasmAdd($AsmObj, " fstp st0 ");POP stack
;st0 =y0
;st1 =x0
;st2 =stepy
;st3 =stepx
;******************x0=x0+stepx
FasmAdd($AsmObj, " fld st3 ");st0=stepx
;st0 =stepx
;st1 =y0
;st2 =x0
;st3 =stepy
;st4 =stepx
FasmAdd($AsmObj, " faddp st2,st0 ");st2=x0+stepx POP 50
;st0 =y0
;st1 =x0+stepx
;st2 =stepy
;st3 =stepx
FasmAdd($AsmObj, " mov eax,0 ");ax = 0
[/autoit] [autoit][/autoit] [autoit]FasmAdd($AsmObj, " cmp ecx,dword[EBP+2Ch] ");vgl ecx mit fensterbreite
FasmAdd($AsmObj, " jl start1 ");wenn micht größer, dann springe zum start1 +2c 16 ohne callback
FasmAdd($AsmObj, " mov ecx,0 ");zähler an den Zeilenanfang der Bitmap
FasmAdd($AsmObj, " fsave [ebp+40h] ");alle Coprozessorregister und den Copro-stack sichern
FasmAdd($AsmObj, " pushad ");alle Prozessorregister sichern
FasmAdd($AsmObj, " mov eax,dword[EBP+34h] ");Adresse der AutoItfunktion in eax laden, evtl Parameter vorher auf den stack pushen
FasmAdd($AsmOBj, " call eax ");AutoIt-Funktion aufrufen, erlaubt einen Interrupt, ansonsten wäre das Fenster während der gesamten Berechnung blockiert
FasmAdd($AsmObj, " popad ");Prozessorregister alle wiederherstellen
FasmAdd($AsmObj, " frstor [ebp+40h] ");coproregister und coprostack wiederherstellen 60
FasmAdd($AsmObj, " fld st2 ");y0=y0+stepy
;st0 =stepy
;st1 =y0
;st2 =x0
;st3 =stepy
;st4 =stepx
FasmAdd($AsmObj, " faddp st1,st0 ");y0=y0+stepy und POP
;st0 =y0+stepy
;st1 =x0
;st2 =stepy
;st3 =stepx
FasmAdd($AsmObj, " fld qword[EBP] ");st0= startx, die spaltenziffern bleiben immer gleich
;st0 =startx=neues x0
;st1 =y0
;st2 =x0
;st3 =stepy
;st4 =stepx
FasmAdd($AsmObj, " fxch st2 ");tausche st2 mit st0
;st0 =x0
;st1 =y0
;st2 =startx=neues x0
;st3 =stepy
;st4 =stepx
FasmAdd($AsmObj, " fstp st0 ");POP
;st0 =y0
;st1 =x0
;st2 =stepy
;st3 =stepx
FasmAdd($AsmObj, " start1: ");Stack wieder aufbauen für die Berechnung
[/autoit] [autoit][/autoit] [autoit]FasmAdd($AsmObj, " inc ecx ");ecx=ecx+1 = ein pixel weiter
FasmAdd($AsmObj, " fld st1 ");x => st0
;st0 =x
;st1 =y0
;st2 =x0
;st3 =stepy
;st4 =stepx
FasmAdd($AsmObj, " fld st1 ");y => st0
;st0 =y
;st1 =x
;st2 =y0
;st3 =x0
;st4 =stepy
;st5 =stepx
FasmAdd($AsmObj, " start: ");die "innere schleife" , Berechnung von x^2-y^2+x0 und 2*x*y+y0 und vergleich 70
FasmAdd($AsmObj, " fld st1 ");x => st0
;st0 =x
;st1 =y
;st2 =x
;st3 =y0
;st4 =x0
FasmAdd($AsmObj, " fmul st0,st0 ");st0 = x^2
;st0 =x^2
;st1 =y
;st2 =x
;st3 =y0
;st4 =x0
FasmAdd($AsmObj, " fld st1 "); y=> st0
;st0 =y
;st1 =x^2
;st2 =y
;st3 =x
;st4 =y0
;st5 =x0
FasmAdd($AsmObj, " fmul st0,st0 ");st0 = y^2
;st0 =y^2
;st1 =x^2
;st2 =y
;st3 =x
;st4 =y0
;st5 =x0
FasmAdd($AsmObj, " fsubp st1,st0 ");st0 = x^2-y^2
;st0 =x^2-y^2
;st1 =y
;st2 =x
;st3 =y0
;st4 =x0
FasmAdd($AsmObj, " fadd st0,st4 ");st0 = x^2-y^2+x0
[/autoit] [autoit][/autoit] [autoit];st0 =x^2-y^2+x0
;st1 =y
;st2 =x
;st3 =y0
;st4 =x0
FasmAdd($AsmObj, " fxch st2 ");st0 = x
;st0 =x
;st1 =y
;st2 =x^2-y^2+x0
;st3 =y0
;st4 =x0
FasmAdd($AsmObj, " fmulp st1,st0 ");st0 = x*y
;st0 =y*x
;st1 =x^2-y^2+x0
;st2 =y0
;st3 =x0
FasmAdd($AsmObj, " fadd st0,st0 ");st0 = x*y+x*y = 2*x*y
;st0 =2*y*x
;st1 =x^2-y^2+x0
;st2 =y0
;st3 =x0
FasmAdd($AsmObj, " fadd st0,st2 ");st0 = x*y+x*y+y = 2*x*y+y0 80
;st0 =2*y*x+y0 neues y
;st1 =x^2-y^2+x0 neues x
;st2 =y0
;st(§) =x0
FasmAdd($AsmObj, " fld st0 ");st0 = y
;st0 =y
;st1 =2*y*x+y0 neues y
;st2 =x^2-y^2+x0 neues x
;st3 =y0
;st4 =x0
FasmAdd($AsmObj, " fmul st0,st0 ");st0 = y^2
;st0 =y^2
;st1 =2*y*x+y0 neues y
;st2 =x^2-y^2+x0 neues x
;st3 =y0
;st4 =x0
FasmAdd($AsmObj, " fld st2 ");st0 = x
;st0 =x
;st1 =y^2
;st2 =2*y*x+y0 neues y
;st3 =x^2-y^2+x0 neues x
;st4 =y0
;st5 =x0
FasmAdd($AsmObj, " fmul st0,st0 ");st0 = x^2
;st0 =x^2
;st1 =y^2
;st2 =2*y*x+y0 neues y
;st3 =x^2-y^2+x0 neues x
;st4 =y0
;st5 =x0
FasmAdd($AsmObj, " faddp st1,st0 ");st0 = y^2+x^2
;FasmAdd($AsmObj, " jmp [user='213939']Exit[/user] ");ansonsten wieder zum :start
;st0 =y^2+x^2
;st1 =2*y*x+y0 neues y
;st2 =x^2-y^2+x0 neues x
;st3 =y0
;st4 =x0
FasmAdd($AsmObj, " fistp dword [EBP+20h] ");aktuellen wert speichern
;st1 =2*y*x+y0 neues y
;st2 =x^2-y^2+x0 neues x
;st3 =y0
;st4 =x0
FasmAdd($AsmObj, " fwait ")
FasmAdd($AsmObj, " cmp dword[EBP+20h],edx ");ist y^2+x^2>tiefe vergleich
FasmAdd($AsmObj, " ja ergebnis ");wenn y^2+x^2 > tiefe dann farbe=eax ausgeben
FasmAdd($AsmObj, " cmp eax,dword[EBP+24h] ");vgl maxiter mit aktueller iteration
FasmAdd($AsmObj, " ja limit ");wenn größer, dann farbe=0 ausgeben 90
FasmAdd($AsmObj, " inc eax ");ax = ax + 1
FasmAdd($AsmObj, " jmp start ");ansonsten wieder zum :start
;ende ASM
$bindata = String(FAsmGetBinary($AsmObj)) ;bytecode
$file = FileOpen("mandel_asm.bin", 18) ;in Datei zum debuggen UND um den Inlinecode für den CallWindowProcW()-call zu erhalten!!!
FileWrite($file, $bindata)
FileClose($file)
ConsoleWrite("Assembler Bytecode: " & $bindata & @CRLF)
Return $bindata ;der binärcode wird zurückgegeben
EndFunc ;==>_Build_Asmcode
Func Asm_mandel($centerx, $centery, $breite, $tiefe, $maxiter, $pointer, $winwidth, $winheight)
$f = $winwidth / $winheight ;verhältnis fensterbreite/fensterhöhe
;Daten in die Struct eintragen, diese Daten werden vom Assemblerprogramm benutzt
;man kann diese Parameter auch "normal" z.B. per MemoryFuncCall("int:cdecl", AsmGetPtr($AsmObj), "ptr", dllstructgetptr($asmstack),"double",$parameter1,"int",Parameter2.....) aufrufen
;aber mit dieser Methode hat man den Vorteil, auch DIREKT den Bytecode verwenden zu können, ohne jedes mal den Assembler-Code zu assemblieren
;ausserdem muss man sich beim Rücksprung nicht um das Aufräumen des Stacks kümmern...
DllStructSetData($asmstack, "startx", $centerx - $breite * 0.5 * (($f - 1) * ($f > 1) + 1)) ;abhängig vom verhältnis ist fensterinhalt immer quadratisch, rund um das Zentrum
DllStructSetData($asmstack, "starty", $centery - $breite * 0.5 * ((1 - $f) * ($f > 1) + $f)) ;
DllStructSetData($asmstack, "stepx", $breite / $winwidth * (($f - 1) * ($f > 1) + 1))
DllStructSetData($asmstack, "stepy", $breite / $winheight * ((1 - $f) * ($f > 1) + $f))
DllStructSetData($asmstack, "tiefe", $tiefe)
DllStructSetData($asmstack, "maxiter", $maxiter)
DllStructSetData($asmstack, "bmpdata", $pointer) ;zeiger auf die bitmapdaten
DllStructSetData($asmstack, "winwidth", $winwidth);fensterbreite
DllStructSetData($asmstack, "winheight", $winheight);fensterhöhe
DllStructSetData($asmstack, "callback", DllCallbackGetPtr($showpercentfunc));Zeiger auf die Einsprungadresse der AutoIt-Func
DllStructSetData($asmstack, "bmppalette", $pointer_palette);fensterhöhe
DllStructSetData($asmstack, "palette", DllStructGetPtr($data_palette));fensterhöhe
;entweder kann man nun aus dem Assembler den....
;$ret=MemoryFuncCall("int:cdecl", FAsmGetFuncPtr($AsmObj), "ptr", dllstructgetptr($asmstack)) ;Assembler aufrufen und Code starten
;_arraydisplay($ret) ;alle rückgabeparameter ansehen
; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret = ' & hex($ret[0]) & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
;return ;wer mag, kann das return auskommentieren und den MemoryFuncCall() und dann den unteren Code laufen lassen
[/autoit] [autoit][/autoit] [autoit];....aufrufen, oder auch die folgende Variante:
;sie hat den Vorteil, daß man den fertigen Bytecode aufrufen kann OHNE den Assembler vorher aufzurufen!
;da die user32.dll in jedem windows vorhanden ist, benötigt man für das Starten des Bytecodes keine weiteren Dateien
$ret = DllCall("user32.dll", "int", "CallWindowProcW", "ptr", $pMemory, "ptr", DllStructGetPtr($asmstack), "int", 0, "int", 0, "int", 0); unsere assemblerfunktion wird aufgerufen
;_arraydisplay($ret) alle Übergabeparameter bzw Rückgabeparameter anschauen
EndFunc ;==>Asm_mandel
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', $DIB_RGB_COLORS, '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
;_arraydisplay($adib)
_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 _MouseEvents()
if $flightflag or $newwindowflag then return ;during flight
$mouse = GUIGetCursorInfo($hgui)
If $mouse[2] Then ;linke maustaste im Fenster
$f = $winx / $winy ;verhältnis fensterbreite/fensterhöhe
$cx = $cx - $breite * (($f - 1) * ($f > 1) + 1) * (0.5 - $mouse[0] / $winx) ;neuer Anfang der Berechnung an der Mausposition für x...
$cy = $cy - $breite * ((1 - $f) * ($f > 1) + $f) * (0.5 - $mouse[1] / $winy) ;...und y- Koordinate
$breite = $breite / $zoom ;neue Fenstergröße willkürlich auf 1/$zoom des ursprünglichen Bildes
;$tiefe =int($tiefe* 1.2)
If $breite > 0.01 Then
$maxiter = 250
Else
$maxiter = (Log($breite) / Log(1.3)) ^ 2
EndIf
; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $maxiter = ' & $maxiter & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$clics += 1
$count = 0
_RenderPic()
EndIf
EndFunc ;==>_MouseEvents
Func _RenderPic()
Opt("GUIOnEventMode", 0) ;oneventmode ausschalten, es soll verhindert werden, daß während des bildaufbaus die gui verändert wird
If $breite < 1E-17 Then MsgBox(0, "Apfelmaennchen", "Eine weitere Vergrößerung könnte infolge der Bereichunterschreitung für 64-Bit-Fließkommazahlen zu unvorhersehbaren Ergebnissen führen :o) ")
$t = TimerInit()
$g = Asm_mandel($cx, $cy, $breite, $tiefe, $maxiter, $pointer, $winx, $winy) ;Assemblercode aufrufen, Bitmap wird im Speicher erstellt
$m = TimerDiff($t)
; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
_showpic()
Opt("GUIOnEventMode", 1)
WinSetTitle($hgui, "", $wintitle)
EndFunc ;==>_RenderPic
Func _showpic()
_WinAPI_BitBlt($hwinDC, 0, 0, $winx, $winy, $hpicDC_palette, 0, 0, $srccopy) ;Bitmap in GUI kopieren
EndFunc ;==>_ShowPic
Func showpercent() ;Wird aus dem Assemblerprogramm aufgerufen, erlaubt Interrupt, ansonsten ist das Fenster für den Zeitraum der Berechnung blockiert!
[/autoit] [autoit][/autoit] [autoit]if $flightflag then return ;during flight
$count += 1 ;zähler für den Fortschritt der Berechnung
;nur jeden 10. Aufruf ans Fenster weitergeben, sonst wird zu sehr gebremst^^
If $count / 10 = Int($count / 10) Then _WinAPI_SetWindowText($hgui, "Berechnung läuft, bitte warten...." & Int($count * 100 / $winy) & "%")
;eventuelle Returnwerte können natürlich vom Assembler ausgewertet werden
EndFunc ;==>showpercent
Func _WindowEvents() ;Fenstergröße geändert usw
;MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$isrendering' & @lf & @lf & 'Return:' & @lf &@gui_ctrlid) ;### Debug MSGBOX
Switch @GUI_CtrlId ;je nach event
Case $GUI_EVENT_CLOSE ;GUI geschlossen
FAsmExit($AsmObj)
_MemVirtualFree($pMemory, 512, $MEM_RELEASE) ;speicher für assemblerdaten freigeben
_WinAPI_DeleteObject($hbitmap) ;bitmap löschen
_WinAPI_DeleteObject($hbitmap_palette) ;bitmap löschen
_WinAPI_DeleteDC($hpicDC) ;DC der Bitmap freigeben
_WinAPI_DeleteDC($hpicDC_palette) ;DC der Bitmap freigeben
_WinAPI_ReleaseDC(0, $hdc) ;
Exit
Case $GUI_EVENT_MINIMIZE ;GUI minimiert
$minimized = 1
Case $GUI_EVENT_MAXIMIZE ;GUI maximiert
$count = 0
$newwindowflag=1
Case $GUI_EVENT_RESTORE ;GUI wiederhergestellt
$count = 0
If $minimized Then
$minimized = 0
Else
$newwindowflag=1
EndIf
Case $GUI_EVENT_RESIZED ;GUI Größe verändert
If $contextflag = 1 Then ;manchmal bekommt das GUI vom Contextmenü ein RESIZED-Event.....
$contextflag = 0
$count = 0
Else
$count = 0
$newwindowflag=1
EndIf
EndSwitch
EndFunc ;==>_WindowEvents
Func _SavePic() ;speichert Bild und die aktuellen Koordinaten in einer Datei
$contextflag = 1
$imgpath = FileSaveDialog("Datei speichern", @ScriptDir, "(*.jpg;*.bmp;*.png)", 16)
If @error Then Return
If StringMid($imgpath, StringLen($imgpath) - 3, 1) <> "." Then $imgpath &= ".JPG"
_ScreenCapture_SaveImage($imgpath, $hbitmap_palette)
$path = StringLeft($imgpath, StringInStr($imgpath, "\", 1, -1)) & "fractalsave.dat"
$file = FileOpen($path, 9)
If @error Then Return MsgBox(0, "Apfelmaennchen-ERROR", "Can not open datafile " & $path & "\fractalsave.dat")
FileWriteLine($file, $imgpath)
FileWriteLine($file, "cx=" & $cx)
FileWriteLine($file, "cy=" & $cy)
FileWriteLine($file, "breite=" & $breite)
FileWriteLine($file, "tiefe=" & $tiefe)
FileWriteLine($file, "maxiter=" & $maxiter)
FileWriteLine($file, ";*****************************")
FileClose($file)
$contextflag = 0
EndFunc ;==>_SavePic
Func _PicBack() ;contextmenu Bild zurück
$contextflag = 1
_showpic()
$breite = $breite * $zoom ;neue Fenstergröße willkürlich auf 1/$zoom des ursprünglichen Bildes
$tiefe = 4
$maxiter = Int($maxiter / 1.2)
_newwindow()
$contextflag = 0
EndFunc ;==>_PicBack
Func _FlightRender() ;Contextmenu Flug rendern
$flightflag=1
Switch @GUI_CtrlId
Case $item4_1
$cx = -1.76853670262974 ;koordinaten des Flugziels
$cy = -0.000753954632767545
_palette1()
Case $item4_2
$cx = -1.2546083918954
$cy = 0.381668128065955
$cx=0.439737459322262
$cy=-0.358206511283955
_palette2()
Case $item4_3
$cx = -0.105349652406611
$cy = 0.925719416059085
_palette4()
Case $item4_4
$cx = -0.711196644430243
$cy = 0.353463499946954
_palette3()
EndSwitch
endfunc
func Flight()
AdlibUnRegister("_ShowPic") ;alle 500ms das Bild darstellen
guictrlsetstate($item4,$GUI_DISABLE)
$flightflag=1
$breite = 5
$tiefe = 5
$maxiter = 110
$zoom = 1.05
WinMove($hgui, "", Default, Default, 200, 230)
_newwindow()
For $i=3 to 1 step -1
WinSettitle($hgui,"",$i)
sleep(1000)
next
$exitflag=0
$contextflag = 1
$wintitle = "Flight..."
For $i = 1 To 600
If $i < 100 Then Sleep(30)
If $i > 400 Then $zoom = 1.1
If $i > 450 Then $zoom = 1.2
$breite /= $zoom
if $newwindowflag then _newWindow()
_renderpic()
if $exitflag then exitloop
If $breite < 3E-17 Then
MsgBox(0, "Fractalflight", "...this is the End of the flight!" & @CRLF & @CRLF & "The magnification ratio to the first picture is now a trillion, which is one million millions....i hope you have enjoyed it!")
If BitAnd(wingetstate($hgui), 16) then guisetstate(@sw_restore,$hgui)
ExitLoop
EndIf
$maxiter *= 1.008
;consolewrite($i&" "&$maxiter & @CRLF )
Next
$wintitle = "Apfelmaennchen by Andy (http://www.AutoIt.de)"
WinMove($hgui, "", Default, Default, 800, 600)
_startnew()
; _renderpic()
$contextflag = 0
$flightflag=0
guictrlsetstate($item4,$GUI_ENABLE)
AdlibRegister("_ShowPic", 500) ;alle 500ms das Bild darstellen
EndFunc ;==>_FlightRender
Func _Loadpic() ;contextmenu Bild laden, bzw Koordinaten aus Datei
$contextflag = 1
_showpic()
ToolTip("Coming soon :o)")
Sleep(1000)
ToolTip("")
$contextflag = 0
EndFunc ;==>_Loadpic
Func _zoom() ;zoomen
$contextflag = 1
Switch @GUI_CtrlId
Case $item5_1
$zoom = 2
Case $item5_2
$zoom = 3
Case $item5_3
$zoom = 4
Case $item5_4
$zoom = 1.2
EndSwitch
$contextflag = 0
EndFunc ;==>_zoom
Func _Palette1()
$contextflag = 1
GUICtrlSetState($item6_1,$gui_checked)
$palette = "0x0000000000000003000000070000000B0000000F00000013000000170000001B0000001F00000023000000270000002B0000002F00000033000000370000003B0000003F00000043000000470000004B0000004F00000053000000570000005B0000005F00000063000000670000006B0000006F00000073000000770000007B0000007F00000083000000870000008B0000008F00000093000000970000009B0000009F000000A3000000A7000000AB000000AF000000B3000000B7000000BB000000BF000000C3000000C7000000CB000000CF000000D3000000D7000000DB000000DF000000E3000000E7000000EB000000EF000000F3000000F7000000FB000000FF000003FF000007FF00000BFF00000FFF000013FF000017FF00001BFF00001FFF000023FF000027FF00002BFF00002FFF000033FF000037FF00003BFF00003FFF000043FF000047FF00004BFF00004FFF000053FF000057FF00005BFF00005FFF000063FF000067FF00006BFF00006FFF000073FF000077FF00007BFF00007FFF000083FF000087FF00008BFF00008FFF000093FF000097FF00009BFF00009FFF0000A3FF0000A7FF0000ABFF0000AFFF0000B3FF0000B7FF0000BBFF0000BFFF0000C3FF0000C7FF0000CBFF0000CFFF0000D3FF0000D7FF0000DBFF0000DFFF0000E3FF0000E7FF0000EBFF0000EFFF0000F3FF0000F7FF0000FBFF0000FFFF0003FFFF0007FFFF000BFFFF000FFFFF0013FFFF0017FFFF001BFFFF001FFFFF0023FFFF0027FFFF002BFFFF002FFFFF0033FFFF0037FFFF003BFFFF003FFFFF0043FFFF0047FFFF004BFFFF004FFFFF0053FFFF0057FFFF005BFFFF005FFFFF0063FFFF0067FFFF006BFFFF006FFFFF0073FFFF0077FFFF007BFFFF007FFFFF0083FFFF0087FFFF008BFFFF008FFFFF0093FFFF0097FFFF009BFFFF009FFFFF00A3FFFF00A7FFFF00ABFFFF00AFFFFF00B3FFFF00B7FFFF00BBFFFF00BFFFFF00C3FFFF00C7FFFF00CBFFFF00CFFFFF00D3FFFF00D7FFFF00DBFFFF00DFFFFF00E3FFFF00E7FFFF00EBFFFF00EFFFFF00F3FFFF00F7FFFF00FBFFFF00FFFFFF00FBFBFB00F7F7F700F3F3F300EFEFEF00EBEBEB00E7E7E700E3E3E300DFDFDF00DBDBDB00D7D7D700D3D3D300CFCFCF00CBCBCB00C7C7C700C3C3C300BFBFBF00BBBBBB00B7B7B700B3B3B300AFAFAF00ABABAB00A7A7A700A3A3A3009F9F9F009B9B9B0097979700939393008F8F8F008B8B8B0087878700838383007F7F7F007B7B7B0077777700737373006F6F6F006B6B6B0067676700636363005F5F5F005B5B5B0057575700535353004F4F4F004B4B4B0047474700434343003F3F3F003B3B3B0037373700333333002F2F2F002B2B2B0027272700232323001F1F1F001B1B1B0017171700131313000F0F0F000B0B0B0007070700030303"
DllStructSetData($data_palette, 1, $palette)
$contextflag = 0
; GUICtrlSetState($item6_1,$gui_checked)
_Asmcode_changecolor()
_GUICtrlMenu_CheckRadioItem(GUICtrlGetHandle($item6),0,3,0)
EndFunc ;==>_Palette1
Func _Palette2()
$contextflag = 1
$palette = "0x0000000000FEFB7E00FEF77D00FEF47B00FEF07A00FDED7900FDE97700FDE67600FDE27500FCDF7300FCDB7200FCD87000FCD46F00FBD16E00FBCD6C00FBCA6B00FBC66A00FBC36800FABF6700FABC6500FAB86400FAB56300F9B16100F9AE6000F9AA5F00F9A75D00F8A35C00F8A05A00F89C5900F8995800F7955600F7925500F78E5400F78A5200F7875100F6834F00F6804E00F67C4D00F6794B00F5754A00F5724900F56E4700F56B4600F4674400F4644300F4604200F45D4000F3593F00F3563E00F3523C00F34F3B00F34B3900F2483800F2443700F2413500F23D3400F13A3300F1363100F1333000F12F2E00F02C2D00F0282C00F0252A00F0212900F01E2800EE212B00EC252E00EA283200E92C3500E72F3800E5333C00E3363F00E23A4200E03D4600DE414900DC444C00DB485000D94B5300D74F5700D5525A00D4565D00D2596100D05D6400CE606700CD646B00CB676E00C96B7100C76E7500C6727800C4757B00C2797F00C07C8200BF808600BD838900BB878C00B98A9000B88E9300B6929600B4959A00B2999D00B19CA000AFA0A400ADA3A700ABA7AB00AAAAAE00A8AEB100A6B1B500A4B5B800A3B8BB00A1BCBF009FBFC2009DC3C5009CC6C9009ACACC0098CDCF0096D1D30095D4D60093D8DA0091DBDD008FDFE0008EE2E4008CE6E7008AE9EA0088EDEE0087F0F10085F4F40083F7F80081FBFB0080FFFF007EFDFF007CFBFF007AF9FF0078F7FF0076F5FF0074F3FF0072F1FF0070EFFF006EEDFF006CEBFF006AE9FF0068E7FF0066E5FF0064E3FF0062E1FF0060DFFF005EDDFF005CDBFF005AD9FF0058D7FF0056D5FF0054D3FF0052D1FF0050CFFF004ECDFF004CCBFF004AC9FF0048C7FF0046C5FF0044C3FF0042C1FF0040BFFF003EBDFF003CBBFF003AB9FF0038B7FF0036B5FF0034B3FF0032B1FF0030AFFF002EADFF002CABFF002AA9FF0028A7FF0026A5FF0024A3FF0022A1FF00209FFF001E9DFF001C9BFF001A99FF001897FF001695FF001493FF001291FF00108FFF000E8DFF000C8BFF000A89FF000887FF000685FF000483FF000281FF000080FF000381FD000783FB000B85F9000F87F7001389F500178BF3001B8DF1001F8FEF002391ED002793EB002B95E9002F97E7003399E500379BE3003B9DE1003F9FDF0043A1DD0047A3DB004BA5D9004FA7D70053A9D50057ABD3005BADD1005FAFCF0063B1CD0067B3CB006BB5C9006FB7C70073B9C50077BBC3007BBDC1007FBFBF0083C1BD0087C3BB008BC5B9008FC7B70093C9B50097CBB3009BCDB1009FCFAF00A3D1AD00A7D3AB00ABD5A900AFD7A700B3D9A500B7DBA300BBDDA100BFDF9F00C3E19D00C7E39B00CBE59900CFE79700D3E99500D7EB9300DBED9100DFEF8F00E3F18D00E7F38B00EBF58900EFF78700F3F98500F7FB8300FBFD81"
DllStructSetData($data_palette, 1, $palette)
$contextflag = 0
; GUICtrlSetState($item6_2,$gui_checked)
_Asmcode_changecolor()
_GUICtrlMenu_CheckRadioItem(GUICtrlGetHandle($item6),0,3,1)
EndFunc ;==>_Palette2
Func _Palette3()
$contextflag = 1
$palette = "0x000000000000980000019601000293020003910300038E0300048C0400058A050006870600078507000782070008800800097D09000A7B0A000A790A000B760B000C740C000D710D000E6F0E000E6C0E000F6A0F0010681000116511001163110012601200135E1300145C140015591500155715001654160017521700184F1800194D1900194B19001A481A001B461B001C431C001C411C001D3E1D001E3C1E001F3A1F0020372000203520002132210022302200232E2300232B230024292400252625002624260027212700271F2700281D2800291A29002A182A002A152A002B132B002C102C002D0E2D002E0C2E002E092E002F072F00300430003102310032003200330031003500300036002F0038002E0039002E003B002D003C002C003E002B0040002A0041002A0043002900440028004600270047002700490026004B0025004C0024004E0023004F0023005100220052002100540020005500200057001F0059001E005A001D005C001C005D001C005F001B0060001A0062001900640019006500180067001700680016006A0015006B0015006D0014006E0013007000120072001100730011007500100076000F0078000E0079000E007B000D007D000C007E000B0080000A0081000A0083000900840008008600070087000700890006008B0005008C0004008E0003008F0003009100020092000100940000009B0000009C0303009E0707009F0B0B00A10F0F00A2131300A4171700A51B1B00A71F1F00A9232300AA272700AC2B2B00AD2F2F00AF333300B0373700B23B3B00B43F3F00B5434300B7474700B84B4B00BA4F4F00BB535300BD575700BE5B5B00C05F5F00C2636300C3676700C56B6B00C66F6F00C8737300C9777700CB7B7B00CD7F7F00CE838300D0878700D18B8B00D38F8F00D4939300D6979700D79B9B00D99F9F00DBA3A300DCA7A700DEABAB00DFAFAF00E1B3B300E2B7B700E4BBBB00E6BFBF00E7C3C300E9C7C700EACBCB00ECCFCF00EDD3D300EFD7D700F0DBDB00F2DFDF00F4E3E300F5E7E700F7EBEB00F8EFEF00FAF3F300FBF7F700FDFBFB00FFFFFF00FBFDFB00F7FBF700F3FAF300EFF8EF00EBF7EB00E7F5E700E3F4E300DFF2DF00DBF0DB00D7EFD700D3EDD300CFECCF00CBEACB00C7E9C700C3E7C300BFE6BF00BBE4BB00B7E2B700B3E1B300AFDFAF00ABDEAB00A7DCA700A3DBA3009FD99F009BD79B0097D6970093D493008FD38F008BD18B0087D0870083CE83007FCD7F007BCB7B0077C9770073C873006FC66F006BC56B0067C3670063C263005FC05F005BBE5B0057BD570053BB53004FBA4F004BB84B0047B7470043B543003FB43F003BB23B0037B0370033AF33002FAD2F002BAC2B0027AA270023A923001FA71F001BA51B0017A4170013A213000FA10F000B9F0B00079E0700039C03"
DllStructSetData($data_palette, 1, $palette)
$contextflag = 0
; GUICtrlSetState($item6_3,$gui_checked)
_Asmcode_changecolor()
_GUICtrlMenu_CheckRadioItem(GUICtrlGetHandle($item6),0,3,2)
EndFunc ;==>_Palette3
Func _Palette4()
$contextflag = 1
$palette = "0x0000000000FEFB8100FEF78300FEF48500FEF08700FDED8800FDE98A00FDE68C00FDE28E00FCDF8F00FCDB9100FCD89300FCD49500FBD19600FBCD9800FBCA9A00FBC69C00FBC39D00FABF9F00FABCA100FAB8A300FAB5A400F9B1A600F9AEA800F9AAAA00F9A7AB00F8A3AD00F8A0AF00F89CB100F899B200F795B400F792B600F78EB800F78AB900F787BB00F683BD00F680BF00F67CC000F679C200F575C400F572C600F56EC700F56BC900F467CB00F464CD00F460CE00F45DD000F359D200F356D400F352D500F34FD700F34BD900F248DB00F244DC00F241DE00F23DE000F13AE200F136E300F133E500F12FE700F02CE900F028EA00F025EC00F021EE00F01EF000EF1FED00EF20EA00EF21E700EE23E400EE24E100EE25DE00ED26DB00ED28D800ED29D500EC2AD200EC2BCF00EC2DCC00EB2EC900EB2FC600EB30C300EB32C000EA33BD00EA34BA00EA35B700E937B400E938B100E939AE00E83AAB00E83CA800E83DA500E73EA200E73F9F00E7419C00E6429900E6439600E6449300E6469100E5478E00E5488B00E5498800E44B8500E44C8200E44D7F00E34E7C00E3507900E3517600E2527300E2537000E2556D00E1566A00E1576700E1586400E15A6100E05B5E00E05C5B00E05D5800DF5F5500DF605200DF614F00DE624C00DE644900DE654600DD664300DD674000DD693D00DC6A3A00DC6B3700DC6C3400DC6E3200D86E3500D56E3800D16E3B00CE6F3E00CA6F4200C76F4500C36F4800C0704B00BD704E00B9705200B6715500B2715800AF715B00AB715E00A8726200A5726500A17268009E736B009A736E009773720093737500907478008C747B0089747E0086758200827585007F7588007B758B0078768E0074769200717695006E7798006A779B0067779E006377A2006078A5005C78A8005978AB005578AE005279B2004F79B5004B79B800487ABB00447ABE00417AC2003D7AC5003A7BC800377BCB00337BCE00307CD2002C7CD500297CD800257CDB00227DDE001E7DE2001B7DE500187EE800147EEB00117EEE000D7EF2000A7FF500067FF800037FFB000080FF000381FD000783FB000B85F9000F87F7001389F500178BF3001B8DF1001F8FEF002391ED002793EB002B95E9002F97E7003399E500379BE3003B9DE1003F9FDF0043A1DD0047A3DB004BA5D9004FA7D70053A9D50057ABD3005BADD1005FAFCF0063B1CD0067B3CB006BB5C9006FB7C70073B9C50077BBC3007BBDC1007FBFBF0083C1BD0087C3BB008BC5B9008FC7B70093C9B50097CBB3009BCDB1009FCFAF00A3D1AD00A7D3AB00ABD5A900AFD7A700B3D9A500B7DBA300BBDDA100BFDF9F00C3E19D00C7E39B00CBE59900CFE79700D3E99500D7EB9300DBED9100DFEF8F00E3F18D00E7F38B00EBF58900EFF78700F3F98500F7FB8300FBFD81"
DllStructSetData($data_palette, 1, $palette)
$contextflag = 0
; GUICtrlSetState($item6_4,$gui_checked)
_Asmcode_changecolor()
_GUICtrlMenu_CheckRadioItem(GUICtrlGetHandle($item6),0,3,3)
EndFunc ;==>_Palette4
Func _startnew()
$exitflag=1
$cx = -0.5 ;CenterX : Zentrum der Fläche in x-Richtung
$cy = 0 ;Centery : Zentrum der Fläche in y-Richtung
$breite = 4 ;die Ausdehnung der Fläche in x-Richtung, y wird proportional angepasst
$tiefe = 5 ;Berechnungstiefe
$maxiter = 200 ;maximale Anzahl der Iterationen, wird je nach zoomfaktor erhöht
$zoom = 4 ;zoomfaktor bei mausclick
_NewWindow()
EndFunc ;==>_startnew
Func _Asmcode_changecolor() ;compares the colour of the source Bitmap with the colour of the palette and writes the palettecolour into the destinationbitmap
FAsmReset($AsmObj)
FasmAdd($AsmObj, " use32 ");
FasmAdd($AsmObj, " mov esi,dword[ESP+04h] ");source bitmap
FasmAdd($AsmObj, " mov edi,dword[ESP+08h] ");destination bitmap
FasmAdd($AsmObj, " mov ecx,dword[esp+0ch] ");lenght bitmap
FasmAdd($AsmObj, " mov ebx,0FFh ");EBX=255
FasmAdd($AsmObj, "L0: ")
FasmAdd($AsmObj, " mov eax,dword[esi] ");EAX=Colour of pixel in source Bitmap
FasmAdd($AsmObj, " xor edx,edx ");EDX=0
FasmAdd($AsmObj, " div ebx ");in EAX steht nun die integerdivision, in EDX steht der Rest! =>edx=modulo(eax,ebx)
FasmAdd($AsmObj, " mov eax,dword[esp+10h] ");anfang der palette
FasmAdd($AsmObj, " shl edx,2 ");edx=edx*4 4 Byte pro Farbe in der palette
FasmAdd($AsmObj, " add edx,eax ");Adresse der Farbe in der palette
FasmAdd($AsmObj, " mov eax,dword[edx+01] ");Farbe in der palette
FasmAdd($AsmObj, " add esi,4 ")
FasmAdd($AsmObj, " mov dword[edi],eax ");Farbe aus der palette in die 2. Bitmap schreiben
FasmAdd($AsmObj, " add edi,4 ")
FasmAdd($AsmObj, " dec ecx ")
FasmAdd($AsmObj, " jnz L0 ")
FasmAdd($AsmObj, " ret ")
$t=timerinit()
$ret=MemoryFuncCall("int:cdecl", FAsmGetFuncPtr($AsmObj), "ptr", dllstructgetdata($asmstack,"bmpdata"), "ptr", dllstructgetdata($asmstack,"bmppalette"), "uint", $winx*$winy, "ptr", dllstructgetptr($data_palette)) ;Assembler aufrufen und Code starten
$m=timerdiff($t)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
;_arraydisplay($ret)
_showpic()
endfunc
autoit.de/wcf/attachment/8385/
Vergleich mit AutoIt-Code:
Spoiler anzeigen
#include <SliderConstants.au3>
#include <GUIConstantsEx.au3>
Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 2)
Global $width, $height, $dc, $centerx, $centery, $apfelbreite, $btnstartpressed
Global $cx, $cy, $centerx1, $centery1, $st, $st1, $apfelbreite1
Global $step, $mousepressed, $maxiteration, $x0, $y0, $flag
$user32 = DllOpen("user32.dll")
$gdi32 = DllOpen("gdi32.dll")
$width = 800
$height = 600
;Startparameter
$maxiteration = 250 ; für 1. durchlauf, dann slider bis zu 1000
$centerx = -.5
$centery = 0
$tiefe = 100
$apfelbreite = 5
$step = 1
;Gui
$Form1 = GUICreate("Apfelmännchen", $width + 100, $height)
$Farbe = PixelGetColor(30, 30)
$Label = GUICtrlCreateLabel("", 0, 0, $width + 10, $height)
$dc = GetDC(WinGetHandle($Form1))
GUICtrlCreateLabel("Steps: ", $width + 20, 15, 60)
$stepslider = GUICtrlCreateSlider($width + 10, 30, 80, 40, BitOR($TBS_TOOLTIPS, $TBS_AUTOTICKS, $TBS_ENABLESELRANGE))
GUICtrlSetLimit(-1, 5, 1)
GUICtrlSetData($stepslider, $step)
GUICtrlCreateLabel("Iterationen: ", $width + 20, 100, 60)
$maxitslider = GUICtrlCreateSlider($width + 10, 115, 80, 40, BitOR($TBS_TOOLTIPS, $TBS_AUTOTICKS, $TBS_ENABLESELRANGE))
GUICtrlSetLimit(-1, 1000, $maxiteration)
GUICtrlSetData($maxitslider, 25)
GUISetState(@SW_SHOW)
GUISetOnEvent($GUI_EVENT_CLOSE, "_EXIT")
GUISetOnEvent($GUI_EVENT_PRIMARYUP, "_mousepressed") ;beim UP der linken Maustaste die func aufrufen
;$centerx=-0.125
;$centery=-0.733333333333333
;$apfelbreite=1.25
;$tiefe=130
;$maxiteration=350
While 1
$mousepressed = 0
$begin = TimerInit()
;Mandelbrot()
;$paintpixel=1 ;das bild ist am entstehen
WinSetTitle($Form1, "", $centerx & " " & $centery & " " & $apfelbreite & " Apfelmännchen :" & Int(TimerDiff($begin) / 1000 & " Sekunden ")) ;Zeit in der Titelleiste anzeigen
$x0 = $centerx - $apfelbreite * .5
$stepx = $apfelbreite / $width * $step
$y0 = $centery - $apfelbreite * .5
$stepy = $apfelbreite / $height * $step
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]For $py = 0 To $height Step $step
$y0 = $y0 + $stepy
$x0 = $centerx - $apfelbreite * .5
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $y0 = ' & $y0 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
For $px = 0 To $width Step $step
If $mousepressed = 1 Then ExitLoop ;Maustaste wurde gedrückt, marker setzen und Berechnung verlassen
$x0 = $x0 + $stepx
; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $x0 = ' & $x0 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
$x = $x0
$y = $y0
$iteration = 0
For $i = 1 To $tiefe
$xtemp = $x * $x - $y * $y + $x0
$y = 2 * $x * $y + $y0
$x = $xtemp
If (($x * $x + $y * $y) > $tiefe Or $iteration > $maxiteration) Then ExitLoop
$iteration += 1
Next
$col = $iteration^4;0xffffff/ log(log($iteration)+1)
setpixel($dc, $px, $py, $col) ;..
Next
If $mousepressed = 1 Then ExitLoop ;Berechnung verlassen
Next
WinSetTitle($Form1, "", $centerx & " " & $centery & " " & $apfelbreite & " Apfelmännchen :" & Int(TimerDiff($begin) / 1000 & " Sekunden ")) ;Zeit in der Titelleiste anzeigen
If $mousepressed = 0 Then ;die Grafik wurde ohne Unterbrechung fertig
;$paintpixel=0
While $mousepressed = 0 ;solange warten, bis linke mMustaste gedrückt
Sleep(100)
WEnd
EndIf
GUICtrlSetBkColor($Label, $Farbe)
WEnd
[/autoit] [autoit][/autoit] [autoit]Func _mousepressed()
$mousepressed = 0 ;
$pos = MouseGetPos() ;Koordinaten der Maus
tooltip(MouseGetPos(0)&" "&MouseGetPos(1))
;If $paintpixel=1 then ;Maustaste wurde innerhalb for/to gedrückt
If $pos[0] < $width And $pos[1] < $height and $pos[0]>0 and $pos[1]>0 Then ;wenn mauspos innerhalb Grafik dann
$flag = 1
$mousepressed = 1 ;Flag setzen
$centerx = $centerx - $apfelbreite * (0.5 - $pos[0] / $width) ;neuer Anfang der Berechnung an der Mausposition für x...
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $centerx = ' & $centerx & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$centery = $centery - $apfelbreite * (0.5 - $pos[1] / $height) ;...und y- Koordinate
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $centery = ' & $centery & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$apfelbreite = $apfelbreite / 4 ;neue Fenstergröße willkürlich auf 1/4 des ursprünglichen Bildes
endif
If $pos[0] < $width+100 And $pos[1] < $height and $pos[0]>$width and $pos[1]>0 Then ;wenn mauspos innerhalb Grafik dann
$step = GUICtrlRead($stepslider) ;steps von Slider übernehmen
$maxiteration = GUICtrlRead($maxitslider) ;und Maxiteration
EndIf
;msgbox(0,"start",$centerx&@crlf&$centery&@crlf&$apfelbreite)
EndFunc ;==>_mousepressed
Func setpixel($dc, $x, $y, $color) ;pixel mit farbe an koordinaten setzen
DllCall($gdi32, "long", "SetPixel", "long", $dc, "long", $x, "long", $y, "long", $color)
EndFunc ;==>pix
Func GetDC($handle)
$dc = DllCall($user32, "int", "GetDC", "hwnd", $handle)
Return $dc[0]
EndFunc ;==>GetDC
func _exit()
Exit
endfunc