From 79b35ed28f5d07ea36f17046944380d624a695f7 Mon Sep 17 00:00:00 2001 From: "Kirill Lipatov (Leency)" Date: Sat, 12 May 2012 22:04:03 +0000 Subject: [PATCH] buddhabrot by macgub git-svn-id: svn://kolibrios.org@2659 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../demos/buddhabrot/trunk/buddhabrot.asm | 376 ++++++++++++++++++ programs/demos/buddhabrot/trunk/build.bat | 3 + 2 files changed, 379 insertions(+) create mode 100644 programs/demos/buddhabrot/trunk/buddhabrot.asm create mode 100644 programs/demos/buddhabrot/trunk/build.bat diff --git a/programs/demos/buddhabrot/trunk/buddhabrot.asm b/programs/demos/buddhabrot/trunk/buddhabrot.asm new file mode 100644 index 0000000000..949e0bb4ed --- /dev/null +++ b/programs/demos/buddhabrot/trunk/buddhabrot.asm @@ -0,0 +1,376 @@ +; App written by randall ported to Kolibri and MenuetOS64 by macgub (www.macgub.hekko.pl). +; Now it use static memory, it is mixed 32bit code and SSE instructions. + +include '../../../macros.inc' + +use32 + + org 0x0 + + db 'MENUET01' ; 8 byte id + dd 0x01 ; header version + dd START ; start of code + dd IMG_END ; size of image + dd I_END ;0x100000 ; memory for app + dd I_END ;0xbffff ; esp + dd 0x0 , 0x0 ; I_Param , I_Icon + +START: ; start of execution + + call draw_window + call Main + call draw_from_buffer + +still: + + +; call Main + + +; mov eax,7 +; mov ebx,screen +; mov ecx,IMG_SIZE*65536+IMG_SIZE +; mov edx,0*65536+0 +; int 0x40 + +; mov eax,23 ; wait here for event +; mov ebx,timeout +; int 0x40 + ; mov eax,11 ; check for event no wait + mov eax,10 ; wait for event + int 0x40 + + cmp eax,1 ; redraw request ? + je red + cmp eax,2 ; key in buffer ? + je key + cmp eax,3 ; button in buffer ? + je button + + jmp noclose + + red: ; redraw + call draw_window + call draw_from_buffer + jmp still + + key: ; key + mov eax,2 ; just read it and ignore + int 0x40 + shr eax,8 + cmp eax, 27 + jne still + mov eax, -1 + int 0x40 + + + button: ; button + mov eax,17 ; get id + int 0x40 + + cmp ah,1 ; button id=1 ? + jne noclose + + mov eax,-1 ; close this program + int 0x40 + noclose: + + jmp still + + +draw_from_buffer: + + mov eax,7 + mov ebx,screen + mov ecx,IMG_SIZE*65536+IMG_SIZE + mov edx,0*65536+0 + int 0x40 +ret + +;------------------------------------------------------------------------------- +; NAME: XORWOW +; DESC: Pseudo random number generator. +; OUT: eax [0;2^32-1] +;------------------------------------------------------------------------------- +macro XORWOW { + mov edx,[g_xorwow_x] ; edx = x + shr edx,2 ; edx = x >> 2 + xor edx,[g_xorwow_x] ; t = x ^ (x >> 2) + mov eax,[g_xorwow_y] ; eax = y + mov [g_xorwow_x],eax ; x = y + mov eax,[g_xorwow_z] ; eax = z + mov [g_xorwow_y],eax ; y = z + mov eax,[g_xorwow_w] ; eax = w + mov [g_xorwow_z],eax ; z = w + mov eax,[g_xorwow_v] ; eax = v + mov [g_xorwow_w],eax ; w = v + mov edi,eax ; edi = v + shl edi,4 ; edi = v << 4 + xor edi,eax ; edi = (v ^ (v << 4)) + mov eax,edx ; eax = t + shl eax,1 ; eax = t << 1 + xor eax,edx ; eax = (t ^ (t << 1)) + xor eax,edi ; eax = (v ^ (v << 4)) ^ (t ^ (t << 1)) + mov [g_xorwow_v],eax ; v = eax + add [g_xorwow_d],362437 ; d += 362437 + mov eax,[g_xorwow_d] ; eax = d + add eax,[g_xorwow_v] ; eax = d + v +} +;------------------------------------------------------------------------------- +; NAME: RANDOM +; DESC: Returns pseudo random number in the range [-0.5;0.5). +; OUT: xmm0.x [-0.5;0.5) +;------------------------------------------------------------------------------- +macro RANDOM { + XORWOW + cvtsi2ss xmm0,eax + mulss xmm0,[g_rand_scale] +} +;------------------------------------------------------------------------------- + +;------------------------------------------------------------------------------- +; NAME: GenerateSequence +; IN: xmm0.x re (c0.x) +; IN: xmm1.x im (c0.y) +; IN: edi array size +; IN/OUT: esi pointer to the allocated array +; OUT: eax generated sequence size +;------------------------------------------------------------------------------- +align 16 +GenerateSequence: + xor eax,eax ; eax is index loop + xorps xmm4,xmm4 ; xmm4 is c.x + xorps xmm5,xmm5 ; xmm5 is c.y +.Loop: + ; cn.x = c.x * c.x - c.y * c.y + c0.x + movaps xmm2,xmm4 + movaps xmm3,xmm5 + mulss xmm2,xmm4 + mulss xmm3,xmm5 + subss xmm2,xmm3 + addss xmm2,xmm0 + movaps xmm6,xmm2 ; xmm6 is cn.x + ; cn.y = 2.0 * c.x * c.y + c0.y + movaps xmm7,xmm4 + mulss xmm7,xmm5 + addss xmm7,xmm7 + addss xmm7,xmm1 ; xmm7 is cn.y + ; store cn + movd dword [esi+eax*8],xmm6 + movd dword [esi+eax*8+4],xmm7 + ; if (cn.x * cn.x + cn.y * cn.y > 10.0) return eax; + movaps xmm2,xmm6 + movaps xmm3,xmm7 + mulss xmm2,xmm6 + mulss xmm3,xmm7 + addss xmm2,xmm3 + ucomiss xmm2,[g_max_dist] + ja .EndLoop + movaps xmm4,xmm6 ; c.x = cn.x + movaps xmm5,xmm7 ; c.y = cn.y + ; continue loop + inc eax + cmp eax,edi + jb .Loop + ; return 0 + xor eax,eax +.EndLoop: + ret +;------------------------------------------------------------------------------- +; NAME: main +; DESC: Program main function. +;------------------------------------------------------------------------------- +align 16 +Main: +img_ptr equ ebp-8 +seq_ptr equ ebp-16 +pixel equ ebp-24 +r13dd equ ebp-64 +r12dd equ ebp-68 +r15dd equ ebp-72 + + push ebp + mov ebp,esp + sub esp,128 + ; mem for the sequence + lea eax,[sequence] + mov [seq_ptr],eax + ; mem for the image + lea eax,[screen] + mov [img_ptr],eax + ; begin loops + mov dword[r13dd],0 ; .LoopIterations counter +.LoopIterations: + mov dword[r12dd],0 ; .LoopOneMillion counter +.LoopOneMillion: + RANDOM + mulss xmm0,[g_range] + movaps xmm1,xmm0 + RANDOM + mulss xmm0,[g_range] + mov edi,SEQ_SIZE + mov esi,[seq_ptr] + call GenerateSequence ; eax = n sequence size + test eax,eax + jz .LoopSequenceEnd + xor ecx,ecx ; ecx = i = 0 loop counter + ; mov r9dd,[seq_ptr] ; r9 = sequence base address + ; mov r8dd,[img_ptr] ; r8 = image base address + movss xmm2,[g_img_size] + movaps xmm3,xmm2 + mulss xmm3,[g_0_5] ; xmm3 = (g_img_size)/2 + movss xmm4,[g_zoom] + mulss xmm4,xmm2 ; xmm4 = g_zoom * g_img_size + movss xmm5,[g_offsetx] ; xmm5 = g_offsetx + movss xmm6,[g_offsety] ; xmm6 = g_offsety +.LoopSequence: + cmp ecx,eax ; i < n + je .LoopSequenceEnd + movd xmm0,[sequence+ecx*8] ; load re + movd xmm1,[sequence+ecx*8+4] ; load im + addss xmm0,xmm5 ; xmm0 = re+g_offsetx + addss xmm1,xmm6 ; xmm1 = im+g_offsety + mulss xmm0,xmm4 ; xmm0 = (re+g_offsetx)*g_img_size*g_zoom + mulss xmm1,xmm4 ; xmm1 = (im+g_offsety)*g_img_size*g_zoom + addss xmm0,xmm3 ; xmm0 = (re+g_offsetx)*g_img_size*g_zoom+g_img_size/2 + addss xmm1,xmm3 ; xmm1 = (im+g_offsety)*g_img_size*g_zoom+g_img_size/2 + cvtss2si edi,xmm0 ; edi = x = int(xmm0.x) + cvtss2si esi,xmm1 ; esi = y = int(xmm1.x) + cmp edi,0 + jl @f + cmp edi,IMG_SIZE + jge @f + cmp esi,0 + jl @f + cmp esi,IMG_SIZE + jge @f + imul esi,esi,IMG_SIZE + add esi,edi + add dword [screen+esi*4],1 +@@: + inc ecx + jmp .LoopSequence +.LoopSequenceEnd: + ; continue .LoopOneMillion + add dword[r12dd],1 + cmp dword[r12dd],1000000 + jb .LoopOneMillion + ; continue .LoopIterations + add dword[r13dd],1 + cmp dword[r13dd],ITERATIONS + jb .LoopIterations + ; find max value + mov dword[r12dd],0 + xor eax,eax ; eax = i = loop counter +.LoopMax: + push ecx + mov ecx,[r12dd] + cmp dword [screen+eax*4],ecx + cmova ecx,dword [screen+eax*4] + mov [r12dd],ecx + pop ecx + inc eax + cmp eax,IMG_SIZE*IMG_SIZE + jb .LoopMax + ; find min value + ; mov r13d,r12d ; r13d = min_val = max_val + push dword[r12dd] + pop dword[r13dd] + xor eax,eax ; eax = i = loop counter +.LoopMin: + push ecx + mov ecx,[r13dd] + cmp dword [screen+eax*4],ecx + + cmovb ecx,dword [screen+eax*4] + mov [r13dd],ecx + pop ecx + inc eax + cmp eax,IMG_SIZE*IMG_SIZE + jb .LoopMin + ; write image pixels + mov byte [pixel+3],255 + ; mov r14,[img_ptr] ; r14 = image base address + ; xor r15d,r15d ; r15d = i = loop counter + mov dword[r15dd],0 + cvtsi2ss xmm0,[r12dd] ; load max_value + cvtsi2ss xmm1,[r13dd] ; load min_value + movaps xmm2,xmm0 + subss xmm2,xmm1 ; xmm2 = r = max_value - min_value + xor ecx,ecx +.LoopWrite: + mov eax,[screen+ecx*4] ; eax = image_value + sub eax,[r13dd] ; eax = image_value - min_value + cvtsi2ss xmm0,eax ; xmm0 = float(image_value - min_value) + addss xmm0,xmm0 ; xmm0 = 2.0f * float(image_value - min_value) + divss xmm0,xmm2 ; xmm0 = 2.0f * float(image_value - min_value) / r + minss xmm0,[g_1_0] ; clamp to 1.0 + maxss xmm0,[g_0_0] ; clamp to 0.0 + mulss xmm0,[g_255_0] ; convert to 0 - 255 + cvtss2si eax,xmm0 + ; write pixel data + mov [screen+ecx*3],eax + inc ecx + cmp ecx,IMG_SIZE*IMG_SIZE + jb .LoopWrite + mov esp,ebp + pop ebp + ret + ; restore img_ptr,seq_ptr,pixel +;------------------------------------------------------------------------------- +; ********************************************* +; ******* WINDOW DEFINITIONS AND DRAW ******** +; ********************************************* +draw_window: + + mcall 12, 1 ; function 12:tell os about windowdraw + + mcall 48, 4 ;get skin width + lea ecx, [50*65536+IMG_SIZE+4+eax] ; [y start] *65536 + [y size] + [skin_height] + mcall 0,<50,IMG_SIZE+9>,,0x74000000,,labelt ;draw window + + mcall 12, 2 ; function 12:tell os about windowdraw + + ret + + + +;------------------------------------------------------------------------------- +align 1 +labelt: + db 'buddhabrot',0 +labelen: + +align 4 +g_xorwow_x dd 123456789 +g_xorwow_y dd 362436069 +g_xorwow_z dd 521288629 +g_xorwow_w dd 88675123 +g_xorwow_v dd 5783321 +g_xorwow_d dd 6615241 +g_rand_scale dd 2.3283064e-10 ; 1.0 / 2^32 + +IMG_SIZE=600 +SEQ_SIZE=50 +ITERATIONS=100 +g_img_size dd 600.0 +g_offsetx dd 0.5 +g_offsety dd 0.0 +g_zoom dd 0.4 + +g_max_dist dd 10.0 +g_range dd 4.2 +g_0_5 dd 0.5 +g_0_0 dd 0.0 +g_1_0 dd 1.0 +g_255_0 dd 255.0 + +IMG_END: +;-------------------- +sequence: + rb SEQ_SIZE*8 +screen: + rb IMG_SIZE*IMG_SIZE*4 +memStack: + rd 1024 +I_END: \ No newline at end of file diff --git a/programs/demos/buddhabrot/trunk/build.bat b/programs/demos/buddhabrot/trunk/build.bat new file mode 100644 index 0000000000..8fc414b3e7 --- /dev/null +++ b/programs/demos/buddhabrot/trunk/build.bat @@ -0,0 +1,3 @@ +@fasm buddhabrot.asm buddhabrot +@kpack buddhabrot +@pause \ No newline at end of file