diff --git a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm
index 0a6ee2e9e2..b52c6e45d7 100644
--- a/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm
+++ b/programs/develop/libraries/libs-dev/libimg/bmp/bmp.asm
@@ -102,8 +102,7 @@ endl
jnz .error
; convert images with <= 8 bpp to 8bpp, other - to 32 bpp
.normal:
- xor eax, eax
- inc eax ; Image.bpp8
+ m2m eax, Image.bpp8
cmp [ebx + bmp.Header.info.BitCount], 8
jbe @f
mov al, Image.bpp32
@@ -119,8 +118,7 @@ endl
pushd [ebx + bmp.Header.info.Width]
jmp .create
.old1:
- xor eax, eax
- inc eax ; Image.bpp8
+ m2m eax, Image.bpp8
cmp [ebx + bmp.Header.info.OldBitCount], 8
jbe @f
mov al, Image.bpp32
diff --git a/programs/develop/libraries/libs-dev/libimg/gif/gif.asm b/programs/develop/libraries/libs-dev/libimg/gif/gif.asm
index 845379764a..07e4a2277d 100644
--- a/programs/develop/libraries/libs-dev/libimg/gif/gif.asm
+++ b/programs/develop/libraries/libs-dev/libimg/gif/gif.asm
@@ -51,7 +51,7 @@ proc img.is.gif _data, _length ;////////////////////////////////////////////////
;;------------------------------------------------------------------------------------------------;;
;< eax = false / true ;;
;;================================================================================================;;
- cmp [_length], 6
+ cmp [_length], sizeof.gif.Header
jb .nope
mov eax, [_data]
cmp dword[eax], 'GIF8'
@@ -82,36 +82,99 @@ proc img.decode.gif _data, _length ;////////////////////////////////////////////
;< eax = 0 (error) or pointer to image ;;
;;================================================================================================;;
locals
+ max_color dd ?
+ cur_color_table_size dd ?
+ transparent_color dd ?
+ background_color dd ?
+ prev_palette dd ?
+ aux_palette dd ?
img dd ?
+ prev_img_data dd ?
+ aux_img_data dd ?
+ aux_img_type dd ?
+ prev_num_colors dd ?
+ main_img dd ?
global_color_table dd ?
global_color_table_size dd ?
endl
- push ebx
+img.decode.gif.main_img equ main_img
+img.decode.gif.prev_img_data equ prev_img_data
+img.decode.gif.transparent_color equ transparent_color
+img.decode.gif.background_color equ background_color
+img.decode.gif._length equ _length
+img.decode.gif.prev_num_colors equ prev_num_colors
+img.decode.gif.prev_palette equ prev_palette
+img.decode.gif.max_color equ max_color
+img.decode.gif._data equ _data
+img.decode.gif.aux_img_data equ aux_img_data
+img.decode.gif.aux_img_type equ aux_img_type
+img.decode.gif.aux_palette equ aux_palette
+; offset of _length parameter for child functions with ebp-based frame
+; child saved ebp, return address, 3 saved registers, 14 local variables
+img.decode.gif._length_child equ _length + 4 + 4 + 4*3 + 4*14
+img.decode.gif.max_color_child equ ebp + 4 + 4 + 4*3
+img.decode.gif.cur_color_table_size_child equ ebp + 4 + 4 + 4*3 + 4
+
+ push ebx esi edi
+ xor eax, eax
+ mov [img], eax
+ mov [main_img], eax
+ mov [prev_img_data], eax
+ mov [aux_img_data], eax
+ mov [aux_img_type], eax
+ mov [prev_palette], eax
+ mov [aux_palette], eax
+; when no previous image is available, use background fill with 1-entry palette
+ inc eax
+ mov [prev_num_colors], eax
+ lea eax, [background_color]
+ mov [prev_palette], eax
+; guard against incorrect gif files, which use Restore-To-Background disposal method, but do not define bgr color
+ mov dword [eax], 0xFFFFFF
+; guard against incorrect gif files without any color tables
+; "If no color table is available at
+; all, the decoder is free to use a system color table or a table of its own. In
+; that case, the decoder may use a color table with as many colors as its
+; hardware is able to support; it is recommended that such a table have black and
+; white as its first two entries, so that monochrome images can be rendered
+; adequately." (c) official gif documentation
+ mov [global_color_table], gif_default_palette
+ mov [global_color_table_size], 2
; img.is.gif is called by caller (img.decode)
; stdcall img.is.gif, [_data], [_length]
; or eax, eax
; jz .error
- mov [global_color_table_size], 0
mov ebx, [_data]
+ sub [_length], sizeof.gif.Header
- test [ebx + gif.Header.lsd.Packed], gif.LSD.Packed.GlobalColorTableFlag
- jz @f
- lea eax, [ebx + sizeof.gif.Header]
- mov [global_color_table], eax
mov cl, [ebx + gif.Header.lsd.Packed]
+ add ebx, sizeof.gif.Header
+; gif.LSD.Packed.GlobalColorTableFlag = 80h
+; test cl, gif.LSD.Packed.GlobalColorTableFlag
+; jz @f
+ test cl, cl
+ jns @f
+ mov [global_color_table], ebx
and cl, gif.LSD.Packed.SizeOfGlobalColorTableMask
- shr cl, gif.LSD.Packed.SizeOfGlobalColorTableShift
- mov eax, 2
+; shr cl, gif.LSD.Packed.SizeOfGlobalColorTableShift ; here Shift = 0
+ push 2
+ pop eax
shl eax, cl
mov [global_color_table_size], eax
lea eax, [eax * 3]
+ sub [_length], eax
+ jbe .error ; there must be at least 1 additional byte after color table
+ movzx ecx, byte [ebx - sizeof.gif.Header + gif.Header.lsd.BackgroundColor]
+ lea ecx, [ecx*3]
+ mov ecx, [ebx + ecx] ; eax = xxBBGGRR, convert to Kolibri color
+ bswap ecx
+ shr ecx, 8
+ mov [background_color], ecx
add ebx, eax
- @@: add ebx, sizeof.gif.Header
-
- mov [img], 0
+ @@:
; @@: cmp byte[ebx + gif.Block.Introducer], gif.Block.Introducer.Extension
; jne .next_image
@@ -128,26 +191,45 @@ endl
jz .error
mov edx, [img]
mov [eax + Image.Previous], edx
+ push sizeof.gif.LogicalScreenDescriptor
+ pop ecx
test edx, edx
jz @f
mov [edx + Image.Next], eax
-@@:
- mov [img], eax
- mov edx, eax
+ xor ecx, ecx
+ @@:
+ push eax
mov [eax + Image.Type], Image.bpp8
- invoke mem.alloc, sizeof.gif.Image
+ add ecx, sizeof.gif.Image
+ invoke mem.alloc, ecx
+ pop edx
or eax, eax
- jz .error
+ jz .error2
mov [edx + Image.Extended], eax
+ xor ecx, ecx
+ cmp [img], ecx
+ jnz @f
+ mov esi, [_data]
+ add esi, gif.Header.lsd
+ lea edi, [eax + sizeof.gif.Image]
+ mov cl, sizeof.gif.LogicalScreenDescriptor
+ rep movsb
+ mov [main_img], edx
+ @@:
+ mov [img], edx
stdcall ._.process_extensions
- cmp byte[ebx + gif.Block.Introducer], gif.Block.Introducer.ImageDescriptor
+ cmp al, gif.Block.Introducer.ImageDescriptor
jne .error
+ sub [_length], sizeof.gif.ImageDescriptor
+ jc .error
movzx eax, [ebx + gif.ImageDescriptor.Width]
movzx ecx, [ebx + gif.ImageDescriptor.Height]
+ push edx
stdcall img._.resize_data, [img], eax, ecx
+ pop edx
or eax, eax
jz .error
@@ -164,12 +246,19 @@ endl
lea esi, [ebx + sizeof.gif.ImageDescriptor]
mov cl, [ebx + gif.ImageDescriptor.Packed]
and cl, gif.ID.Packed.SizeOfLocalColorTableMask
- shr cl, gif.ID.Packed.SizeOfLocalColorTableShift
- mov eax, 2
+; here Shift = 0
+; shr cl, gif.ID.Packed.SizeOfLocalColorTableShift
+ push 2
+ pop eax
shl eax, cl
mov ecx, eax
lea eax, [eax*3]
add ebx, eax
+ sub [_length], eax
+ jbe .error ; because we load additional byte, check is 'jbe', not 'jc'
+@@:
+ mov [cur_color_table_size], ecx
+ dec [cur_color_table_size]
@@:
lodsd
dec esi
@@ -179,24 +268,105 @@ endl
loop @b
add ebx, sizeof.gif.ImageDescriptor
stdcall ._.process_image
-
- .decoded:
- or eax, eax
+ push ebx
+ mov edx, [img]
+ push edx
+ stdcall ._.superimpose
+ pop edx
+ push edx
+ stdcall ._.dispose
+ pop edx
+ mov edx, [edx + Image.Previous]
+ test edx, edx
+ jz .nofreeprev
+ mov ebx, [edx + Image.Extended]
+ cmp [ebx + gif.Image.gce.DelayTime], 0
+ jnz .nofreeprev
+ mov esi, [prev_palette]
+ cmp esi, [edx + Image.Palette]
+ jnz @f
+ mov ecx, [prev_num_colors]
+ stdcall ._.alloc_aux_palette
+ test eax, eax
+ jz .nofreeprev
+ mov [prev_palette], eax
+ @@:
+ mov esi, [prev_img_data]
+ cmp esi, [edx + Image.Data]
+ jnz .noprevdata
+ push 1
+ pop eax
+ cmp [edx + Image.Type], Image.bpp8
jz @f
- stdcall img.destroy, [img]
- jmp .error
-
- @@: mov eax, [img]
- ret
+ mov al, 3
+ @@:
+ cmp [aux_img_type], eax
+ jb .resetaux
+ mov edi, [aux_img_data]
+ imul eax, [edx + Image.Width]
+ imul eax, [edx + Image.Height]
+ xchg eax, ecx
+ rep movsb
+ jmp .noprevdata
+ .resetaux:
+ mov [aux_img_type], eax
+ mov eax, [aux_img_data]
+ test eax, eax
+ jz @f
+ invoke mem.free, eax
+ @@:
+ xor eax, eax
+ xchg eax, [edx + Image.Data]
+ mov [aux_img_data], eax
+ .noprevdata:
+ cmp edx, [main_img]
+ jnz @f
+ mov eax, [edx + Image.Next]
+ mov [main_img], eax
+ mov esi, [eax + Image.Extended]
+ mov edi, [edx + Image.Extended]
+ mov [edx + Image.Extended], esi
+ mov [eax + Image.Extended], edi
+ push sizeof.gif.Image
+ pop ecx
+ rep movsb
+ @@:
+ stdcall img.destroy.layer, edx
+ .nofreeprev:
+ pop ebx
+ test ebx, ebx
+ jz .ret
+ jmp .next_image
+
+ .error2:
+ mov [img], edx
.error:
mov eax, [img]
test eax, eax
+ jz .ret
+ cmp [main_img], eax
+ jnz @f
+ and [main_img], 0
+ @@:
+ stdcall img.destroy.layer, eax
+ .ret:
+ mov eax, [aux_img_data]
+ test eax, eax
jz @f
- stdcall img.destroy, eax
-@@:
- xor eax, eax
- pop ebx
+ invoke mem.free, eax
+ @@:
+ mov eax, [aux_palette]
+ test eax, eax
+ jz @f
+ invoke mem.free, eax
+ @@:
+ mov eax, [main_img]
+ cmp [eax + Image.Next], 0
+ jz @f
+ or [eax + Image.Flags], Image.IsAnimated
+ @@:
+ pop edi esi ebx
ret
endp
@@ -224,26 +394,6 @@ endp
;;================================================================================================;;
-;;================================================================================================;;
-proc img.decode.gif._.skip_data ;/////////////////////////////////////////////////////////////////;;
-;;------------------------------------------------------------------------------------------------;;
-;? --- TBD --- ;;
-;;------------------------------------------------------------------------------------------------;;
-;> ebx = pointer to data blocks array ;;
-;;------------------------------------------------------------------------------------------------;;
-;< eax = pointer to data right after data blocks array ;;
-;;================================================================================================;;
- push ecx
- xor ecx, ecx
- @@: mov cl, [esi]
- or cl, cl
- jz @f
- lea esi, [esi + ecx + 1]
- jmp @b
- @@: pop ecx
- ret
-endp
-
;;================================================================================================;;
proc img.decode.gif._.process_extensions ;////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
@@ -254,65 +404,65 @@ proc img.decode.gif._.process_extensions ;//////////////////////////////////////
;;------------------------------------------------------------------------------------------------;;
;< --- TBD --- ;;
;;================================================================================================;;
- push edx
mov esi, ebx
+ xor eax, eax
+ mov [edx + Image.Delay], eax
.next_block:
- mov al, [esi + gif.Block.Introducer]
+ dec [img.decode.gif._length]
+ js .exit_err
+ lodsb ; load gif.Block.Introducer
cmp al, gif.Block.Introducer.Extension
- je .ext_block
-; cmp al, gif.Block.Introducer.ImageDescriptor
-; je .exit
-; cmp al, gif.Block.Introducer.EndOfFile
-; je .exit
- jmp .exit
+ jne .exit
.ext_block:
- mov al, [esi + gif.Extension.Label]
- cmp al, gif.Extension.Label.PlainText
- je .plain_text_ext
+ dec [img.decode.gif._length]
+ js .exit_err
+ lodsb ; load gif.Extension.Label
cmp al, gif.Extension.Label.GraphicsControl
je .graphics_control_ext
- cmp al, gif.Extension.Label.Comment
- je .comment_ext
- cmp al, gif.Extension.Label.Application
- je .application_ext
- jmp .exit
-
- .plain_text_ext:
- add esi, gif.PlainTextExtension.PlainTextData
- stdcall img.decode.gif._.skip_data
- jmp .next_ext_block
+; cmp al, gif.Extension.Label.PlainText
+; je .plain_text_ext
+; cmp al, gif.Extension.Label.Comment
+; je .comment_ext
+; cmp al, gif.Extension.Label.Application
+; je .application_ext
+; skip all other extensions
+ .skip_ext:
+ dec [img.decode.gif._length]
+ js .exit_err
+ lodsb ; load BlockSize
+ .1:
+ test al, al
+ jz .next_block
+ sub [img.decode.gif._length], eax
+ jc .exit_err
+ add esi, eax
+ jmp .skip_ext
.graphics_control_ext:
+ dec [img.decode.gif._length]
+ js .exit_err
+ lodsb ; load BlockSize; must be sizeof.gif.GraphicsControlExtension
+ cmp al, sizeof.gif.GraphicsControlExtension
+ jnz .1
+ sub [img.decode.gif._length], eax
+ jc .exit_err
push edi
+ movzx edi, [esi + gif.GraphicsControlExtension.DelayTime]
+ mov [edx + Image.Delay], edi
mov edi, [edx + Image.Extended]
add edi, gif.Image.gce
- mov ecx, sizeof.gif.GraphicsControlExtension
+ mov ecx, eax
rep movsb
pop edi
- jmp .next_ext_block
+ jmp .skip_ext
- .comment_ext:
- add esi, gif.CommentExtension.CommentData
- stdcall img.decode.gif._.skip_data
- jmp .next_ext_block
-
- .application_ext:
- add esi, gif.ApplicationExtension.ApplicationData
- stdcall img.decode.gif._.skip_data
- jmp .next_ext_block
-
- .next_ext_block:
- mov al, [esi + gif.Block.Introducer]
- cmp al, gif.Block.Introducer.EndOfData
- jne .exit
- inc esi
- jmp .next_block
+ .exit_err:
+ xor eax, eax
.exit:
mov ebx, esi
- pop edx
ret
endp
@@ -354,6 +504,7 @@ endl
inc eax
mov [row_end], eax
and [pass], 0
+ and dword [img.decode.gif.max_color_child], 0
mov eax, [edx + Image.Extended]
test [eax + gif.Image.info.Packed], gif.ID.Packed.InterleaceFlag
jz @f
@@ -362,15 +513,21 @@ endl
@@: mov esi, ebx
mov edi, [edx + Image.Data]
- push edi
+ sub dword [img.decode.gif._length_child], 2
+ jc .error
movzx ecx, byte[esi]
inc esi
+ cmp cl, 12
+ jae .error
mov [codesize], ecx
inc [codesize]
- mov edi, [workarea]
xor eax, eax
lodsb ; eax - block_count
+ sub [img.decode.gif._length_child], eax
+ jc .error
add eax, esi
+ push edi
+ mov edi, [workarea]
mov [block_ofs], eax
mov [bit_count], 8
mov eax, 1
@@ -400,19 +557,22 @@ endl
.cycle:
movzx ebx, ax
call .get_symbol
- cmp eax, edx
- jae .notintable
- cmp eax, [CC]
- je .reinit
cmp eax, [EOI]
je .end
+ cmp eax, edx
+ ja .error
+ je .notintable
+ cmp eax, [CC]
+ je .reinit
call .output
.add:
+ cmp edx, 0x00001000
+ jae .cycle
mov ecx, [workarea]
mov [ecx + edx * 4], ebx
- cmp edx, 0x00000FFF
- jae .cycle
inc edx
+ cmp edx, 0x1000
+ je .noinc
bsr ebx, edx
cmp ebx, [compsize]
jne .noinc
@@ -436,15 +596,26 @@ endl
cmp [workarea], 0
je @f
invoke mem.free, [workarea]
- @@: xor eax, eax
- ret
+ @@:
+ mov ebx, [block_ofs]
+ @@:
+ dec [img.decode.gif._length_child]
+ js @f
+ movzx eax, byte [ebx]
+ inc ebx
+ test eax, eax
+ jz .ret
+ sub [img.decode.gif._length_child], eax
+ jc @f
+ add ebx, eax
+ jmp @b
.error:
cmp [workarea], 0
je @f
invoke mem.free, [workarea]
- @@: xor eax, eax
- inc eax
+ @@: xor ebx, ebx
+ .ret:
ret
;;------------------------------------------------------------------------------------------------;;
@@ -455,32 +626,35 @@ img.decode.gif._.process_image.get_symbol:
xor eax, eax
.shift:
- ror byte[esi], 1
- rcr eax,1
dec [bit_count]
- jnz .loop1
+ jns .loop1
inc esi
cmp esi, [block_ofs]
jb .noblock
push eax
xor eax, eax
+ sub [img.decode.gif._length_child], 1
+ jc .error_eof
lodsb
test eax, eax
jnz .nextbl
- mov eax, [EOI]
- sub esi, 2
- add esp, 8
- jmp .exit
+ .error_eof:
+ add esp, 12
+ jmp img.decode.gif._.process_image.error
.nextbl:
+ sub [img.decode.gif._length_child], eax
+ jc .error_eof
add eax, esi
mov [block_ofs], eax
pop eax
.noblock:
- mov [bit_count], 8
+ mov [bit_count], 7
.loop1:
+ ror byte[esi], 1
+ rcr eax,1
loop .shift
pop ecx
rol eax, cl
@@ -506,8 +680,16 @@ img.decode.gif._.process_image.output:
.loop2:
pop ax
- stosb
+ cmp al, byte [img.decode.gif.cur_color_table_size_child]
+ jbe @f ; guard against incorrect GIFs
+ mov al, 0
+ @@: cmp al, byte [img.decode.gif.max_color_child]
+ jbe @f
+ mov [img.decode.gif.max_color_child], al
+ @@: stosb
+ cmp edi, [img_end]
+ jz .done
cmp edi, [row_end]
jb .norowend
mov eax, [width]
@@ -546,8 +728,847 @@ img.decode.gif._.process_image.output:
pop edx eax esi
retn
+ .done:
+ lea esp, [esp+(ecx-1)*2]
+ pop edx eax esi eax
+ jmp img.decode.gif._.process_image.exit
+
endp
+;;================================================================================================;;
+proc img.decode.gif._.is_logical_screen ;/////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Determines whether GIF image occupies the whole logical screen ;;
+;;------------------------------------------------------------------------------------------------;;
+;> eax = extended image data ;;
+;> ebx = main image ;;
+;;------------------------------------------------------------------------------------------------;;
+;< ZF set <=> image area equals logical screen ;;
+;;================================================================================================;;
+ mov ebx, [ebx + Image.Extended]
+ cmp [eax + gif.Image.info.Left], 0
+ jnz @f
+ cmp [eax + gif.Image.info.Top], 0
+ jnz @f
+ mov cx, [eax + gif.Image.info.Width]
+ cmp cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
+ jnz @f
+ mov cx, [eax + gif.Image.info.Height]
+ cmp cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
+@@: retn
+endp
+
+main_img equ img.decode.gif.main_img
+transparent_color equ img.decode.gif.transparent_color
+background_color equ img.decode.gif.background_color
+prev_num_colors equ img.decode.gif.prev_num_colors
+prev_palette equ img.decode.gif.prev_palette
+max_color equ img.decode.gif.max_color
+prev_img_data equ img.decode.gif.prev_img_data
+_data equ img.decode.gif._data
+aux_img_data equ img.decode.gif.aux_img_data
+aux_img_type equ img.decode.gif.aux_img_type
+aux_palette equ img.decode.gif.aux_palette
+
+;;================================================================================================;;
+proc img.decode.gif._.superimpose ;///////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+ mov ebx, [main_img]
+ mov eax, [edx + Image.Extended]
+ or [transparent_color], -1 ; no transparent color
+ test byte [eax + gif.Image.gce.Packed], 1
+ jz @f
+ movzx ecx, byte [eax + gif.Image.gce.ColorIndex]
+ mov [transparent_color], ecx
+ cmp edx, ebx
+ jnz .has_transparency
+ shl ecx, 2
+ add ecx, [edx + Image.Palette]
+ mov dword [background_color], 0xFFFFFF ; white background
+ mov dword [ecx], 0xFFFFFF
+; mov esi, [_data]
+; test [esi+gif.Header.lsd.Packed], gif.LSD.Packed.GlobalColorTableFlag
+; jz @f
+; movzx ecx, [esi+gif.Header.lsd.BackgroundColor]
+; push ecx
+; shl ecx, 2
+; add ecx, [edx + Image.Palette]
+; mov dword [ecx], 0xFFFFFF
+; pop ecx
+; lea ecx, [ecx*3]
+; add esi, ecx
+; mov byte [esi+sizeof.gif.Header+0], 0xFF
+; mov byte [esi+sizeof.gif.Header+1], 0xFF
+; mov byte [esi+sizeof.gif.Header+2], 0xFF
+@@:
+ call img.decode.gif._.is_logical_screen
+ jnz .has_transparency
+; image is not transparent, so keep it as is
+ retn
+
+.has_transparency:
+; image has transparent areas, we must superimpose it on the previous
+ mov ecx, [prev_num_colors]
+ cmp ecx, 0x100
+ ja .superimpose_on_rgb
+; create common palette
+ sub esp, 3FCh
+ push eax
+ mov edi, esp
+ push ecx
+ mov esi, [prev_palette]
+ rep movsd
+ pop ecx
+ mov esi, [edx + Image.Palette]
+ xor ebx, ebx
+ mov edi, esp
+ sub esp, 100h
+.create_palette_loop:
+ push ecx
+ lodsd
+ cmp ebx, [transparent_color]
+ jz .nochange
+ cmp ebx, ecx
+ jae @f
+ cmp eax, [edi+ebx*4]
+ jz .nochange
+@@:
+ push edi
+ repnz scasd
+ pop edi
+ jnz .increase_palette
+ sub ecx, [esp]
+ not ecx ; cl = index of new color in current palette
+ jmp .palette_common
+.increase_palette:
+ mov ecx, [esp]
+ test ch, ch
+ jnz .output_to_rgb
+ inc dword [esp]
+ mov [edi+ecx*4], eax
+ jmp .palette_common
+.nochange:
+ mov ecx, ebx
+.palette_common:
+ mov [ebx+esp+4], cl
+ pop ecx
+ inc ebx
+ cmp ebx, [max_color]
+ jbe .create_palette_loop
+ mov [max_color], ecx
+; if image occupies only part of logical screen, allocate memory for full logical screen
+ mov ebx, [main_img]
+ mov eax, [edx + Image.Extended]
+ mov esi, [edx + Image.Data]
+ call img.decode.gif._.is_logical_screen
+ jz @f
+ and [edx + Image.Data], 0
+ push edx
+ movzx eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
+ push eax
+ movzx eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
+ stdcall img._.resize_data, edx, eax
+ pop edx
+ test eax, eax
+ jz .palette_nomem
+@@:
+; copy final palette to Image.Palette
+ push esi esi
+ mov esi, edi
+ mov edi, [edx + Image.Palette]
+ mov ecx, [max_color]
+ dec [max_color]
+ rep movsd
+ mov esi, [prev_img_data]
+ mov edi, [edx + Image.Data]
+; do superimpose, [esp] -> source data, esi -> prev image data
+; (NULL if previous image is filled with background color), esp+8 -> correspondence between
+; used palette and final palette, edi -> destination data
+ mov ebx, [edx + Image.Extended]
+; first Top rows are copied from [prev_img_data] or filled with bgr
+ movzx ecx, [ebx + gif.Image.info.Top]
+ cmp ecx, [edx + Image.Height]
+ jb @f
+ mov ecx, [edx + Image.Height]
+@@:
+ push ecx
+ imul ecx, [edx + Image.Width]
+ call .rep_movsb_or_stosb
+ pop ecx
+; convert rows
+ sub ecx, [edx + Image.Height]
+ neg ecx
+ push ecx
+ cmp cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Height]
+@@:
+ jecxz .norows
+.convert_rows:
+ push ecx
+ movzx ecx, [ebx + gif.Image.info.Left]
+ cmp ecx, [edx + Image.Width]
+ jb @f
+ mov ecx, [edx + Image.Width]
+@@:
+ push ecx
+ call .rep_movsb_or_stosb
+ pop ecx
+ sub ecx, [edx + Image.Width]
+ neg ecx
+ push ecx edx
+ mov edx, [esp+16] ; source data
+ cmp cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Width]
+@@:
+ jecxz .norowsi
+.rowsloop:
+ movzx eax, byte [edx]
+ inc edx
+ cmp eax, [transparent_color]
+ jz .rows_transparent
+ mov al, [eax+esp+24]
+ stosb
+ call .lodsb
+ jmp @f
+.rows_transparent:
+ call .lodsb
+ stosb
+@@:
+ loop .rowsloop
+.norowsi:
+ pop edx ecx
+ sub cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ call .rep_movsb_or_stosb
+@@:
+ movzx eax, [ebx + gif.Image.info.Width]
+ add [esp+8], eax
+ pop ecx
+ loop .convert_rows
+.norows:
+ pop ecx
+ sub cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ imul ecx, [edx + Image.Width]
+ call .rep_movsb_or_stosb
+@@:
+; free old image data if we have allocated new copy
+ pop esi esi
+ cmp esi, [edx + Image.Data]
+ jz @f
+ invoke mem.free, esi
+@@:
+; cleanup stack and return
+ add esp, 500h
+ retn
+.palette_nomem:
+ mov [edx + Image.Data], esi
+ jmp @b
+
+.output_to_rgb:
+ pop ecx
+ add esp, 500h
+; compose two palette-based images to one RGB image
+ xor esi, esi
+ xchg esi, [edx + Image.Data]
+ push esi
+ mov ebx, [_data]
+ push [edx + Image.Palette]
+ mov byte [edx + Image.Type], Image.bpp24
+ push edx
+ movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
+ push eax
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ stdcall img._.resize_data, edx, eax
+ pop edx
+ test eax, eax
+ jz .convrgb_nomem
+ push esi
+ mov edi, [edx + Image.Data]
+ mov esi, [prev_img_data]
+ mov ebx, [edx + Image.Extended]
+; first Top rows are copied from [prev_img_data] or filled with bgr
+ movzx ecx, [ebx + gif.Image.info.Top]
+ cmp ecx, [edx + Image.Height]
+ jb @f
+ mov ecx, [edx + Image.Height]
+@@:
+ push ecx
+ imul ecx, [edx + Image.Width]
+ call .convrgb_prev
+ pop ecx
+; convert rows
+ sub ecx, [edx + Image.Height]
+ neg ecx
+ push ecx
+ cmp cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Height]
+@@:
+ jecxz .convrgb_norows
+.convrgb_convert_rows:
+ push ecx
+ movzx ecx, [ebx + gif.Image.info.Left]
+ cmp ecx, [edx + Image.Width]
+ jb @f
+ mov ecx, [edx + Image.Width]
+@@:
+ push ecx
+ call .convrgb_prev
+ pop ecx
+ sub ecx, [edx + Image.Width]
+ neg ecx
+ push ecx edx
+ mov edx, [esp+16] ; source data
+ cmp cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Width]
+@@:
+ jecxz .convrgb_norowsi
+.convrgb_rowsloop:
+ movzx eax, byte [edx]
+ inc edx
+ cmp eax, [transparent_color]
+ jz .convrgb_rows_transparent
+ shl eax, 2
+ add eax, [esp+20] ; source palette
+ mov eax, [eax]
+ stosw
+ shr eax, 16
+ stosb
+ call .convrgb_lodsb
+ jmp @f
+.convrgb_rows_transparent:
+ call .convrgb_lodsb
+ stosw
+ shr eax, 16
+ stosb
+@@:
+ loop .convrgb_rowsloop
+.convrgb_norowsi:
+ pop edx ecx
+ sub cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ call .convrgb_prev
+@@:
+ movzx eax, [ebx + gif.Image.info.Width]
+ add [esp+8], eax
+ pop ecx
+ loop .convrgb_convert_rows
+.convrgb_norows:
+ pop ecx
+ sub cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ imul ecx, [edx + Image.Width]
+ call .convrgb_prev
+@@:
+; free old image data
+ pop esi esi ;esi
+ invoke mem.free;, esi
+ retn
+.convrgb_nomem:
+ pop esi esi
+ retn
+
+.superimpose_on_rgb:
+; previous image is RGB, new image has transparent areas
+ xor esi, esi
+ xchg esi, [edx + Image.Data]
+ push esi
+ mov ebx, [_data]
+ push [edx + Image.Palette]
+ mov byte [edx + Image.Type], Image.bpp24
+ push edx
+ movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
+ push eax
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ stdcall img._.resize_data, edx, eax
+ pop edx
+ test eax, eax
+ jz .rgb_nomem
+ push esi
+ mov edi, [edx + Image.Data]
+ mov esi, [prev_img_data]
+ mov ebx, [edx + Image.Extended]
+; first Top rows are copied from [prev_img_data] or filled with bgr
+ movzx ecx, [ebx + gif.Image.info.Top]
+ cmp ecx, [edx + Image.Height]
+ jb @f
+ mov ecx, [edx + Image.Height]
+@@:
+ push ecx
+ lea ecx, [ecx*3]
+ imul ecx, [edx + Image.Width]
+ rep movsb
+ pop ecx
+; convert rows
+ sub ecx, [edx + Image.Height]
+ neg ecx
+ push ecx
+ cmp cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Height]
+@@:
+ jecxz .rgb_norows
+.rgb_convert_rows:
+ push ecx
+ movzx ecx, [ebx + gif.Image.info.Left]
+ cmp ecx, [edx + Image.Width]
+ jb @f
+ mov ecx, [edx + Image.Width]
+@@:
+ push ecx
+ lea ecx, [ecx*3]
+ rep movsb
+ pop ecx
+ sub ecx, [edx + Image.Width]
+ neg ecx
+ push ecx edx
+ mov edx, [esp+16] ; source data
+ cmp cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ mov cx, [ebx + gif.Image.info.Width]
+@@:
+ jecxz .rgb_norowsi
+.rgb_rowsloop:
+ movzx eax, byte [edx]
+ inc edx
+ cmp eax, [transparent_color]
+ jz .rgb_rows_transparent
+ shl eax, 2
+ add eax, [esp+20] ; source palette
+ mov eax, [eax]
+ stosw
+ shr eax, 16
+ stosb
+ add esi, 3
+ jmp @f
+.rgb_rows_transparent:
+ movsb
+ movsb
+ movsb
+@@:
+ loop .rgb_rowsloop
+.rgb_norowsi:
+ pop edx ecx
+ sub cx, [ebx + gif.Image.info.Width]
+ jbe @f
+ lea ecx, [ecx*3]
+ rep movsb
+@@:
+ movzx eax, [ebx + gif.Image.info.Width]
+ add [esp+8], eax
+ pop ecx
+ loop .rgb_convert_rows
+.rgb_norows:
+ pop ecx
+ sub cx, [ebx + gif.Image.info.Height]
+ jbe @f
+ imul ecx, [edx + Image.Width]
+ lea ecx, [ecx*3]
+ rep movsb
+@@:
+; free old image data
+ pop esi esi ;esi
+ invoke mem.free;, esi
+ retn
+.rgb_nomem:
+ pop esi esi
+ retn
+
+.lodsb:
+ xor eax, eax
+ test esi, esi
+ jz @f
+ lodsb
+@@: retn
+
+.rep_movsb_or_stosb:
+ test esi, esi
+ jz .rmos1
+ rep movsb
+ jmp .rmos2
+.rmos1: xor eax, eax ; background index in final palette is 0 in bgr mode
+ rep stosb
+.rmos2: retn
+
+.convrgb_prev:
+ jecxz .convrgb_noprev
+ test esi, esi
+ jz .convrgb_prev_bgr
+@@:
+ xor eax, eax
+ lodsb
+ shl eax, 2
+ add eax, [prev_palette]
+ mov eax, [eax]
+ stosw
+ shr eax, 16
+ stosb
+ loop @b
+ retn
+.convrgb_prev_bgr:
+@@:
+ mov eax, [background_color]
+ stosw
+ shr eax, 16
+ stosb
+ loop @b
+.convrgb_noprev:
+ retn
+.convrgb_lodsb:
+ xor eax, eax
+ test esi, esi
+ jz @f
+ lodsb
+ shl eax, 2
+ add eax, [prev_palette]
+ mov eax, [eax]
+ retn
+@@: mov eax, [background_color]
+ retn
+
+endp
+
+;;================================================================================================;;
+proc img.decode.gif._.dispose ;///////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> edx = image data ;;
+;;------------------------------------------------------------------------------------------------;;
+;< --- TBD --- ;;
+;;================================================================================================;;
+ mov ebx, [edx + Image.Extended]
+ mov al, [ebx + gif.Image.gce.Packed]
+ shr al, 2
+ and al, 7
+ cmp al, 2
+ jz .background
+ cmp al, 3
+ jz .previous
+; don't dispose - set prev_img and related vars to current image
+ mov eax, [edx + Image.Data]
+ mov [prev_img_data], eax
+ cmp [edx + Image.Type], Image.bpp8
+ jnz @f
+ mov eax, [max_color]
+ inc eax
+ mov [prev_num_colors], eax
+ mov eax, [edx + Image.Palette]
+ mov [prev_palette], eax
+ retn
+@@:
+ or [prev_num_colors], -1
+ and [prev_palette], 0
+.previous:
+ retn
+.background:
+ cmp [prev_img_data], 0
+ jz .bgr_full
+ mov ebx, [main_img]
+ mov eax, [edx + Image.Extended]
+ call img.decode.gif._.is_logical_screen
+ jnz @f
+.bgr_full:
+ xor eax, eax
+ mov [prev_img_data], eax
+ inc eax
+ mov [prev_num_colors], eax
+ lea eax, [background_color]
+ mov [prev_palette], eax
+ retn
+@@:
+ cmp [prev_num_colors], 0x100
+ ja .rgb
+ mov eax, [background_color]
+ mov edi, [prev_palette]
+ mov ecx, [prev_num_colors]
+ repnz scasd
+ jz .palette_ok
+ cmp [prev_num_colors], 0x100
+ jz .convert_rgb
+ push 1
+ pop eax
+ stdcall img.decode.gif._.alloc_aux_img
+ test eax, eax
+ jz .previous
+ mov ecx, [prev_num_colors]
+ mov esi, [prev_palette]
+ call img.decode.gif._.alloc_aux_palette
+ test eax, eax
+ jz .previous
+ mov [prev_palette], eax
+ mov eax, [background_color]
+ stosd
+ mov eax, [prev_num_colors] ; eax = index of background color
+ inc [prev_num_colors]
+ jmp .bpp8_common
+.palette_ok:
+ push 1
+ pop eax
+ stdcall img.decode.gif._.alloc_aux_img
+ test eax, eax
+ jz .previous
+ sub edi, [prev_palette]
+ shr edi, 2
+ lea eax, [edi-1] ; eax = index of background color
+.bpp8_common:
+ push eax
+ mov ebx, [_data]
+ mov esi, [prev_img_data]
+ mov edi, [aux_img_data]
+ mov [prev_img_data], edi
+ cmp esi, edi
+ jz @f
+ movzx ecx, [ebx + gif.Header.lsd.ScreenWidth]
+ movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
+ imul ecx, eax
+ push edi
+ rep movsb
+ pop edi
+@@:
+ movzx esi, [ebx + gif.Header.lsd.ScreenHeight]
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ mov edx, [edx + Image.Extended]
+ movzx ecx, [edx + gif.Image.info.Top]
+ sub esi, ecx
+ jbe .bpp8_ret
+ imul ecx, eax
+ add edi, ecx
+ cmp si, [edx + gif.Image.info.Height]
+ jb @f
+ mov si, [edx + gif.Image.info.Height]
+@@:
+ movzx ecx, [edx + gif.Image.info.Left]
+ sub eax, ecx
+ jbe .bpp8_ret
+ add edi, ecx
+ cmp ax, [edx + gif.Image.info.Width]
+ jb @f
+ mov ax, [edx + gif.Image.info.Width]
+@@:
+ xchg eax, ecx
+ movzx edx, [ebx + gif.Header.lsd.ScreenWidth]
+ sub edx, ecx
+ pop eax
+@@:
+ push ecx
+ rep stosb
+ pop ecx
+ add edi, edx
+ dec esi
+ jnz @b
+ push eax
+.bpp8_ret:
+ pop eax
+ retn
+.convert_rgb:
+ push 3
+ pop eax
+ stdcall img.decode.gif._.alloc_aux_img
+ test eax, eax
+ jz .previous
+ or [prev_num_colors], -1
+ mov ebx, [_data]
+ mov esi, [prev_img_data]
+ mov edi, [aux_img_data]
+ mov [prev_img_data], edi
+ movzx ecx, [ebx + gif.Header.lsd.ScreenWidth]
+ movzx eax, [ebx + gif.Header.lsd.ScreenHeight]
+ imul ecx, eax
+ push edx
+ xor edx, edx
+ xchg edx, [prev_palette]
+ add edi, ecx
+ add esi, ecx
+ add edi, ecx
+ add edi, ecx
+@@:
+ dec esi
+ movzx eax, byte [esi]
+ mov eax, [eax*4+edx]
+ sub edi, 3
+ mov [edi], ax
+ shr eax, 16
+ mov [edi+2], al
+ loop @b
+ pop edx
+ movzx esi, [ebx + gif.Header.lsd.ScreenHeight]
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ mov edx, [edx + Image.Extended]
+ movzx ecx, [edx + gif.Image.info.Top]
+ sub esi, ecx
+ jbe .convert_rgb_ret
+ imul ecx, eax
+ lea ecx, [ecx*3]
+ add edi, ecx
+ cmp si, [edx + gif.Image.info.Height]
+ jb @f
+ mov si, [edx + gif.Image.info.Height]
+@@:
+ movzx ecx, [edx + gif.Image.info.Left]
+ sub eax, ecx
+ jbe .convert_rgb_ret
+ lea ecx, [ecx*3]
+ add edi, ecx
+ cmp ax, [edx + gif.Image.info.Width]
+ jb @f
+ mov ax, [edx + gif.Image.info.Width]
+@@:
+ xchg eax, ecx
+ movzx edx, [ebx + gif.Header.lsd.ScreenWidth]
+ sub edx, ecx
+ mov eax, [background_color]
+ lea edx, [edx*3]
+.convert_rgb_loop:
+ push ecx
+@@:
+ stosw
+ shr eax, 16
+ stosb
+ loop @b
+ pop ecx
+ add edi, edx
+ dec esi
+ jnz .convert_rgb_loop
+.convert_rgb_ret:
+ retn
+.rgb:
+ push 3
+ pop eax
+ stdcall img.decode.gif._.alloc_aux_img
+ test eax, eax
+ jz .previous
+ or [prev_num_colors], -1
+ and [prev_palette], 0
+ mov ebx, [_data]
+ mov esi, [prev_img_data]
+ mov edi, [aux_img_data]
+ mov [prev_img_data], edi
+ cmp esi, edi
+ jz @f
+ movzx ecx, [ebx + gif.Header.lsd.ScreenHeight]
+ push ecx
+ movzx eax, [ebx + gif.Header.lsd.ScreenWidth]
+ imul ecx, eax
+ lea ecx, [ecx*3]
+ push edi
+ rep movsb
+ pop edi
+ pop esi
+ mov edx, [edx + Image.Extended]
+ movzx ecx, [edx + gif.Image.info.Top]
+ sub esi, ecx
+ jbe .rgb_ret
+ imul ecx, eax
+ lea ecx, [ecx*3]
+ add edi, ecx
+ cmp si, [edx + gif.Image.info.Height]
+ jb @f
+ mov si, [edx + gif.Image.info.Height]
+@@:
+ movzx ecx, [edx + gif.Image.info.Left]
+ sub eax, ecx
+ jbe .rgb_ret
+ lea ecx, [ecx*3]
+ add edi, ecx
+ cmp ax, [edx + gif.Image.info.Width]
+ jb @f
+ mov ax, [edx + gif.Image.info.Width]
+@@:
+ xchg eax, ecx
+ movzx edx, [ebx + gif.Header.lsd.ScreenWidth]
+ sub edx, ecx
+ mov eax, [background_color]
+ lea edx, [edx*3]
+.rgb_loop:
+ push ecx
+@@:
+ stosw
+ shr eax, 16
+ stosb
+ loop @b
+ pop ecx
+ add edi, edx
+ dec esi
+ jnz .rgb_loop
+.rgb_ret:
+ retn
+
+endp
+
+;;================================================================================================;;
+proc img.decode.gif._.alloc_aux_img ;/////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Allocate auxiliary memory for previous image ;;
+;;------------------------------------------------------------------------------------------------;;
+;> eax = image type: 1 = bpp8, 3 = bpp24 ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = [aux_img_data] ;;
+;;================================================================================================;;
+ cmp [aux_img_type], eax
+ jae @f
+ push edx eax
+ movzx ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
+ mul ecx
+ movzx ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
+ mul ecx
+ invoke mem.realloc, [aux_img_data], eax
+ pop ecx edx
+ test eax, eax
+ jz @f
+ mov [aux_img_type], ecx
+ mov [aux_img_data], eax
+@@: retn
+
+endp
+
+;;================================================================================================;;
+proc img.decode.gif._.alloc_aux_palette ;/////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Allocate and fill aux_palette ;;
+;;------------------------------------------------------------------------------------------------;;
+;> esi -> palette, ecx = palette size ;;
+;;------------------------------------------------------------------------------------------------;;
+;< [aux_palette] set ;;
+;;================================================================================================;;
+ mov eax, [aux_palette]
+ test eax, eax
+ jnz @f
+ push edx ecx
+ invoke mem.alloc, 0x400
+ pop ecx edx
+ test eax, eax
+ jz .ret
+ mov [aux_palette], eax
+@@:
+ mov edi, eax
+ rep movsd
+.ret:
+ retn
+
+endp
+
+restore main_img
+restore transparent_color
+restore background_color
+restore prev_num_colors
+restore prev_palette
+restore max_color
+restore prev_img_data
+restore _data
+restore aux_img_data
+restore aux_img_type
+restore aux_palette
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
diff --git a/programs/develop/libraries/libs-dev/libimg/gif/gif.inc b/programs/develop/libraries/libs-dev/libimg/gif/gif.inc
index 264233eafc..d45a7ff31b 100644
--- a/programs/develop/libraries/libs-dev/libimg/gif/gif.inc
+++ b/programs/develop/libraries/libs-dev/libimg/gif/gif.inc
@@ -61,7 +61,9 @@ gif.Block.Introducer.ImageDescriptor = 0x2C
gif.Block.Introducer.EndOfFile = 0x3B
struct gif.ImageDescriptor ; GIF87a
- b gif.Block ; Introducer = 2Ch (',')
+; we read Introducer before parsing gif.ImageDescriptor,
+; so it is convenient to not include it in struct
+; b gif.Block ; Introducer = 2Ch (',')
Left dw ? ; X position of image on the display
Top dw ? ; Y position of image on the display
Width dw ? ; Width of the image in pixels
@@ -89,8 +91,8 @@ gif.Extension.Label.Comment = 0xFE
gif.Extension.Label.Application = 0xFF
struct gif.PlainTextExtension ; GIF89a
- e gif.Extension ; Label = 01h
- BlockSize db ? ; Size of Extension Block (always 0Ch)
+; e gif.Extension ; Label = 01h
+; BlockSize db ? ; Size of Extension Block (always 0Ch)
TextGridLeft dw ? ; X position of text grid in pixels
TextGridTop dw ? ; Y position of text grid in pixels
TextGridWidth dw ? ; Width of the text grid in pixels
@@ -104,8 +106,10 @@ struct gif.PlainTextExtension ; GIF89a
ends
struct gif.GraphicsControlExtension ; GIF89a
- e gif.Extension ; Label = F9h
- BlockSize db ? ; Size of remaining fields (always 04h)
+; e gif.Extension ; Label = F9h
+; BlockSize db ? ; Size of remaining fields (always 04h)
+; previous fields are not included in this structure for convenience
+; (they are parsed before this)
Packed db ? ; Method of graphics disposal to use
DelayTime dw ? ; Hundredths of seconds to wait
ColorIndex db ? ; Transparent Color Index
@@ -130,8 +134,9 @@ ends
;;------------------------------------------------------------------------------------------------;;
struct gif.Image
- gce gif.GraphicsControlExtension
info gif.ImageDescriptor
+ gce gif.GraphicsControlExtension
+; lsd gif.LogicalScreenDescriptor ; saved only in first image
ends
gif.Null equ 0x1000
diff --git a/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm
index fe9d6a4b9d..88b8274ba1 100644
--- a/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm
+++ b/programs/develop/libraries/libs-dev/libimg/jpeg/jpeg.asm
@@ -474,8 +474,8 @@ img.decode.jpg:
; image type: 8 bpp for grayscale JPEGs, 24 bpp for normal,
; 32 bpp for Adobe YCCK
push Image.bpp8
- pop eax
- cmp edi, 1
+ pop eax ; Image.bpp8 = 1
+ cmp edi, eax
jz @f
inc eax ; Image.bpp24 = 2
cmp edi, 3
@@ -1621,9 +1621,9 @@ handle_progressive:
stosd ; dd VFactor_i+1 - (height % VFactor_i)
pop ecx
xor eax, eax
- cmp ebp, 1
- cmc
- rcr eax, 1
+ test ebp, ebp
+ setnp al
+ ror eax, 1
stosd ; dd DCPrediction
mov eax, ebp
stosd ; dd ComponentOffset
diff --git a/programs/develop/libraries/libs-dev/libimg/libimg.asm b/programs/develop/libraries/libs-dev/libimg/libimg.asm
index 6e740dd20f..7e61ffa0bc 100644
--- a/programs/develop/libraries/libs-dev/libimg/libimg.asm
+++ b/programs/develop/libraries/libs-dev/libimg/libimg.asm
@@ -35,11 +35,8 @@ include 'bmp/bmp.asm'
include 'gif/gif.asm'
include 'jpeg/jpeg.asm'
include 'png/png.asm'
-
-mem.alloc dd ?
-mem.free dd ?
-mem.realloc dd ?
-dll.load dd ?
+include 'tga/tga.asm'
+include 'z80/z80.asm'
;;================================================================================================;;
proc lib_init ;///////////////////////////////////////////////////////////////////////////////////;;
@@ -60,6 +57,14 @@ proc lib_init ;/////////////////////////////////////////////////////////////////
call img.initialize.jpeg
+ xor eax, eax
+ cpuid
+ cmp ecx, 'ntel'
+ jnz @f
+ mov dword [img._.do_rgb.handlers + (Image.bpp15-1)*4], img._.do_rgb.bpp15.intel
+ mov dword [img._.do_rgb.handlers + (Image.bpp16-1)*4], img._.do_rgb.bpp16.intel
+ @@:
+
.ok: xor eax,eax
ret
endp
@@ -211,10 +216,267 @@ proc img._.do_rgb ;/////////////////////////////////////////////////////////////
mov ecx, [esi + Image.Width]
imul ecx, [esi + Image.Height]
mov eax, [esi + Image.Type]
- dec eax
- jz .bpp8
- dec eax
- jz .bpp24
+ jmp dword [.handlers + (eax-1)*4]
+
+align 16
+.bpp8:
+; 8 BPP -> 24 BPP
+ push ebx
+ mov ebx, [esi + Image.Palette]
+ mov esi, [esi + Image.Data]
+@@:
+ movzx eax, byte [esi]
+ add esi, 1
+ mov eax, [ebx + eax*4]
+ mov [edi], eax
+ add edi, 3
+ sub ecx, 1
+ jnz @b
+ pop ebx
+ ret
+
+; 15 BPP -> 24 BPP
+.bpp15.intel:
+ push ebx ebp
+ sub ecx, 4
+ jb .bpp15.tail
+align 16
+.bpp15.intel.loop:
+repeat 2
+ mov ebx, [esi]
+ mov al, [esi]
+ mov ah, [esi+1]
+ add esi, 4
+ and al, 0x1F
+ and ah, 0x1F shl 2
+ mov ebp, ebx
+ mov dl, al
+ mov dh, ah
+ shr al, 2
+ shr ah, 4
+ shl dl, 3
+ shl dh, 1
+ and ebp, 0x1F shl 5
+ add al, dl
+ add ah, dh
+ shr ebp, 2
+ mov [edi], al
+ mov [edi+2], ah
+ mov eax, ebx
+ mov ebx, ebp
+ shr eax, 16
+ shr ebx, 5
+ add ebx, ebp
+ mov ebp, eax
+ mov [edi+1], bl
+ and eax, (0x1F) or (0x1F shl 10)
+ and ebp, 0x1F shl 5
+ lea edx, [eax+eax]
+ shr al, 2
+ mov ebx, ebp
+ shr ah, 4
+ shl dl, 2
+ shr ebx, 2
+ shr ebp, 7
+ add al, dl
+ add ah, dh
+ mov [edi+3], al
+ add ebx, ebp
+ mov [edi+5], ah
+ mov [edi+4], bl
+ add edi, 6
+end repeat
+ sub ecx, 4
+ jnb .bpp15.intel.loop
+.bpp15.tail:
+ add ecx, 4
+ jz .bpp15.done
+@@:
+ movzx eax, word [esi]
+ mov ebx, eax
+ add esi, 2
+ and eax, (0x1F) or (0x1F shl 10)
+ and ebx, 0x1F shl 5
+ lea edx, [eax+eax]
+ shr al, 2
+ mov ebp, ebx
+ shr ebx, 2
+ shr ah, 4
+ shl dl, 2
+ shr ebp, 7
+ add eax, edx
+ add ebx, ebp
+ mov [edi], al
+ mov [edi+1], bl
+ mov [edi+2], ah
+ add edi, 3
+ sub ecx, 1
+ jnz @b
+.bpp15.done:
+ pop ebp ebx
+ ret
+
+.bpp15.amd:
+ push ebx ebp
+ sub ecx, 4
+ jb .bpp15.tail
+align 16
+.bpp15.amd.loop:
+repeat 4
+if (% mod 2) = 1
+ mov eax, dword [esi]
+ mov ebx, dword [esi]
+else
+ movzx eax, word [esi]
+ mov ebx, eax
+end if
+ add esi, 2
+ and eax, (0x1F) or (0x1F shl 10)
+ and ebx, 0x1F shl 5
+ lea edx, [eax+eax]
+ shr al, 2
+ mov ebp, ebx
+ shr ebx, 2
+ shr ah, 4
+ shl dl, 2
+ shr ebp, 7
+ add eax, edx
+ add ebx, ebp
+ mov [edi], al
+ mov [edi+1], bl
+ mov [edi+2], ah
+ add edi, 3
+end repeat
+ sub ecx, 4
+ jnb .bpp15.amd.loop
+ jmp .bpp15.tail
+
+; 16 BPP -> 24 BPP
+.bpp16.intel:
+ push ebx ebp
+ sub ecx, 4
+ jb .bpp16.tail
+align 16
+.bpp16.intel.loop:
+repeat 2
+ mov ebx, [esi]
+ mov al, [esi]
+ mov ah, [esi+1]
+ add esi, 4
+ and al, 0x1F
+ and ah, 0x1F shl 3
+ mov ebp, ebx
+ mov dl, al
+ mov dh, ah
+ shr al, 2
+ shr ah, 5
+ shl dl, 3
+ and ebp, 0x3F shl 5
+ add al, dl
+ add ah, dh
+ shr ebp, 3
+ mov [edi], al
+ mov [edi+2], ah
+ mov eax, ebx
+ mov ebx, ebp
+ shr eax, 16
+ shr ebx, 6
+ add ebx, ebp
+ mov ebp, eax
+ mov [edi+1], bl
+ and eax, (0x1F) or (0x1F shl 11)
+ and ebp, 0x3F shl 5
+ mov edx, eax
+ shr al, 2
+ mov ebx, ebp
+ shr ah, 5
+ shl dl, 3
+ shr ebx, 3
+ shr ebp, 9
+ add al, dl
+ add ah, dh
+ mov [edi+3], al
+ add ebx, ebp
+ mov [edi+5], ah
+ mov [edi+4], bl
+ add edi, 6
+end repeat
+ sub ecx, 4
+ jnb .bpp16.intel.loop
+.bpp16.tail:
+ add ecx, 4
+ jz .bpp16.done
+@@:
+ movzx eax, word [esi]
+ mov ebx, eax
+ add esi, 2
+ and eax, (0x1F) or (0x1F shl 11)
+ and ebx, 0x3F shl 5
+ mov edx, eax
+ shr al, 2
+ mov ebp, ebx
+ shr ebx, 3
+ shr ah, 5
+ shl dl, 3
+ shr ebp, 9
+ add eax, edx
+ add ebx, ebp
+ mov [edi], al
+ mov [edi+1], bl
+ mov [edi+2], ah
+ add edi, 3
+ sub ecx, 1
+ jnz @b
+.bpp16.done:
+ pop ebp ebx
+ ret
+
+.bpp16.amd:
+ push ebx ebp
+ sub ecx, 4
+ jb .bpp16.tail
+align 16
+.bpp16.amd.loop:
+repeat 4
+if (% mod 2) = 1
+ mov eax, dword [esi]
+ mov ebx, dword [esi]
+else
+ movzx eax, word [esi]
+ mov ebx, eax
+end if
+ add esi, 2
+ and eax, (0x1F) or (0x1F shl 11)
+ and ebx, 0x3F shl 5
+ mov edx, eax
+ shr al, 2
+ mov ebp, ebx
+ shr ebx, 3
+ shr ah, 5
+ shl dl, 3
+ shr ebp, 9
+ add eax, edx
+ add ebx, ebp
+ mov [edi], al
+ mov [edi+1], bl
+ mov [edi+2], ah
+ add edi, 3
+end repeat
+ sub ecx, 4
+ jnb .bpp16.amd.loop
+ jmp .bpp16.tail
+
+align 16
+.bpp24:
+; 24 BPP -> 24 BPP
+ lea ecx, [ecx*3 + 3]
+ mov esi, [esi + Image.Data]
+ shr ecx, 2
+ rep movsd
+ ret
+
+align 16
+.bpp32:
; 32 BPP -> 24 BPP
mov esi, [esi + Image.Data]
@@ -231,31 +493,6 @@ proc img._.do_rgb ;/////////////////////////////////////////////////////////////
@@:
ret
-.bpp24:
-; 24 BPP -> 24 BPP
- lea ecx, [ecx*3 + 3]
- mov esi, [esi + Image.Data]
- shr ecx, 2
- rep movsd
- ret
-
-.bpp8:
-; 8 BPP -> 24 BPP
- push ebx
- mov ebx, [esi + Image.Palette]
- mov esi, [esi + Image.Data]
-@@:
- movzx eax, byte [esi]
- add esi, 1
- mov eax, [ebx + eax*4]
- mov [edi], ax
- shr eax, 16
- mov [edi+2], al
- add edi, 3
- sub ecx, 1
- jnz @b
- pop ebx
- ret
endp
;;================================================================================================;;
@@ -334,6 +571,32 @@ proc img.create _width, _height, _type ;////////////////////////////////////////
ret
endp
+;;================================================================================================;;
+proc img.destroy.layer _img ;/////////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;> --- TBD --- ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+ mov eax, [_img]
+ mov edx, [eax + Image.Previous]
+ test edx, edx
+ jz @f
+ push [eax + Image.Next]
+ pop [edx + Image.Next]
+@@:
+ mov edx, [eax + Image.Next]
+ test edx, edx
+ jz @f
+ push [eax + Image.Previous]
+ pop [edx + Image.Previous]
+@@:
+ stdcall img._.delete, eax
+ ret
+endp
+
;;================================================================================================;;
proc img.destroy _img ;///////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
@@ -343,8 +606,33 @@ proc img.destroy _img ;/////////////////////////////////////////////////////////
;;------------------------------------------------------------------------------------------------;;
;< eax = false / true ;;
;;================================================================================================;;
- ;TODO: link Next and Previous
- stdcall img._.delete, [_img]
+ push 1
+ mov eax, [_img]
+ mov eax, [eax + Image.Previous]
+.destroy_prev_loop:
+ test eax, eax
+ jz .destroy_prev_done
+ pushd [eax + Image.Previous]
+ stdcall img._.delete, eax
+ test eax, eax
+ jnz @f
+ mov byte [esp+4], 0
+@@:
+ pop eax
+ jmp .destroy_prev_loop
+.destroy_prev_done:
+ mov eax, [_img]
+.destroy_next_loop:
+ pushd [eax + Image.Next]
+ stdcall img._.delete, eax
+ test eax, eax
+ jnz @f
+ mov byte [esp+4], 0
+@@:
+ pop eax
+ test eax, eax
+ jnz .destroy_next_loop
+ pop eax
ret
endp
@@ -417,9 +705,9 @@ proc img.unlock_bits _img, _lock ;//////////////////////////////////////////////
endp
;;================================================================================================;;
-proc img.flip _img, _flip_kind ;//////////////////////////////////////////////////////////////////;;
+proc img.flip.layer _img, _flip_kind ;////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
-;? Flip image ;;
+;? Flip image layer ;;
;;------------------------------------------------------------------------------------------------;;
;> _img = pointer to image ;;
;> _flip_kind = one of FLIP_* constants ;;
@@ -493,12 +781,9 @@ endl
mov esi, [ebx + Image.Data]
mov edi, [scanline_len]
add edi, esi
+ jmp dword [.handlers_horz + (eax-1)*4]
- dec eax
- jz .bpp8.2
- dec eax
- jz .bpp24.2
-
+.bpp32_horz:
sub edi, 4
.next_line_horz:
@@ -521,7 +806,29 @@ endl
jnz .next_line_horz
jmp .exit
-.bpp8.2:
+.bpp1x_horz:
+ sub edi, 2
+ .next_line_horz1x:
+ push ecx esi edi
+
+ mov ecx, [ebx + Image.Width]
+ @@: mov ax, [esi]
+ mov dx, [edi]
+ mov [edi], ax
+ mov [esi], dx
+ add esi, 2
+ sub edi, 2
+ sub ecx, 2
+ ja @b
+
+ pop edi esi ecx
+ add esi, [scanline_len]
+ add edi, [scanline_len]
+ dec ecx
+ jnz .next_line_horz1x
+ jmp .exit
+
+.bpp8_horz:
dec edi
.next_line_horz8:
push ecx esi edi
@@ -544,13 +851,12 @@ endl
jnz .next_line_horz8
jmp .exit
-.bpp24.2:
+.bpp24_horz:
sub edi, 3
- .next_line_horz32:
+ .next_line_horz24:
push ecx esi edi
mov ecx, [ebx + Image.Width]
- shr ecx, 1
@@:
mov al, [esi]
mov dl, [edi]
@@ -566,14 +872,14 @@ endl
mov [esi+2], dl
add esi, 3
sub edi, 3
- sub ecx, 1
- jnz @b
+ sub ecx, 2
+ ja @b
pop edi esi ecx
add esi, [scanline_len]
add edi, [scanline_len]
dec ecx
- jnz .next_line_horz32
+ jnz .next_line_horz24
.exit:
xor eax, eax
@@ -588,9 +894,40 @@ endl
endp
;;================================================================================================;;
-proc img.rotate _img, _rotate_kind ;//////////////////////////////////////////////////////////////;;
+proc img.flip _img, _flip_kind ;//////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
-;? Rotate image ;;
+;? Flip all layers of image ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _img = pointer to image ;;
+;> _flip_kind = one of FLIP_* constants ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+ push 1
+ mov ebx, [_img]
+@@:
+ mov eax, [ebx + Image.Previous]
+ test eax, eax
+ jz .loop
+ mov ebx, eax
+ jmp @b
+.loop:
+ stdcall img.flip.layer, ebx, [_flip_kind]
+ test eax, eax
+ jnz @f
+ mov byte [esp], 0
+@@:
+ mov ebx, [ebx + Image.Next]
+ test ebx, ebx
+ jnz .loop
+ pop eax
+ ret
+endp
+
+;;================================================================================================;;
+proc img.rotate.layer _img, _rotate_kind ;////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Rotate image layer ;;
;;------------------------------------------------------------------------------------------------;;
;> _img = pointer to image ;;
;> _rotate_kind = one of ROTATE_* constants ;;
@@ -646,7 +983,57 @@ endl
jz .rotate_ccw8
cmp [ebx + Image.Type], Image.bpp24
jz .rotate_ccw24
+ cmp [ebx + Image.Type], Image.bpp32
+ jz .rotate_ccw32
+ .next_column_ccw_low1x:
+ dec ecx
+ js .exchange_dims
+ push ecx
+
+ mov edx, [scanline_len_old]
+ add [scanline_len_old], -2
+
+ mov ecx, [scanline_pixels_new]
+ mov esi, [ebx + Image.Data]
+ mov edi, [line_buffer]
+ @@: mov ax, [esi]
+ mov [edi], ax
+ add esi, edx
+ add edi, 2
+ sub ecx, 1
+ jnz @b
+
+ mov eax, [scanline_pixels_new]
+ mov edi, [ebx + Image.Data]
+ lea esi, [edi + 2]
+ mov edx, [scanline_len_old]
+ @@: mov ecx, edx
+ shr ecx, 2
+ rep movsd
+ mov ecx, edx
+ and ecx, 3
+ rep movsb
+ add esi, 1
+ sub eax, 1
+ jnz @b
+
+ mov eax, [scanline_len_new]
+ sub [pixels_ptr], eax
+ mov ecx, [scanline_pixels_new]
+ mov esi, [line_buffer]
+ mov edi, [pixels_ptr]
+ mov edx, ecx
+ shr ecx, 2
+ rep movsd
+ mov ecx, edx
+ and ecx, 3
+ rep movsb
+
+ pop ecx
+ jmp .next_column_ccw_low1x
+
+.rotate_ccw32:
.next_column_ccw_low:
dec ecx
js .exchange_dims
@@ -809,7 +1196,59 @@ endl
jz .rotate_cw8
cmp [ebx + Image.Type], Image.bpp24
jz .rotate_cw24
+ cmp [ebx + Image.Type], Image.bpp32
+ jz .rotate_cw32
+ .next_column_cw_low1x:
+ dec ecx
+ js .exchange_dims
+ push ecx
+
+ mov edx, [scanline_len_old]
+ add [scanline_len_old], -2
+
+ mov ecx, [scanline_pixels_new]
+ mov esi, [pixels_ptr]
+ add esi, -2
+ mov edi, [line_buffer]
+ @@: mov ax, [esi]
+ mov [edi], ax
+ sub esi, edx
+ add edi, 2
+ sub ecx, 1
+ jnz @b
+
+ mov eax, [scanline_pixels_new]
+ dec eax
+ mov edi, [ebx + Image.Data]
+ add edi, [scanline_len_old]
+ lea esi, [edi + 2]
+ mov edx, [scanline_len_old]
+ @@: mov ecx, edx
+ shr ecx, 2
+ rep movsd
+ mov ecx, edx
+ and ecx, 3
+ rep movsb
+ add esi, 3
+ sub eax, 1
+ jnz @b
+
+ mov eax, [scanline_len_new]
+ sub [pixels_ptr], eax
+ mov ecx, eax
+ mov esi, [line_buffer]
+ mov edi, [pixels_ptr]
+ shr ecx, 2
+ rep movsd
+ mov ecx, eax
+ and ecx, 3
+ rep movsb
+
+ pop ecx
+ jmp .next_column_cw_low1x
+
+.rotate_cw32:
.next_column_cw_low:
dec ecx
js .exchange_dims
@@ -976,6 +1415,92 @@ endl
ret
endp
+;;================================================================================================;;
+proc img.rotate _img, _rotate_kind ;//////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Rotate all layers of image ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _img = pointer to image ;;
+;> _rotate_kind = one of ROTATE_* constants ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+ push 1
+ mov ebx, [_img]
+@@:
+ mov eax, [ebx + Image.Previous]
+ test eax, eax
+ jz .loop
+ mov ebx, eax
+ jmp @b
+.loop:
+ stdcall img.rotate.layer, ebx, [_rotate_kind]
+ test eax, eax
+ jnz @f
+ mov byte [esp], 0
+@@:
+ mov ebx, [ebx + Image.Next]
+ test ebx, ebx
+ jnz .loop
+ pop eax
+ ret
+endp
+
+;;================================================================================================;;
+proc img.draw _img, _x, _y, _width, _height, _xpos, _ypos ;///////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Draw image in the window ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _img = pointer to image ;;
+;>_x = x-coordinate in the window ;;
+;>_y = y-coordinate in the window ;;
+;>_width = maximum width to draw ;;
+;>_height = maximum height to draw ;;
+;>_xpos = offset in image by x-axis ;;
+;>_ypos = offset in image by y-axis ;;
+;;------------------------------------------------------------------------------------------------;;
+;< no return value ;;
+;;================================================================================================;;
+ push ebx esi edi
+ mov ebx, [_img]
+ stdcall img._.validate, ebx
+ test eax, eax
+ jnz .done
+ mov ecx, [ebx + Image.Width]
+ sub ecx, [_xpos]
+ jbe .done
+ cmp ecx, [_width]
+ jb @f
+ mov ecx, [_width]
+@@:
+ mov edx, [ebx + Image.Height]
+ sub edx, [_ypos]
+ jbe .done
+ cmp edx, [_height]
+ jb @f
+ mov edx, [_height]
+@@:
+ mov eax, [ebx + Image.Width]
+ sub eax, ecx
+ call img._.get_scanline_len
+ shl ecx, 16
+ add ecx, edx
+ mov edx, [_x - 2]
+ mov dx, word [_y]
+ mov esi, [ebx + Image.Type]
+ mov esi, [type2bpp + (esi-1)*4]
+ mov edi, [ebx + Image.Palette]
+ mov ebx, [ebx + Image.Data]
+ push ebp
+ push 65
+ pop ebp
+ xchg eax, ebp
+ int 40h
+ pop ebp
+.done:
+ pop edi esi ebx
+ ret
+endp
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
@@ -1015,6 +1540,7 @@ proc img._.new ;////////////////////////////////////////////////////////////////
xor ecx, ecx
mov [eax + Image.Data], ecx
mov [eax + Image.Type], ecx
+ mov [eax + Image.Flags], ecx
mov [eax + Image.Extended], ecx
mov [eax + Image.Previous], ecx
mov [eax + Image.Next], ecx
@@ -1118,7 +1644,10 @@ img._.get_scanline_len: ;///////////////////////////////////////////////////////
jz .bpp8.1
cmp [ebx + Image.Type], Image.bpp24
jz .bpp24.1
- shl eax, 2
+ add eax, eax
+ cmp [ebx + Image.Type], Image.bpp32
+ jnz @f
+ add eax, eax
jmp @f
.bpp24.1:
lea eax, [eax*3]
@@ -1135,7 +1664,7 @@ img._.get_scanline_len: ;///////////////////////////////////////////////////////
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;
-
+align 4
img._.formats_table:
.bmp dd img.is.bmp, img.decode.bmp, img.encode.bmp
; .ico dd img.is.ico, img.decode.ico, img.encode.ico
@@ -1143,8 +1672,26 @@ img._.formats_table:
.gif dd img.is.gif, img.decode.gif, img.encode.gif
.png dd img.is.png, img.decode.png, img.encode.png
.jpg dd img.is.jpg, img.decode.jpg, img.encode.jpg
+ .tga dd img.is.tga, img.decode.tga, img.encode.tga
+ .z80 dd img.is.z80, img.decode.z80, img.encode.z80 ;this must be the last entry as there are no
+ ;signatures in z80 screens at all
dd 0
+align 4
+type2bpp dd 8, 24, 32, 15, 16
+img._.do_rgb.handlers:
+ dd img._.do_rgb.bpp8
+ dd img._.do_rgb.bpp24
+ dd img._.do_rgb.bpp32
+ dd img._.do_rgb.bpp15.amd ; can be overwritten in lib_init
+ dd img._.do_rgb.bpp16.amd ; can be overwritten in lib_init
+
+img.flip.layer.handlers_horz:
+ dd img.flip.layer.bpp8_horz
+ dd img.flip.layer.bpp24_horz
+ dd img.flip.layer.bpp32_horz
+ dd img.flip.layer.bpp1x_horz
+ dd img.flip.layer.bpp1x_horz
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
@@ -1160,23 +1707,27 @@ align 4
export \
lib_init , 'lib_init' , \
- 0x00010003 , 'version' , \
+ 0x00010004 , 'version' , \
img.is_img , 'img.is_img' , \
img.info , 'img.info' , \
img.from_file , 'img.from_file' , \
img.to_file , 'img.to_file' , \
img.from_rgb , 'img.from_rgb' , \
img.to_rgb , 'img.to_rgb' , \
- img.to_rgb2 , 'img.to_rgb2' , \
+ img.to_rgb2 , 'img.to_rgb2' , \
img.decode , 'img.decode' , \
img.encode , 'img.encode' , \
img.create , 'img.create' , \
img.destroy , 'img.destroy' , \
+ img.destroy.layer, 'img.destroy.layer', \
img.count , 'img.count' , \
img.lock_bits , 'img.lock_bits' , \
img.unlock_bits , 'img.unlock_bits' , \
img.flip , 'img.flip' , \
- img.rotate , 'img.rotate'
+ img.flip.layer , 'img.flip.layer' , \
+ img.rotate , 'img.rotate' , \
+ img.rotate.layer, 'img.rotate.layer', \
+ img.draw , 'img.draw'
; import from deflate unpacker
; is initialized only when PNG loading is requested
@@ -1187,11 +1738,21 @@ library kfar_arc, '../File Managers/kfar_arc.obj'
import kfar_arc, \
deflate_unpack2, 'deflate_unpack2'
+align 4
; mutex for unpacker loading
deflate_loader_mutex dd 0
+; default palette for GIF - b&w
+gif_default_palette:
+ db 0, 0, 0
+ db 0xFF, 0xFF, 0xFF
+
section '.data' data readable writable align 16
; uninitialized data - global constant tables
+mem.alloc dd ?
+mem.free dd ?
+mem.realloc dd ?
+dll.load dd ?
; data for YCbCr -> RGB translation
color_table_1 rd 256
diff --git a/programs/develop/libraries/libs-dev/libimg/libimg.inc b/programs/develop/libraries/libs-dev/libimg/libimg.inc
index aa28ea26bb..96163c3638 100644
--- a/programs/develop/libraries/libs-dev/libimg/libimg.inc
+++ b/programs/develop/libraries/libs-dev/libimg/libimg.inc
@@ -34,11 +34,20 @@ struct Image
Data dd ?
Palette dd ? ; used iff Type eq Image.bpp8
Extended dd ?
+ Flags dd ? ; bitfield
+ Delay dd ? ; used iff Image.IsAnimated is set in Flags
ends
-Image.bpp8 = 1
+; values for Image.Type
+; must be consecutive to allow fast switch on Image.Type in support functions
+Image.bpp8 = 1
Image.bpp24 = 2
Image.bpp32 = 3
+Image.bpp15 = 4
+Image.bpp16 = 5
+
+; bits in Image.Flags
+Image.IsAnimated = 1
FLIP_VERTICAL = 0x01
FLIP_HORIZONTAL = 0x02
diff --git a/programs/develop/libraries/libs-dev/libimg/png/png.asm b/programs/develop/libraries/libs-dev/libimg/png/png.asm
index 1a125f4eac..0191667f22 100644
--- a/programs/develop/libraries/libs-dev/libimg/png/png.asm
+++ b/programs/develop/libraries/libs-dev/libimg/png/png.asm
@@ -515,6 +515,8 @@ align 4
mov [edi+2], al
mov al, [esi+3]
mov [edi+3], al
+ add esi, 4
+ add edi, 4
sub ecx, 4
jnz @b
sub edx, 1
@@ -737,8 +739,10 @@ end repeat
sub ebx, ecx
jc .convert_done
@@:
- convert_16_to_8
+ mov ax, [esi]
add esi, 2
+ convert_16_to_8
+ mov [edi], al
add edi, 1
sub ecx, 2
jnz @b
@@ -821,8 +825,10 @@ end repeat
sub ebx, ecx
jc .convert_done
@@:
- convert_16_to_8
+ mov ax, [esi]
add esi, 4
+ convert_16_to_8
+ mov [edi], al
add edi, 1
sub ecx, 4
jnz @b
diff --git a/programs/develop/libraries/libs-dev/libimg/tga/tga.asm b/programs/develop/libraries/libs-dev/libimg/tga/tga.asm
new file mode 100644
index 0000000000..82051a75bf
--- /dev/null
+++ b/programs/develop/libraries/libs-dev/libimg/tga/tga.asm
@@ -0,0 +1,250 @@
+;;================================================================================================;;
+;;//// tga.asm //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+;; ;;
+;; References: ;;
+;; 1. Hiview 1.2 by Mohammad A. REZAEI ;;
+;; ;;
+;;================================================================================================;;
+
+include 'tga.inc'
+
+;;================================================================================================;;
+proc img.is.tga _data, _length ;//////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Determine if raw data could be decoded (is in Targa format) ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+ cmp [_length], 18
+ jbe .nope
+ mov eax, [_data]
+ push ebx
+ mov ebx,[eax+1] ;bl=cmatype,bh=subtype
+ cmp bl,1 ;cmatype is in [0..1]
+ ja .nope
+ cmp bh,11 ;subtype is in [1..3] (non-rle) or in [9..11] (rle)
+ ja .nope
+ cmp bh,9
+ jae .cont1
+ cmp bh,3
+ ja .nope
+.cont1: ;continue testing
+ mov ebx,[eax+16] ;bl=bpp, bh=flags //image descriptor
+ test ebx,111b ;bpp must be 8, 15, 16, 24 or 32
+ jnz .maybe15
+ shr bl,3
+ cmp bl,4
+ ja .nope
+ jmp .cont2
+.maybe15:
+ cmp bl,15
+ jne .nope
+.cont2: ;continue testing
+ test bh,tga.flags.interlace_type ;deinterlacing is not supported yet
+ jnz .nope
+ cmp byte[eax+7],24 ;test palette bpp - only 24 and 32 are supported
+ je .yep
+ cmp byte[eax+7],32 ;test palette bpp - only 24 and 32 are supported
+ je .yep
+.nope:
+ xor eax, eax
+ pop ebx
+ ret
+
+.yep:
+ xor eax, eax
+ inc eax
+ pop ebx
+ ret
+endp
+
+;;================================================================================================;;
+proc img.decode.tga _data, _length ;//////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Decode data into image if it contains correctly formed raw data in Targa format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to image ;;
+;;================================================================================================;;
+locals
+ IMGwidth dd ?
+ IMGheight dd ?
+ IMGbpp dd ?
+ DupPixelCount dd ?
+ TgaBlockCount dd ?
+endl
+ pushad
+ cld ;paranoia
+ and [DupPixelCount],0 ;prepare variables
+ and [TgaBlockCount],0 ;prepare variables
+ mov eax,[_data]
+ movzx esi,byte[eax]
+ lea esi,[esi+eax+18] ;skip comment and header
+ mov ebx,[eax+12]
+ movzx ecx,bx ;ecx=width
+ shr ebx,16 ;ebx=height
+ mov [IMGwidth],ecx
+ mov [IMGheight],ebx
+ movzx edx,byte[eax+16]
+ cmp edx,16
+ jnz @f
+ dec edx ;16bpp tga images are really 15bpp ARGB
+@@:
+ sub edx, 16 - Image.bpp16 ; 15 -> Image.bpp15, 16 -> Image.bpp16
+ mov [IMGbpp],edx
+ stdcall img.create,ecx,ebx,edx
+ mov [esp+28],eax ;save return value
+ test eax,eax ;failed to allocate?
+ jz .locret ;then exit
+ cmp edx,8
+ jne .palette_parsed
+ mov edi,[eax+Image.Palette]
+ mov ecx,[_data]
+ cmp byte[ecx+2],3 ;we also have grayscale subtype
+ jz .write_grayscale_palette ;that don't hold palette in file
+ cmp byte[ecx+2],11
+ jz .write_grayscale_palette
+ mov dh,[ecx+7] ;size of colormap entries in bits
+ movzx ecx,word[ecx+5] ;number of colormap entries
+ cmp dh,24
+ jz .skip_24bpp_palette ;test if colormap entries are 24bpp
+ rep movsd ;else they are 32 bpp
+ jmp .palette_parsed
+.write_grayscale_palette:
+ push eax
+ mov ecx,0x100
+ xor eax,eax
+@@:
+ stosd
+ add eax,0x010101
+ loop @b
+ pop eax
+ jmp .palette_parsed
+.skip_24bpp_palette:
+ push eax
+@@:
+ lodsd
+ dec esi
+ and eax,0xFFFFFF
+; bswap eax
+; shr eax,8
+ stosd
+ loop @b
+ pop eax
+.palette_parsed:
+ mov edi,[eax+Image.Data]
+ imul ebx,[IMGwidth] ;ebx=width*height
+
+ mov edx,[IMGbpp]
+ add edx,7
+ shr edx,3 ;edx=bytes per pixel
+ mov dh,dl ;dh=dl=bytes per pixel
+
+ mov eax,[_data]
+ cmp byte[eax+2],9
+ jb .not_an_rle
+.tga_read_rle_pixel:
+ cmp [DupPixelCount],0 ;Duplicate previously read pixel?
+ jg .duplicate_previously_read_pixel
+ dec [TgaBlockCount] ;Decrement pixels remaining in block
+ jns .read_non_rle_pixel
+ xor eax,eax
+ lodsb
+ test al,al ;Start of duplicate-pixel block?
+ jns .2
+ and al,0x7f
+ mov [DupPixelCount],eax ;Number of duplications after this one
+ and [TgaBlockCount],0 ;Then read new block header
+ jmp .read_non_rle_pixel
+.2:
+ mov dword[TgaBlockCount],eax
+.read_non_rle_pixel:
+ xor eax,eax
+ mov dl,dh
+@@:
+ shl eax,8
+ lodsb
+ dec dl
+ jnz @b
+ cmp dh,3
+ jne .put_pixel
+ bswap eax
+ shr eax,8
+ jmp .put_pixel
+.duplicate_previously_read_pixel:
+ dec [DupPixelCount]
+.put_pixel:
+ mov dl,dh
+ push eax
+@@:
+ stosb
+ shr eax,8
+ dec dl
+ jnz @b
+ pop eax
+ dec ebx
+ jnz .tga_read_rle_pixel
+ jmp .locret
+.not_an_rle:
+ movzx edx,dl ;dh contains bpp too (for decoding needs)
+ imul edx,ebx
+ mov ecx,edx
+ rep movsb ;just copy the image
+.locret:
+ popad
+ ret
+endp
+
+;;================================================================================================;;
+proc img.encode.tga _img, _p_length ;/////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Encode image into raw data in Targa format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _img = pointer to image ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to encoded data ;;
+;< _p_length = encoded data length ;;
+;;================================================================================================;;
+ xor eax, eax
+ ret
+endp
+
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below are private procs you should never call directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below is private data you should never use directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+;
\ No newline at end of file
diff --git a/programs/develop/libraries/libs-dev/libimg/tga/tga.inc b/programs/develop/libraries/libs-dev/libimg/tga/tga.inc
new file mode 100644
index 0000000000..d277ac322c
--- /dev/null
+++ b/programs/develop/libraries/libs-dev/libimg/tga/tga.inc
@@ -0,0 +1,35 @@
+;;================================================================================================;;
+;;//// tga.inc //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+
+struct tga.FileHeader
+ CommentLength db ?
+ ColormapType db ?
+ SubType db ?
+ DontKnow1 dw ?
+ ColormapSize dw ?
+ ColormapBpp db ?
+ DontKnow2 dd ?
+ Width dw ?
+ Height dw ?
+ BitPerPixel db ?
+ DontKnow3 db ?
+ends
+
+tga.flags.top_down_row_order equ 32 ;bit5
+tga.flags.interlace_type equ 192;bits6/7
diff --git a/programs/develop/libraries/libs-dev/libimg/z80/z80.asm b/programs/develop/libraries/libs-dev/libimg/z80/z80.asm
new file mode 100644
index 0000000000..5f7efddfe4
--- /dev/null
+++ b/programs/develop/libraries/libs-dev/libimg/z80/z80.asm
@@ -0,0 +1,257 @@
+;;================================================================================================;;
+;;//// z80.asm //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+;; ;;
+;; References: ;;
+;; 1. ;;
+;; ;;
+;;================================================================================================;;
+
+include 'z80.inc'
+
+;;================================================================================================;;
+proc img.is.z80 _data, _length ;//////////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Determine if raw data could be decoded (is in z80 screen format) ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = false / true ;;
+;;================================================================================================;;
+ xor eax,eax
+ cmp [_length],6929
+ setz al
+ je @f
+ cmp [_length],6912
+ setz al
+@@:
+ ret
+endp
+
+;;================================================================================================;;
+proc img.decode.z80 _data, _length ;//////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Decode data into image if it contains correctly formed raw data in z80 screen format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _data = raw data as read from file/stream ;;
+;> _length = data length ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to image ;;
+;;================================================================================================;;
+;---------------------------------------------------------------------------------------------------
+;During the decoding:
+;bl - PixelLeft (this means how much pixels left to put in current string)
+;bh - CurrentString
+;High half of ebx - use DualStos (two frames per one pixel_write)
+;cl - PixelColorIndexInPalette
+;ch - BackgroundColorIndexInPalette
+;High half of ecx - blinking flag
+;edx - address of current attribute byte
+;---------------------------------------------------------------------------------------------------
+locals
+ frame1 dd ?
+ OffsetIn2ndFrame dd ?
+endl
+ xor eax,eax
+ pushad
+ cld ;paranoia
+ stdcall img.create,256,192,Image.bpp8
+ test eax,eax
+ jz img.decode.z80.locret ;test if allocation failed
+ mov [frame1],eax
+ mov esi,z80._._16color_palette
+ mov ecx,16
+ mov edi,[eax+Image.Palette]
+ rep movsd ;write palette for the first frame
+ mov esi,[_data]
+ cmp [_length],6929
+ jne @f
+ add esi,17 ;in case of 6929 byte files we just skip the info in the begininning.
+@@:
+;---------------------------------------------------------------------------------------------------
+;At first we'll determine if there are any blinking pixels
+;if no - we'll produce statical single image
+ mov ecx,768
+ lea edx,[esi+6912-768];edx points to attribute area
+ xor ebx,ebx ;begin from <0,0> (for further decoding)
+@@:
+ test byte[edx+ecx-1],z80.BlinkFlag ;such addressing is a good optimisation
+ ;(as I hope), edx is unchanged
+ jnz .decode_z80_with_blinking
+ loop @b
+.decode_z80_without_blinking:
+ jmp .decode_z80_main_stage
+
+.decode_z80_with_blinking:
+ or ebx,0xFFFF0000 ;use DualStos
+ mov ecx,eax ;eax still points to the first frame
+ stdcall img.create,256,192,Image.bpp8
+ test eax,eax
+ jz img.decode.z80.failed
+ mov [eax+Image.Previous],ecx
+ mov [ecx+Image.Next],eax
+ mov esi,z80._._16color_palette
+ mov ecx,16
+ mov edi,[eax+Image.Palette]
+ rep movsd ;write palette for the second frame
+ mov eax,[eax+Image.Data]
+ mov [OffsetIn2ndFrame],eax
+;-------------------------------------------------------------------------------
+.decode_z80_main_stage:
+;2nd stage - convert z80 screen to 8bpp image with palette
+.decode_z80_main_stage_main_loop:
+ test bl,7
+ jnz .decode_z80_main_stage_put_now
+
+._z80_update_attributes:
+ movsx ecx,byte[edx] ;note that BlinkFlag is the highest bit in attribute
+ ;byte, so ecx's highest bit is set automatically
+ shl ecx,5
+ shr cl,5
+ and ch,0xF
+ test ch,1000b
+ jz @f
+ or ecx,1000b ;it has the same size with 'or cl,1000b' but could be faster
+@@:
+ inc edx
+
+ lodsb
+ mov ah,al
+
+.decode_z80_main_stage_put_now:
+ shl ah,1
+;-------------------------------------------------------------------------------
+._z80_put_pixel:
+;In: CF - put pixel with color CL, !CF - pixel with color CH
+;High parts of ebx and ecx - as described above
+ mov al,cl ;'mov' doesn't affect flags
+ jc @f
+ mov al,ch
+@@:
+ stosb ;'stosb' doesn't affect flags
+
+ test ebx,ebx
+ jns @f
+ test ecx,ecx
+ jns .1
+ mov al,ch
+.1:
+ xchg [OffsetIn2ndFrame],edi
+ stosb
+ xchg [OffsetIn2ndFrame],edi
+@@:
+ inc bl ;next pixel
+ jz .decode_z80_main_stage_row_finished
+ jmp .decode_z80_main_stage_main_loop
+;-------------------------------------------------------------------------------
+.decode_z80_main_stage_row_finished:
+ cmp bh,191 ;is image finished?
+ jb .decode_z80_main_stage_image_not_finished ;no.
+.decode_z80_finish:
+ jmp .locret ;now really finished
+;-------------------------------------------------------------------------------
+;or not finished yet. Branch according to a row number (see documentation)
+.decode_z80_main_stage_next_third:
+ sub bh,7
+ sub edi,256*(8-1)
+ jmp .decode_z80_main_stage_main_loop
+
+.decode_z80_main_stage_image_not_finished:
+;next row
+ add bh,8 ;refer to documentation
+ add edi,256*(8-1)
+
+;if finished row is 63 or 127 then we process next third of the image
+ cmp bh,63+8
+ je .decode_z80_main_stage_next_third
+ cmp bh,127+8
+ je .decode_z80_main_stage_next_third
+
+ cmp bh,56+8 ;if finished row in [56;63) or [120;127) or [184;191)
+ jb .decode_z80_main_stage_main_loop
+ cmp bh,63+8
+ jb .4
+ cmp bh,120+8
+ jb .decode_z80_main_stage_main_loop
+ cmp bh,127+8
+ jb .4
+ cmp bh,184+8
+ jb .decode_z80_main_stage_main_loop
+;note that if we are here then bh is < 191 (see label .2) but >= 184+8
+.4:
+;and if we here then bh is in [56;63) or [120;127) or [184;191)
+ sub bh,(8+56-1)
+ sub edi,256*(8+56-1)
+ sub edx,z80.AttrString*8
+ jmp .decode_z80_main_stage_main_loop
+img.decode.z80.locret:
+ popad
+ ret
+img.decode.z80.failed:
+ stdcall img.destroy,[frame1]
+ jmp img.decode.z80.locret
+endp
+
+;;================================================================================================;;
+proc img.encode.z80 _img, _p_length ;/////////////////////////////////////////////////////////////;;
+;;------------------------------------------------------------------------------------------------;;
+;? Encode image into raw data in z80 screen format ;;
+;;------------------------------------------------------------------------------------------------;;
+;> _img = pointer to image ;;
+;;------------------------------------------------------------------------------------------------;;
+;< eax = 0 (error) or pointer to encoded data ;;
+;< _p_length = encoded data length ;;
+;;================================================================================================;;
+ xor eax, eax
+ ret
+endp
+
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below are private procs you should never call directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;! Below is private data you should never use directly from your code ;;
+;;================================================================================================;;
+;;////////////////////////////////////////////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+z80._._16color_palette:
+dd 0 ; black
+dd 0x000000b0 ; blue
+dd 0x00b00000 ; red
+dd 0x00b000b0 ; magenta
+dd 0x0000b000 ; green
+dd 0x0000b0b0 ; cyan
+dd 0x00b0b000 ; yellow
+dd 0x00b0b0b0 ; gray
+dd 0 ; black
+dd 0x000000ff ; light blue
+dd 0x00ff0000 ; light red
+dd 0x00ff00ff ; light magenta
+dd 0x0000ff00 ; light green
+dd 0x0000ffff ; light cyan
+dd 0x00ffff00 ; light yellow
+dd 0x00ffffff ; white
diff --git a/programs/develop/libraries/libs-dev/libimg/z80/z80.inc b/programs/develop/libraries/libs-dev/libimg/z80/z80.inc
new file mode 100644
index 0000000000..4be190035a
--- /dev/null
+++ b/programs/develop/libraries/libs-dev/libimg/z80/z80.inc
@@ -0,0 +1,23 @@
+;;================================================================================================;;
+;;//// z80.inc //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;;
+;;================================================================================================;;
+;; ;;
+;; This file is part of Common development libraries (Libs-Dev). ;;
+;; ;;
+;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
+;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
+;; of the License, or (at your option) any later version. ;;
+;; ;;
+;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
+;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
+;; Lesser General Public License for more details. ;;
+;; ;;
+;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
+;; If not, see . ;;
+;; ;;
+;;================================================================================================;;
+z80.PixColor equ 000111b
+z80.BgrColor equ 111000b
+z80.BrightFlag equ (1 shl 6)
+z80.BlinkFlag equ (1 shl 7)
+z80.AttrString equ 32
\ No newline at end of file