kolibrios/programs/media/kiv/trunk/kiv.asm
Evgeny Grechnikov (Diamond) 9fa3e91df1 kiv: support for animated images
git-svn-id: svn://kolibrios.org@1080 a494cfbc-eb01-0410-851d-a64ba20cac60
2009-05-24 16:48:56 +00:00

1070 lines
18 KiB
NASM

use32
org 0x0
db 'MENUET01'
dd 0x01, START, I_END, 0x4000, 0x4000, @PARAMS, 0x0
;-----------------------------------------------------------------------------
FALSE = 0
TRUE = 1
include '../../../proc32.inc'
include '../../../macros.inc'
include 'dll.inc'
include '../../../develop/libraries/libs-dev/libio/libio.inc'
include '../../../develop/libraries/libs-dev/libimg/libimg.inc'
;-----------------------------------------------------------------------------
START:
mcall 68, 11
stdcall dll.Load, @IMPORT
or eax, eax
jnz exit
invoke sort.START, 1
mov ecx, 1 ; for 15.4: 1 = tile
cmp word [@PARAMS], '\T'
jz set_bgr
inc ecx ; for 15.4: 2 = stretch
cmp word [@PARAMS], '\S'
jz set_bgr
cmp byte [@PARAMS], 0
jnz params_given
call opendialog
jc exit
mov esi, path
mov edi, @PARAMS
mov ecx, 512/4
rep movsd
mov byte [edi-1], 0
jmp params_given
set_bgr:
mcall 15, 4
mov eax, @PARAMS + 4
call load_image
jc exit
call set_as_bgr
jmp exit
params_given:
mov eax, @PARAMS
call load_image
jc exit
;-----------------------------------------------------------------------------
red:
call draw_window
still:
mov eax, [image]
test byte [eax + Image.Flags], Image.IsAnimated
push 10
pop eax
jz @f
mcall 26, 9
mov edx, [cur_frame]
mov ebx, [cur_frame_time]
add ebx, [edx + Image.Delay]
sub ebx, eax
cmp ebx, [edx + Image.Delay]
ja red_update_frame
test ebx, ebx
jz red_update_frame
push 23
pop eax
@@:
mcall
dec eax
js red_update_frame
jz red
dec eax
jnz button
key:
mcall 2
jmp still
red_update_frame:
mov eax, [cur_frame]
mov eax, [eax + Image.Next]
test eax, eax
jnz @f
mov eax, [image]
@@:
mov [cur_frame], eax
mcall 26, 9
mov [cur_frame_time], eax
mcall 9, procinfo, -1
call draw_cur_frame
jmp still
button:
mcall 17
shr eax, 8
; flip horizontally
cmp eax, 'flh'
jne @f
invoke img.flip, [image], FLIP_HORIZONTAL
jmp redraw_image
; flip vertically
@@: cmp eax, 'flv'
jne @f
invoke img.flip, [image], FLIP_VERTICAL
jmp redraw_image
; flip both horizontally and vertically
@@: cmp eax, 'flb'
jne @f
invoke img.flip, [image], FLIP_BOTH
jmp redraw_image
; rotate left
@@: cmp eax, 'rtl'
jne @f
push ROTATE_90_CCW
.rotate_common:
invoke img.rotate, [image]
mov eax, [image]
test eax, eax ; clear ZF flag
call update_image_sizes
jmp redraw_image
; rotate right
@@: cmp eax, 'rtr'
jne @f
push ROTATE_90_CW
jmp .rotate_common
; open new file
@@: cmp eax, 'opn'
jne @f
call opendialog
jc still
push [image]
mov eax, path
call load_image
jc .restore_old
mov esi, path
mov edi, @PARAMS
mov ecx, 512/4
rep movsd
mov byte [edi-1], 0
invoke img.destroy
call free_directory
jmp red
.restore_old:
pop [image]
call init_frame
jmp still
; set background
@@:
cmp eax, 'bgr'
jne @f
call set_as_bgr
jmp still
@@:
cmp eax, 'bck'
jnz @f
call prev_image
jmp still
@@:
cmp eax, 'fwd'
jnz @f
call next_image
jmp still
@@:
cmp eax, 1
jne still
exit:
mcall -1
redraw_image = red
load_image:
and [img_data], 0
push eax
invoke file.open, eax, O_READ
or eax, eax
jz .error_pop
mov [fh], eax
invoke file.size
mov [img_data_len], ebx
stdcall mem.Alloc, ebx
test eax, eax
jz .error_close
mov [img_data], eax
invoke file.read, [fh], eax, [img_data_len]
cmp eax, -1
jz .error_close
cmp eax, [img_data_len]
jnz .error_close
invoke file.close, [fh]
inc eax
jz .error
; img.decode checks for img.is_img
; invoke img.is_img, [img_data], [img_data_len]
; or eax, eax
; jz exit
invoke img.decode, [img_data], [img_data_len]
or eax, eax
jz .error
cmp [image], 0
pushf
mov [image], eax
call init_frame
popf
call update_image_sizes
call free_img_data
clc
ret
.error_free:
invoke img.destroy, [image]
jmp .error
.error_pop:
pop eax
jmp .error
.error_close:
invoke file.close, [fh]
.error:
call free_img_data
stc
ret
free_img_data:
mov eax, [img_data]
test eax, eax
jz @f
stdcall mem.Free, eax
@@:
ret
update_image_sizes:
pushf
mov edx, [eax + Image.Width]
mov [draw_width], edx
add edx, 19
cmp edx, 40 + 25*9
jae @f
mov edx, 40 + 25*9
@@:
mov [wnd_width], edx
mov esi, [eax + Image.Height]
mov [draw_height], esi
add esi, 44
mov [wnd_height], esi
popf
jz .no_resize
mcall 48, 4
add esi, eax
mcall 67,-1,-1
.no_resize:
ret
set_as_bgr:
mov esi, [image]
mov ecx, [esi + Image.Width]
mov edx, [esi + Image.Height]
mcall 15, 1
mcall 15, 6
test eax, eax
jz @f
push eax
invoke img.to_rgb2, esi, eax
pop ecx
mcall 15, 7
@@:
mcall 15, 3
ret
prev_image:
call load_directory
cmp [directory_ptr], 0
jz .ret
mov ebx, [directory_ptr]
mov eax, [cur_file_idx]
cmp eax, -1
jnz @f
mov eax, [ebx+4]
@@:
push [image]
.scanloop:
dec eax
jns @f
mov eax, [ebx+4]
dec eax
cmp [cur_file_idx], -1
jz .notfound
@@:
cmp eax, [cur_file_idx]
jz .notfound
push eax ebx
imul esi, eax, 304
add esi, [directory_ptr]
add esi, 32 + 40
mov edi, curdir
@@:
inc edi
cmp byte [edi-1], 0
jnz @b
mov byte [edi-1], '/'
@@:
lodsb
stosb
test al, al
jnz @b
mov eax, curdir
call load_image
pushf
mov esi, curdir
push esi
mov edi, @PARAMS
mov ecx, 512/4
rep movsd
mov byte [edi-1], 0
pop esi
@@:
lodsb
test al, al
jnz @b
@@:
dec esi
cmp byte [esi], '/'
jnz @b
mov byte [esi], 0
popf
pop ebx eax
jc .scanloop
mov [cur_file_idx], eax
invoke img.destroy
.ret:
ret
.notfound:
pop [image]
call init_frame
ret
next_image:
call load_directory
cmp [directory_ptr], 0
jz .ret
mov ebx, [directory_ptr]
mov eax, [cur_file_idx]
push [image]
.scanloop:
inc eax
cmp eax, [ebx+4]
jb @f
xor eax, eax
cmp [cur_file_idx], -1
jz .notfound
@@:
cmp eax, [cur_file_idx]
jz .notfound
push eax ebx
imul esi, eax, 304
add esi, [directory_ptr]
add esi, 32 + 40
mov edi, curdir
@@:
inc edi
cmp byte [edi-1], 0
jnz @b
mov byte [edi-1], '/'
@@:
lodsb
stosb
test al, al
jnz @b
mov eax, curdir
call load_image
pushf
mov esi, curdir
push esi
mov edi, @PARAMS
mov ecx, 512/4
rep movsd
mov byte [edi-1], 0
pop esi
@@:
lodsb
test al, al
jnz @b
@@:
dec esi
cmp byte [esi], '/'
jnz @b
mov byte [esi], 0
popf
pop ebx eax
jc .scanloop
mov [cur_file_idx], eax
invoke img.destroy
.ret:
ret
.notfound:
pop [image]
call init_frame
ret
load_directory:
cmp [directory_ptr], 0
jnz .ret
mov esi, @PARAMS
mov ecx, esi
@@:
lodsb
test al, al
jnz @b
@@:
dec esi
cmp byte [esi], '/'
jnz @b
mov [last_name_component], esi
sub esi, ecx
xchg ecx, esi
mov edi, curdir
rep movsb
mov byte [edi], 0
mcall 68, 12, 0x1000
test eax, eax
jz .ret
mov ebx, readdir_fileinfo
mov dword [ebx+12], (0x1000 - 32) / 304
mov dword [ebx+16], eax
mcall 70
cmp eax, 6
jz .dirok
test eax, eax
jnz free_directory
mov edx, [directory_ptr]
mov ecx, [edx+8]
mov [readblocks], ecx
imul ecx, 304
add ecx, 32
mcall 68, 20
test eax, eax
jz free_directory
mov [directory_ptr], eax
mcall 70, readdir_fileinfo
.dirok:
cmp ebx, 0
jle free_directory
mov eax, [directory_ptr]
add eax, 32
mov edi, eax
push 0
.dirskip:
push eax
test byte [eax], 18h
jnz .nocopy
lea esi, [eax+40]
mov ecx, esi
@@:
lodsb
test al, al
jnz @b
@@:
dec esi
cmp esi, ecx
jb .noext
cmp byte [esi], '.'
jnz @b
inc esi
mov ecx, [esi]
or ecx, 0x202020
cmp ecx, 'jpg'
jz .copy
cmp ecx, 'bmp'
jz .copy
cmp ecx, 'gif'
jz .copy
cmp ecx, 'png'
jz .copy
cmp ecx, 'jpe'
jz .copy
cmp ecx, 'jpeg'
jz @f
cmp ecx, 'jpeG'
jnz .nocopy
@@:
cmp byte [esi+4], 0
jnz .nocopy
.copy:
mov esi, [esp]
mov ecx, 304 / 4
rep movsd
inc dword [esp+4]
.nocopy:
.noext:
pop eax
add eax, 304
dec ebx
jnz .dirskip
mov eax, [directory_ptr]
pop ebx
mov [eax+4], ebx
test ebx, ebx
jz free_directory
push 0 ; sort mode
push ebx
add eax, 32
push eax
call [SortDir]
xor eax, eax
mov edi, [directory_ptr]
add edi, 32 + 40
.scan:
mov esi, [last_name_component]
inc esi
push edi
invoke strcmpi
pop edi
jz .found
inc eax
add edi, 304
dec ebx
jnz .scan
or eax, -1
.found:
mov [cur_file_idx], eax
.ret:
ret
free_directory:
mcall 68, 13, [directory_ptr]
and [directory_ptr], 0
ret
init_frame:
push eax
mov eax, [image]
mov [cur_frame], eax
test byte [eax + Image.Flags], Image.IsAnimated
jz @f
push ebx
mcall 26, 9
pop ebx
mov [cur_frame_time], eax
@@:
pop eax
ret
draw_window:
cmp [bFirstDraw], 0
jz .posok
or ecx, -1
mcall 9, procinfo
cmp dword [ebx + 66], 0
jle .noredraw
mov edx, ecx
mov esi, ecx
cmp dword [ebx + 42], 40 + 25 * 9
jae @f
mov edx, 40 + 25 * 9
@@:
cmp dword [ebx + 46], 70
jae @f
mov esi, 70
@@:
mov eax, edx
and eax, esi
cmp eax, -1
jz @f
mov ebx, ecx
mcall 67
@@:
.posok:
mcall 12, 1
mcall 48, 4
mov ebp, eax ; save skin height
add eax, [wnd_height]
__mov ebx, 100, 0
add ebx, [wnd_width]
lea ecx, [100*65536 + eax]
mcall 0, , , 0x73FFFFFF, , s_header
mcall 9, procinfo, -1
mov [bFirstDraw], 1
mov ebx, [procinfo + 62]
inc ebx
mcall 13, , <0, 35>, 0xFFFFFF
mov ecx, [procinfo + 66]
inc ecx
mov esi, [draw_height]
add esi, 35
sub ecx, esi
jbe @f
push esi
shl esi, 16
add ecx, esi
pop esi
mcall
xor ecx, ecx
@@:
add ecx, esi
add ecx, 35*10000h - 35
__mov ebx, 0, 5
mcall
mov esi, [draw_width]
add esi, ebx
mov ebx, [procinfo+62]
inc ebx
sub ebx, esi
jbe @f
shl esi, 16
add ebx, esi
mcall
@@:
mov ebx, [procinfo + 62]
push ebx
mcall 38, , <30, 30>, 0x007F7F7F
mcall , <5 + 25 * 1, 5 + 25 * 1>, <0, 30>
mcall , <10 + 25 * 3, 10 + 25 * 3>
mcall , <15 + 25 * 4, 15 + 25 * 4>
pop ebx
sub ebx, 25 * 5 + 10
push ebx
imul ebx, 10001h
mcall
mcall 8, <5 + 25 * 0, 20>, <5, 20>, 'opn'+40000000h
mcall , <10 + 25 * 1, 20>, , 'bck'+40000000h
mcall , <10 + 25 * 2, 20>, , 'fwd'+40000000h
mcall , <15 + 25 * 3, 20>, , 'bgr'+40000000h
pop ebx
add ebx, 5
shl ebx, 16
mov bl, 20
mcall , , , 'flh'+40000000h
add ebx, 25 * 65536
mcall , , , 'flv'+40000000h
add ebx, 30 * 65536
mcall , , , 'rtr'+40000000h
add ebx, 25 * 65536
mcall , , , 'rtl'+40000000h
add ebx, 25 * 65536
mcall , , , 'flb'+40000000h
mov ebp, (numimages-1)*20
mcall 65, buttons+openbtn*20, <20, 20>, <5 + 25 * 0, 5>, 8, palette
mcall , buttons+backbtn*20, , <10 + 25 * 1, 5>
mcall , buttons+forwardbtn*20, , <10 + 25 * 2, 5>
mcall , buttons+bgrbtn*20, , <15 + 25 * 3, 5>
mov edx, [procinfo + 62]
sub edx, 25 * 5 + 4
shl edx, 16
mov dl, 5
mcall , buttons+fliphorzbtn*20
add edx, 25 * 65536
mcall , buttons+flipvertbtn*20
add edx, 30 * 65536
mcall , buttons+rotcwbtn*20
add edx, 25 * 65536
mcall , buttons+rotccwbtn*20
add edx, 25 * 65536
mcall , buttons+rot180btn*20
call draw_cur_frame
mcall 12, 2
.noredraw:
ret
draw_cur_frame:
push 0 ; ypos
push 0 ; xpos
mov eax, [procinfo+66]
sub eax, 34
push eax ; max height
mov eax, [procinfo+62]
sub eax, 4
push eax ; max width
push 35 ; y
push 5 ; x
push [cur_frame]
call [img.draw]
ret
; void* __stdcall mem.Alloc(unsigned size);
mem.Alloc:
push ebx ecx
mov ecx, [esp+12]
mcall 68, 12
pop ecx ebx
ret 4
; void* __stdcall mem.ReAlloc(void* mptr, unsigned size);
mem.ReAlloc:
push ebx ecx edx
mov edx, [esp+16]
mov ecx, [esp+20]
mcall 68, 20
pop edx ecx ebx
ret 8
; void __stdcall mem.Free(void* mptr);
mem.Free:
push ebx ecx
mov ecx, [esp+12]
mcall 68, 13
pop ecx ebx
ret 4
;-----------------------------------------------------------------------------
s_header db 'Kolibri Image Viewer', 0
;-----------------------------------------------------------------------------
opendialog:
;
; STEP 1 Run SYSXTREE with parametrs MYPID 4 bytes in dec,
; 1 byte space, 1 byte type of dialog (O - Open ,S - Save)
;
;; mov esi,path
mov edi,path
xor eax,eax
mov ecx,(1024+16)/4
rep stosd
;mov [get_loops],0
mov [dlg_pid_get],0
; Get my PID in dec format 4 bytes
mov eax,9
mov ebx,procinfo
or ecx,-1
mcall
; convert eax bin to param dec
mov eax,dword [procinfo+30] ;offset of myPID
mov edi,param+4-1 ;offset to 4 bytes
mov ecx,4
mov ebx,10
new_d:
xor edx,edx
div ebx
add dl,'0'
mov [edi],dl
dec edi
loop new_d
; wirite 1 byte space to param
mov [param+4],byte 32 ;Space for next parametr
; and 1 byte type of dialog to param
mov [param+5],byte 'O' ;Get Open dialog (Use 'S' for Save dialog)
;
; STEP2 prepare IPC area for get messages
;
; prepare IPC area
mov [path],dword 0
mov [path+4],dword 8
; define IPC memory
mov eax,60
mov ebx,1 ; define IPC
mov ecx,path ; offset of area
mov edx,1024+16 ; size
mcall
; change wanted events list 7-bit IPC event
mov eax,40
mov ebx,01000111b
cmp [image], 0
jnz @f
mov bl, 01000110b
@@:
mcall
;
; STEP 3 run SYSTEM XTREE with parameters
;
mov eax,70
mov ebx,run_fileinfo
mcall
mov [get_loops],0
getmesloop:
mov eax,23
mov ebx,50 ;0.5 sec
mcall
dec eax
jz mred
dec eax
jz mkey
dec eax
jz mbutton
cmp al, 7-3
jz mgetmes
; Get number of procces
mov ebx,procinfo
mov ecx,-1
mov eax,9
mcall
mov ebp,eax
loox:
mov eax,9
mov ebx,procinfo
mov ecx,ebp
mcall
mov eax,[DLGPID]
cmp [procinfo+30],eax ;IF Dialog find
je dlg_is_work ;jmp to dlg_is_work
dec ebp
jnz loox
jmp erroff
dlg_is_work:
cmp [procinfo+50],word 9 ;If slot state 9 - dialog is terminated
je erroff ;TESTODP2 terminated too
cmp [dlg_pid_get],dword 1
je getmesloop
inc [get_loops]
cmp [get_loops],4 ;2 sec if DLG_PID not get, TESTOP2 terminated
jae erroff
jmp getmesloop
mred:
cmp [image], 0
jz getmesloop
call draw_window
jmp getmesloop
mkey:
mov eax,2
mcall ; read (eax=2)
jmp getmesloop
mbutton:
mov eax,17 ; get id
mcall
cmp ah,1 ; button id=1 ?
jne getmesloop
mov eax,-1 ; close this program
mcall
mgetmes:
; If dlg_pid_get then second message get jmp to still
cmp [dlg_pid_get],dword 1
je ready
; First message is number of PID SYSXTREE dialog
; convert PID dec to PID bin
movzx eax,byte [path+16]
sub eax,48
imul eax,10
movzx ebx,byte [path+16+1]
add eax,ebx
sub eax,48
imul eax,10
movzx ebx,byte [path+16+2]
add eax,ebx
sub eax,48
imul eax,10
movzx ebx,byte [path+16+3]
add eax,ebx
sub eax,48
mov [DLGPID],eax
; Claear and prepare IPC area for next message
mov [path],dword 0
mov [path+4],dword 8
mov [path+8],dword 0
mov [path+12],dword 0
mov [path+16],dword 0
; Set dlg_pid_get for get next message
mov [dlg_pid_get],dword 1
cmp [image], 0
jz getmesloop
call draw_window
jmp getmesloop
ready:
;
; The second message get
; Second message is 100 bytes path to SAVE/OPEN file
; shl path string on 16 bytes
;
mov esi,path+16
mov edi,path
mov ecx,1024/4
rep movsd
mov [edi],byte 0
openoff:
mcall 40, 7
clc
ret
erroff:
mcall 40, 7
stc
ret
;-----------------------------------------------------------------------------
align 4
@IMPORT:
library \
libio , 'libio.obj' , \
libgfx , 'libgfx.obj' , \
libimg , 'libimg.obj' , \
sort , 'sort.obj'
import libio , \
libio.init , 'lib_init' , \
file.size , 'file.size' , \
file.open , 'file.open' , \
file.read , 'file.read' , \
file.close , 'file.close'
import libgfx , \
libgfx.init , 'lib_init' , \
gfx.open , 'gfx.open' , \
gfx.close , 'gfx.close' , \
gfx.pen.color , 'gfx.pen.color' , \
gfx.line , 'gfx.line'
import libimg , \
libimg.init , 'lib_init' , \
img.is_img , 'img.is_img' , \
img.to_rgb2 , 'img.to_rgb2', \
img.decode , 'img.decode' , \
img.flip , 'img.flip' , \
img.rotate , 'img.rotate' , \
img.destroy , 'img.destroy', \
img.draw , 'img.draw'
import sort, sort.START, 'START', SortDir, 'SortDir', strcmpi, 'strcmpi'
bFirstDraw db 0
;-----------------------------------------------------------------------------
virtual at 0
file 'kivicons.bmp':0xA,4
load offbits dword from 0
end virtual
numimages = 9
openbtn = 0
backbtn = 1
forwardbtn = 2
bgrbtn = 3
fliphorzbtn = 4
flipvertbtn = 5
rotcwbtn = 6
rotccwbtn = 7
rot180btn = 8
palette:
file 'kivicons.bmp':0x36,offbits-0x36
buttons:
file 'kivicons.bmp':offbits
repeat 10
y = % - 1
z = 20 - %
repeat numimages*5
load a dword from $ - numimages*20*20 + numimages*20*y + (%-1)*4
load b dword from $ - numimages*20*20 + numimages*20*z + (%-1)*4
store dword a at $ - numimages*20*20 + numimages*20*z + (%-1)*4
store dword b at $ - numimages*20*20 + numimages*20*y + (%-1)*4
end repeat
end repeat
; DATA AREA
get_loops dd 0
dlg_pid_get dd 0
DLGPID dd 0
param:
dd 0 ; My dec PID
dd 0,0 ; Type of dialog
run_fileinfo:
dd 7
dd 0
dd param
dd 0
dd 0
;run_filepath
db '/sys/SYSXTREE',0
readdir_fileinfo:
dd 1
dd 0
dd 0
readblocks dd 0
directory_ptr dd 0
;-----------------------------------------------------------------------------
I_END:
curdir rb 1024
align 4
img_data dd ?
img_data_len dd ?
fh dd ?
image dd ?
wnd_width dd ?
wnd_height dd ?
draw_width dd ?
draw_height dd ?
last_name_component dd ?
cur_file_idx dd ?
cur_frame_time dd ?
cur_frame dd ?
ctx dd ?
procinfo: rb 1024
path: rb 1024+16
@PARAMS rb 512