57dc665138
git-svn-id: svn://kolibrios.org@6160 a494cfbc-eb01-0410-851d-a64ba20cac60
421 lines
9.9 KiB
NASM
421 lines
9.9 KiB
NASM
;"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 than 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 ah, 27 ; Test Esc key press in ASCII
|
|
jne 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 |