;"Web" demo for KolibriOS, version 0.3 ;Copyright Alexander Meshcheryakov (Self-Perfection), 2009 ;Contact me: alexander.s.m@gmail.com ;distributed under BSD license ;Used assumptions: ; 1) Screen resolution does not change while app is running ; 2) Screen width bigger then height ; 3) Screen width and height are even (2*k) include "macros.inc" background_cl = 0x000000 foreground_cl = 0xFFFFFF delay = 4 ; debug = 1 MEOS_APP_START CODE ;Preinit. Randomize start counter mcall 3 mov [initial_counter], eax ;init with system time ;Query screen size mcall 14 add eax, 0x00010001 mov dword [y_max], eax ;store x_max and y_max shr eax, 1 mov dword [radius], eax ;store radius and x_center ;Calc line_number mov ax, [y_max] mov dx, 0 mov bx, 5 div bx mov word [half_line_number], ax movzx edx, ax ;edx = half_line_number imul edx, 2 * line_coords_element_size ;Space needed for line_coords_array ;Demand memory mcall 68, 11 ; Init heap test eax, eax ; Is heap successfully inited? jnz @f mcall -1 ; Netu pamjati?! Nu i nahuj vas @@: movzx ecx, [y_max] inc ecx movzx eax, [x_max] imul ecx, eax ;[Remember to left here space for 1-2 emergency lines at bottom] add ecx, edx ;And add space for line_coords_array mcall 68, 12, test eax, eax ; Did we get something non zero? jnz @f mcall -1 @@: mov [line_coords_array_pointer], eax add eax, edx mov [image_pointer], eax call clear_offscreen_bitmap ;Calc fixed line ends coords fninit fldpi fidiv word [half_line_number] ;Now st0 contains angle step of line start points mov eax, [line_coords_array_pointer] ;cleanup: comment movzx ecx, word [half_line_number] shl ecx, 1 fld st ;skip zero angle to avoid 1px fixed line at right side calculate_next_line_start_point: fld st ;Calculate line start points coords fsincos fimul [radius] fiadd [x_center] fistp word [eax+start_x_offset] ; fchs ;affects direction, uncomment with corresponding line below fimul [radius] fiadd [radius] fistp word [eax+start_y_offset] ;Calculate line start point pointer movzx ebx, word [eax+start_y_offset] movzx edx, word [x_max] imul ebx, edx movzx edx, word [eax+start_x_offset] add ebx, edx add ebx, [image_pointer] mov [eax+line_start_pointer_offset], ebx fadd st0, st1 add eax, line_coords_element_size ;Move to next element in line_coords_array loop calculate_next_line_start_point fstp st0 ;drop current angle fidiv [divider] ;change angle step draw_window: ;Start line coords calculation fld st ;skip zero angle to avoid 1px fixed line at right side ;Use time since start to get current counter value mcall 26, 9 add eax, [initial_counter] mov [current_counter], eax mov eax, [line_coords_array_pointer] ;cleanup: comment movzx ecx, word [half_line_number] shl ecx, 1 calculate_next_line_end_point: fld st ;Calculate line end points fimul [current_counter] fsincos fimul [radius] fiadd [x_center] fistp word [eax+2] ; fchs ;affects direction, uncomment with corresponding line above fimul [radius] fiadd [radius] fistp word [eax+6] fadd st0, st1 add eax, line_coords_element_size ;Move to next element in line_coords_array loop calculate_next_line_end_point fstp st0 ;drop current angle inc dword [initial_counter] ; ********************************************* ; *******Draw lines on offscreen bitmap******** ; ********************************************* ;draw end points movzx edi, [half_line_number] shl edi, 1 mov esi, [line_coords_array_pointer] draw_next_line: if defined debug ;Draw red points next to line ends in debug mode movzx ebx, word [esi+start_y_offset] movzx eax, word [x_max] imul eax, ebx movzx ebx, word [esi+start_x_offset] add eax, ebx add eax, dword [image_pointer] inc eax mov [eax], byte red_cl_index movzx ebx, word [esi+end_y_offset] movzx eax, word [x_max] imul eax, ebx movzx ebx, word [esi+end_x_offset] add eax, ebx add eax, dword [image_pointer] inc eax ;Move one right to make more visible mov [eax], byte red_cl_index end if ;Drawing lines. Need to keep esi and edi values in process mov eax, [esi+line_start_pointer_offset] check_horizontal_line: mov bx, word [esi+start_y_offset] cmp bx, word [esi+end_y_offset] jnz general_draw_line ;Jump to next test if dy!=0 pusha movzx ecx, word [esi+end_x_offset] sub cx, word [esi+start_x_offset] jnc @f neg cx sub eax, ecx @@: cld inc cx mov edi, eax mov al, foreground_cl_index rep stos byte [edi] popa jmp line_drawing_end ;General line draw algorithm. Based on Bresenham's algorithm (below) but heavily optimized ; function line(x0, x1, y0, y1) ; boolean steep := abs(y1 - y0) > abs(x1 - x0) ; if steep then ; swap(x0, y0) ; swap(x1, y1) ; if x0 > x1 then ; swap(x0, x1) ; swap(y0, y1) ; int deltax := x1 - x0 ; int deltay := abs(y1 - y0) ; int error := deltax / 2 ; int ystep ; int y := y0 ; if y0 < y1 then ystep := 1 else ystep := -1 ; for x from x0 to x1 ; if steep then plot(y,x) else plot(x,y) ; error := error - deltay ; if error < 0 then ; y := y + ystep ; error := error + deltax general_draw_line: pusha ;init step_base and step_secondary mov edx, esi mov esi, 1 movzx edi, word [x_max] ;calc initial delta_base & delta_secondary values movzx ebx, word [edx+end_x_offset] sub bx, [edx+start_x_offset] jnc @f neg bx neg esi @@: movzx ecx, word [edx+end_y_offset] sub cx, [edx+start_y_offset] jnc @f neg cx neg edi @@: ;compare abs(y1 - y0) and abs(x1 - x0) cmp bx, cx jnc @f xchg ebx, ecx xchg esi, edi @@: shl ebx, 16 mov bx, cx rol ebx, 16 mov cx, bx ;init counter inc cx mov dx, bx ;init error shr dx, 1 rol ebx, 16 ;At current point: ;eax = current point pointer ;ebx = (delta_base shl 16) + delta_secondary ;ecx = counter ;[e]dx = error ;esi = step_base ;edi = step_secondary brasenham_plot_point: mov byte [eax], foreground_cl_index add eax, esi sub dx, bx jnc end_loop ; y := y + ystep ; error := error + deltax change_y: add eax, edi rol ebx, 16 add dx, bx rol ebx, 16 end_loop: loopw brasenham_plot_point end_bresenham: popa line_drawing_end: add esi, line_coords_element_size ;Move to next element in line_coords_array dec edi jnz draw_next_line ; ********************************************* ; ******* WINDOW DEFINITIONS AND DRAW ******** ; ********************************************* ; mcall 18, 14 ;Wait for scanning (it seems doesn't do any good now) ; start redraw (without calling 12 proc our window overwrites window that above it) mcall 12, 1 xor eax,eax movzx ebx, [x_max] movzx ecx, [y_max] mov edx, 0x01000000 ;Window style ;Draw nothing ; mov edx, 0x00000000 ;Window style ; mov esi, 0x00000000 ;Header color (prevent odd color line on top of window in random cases) mcall ;Define window mov ebp, 0 mov ecx, dword [y_max] mcall 65, [image_pointer], , <0,0>, 8, palette mcall 12, 2 ; end redraw call clear_offscreen_bitmap wait_event: mcall 23, delay ; mcall 10 test eax, 0xFFFF - 1 ;Test for 0 (delay passed) or 1 (redraw) event jz draw_window ; Delay passed or redraw event dec eax dec eax jnz exit ; If not key then Alt+F4 ; key pressed, read it and ignore mcall 2 cmp eax, 0x1B00 ;Test for Escape key press jnz wait_event ; button pressed; we have only one button, close ; also seems to handle Alt+F4 exit: mcall -1 clear_offscreen_bitmap: mov edi, [image_pointer] movzx ecx, [y_max] movzx eax, [x_max] imul ecx, eax shr ecx, 2 ;dword is 4 bytes mov eax, 0 rep stos dword [edi] ret DATA divider dw 5000 palette: background_cl_index = 0 dd background_cl foreground_cl_index = 1 dd foreground_cl if defined debug red_cl_index = 2 dd 0x00FF0000 ;Cleanup this! end if UDATA image_pointer dd ? initial_counter dd ? current_counter dd ? ;counter + current time half_line_number dw ? y_max dw ? ; screen size x_max dw ? radius dw ? x_center dw ? line_coords_array_pointer dd ? ; line_coords_array: ; repeat 1000 ;line_number ; dw ? ;start_x ; dw ? ;end_x ; dw ? ;start_y ; dw ? ;end_y ; dd ? ;line_start_pointer ; end repeat start_x_offset = 0 end_x_offset = 2 start_y_offset = 4 end_y_offset = 6 line_start_pointer_offset = 8 line_coords_element_size = 12 MEOS_APP_END