Code: Select all
; nasm -f bin "imgC.asm" -o "imgC.kex"
ORG 0
BITS 32
; ------------------------------------------------------------- ;
PATH_SIZE equ 1024
PARAMS_SIZE equ 256
STACK_SIZE equ 2048
; ------------------------------------------------------------- ;
CANNOT_OPEN_SRC equ 1
SRC_NOT_AVAILABLE equ 2
DECODE_ERROR equ 3
OPTIONS_INCORRECT equ 4
NO_INPUT_PARAMS equ 5
NO_INPUT_SRC equ 6
SRC_IS_EMPTY equ 7
MEM_ALLOC_ERROR equ 8
ENCODE_ERROR equ 9
CANNOT_SAVE_DST equ 10
FLIP_ERROR equ 11
ROTATE_ERROR equ 12
; ------------------------------------------------------------- ;
FLIP_VERTICAL equ 1
FLIP_HORIZONTAL equ 2
FLIP_BOTH equ 3
; ------------------------------------------------------------- ;
ROTATE_90_CW equ 1
ROTATE_180 equ 2
ROTATE_270_CW equ 3
ROTATE_90_CCW equ ROTATE_270_CW
ROTATE_270_CCW equ ROTATE_90_CW
; ------------------------------------------------------------- ;
LIBIMG_SCALE_STRETCH equ 3
LIBIMG_INTER_BILINEAR equ 1
; ------------------------------------------------------------- ;
BPP8I equ 1
BPP24 equ 2
BPP32 equ 3
BPP15 equ 4
BPP16 equ 5
BPP1 equ 6
BPP8G equ 7
BPP2I equ 8
BPP4I equ 9
BPP8A equ 10
; ------------------------------------------------------------- ;
MENUET01 db 'MENUET01'
version dd 1
program.start dd start_
program.end dd end_
program.memory dd end_ + PATH_SIZE + PARAMS_SIZE + STACK_SIZE
program.stack dd end_ + PATH_SIZE + PARAMS_SIZE + STACK_SIZE
program.params dd end_ + PATH_SIZE
program.path dd end_
; ------------------------------------------------------------- ;
src dd 0
format_id dd 0
extension dd 0
options dd 0
flip dd 0
rotate dd 0
img_type dd 0
scale: dd 0
.width dd 0
.height dd 0
convert dd 0
; ------------------------------------------------------------- ;
formats:
dd sz_bmp
dd sz_ico
dd sz_cur
dd sz_gif
dd sz_png
dd sz_jpeg
dd sz_tga
dd sz_pcx
dd sz_xcf
dd sz_tiff
dd sz_pnm
dd sz_wbmp
dd sz_z80
.end:
sz_bmp db "bmp",0
sz_ico db "ico",0
sz_cur db "cur",0
sz_gif db "gif",0
sz_png db "png",0
sz_jpeg db "jpeg",0
sz_tga db "tga",0
sz_pcx db "pcx",0
sz_xcf db "xcf",0
sz_tiff db "tiff",0
sz_pnm db "pnm",0
sz_wbmp db "wbmp",0
sz_z80 db "scr",0
; ------------------------------------------------------------- ;
libimg dd 0
libimg_init dd 0
img_decode dd 0
img_encode dd 0
img_scale dd 0
img_convert dd 0
img_flip dd 0
img_rotate dd 0
img_destroy dd 0
; ------------------------------------------------------------- ;
sz_libimg db "/sys/lib/libimg.obj",0
sz_img_decode db "img_decode",0
sz_lib_init db "lib_init",0
sz_img_destroy db "img_destroy",0
sz_img_encode db "img_encode",0
sz_img_scale db "img_scale",0
sz_img_convert db "img_convert",0
sz_img_flip db "img_flip",0
sz_img_rotate db "img_rotate",0
sz_notify db "/sys/@notify",0
; ------------------------------------------------------------- ;
srcpath dd 0
dstpath dd 0
; ------------------------------------------------------------- ;
errors:
resd 1
dd sz_src_not_found
dd sz_src_not_available
dd sz_decode_error
dd sz_options_incorrect
dd sz_no_input_params
dd sz_no_input_src
dd sz_src_is_empty
dd sz_mem_alloc_error
dd sz_encode_error
dd sz_cannot_save_dst
dd sz_flip_error
dd sz_rotate_error
libimg_errors:
resd 1
dd sz_out_of_memory
dd sz_format
dd sz_conditions
dd sz_bit_depth
dd sz_encoder
dd sz_src_type
dd sz_scale
dd sz_inter
dd sz_not_inplemented
dd sz_invalid_input
sz_src_not_found db "cannot open source file",0
sz_src_not_available db "source file not available",0
sz_decode_error db "decode error",0
sz_options_incorrect db "options incorrect",0
sz_no_input_params db "no input parameters",0
sz_no_input_src db "no input source file",0
sz_src_is_empty db "source file is empty",0
sz_mem_alloc_error db "memory allocation error",0
sz_encode_error db "encode error",0
sz_cannot_save_dst db "cannot save dest. file",0
sz_flip_error db "flip error",0
sz_rotate_error db "rotate error",0
sz_out_of_memory db "out of memory",0
sz_format db "format is not supported",0
sz_conditions db "specific conditions cannot be satisfied",0
sz_bit_depth db "bit depth cannot be preserved",0
sz_encoder db "encoder",0
sz_src_type db "src type",0
sz_scale db "scale",0
sz_inter db "inter",0
sz_not_inplemented db "not inplemented",0
sz_invalid_input db "invalid input",0
; ------------------------------------------------------------- ;
load.library:
mov eax, 68
mov ebx, 19
mov ecx, [esp + 4]
int 64
ret 4
; ------------------------------------------------------------- ;
getprocaddress:
mov edx, [esp + 8]
xor eax, eax
test edx, edx
jz .end
.next:
cmp [edx], dword 0
jz .end
xor eax, eax
mov esi, [edx]
mov edi, [esp + 4]
.next_:
lodsb
scasb
jne .fail
or al, al
jnz .next_
jmp .ok
.fail:
add edx, 8
jmp .next
.ok:
mov eax, [edx + 4]
.end:
ret 8
; ------------------------------------------------------------- ;
%define lib_init [esp + 4 + 8 * 4]
dll.init:
pushad
mov eax, memory.allocate
mov ebx, memory.free
mov ecx, memory.reallocate
mov edx, .dll_load
call lib_init
popad
ret 4
%undef lib_init
.dll_load:
push ebp
mov ebp, esp
mov esi, [ebp + 8]
.next_lib:
mov edx, [esi]
or edx, edx
jz .exit
push esi
mov esi, [esi + 4]
mov edi, .lib_name
.b:
lodsb
stosb
or al, al
jnz .b
push .lib_path
call load.library
or eax, eax
jz .fail
mov ecx, [eax]
cmp dword [ecx + 4], "init"
jne .skip_init
push dword [eax + 4]
call dll.init
.skip_init:
mov ecx, eax
mov ebx, edx
test edx, edx
jz .done
.next:
mov eax, [ebx]
test eax, eax
jz .done
push ecx
push eax
call getprocaddress
or eax, eax
jz .f
mov [ebx], eax
add ebx, 4
jmp .next
.f:
mov [esp], eax
.done:
pop esi
add esi, 8
jmp .next_lib
.exit:
xor eax, eax
jmp .return
.fail:
pop esi
inc eax
.return:
pop ebp
ret 4
.lib_path:
db "/sys/lib/"
.lib_name:
resb 32
; ------------------------------------------------------------- ;
file.read:
mov eax, [esp + 12]
mov edx, [esp + 8]
mov ecx, [esp + 4]
mov ebx, .file_info
mov [.file_path], eax
mov [.buffer], edx
mov [.count], ecx
mov eax, 70
int 64
ret 12
.file_info:
dd 0
dd 0
dd 0
.count:
dd 0
.buffer:
dd 0
db 0
.file_path:
dd 0
; ------------------------------------------------------------- ;
file.write:
mov eax, [esp + 12]
mov ecx, [esp + 8]
mov edx, [esp + 4]
mov ebx, .file_info
mov [.file_path], eax
mov [.buffer], ecx
mov [.count], edx
mov eax, 70
int 64
ret 12
.file_info:
dd 2
dd 0
dd 0
.count:
dd 0
.buffer:
dd 0
db 0
.file_path:
dd 0
; ------------------------------------------------------------- ;
file.run:
mov eax, [esp + 8]
mov ecx, [esp + 4]
mov ebx, .file_info
mov [.file_path], eax
mov [.params], ecx
mov eax, 70
int 64
ret 8
.file_info:
dd 7
dd 0
.params:
dd 0
dd 0
dd 0
db 0
.file_path:
dd 0
; ------------------------------------------------------------- ;
memory.allocate:
push ebx
push ecx
mov ecx, [esp + 12]
mov eax, 68
mov ebx, 12
int 64
pop ecx
pop ebx
ret 4
; ------------------------------------------------------------- ;
memory.reallocate:
push ebx
push ecx
push edx
mov edx, [esp + 16]
mov ecx, [esp + 20]
mov eax, 68
mov ebx, 20
int 64
pop edx
pop ecx
pop ebx
ret 8
; ------------------------------------------------------------- ;
memory.free:
push ebx
push ecx
mov ecx, [esp + 12]
mov eax, 68
mov ebx, 13
int 64
pop ecx
pop ebx
ret 4
; ------------------------------------------------------------- ;
; ------------------------------------------------------------- ;
; ==========================| START |========================== ;
; ------------------------------------------------------------- ;
start_:
xor eax, eax
mov esi, [program.params]
; check if params exists
cmp [esi], byte 0
jne .params_exists
mov [errors], dword NO_INPUT_PARAMS
jmp .check_errors
.params_exists:
; check if options exists
cmp [esi], byte "/"
jne .options_exists
je .src_path_exists
.options_exists:
mov [options], esi
; check if src path exists
or eax, -1
.check_src:
inc eax
cmp [esi + eax], byte "/"
je .src_path_exists
cmp [esi + eax], byte 0
jne .check_src
.src_path_not_exists:
mov [errors], dword NO_INPUT_SRC
jmp .check_errors
.src_path_exists:
mov [srcpath], esi
add [srcpath], eax
or eax, -1
.find_end_src_path:
inc eax
cmp [esi + eax], byte ">"
je .end_src_path_found
cmp [esi + eax], byte 0
jne .find_end_src_path
.end_src_path_found:
mov [esi + eax], byte 0
add esi, eax
inc esi
; check if dst path exists
or eax, -1
.check_dst:
inc eax
cmp [esi + eax], byte "/"
je .dst_path_exists
cmp [esi + eax], byte 0
jne .check_dst
.dst_path_not_exists:
; if not make it same as srcpath
xor eax, eax
mov esi, [srcpath]
.dst_path_exists:
mov [dstpath], esi
add [dstpath], eax
; check dst extension
or eax, -1
xor ecx, ecx
.check_ext:
inc eax
cmp [esi + eax], byte "."
jne .skip
mov ecx, eax
inc ecx
.skip:
cmp [esi + eax], byte 0
jne .check_ext
jcxz .no_ext
mov eax, ecx
.no_ext:
lea eax, [esi + eax]
mov [extension], eax
; check if options correct
mov esi, [options]
test esi, esi
jz .options_correct
.next_option:
lodsb
cmp al, "/"
je .options_correct
.flip: ; |-------------------------------------------- ;
cmp al, "f"
jne .rotate
lodsb
.fv:
cmp al, "v"
jne .fh
or [flip], dword FLIP_VERTICAL
jmp .next_option
.fh:
cmp al, "h"
jne .fb
or [flip], dword FLIP_HORIZONTAL
jmp .next_option
.fb:
cmp al, "b"
jne .options_incorrect
or [flip], dword FLIP_BOTH
jmp .next_option
.rotate: ; |------------------------------------------- ;
cmp al, "r"
jne .scale
lodsb
.r90:
cmp al, "9"
jne .r180
lodsb
cmp al, "0"
jne .options_incorrect
mov [rotate], dword ROTATE_90_CW
jmp .next_option
.r180:
cmp al, "1"
jne .r270
lodsb
cmp al, "8"
jne .options_incorrect
lodsb
cmp al, "0"
jne .options_incorrect
mov [rotate], dword ROTATE_180
jmp .next_option
.r270:
cmp al, "2"
jne .options_incorrect
lodsb
cmp al, "7"
jne .options_incorrect
lodsb
cmp al, "0"
jne .options_incorrect
mov [rotate], dword ROTATE_270_CW
jmp .next_option
.scale: ; |-------------------------------------------- ;
cmp al, "s"
jne .convert
cmp [esi], byte "%"
jne .no_percent
mov [scale], byte "%"
inc esi
.no_percent:
xor eax, eax
xor ecx, ecx
.next_w:
lodsb
sub al, 48
cmp al, 9
jnbe .done_w
lea ecx, [ecx + ecx * 4]
lea ecx, [eax + ecx * 2]
jmp .next_w
.done_w:
mov [scale.width], ecx
cmp al, "x" - 48
jne .options_incorrect
xor eax, eax
xor ecx, ecx
.next_h:
lodsb
sub al, 48
cmp al, 9
jnbe .done_h
lea ecx, [ecx + ecx * 4]
lea ecx, [eax + ecx * 2]
jmp .next_h
.done_h:
mov [scale.height], ecx
jmp .next_option
.convert: ; |-------------------------------------------- ;
cmp al, "b"
jne .space
lodsw
cmp ax, "pp"
jne .options_incorrect
lodsw
.8i:
cmp ax, "8i"
jne .24
mov [convert], dword BPP8I
jmp .next_option
.24:
cmp ax, "24"
jne .32
mov [convert], dword BPP24
jmp .next_option
.32:
cmp ax, "32"
jne .15
mov [convert], dword BPP32
jmp .next_option
.15:
cmp ax, "15"
jne .16
mov [convert], dword BPP15
jmp .next_option
.16:
cmp ax, "16"
jne .1
mov [convert], dword BPP16
jmp .next_option
.1:
cmp al, "1"
jne .8g
dec esi
mov [convert], dword BPP1
jmp .next_option
.8g:
cmp ax, "8g"
jne .2i
mov [convert], dword BPP8G
jmp .next_option
.2i:
cmp ax, "2i"
jne .4i
mov [convert], dword BPP2I
jmp .next_option
.4i:
cmp ax, "4i"
jne .8a
mov [convert], dword BPP4I
jmp .next_option
.8a:
cmp ax, "8a"
jne .options_incorrect
mov [convert], dword BPP8A
jmp .next_option
.space: ; |-------------------------------------------- ;
cmp al, " "
jne .options_incorrect
jmp .next_option
.options_incorrect:
mov [errors], dword OPTIONS_INCORRECT
jmp .check_errors
.options_correct:
; get format id by file extension
mov esi, formats
mov ecx, (formats.end - formats) / 4
mov edx, [extension]
.find_format:
lodsd
mov eax, [eax]
cmp [edx], eax
je .format_found
loop .find_format
.format_found:
neg ecx
add ecx, (formats.end - formats) / 4
inc ecx
mov [format_id], ecx
; check if src path available
mov [esp - (25 + 40) + 0], dword 5
mov [esp - (25 + 40) + 8], dword 0
mov [esp - (25 + 40) + 20], byte 0
lea eax, [esp - 40]
mov [esp - (25 + 40) + 16], eax
lea ebx, [esp - (25 + 40)]
mov eax, [srcpath]
mov [esp - (25 + 40) + 21], eax
mov eax, 70
int 64
test eax, eax
jz .src_available
mov [errors], dword SRC_NOT_AVAILABLE
jmp .check_errors
.src_available:
mov eax, [esp - (25 + 40) + 25 + 32] ; file.size
test eax, eax
jnz .src_not_empty
mov [errors], dword SRC_IS_EMPTY
jmp .check_errors
.src_not_empty:
push eax
; try to load libimg
push sz_libimg
call load.library
test eax, eax
jnz .libimg_loaded
.libimg_loaded:
mov [libimg], eax
mov ecx, eax
mov ebx, getprocaddress
push ecx
push sz_img_decode
call ebx
mov [img_decode], eax
push ecx
push sz_img_destroy
call ebx
mov [img_destroy], eax
push ecx
push sz_img_encode
call ebx
mov [img_encode], eax
push ecx
push sz_img_scale
call ebx
mov [img_scale], eax
push ecx
push sz_img_convert
call ebx
mov [img_convert], eax
push ecx
push sz_img_flip
call ebx
mov [img_flip], eax
push ecx
push sz_img_rotate
call ebx
mov [img_rotate], eax
push ecx
push sz_lib_init
call ebx
push eax
call dll.init
; if it loaded, open src image ; |----------------------------------- ;
pop ecx; file.size
push ecx
call memory.allocate
test eax, eax
jnz .allocated
mov [errors], dword MEM_ALLOC_ERROR
jmp .check_errors
.allocated:
mov edi, eax
push dword [srcpath]
push eax
push ecx
call file.read
test eax, eax
jz .opened
mov [errors], dword CANNOT_OPEN_SRC
jmp .check_errors
.opened:
; if it opened, try to decode ; |------------------------------------ ;
push dword 0
push ecx
push edi
call [img_decode]
test eax, eax
jnz .decoded
mov [errors], dword DECODE_ERROR
jmp .check_errors
.decoded:
mov [src], eax
; if need flip then flip ; |----------------------------------------- ;
cmp [flip], dword 0
je .flipped
push dword [flip]
push dword [src]
call [img_flip]
test eax, eax
jnz .flipped
mov [errors], dword FLIP_ERROR
jmp .check_errors
.flipped:
; if need rotate then rotate ; |------------------------------------- ;
cmp [rotate], dword 0
je .rotated
push dword [rotate]
push dword [src]
call [img_rotate]
test eax, eax
jnz .rotated
mov [errors], dword ROTATE_ERROR
jmp .check_errors
.rotated:
; if need scale then scale ; |--------------------------------------- ;
cmp [scale.height], dword 0
je .scaled
cmp [scale.width], dword 0
je .scaled
cmp [scale], byte "%"
je .percent
push dword [scale.height]
push dword [scale.width]
jmp .wh_pushed
.percent:
mov ecx, [src]
mov ebx, 100
mov eax, [ecx + 8]
mul dword [scale.height]
div ebx
push eax
mov eax, [ecx + 4]
mul dword [scale.width]
div ebx
push eax
.wh_pushed:
push dword LIBIMG_INTER_BILINEAR
push dword LIBIMG_SCALE_STRETCH
push dword 0
mov eax, [src]
push dword [eax + 8]
push dword [eax + 4]
push dword 0
push dword 0
push dword [src]
call [img_scale]
mov [src], eax
test eax, eax
jnz .scaled
lea eax, [(libimg_errors - errors) / 4 + ecx]
mov [errors], eax
jmp .check_errors
.scaled:
; if need convert, try to convert; |--------------------------------- ;
cmp [convert], dword 0
je .converted
push dword 0
push dword [convert]
push dword 0
push dword [src]
call [img_convert]
mov [src], eax
test eax, eax
jnz .converted
lea eax, [(libimg_errors - errors) / 4 + ecx]
mov [errors], eax
jmp .check_errors
.converted:
; try to encode ; |------------------------------------------------- ;
push 0
push dword [format_id]
push dword [src]
call [img_encode]
test eax, eax
jnz .encoded
lea eax, [(libimg_errors - errors) / 4 + ecx]
mov [errors], eax;dword ENCODE_ERROR
jmp .check_errors
.encoded:
; if converted, try to save ; |-------------------------------------- ;
push dword [dstpath]
push eax
push ecx
call file.write
test eax, eax
jz .saved
mov [errors], dword CANNOT_SAVE_DST
jmp .check_errors
.saved:
; if errors not occured, just exit
.check_errors:
mov eax, [errors]
test eax, eax
jz .just_exit
; else output error messages
push sz_notify
push dword [errors + eax*4]
call file.run
.just_exit:
program.terminate: ; |-------------------------------------------- ;
or eax, -1
int 64
; ------------------------------------------------------------- ;
end_: