; 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: