Jump to content

Fractals & AutoIt => have Fun!


AndyG
 Share

Recommended Posts

Hi,

while playing around with the asm.au3 and searching for some of my 8088/87-Assemblerscripts (hehe, these handwritten copies are missing since the early 80s), i remember to wrote a Fractal-Program (*.com-File) where the code of the calculation was running completely in the Registerstack (ST(0)-ST(7) each 80 byte) of the math. Coprocessor8087. The graphics was in CGA with 4, later EGA with 16 colors....

So time goes byte and the computers becomes 1000 times faster, but the number of the math. Register remained the same 8. Oh, i´m sorry, there was a really big change, these registers (and some add/sub/mul-calculations) are called "MMX" since 1997!

Today I am scripting just for fun with AutoIt, and the mentioned asm.au3 is something like an "Inline-assembler" (sic). I put together fun&AutoIt&assembler&"goodoldtimes" and sometimes something happens...

apfelmaennchen.zip

Have Fun!

Click into the picture to zoom at the position of the mousecursor, feel free to change the windowsize, and try a rightclick to explore some "features"  :(

Please excuse that the comments of the script are in german, but if you are interested in something, i´ll try to explain^^

Andy

(I had a big fight with this "assembler", i didn´t found a possibility to jump forward to a label, so the assemblercode is not optimized, nor particularly beautiful. I have decided to transfer the parameters to the assemblercode by a struct, so it is now  possible to use only the bytecode (like in trancexx´s excellent examples) without any changings and without additional asmcode or dll.

I think that a optimized assemblercode is not really readable for beginners. I didn´t like to fill cachelines, use more but faster code to avoid some additional clock cycles, unrolling loops, optimize branch .....too much hard stuff :lol: . But i think with some optimizations and use of SSE-instructions instead of SIMD it is possible to double/triple the speed.

There is a call(back) of an AutoIt-function  from the assemblercode, because i want to have an "Interrupt" during the calculation. Awesome loss of speed (100ms), but who cares...   :mellow:  ) 

Posted ImagePosted ImagePosted ImagePosted Image

Edited by AndyG
Link to comment
Share on other sites

Link to comment
Share on other sites

Link to comment
Share on other sites

There would be different problems with the script, that's for sure.

And the older the system chances to work are bigger. I expect DEP issues on Vista or 7.

AndyG, if I were you I would switch to subrogation for loading assembler dll and pointer calls.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Script crashed on exit and I can not get increase more x4 (one click on the window).

Can you change the windowsize? What happens after that?

How can I get an images that on the screenshots?

The first click should be somewhere at a position with some color, the "infinity" is colored black and takes much time to calculate.

What happens if you click "Save Pic" in the contextmenu?

Because of the simple maths (Mandelbrot-Fractal) you could make the Pictures without any assemblercode....here an example...but not very fast  :rolleyes:Because the Script zooms until the acurracy of the 64-Bit floating-point-numbers is reached, there are many very interesting places.

Btw, the maximum-zoom is comparable with a camera which has a zoom lense to photograph an ATOM on the surface of the moon.

#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



    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
            $x = $x0
            $y = $y0
            $iteration = 0
            while (($x * $x + $y * $y) < $tiefe and $iteration < $maxiteration)
                $xtemp = $x * $x - $y * $y + $x0
                $y = 2 * $x * $y + $y0
                $x = $xtemp
                $iteration += 1
            wend
            $col = $iteration^3;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

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
Link to comment
Share on other sites

Im surprised it works on my lousey old system.

works fine with a PIII@1200Mhz^^

@trancexx

you are definitely right, the older the system the better....i´ll take a look at the "subrogation".But at this point it should be better to work with a "real" Assembler/Debugger and include(inject) the assembled Bytecode into the memory. I have no fun counting opcodes to find the targetadress of a jump^^ 

/EDIT/  I like the simplicity of the 

$ret=DllCall("user32.dll", "int", "CallWindowProcW", "ptr", $pmemory, "ptr", dllstructgetptr($asmstack) , "int", 0, "int", 0, "int", 0)
no need of a dll or exe....very close to an inline-asm....But i dont have a 64Bit-OS to play with, does it work at 64Bit? Edited by AndyG
Link to comment
Share on other sites

I meant for assembler part, not code execution.

MemoryDll.au3 and ASM.au3 are causing DEP issues.

Of course CallWindowProcW works. It's only generated code that is x86.

I saw people using x64 systems to have #AutoIt3Wrapper_UseX64=n line in scripts when they want x86 run.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

I saw people using x64 systems to have #AutoIt3Wrapper_UseX64=n line in scripts when they want x86 run.

It is still not running properly although you compile it with x32! E.g. when you resize the window the script will crash.

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

 

Of course CallWindowProcW works. It's only generated code that is x86.

Ok, in the script is the Asm_Mandel()-Function. If you comment the MemoryFuncCall() and the "return" after it, the CallWindowProc is running.  Ahhhhh....now i understand, the making of the bytecode crashes the script....not the bytecode itsself?

/edit/ questionmark instead of dot...

Edited by AndyG
Link to comment
Share on other sites

@UEZ

hmmm, i checked the dllcall,

$adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', $DIB_RGB_COLORS, 'ptr*', 0, 'ptr', 0, 'uint', 0)



should be

$adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', $DIB_RGB_COLORS, 'ptr*', 0, 'ptr', 0, 'dword', 0)
and found aa wrong type.

 

Edited by AndyG
Link to comment
Share on other sites

 Ok, in the script is the Asm_Mandel()-Function. If you comment the MemoryFuncCall() and the "return" after it, the CallWindowProc is running.  Ahhhhh....now i understand, the making of the bytecode crashes the script....not the bytecode itsself?

/edit/ questionmark instead of dot...

Yes.

Sorry if I wasn't clear enough.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...