commit 9742c47cb75c5fd4156a674885159e0a58ca9cb4 Author: Eren <66168591+Elpisdev@users.noreply.github.com> Date: Thu Nov 14 23:30:43 2024 +0300 xd xd diff --git a/bar.asm b/bar.asm new file mode 100644 index 0000000..185c392 --- /dev/null +++ b/bar.asm @@ -0,0 +1,340 @@ +section .data + FILENAME_SIZE equ 256 + +section .bss + bar_num_files resw 1 + bar_file_size resd 1 + bar_bytes_remaining resd 1 + bar_filename_buffer resb FILENAME_SIZE + bar_temp_filename resb FILENAME_SIZE + bar_check1 resd 1 + bar_check2 resd 1 + bar_current_dir resb 260 + +section .text +extract_bar: + push ebp + mov ebp, esp + + push 0 + push bytes_read + push 10 + push header_buffer + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz cleanup + + push 0 + push bytes_read + push 2 + push bar_num_files + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz cleanup + +bar_extract_loop: + movzx ecx, word [bar_num_files] + test ecx, ecx + jz cleanup + + push 0 + push bytes_read + push FILENAME_SIZE + push bar_filename_buffer + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz cleanup + + call bar_process_filename + + push 0 + push bytes_read + push 8 + push bar_check1 + push dword [file_handle] + call _ReadFile@20 + + call bar_read_file_size + test eax, eax + jz cleanup + + call bar_create_output_path + call bar_extract_file_data + test eax, eax + jz cleanup + + dec word [bar_num_files] + jmp bar_extract_loop + +.invalid_format: + push 0 + push bytes_written + push msg_invalid_bar_len + push msg_invalid_bar + push dword [stdout_handle] + call _WriteFile@20 + jmp cleanup + +bar_process_filename: + push ebp + mov ebp, esp + + mov al, [bar_filename_buffer + FILENAME_SIZE - 1] + cmp al, 0xFE + je .fe_format + + mov esi, bar_filename_buffer + mov edi, bar_temp_filename + mov ecx, FILENAME_SIZE - 4 + rep movsb + mov byte [edi], 0 + + push FILE_CURRENT + push 0 + push -4 + push dword [file_handle] + call _SetFilePointer@16 + cmp eax, 0xFFFFFFFF + je .error + + jmp .clean_filename + +.fe_format: + mov esi, bar_filename_buffer + mov edi, bar_temp_filename +.find_fe: + lodsb + cmp al, 0xFE + je .fe_found + stosb + cmp esi, bar_filename_buffer + FILENAME_SIZE + jb .find_fe +.fe_found: + mov byte [edi], 0 + +.clean_filename: + mov edi, bar_temp_filename + xor edx, edx +.trim_loop: + mov al, [edi] + test al, al + jz .trim_done + cmp al, ' ' + je .next_trim + cmp al, '.' + je .next_trim + cmp al, 9 + je .next_trim + cmp al, 13 + je .next_trim + cmp al, 10 + je .next_trim + mov edx, edi +.next_trim: + inc edi + cmp edi, bar_temp_filename + FILENAME_SIZE + jb .trim_loop + +.trim_done: + mov edi, edx + inc edi + mov byte [edi], 0 + + mov edi, bar_temp_filename +.convert_slashes: + mov al, [edi] + test al, al + jz .done + cmp al, '\\' + jne .next_char + mov byte [edi], '/' +.next_char: + inc edi + jmp .convert_slashes + +.done: + mov esp, ebp + pop ebp + ret + +.error: + mov esp, ebp + pop ebp + ret + +bar_read_file_size: + push ebp + mov ebp, esp + + push 0 + push bytes_read + push 4 + push bar_file_size + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .error + + push 0 + push bytes_read + push 4 + push bar_check1 + push dword [file_handle] + call _ReadFile@20 + + mov esp, ebp + pop ebp + ret + +.error: + mov esp, ebp + pop ebp + ret + +bar_create_output_path: + push ebp + mov ebp, esp + + mov esi, input_file + mov edi, output_path +.copy_path: + lodsb + stosb + test al, al + jnz .copy_path + + dec edi + mov esi, extract_suffix + mov ecx, extract_suffix_len + rep movsb + + mov byte [edi], '/' + inc edi + + mov esi, bar_temp_filename +.copy_name: + lodsb + test al, al + jz .done + stosb + jmp .copy_name +.done: + mov byte [edi], 0 + + mov esi, output_path + mov edi, bar_current_dir +.create_dirs: + lodsb + stosb + test al, al + jz .dirs_done + cmp al, '/' + jne .create_dirs + + mov byte [edi-1], 0 + push eax + + push 0 + push bar_current_dir + call _CreateDirectoryA@8 + + pop eax + mov byte [edi-1], '/' + jmp .create_dirs +.dirs_done: + + mov esp, ebp + pop ebp + ret + +bar_extract_file_data: + push ebp + mov ebp, esp + + push 0 + push bytes_written + push msg_extract_len + push msg_extract + push dword [stdout_handle] + call _WriteFile@20 + + mov esi, output_path + call string_length + push 0 + push bytes_written + push eax + push output_path + push dword [stdout_handle] + call _WriteFile@20 + + push 0 + push bytes_written + push msg_newline_len + push msg_newline + push dword [stdout_handle] + call _WriteFile@20 + + push 0 + push FILE_ATTRIBUTE_NORMAL + push CREATE_ALWAYS + push 0 + push 0 + push GENERIC_WRITE + push output_path + call _CreateFileA@28 + + cmp eax, INVALID_HANDLE_VALUE + je .error + mov ebx, eax + + mov ecx, [bar_file_size] + mov [bar_bytes_remaining], ecx + +.copy_loop: + mov eax, CHUNK_SIZE + cmp [bar_bytes_remaining], eax + jb .last_chunk + jmp .do_copy + +.last_chunk: + mov eax, [bar_bytes_remaining] + +.do_copy: + push 0 + push bytes_read + push eax + push chunk_buffer + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .error + + push 0 + push bytes_written + push dword [bytes_read] + push chunk_buffer + push ebx + call _WriteFile@20 + test eax, eax + jz .error + + mov eax, [bytes_read] + sub [bar_bytes_remaining], eax + jnz .copy_loop + + push ebx + call _CloseHandle@4 + mov eax, 1 + jmp .done + +.error: + push ebx + call _CloseHandle@4 + xor eax, eax +.done: + mov esp, ebp + pop ebp + ret \ No newline at end of file diff --git a/dtwo.asm b/dtwo.asm new file mode 100644 index 0000000..f28e05e --- /dev/null +++ b/dtwo.asm @@ -0,0 +1,256 @@ +section .data + d2_flag_value db 1 + +section .bss + d2_num_files resd 1 + d2_file_count resd 1 + d2_path_len resd 1 + d2_file_size resd 1 + d2_flag resb 1 + d2_path_buffer resb 1024 + +section .text +extract_d2: + push ebp + mov ebp, esp + + push 0 + push bytes_read + push 4 + push d2_num_files + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + + push FILE_CURRENT + push 0 + push 4 + push dword [file_handle] + call _SetFilePointer@16 + + mov eax, [d2_num_files] + mov [d2_file_count], eax + +.process_files: + mov eax, [d2_file_count] + test eax, eax + jz .done + + push 0 + push bytes_read + push 1 + push d2_flag + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + + mov al, [d2_flag] + cmp al, [d2_flag_value] + jne .done + + push 0 + push bytes_read + push 4 + push d2_path_len + push dword [file_handle] + call _ReadFile@20 + + push 0 + push bytes_read + push 4 + push d2_file_size + push dword [file_handle] + call _ReadFile@20 + + push FILE_CURRENT + push 0 + push 16 + push dword [file_handle] + call _SetFilePointer@16 + + mov eax, [d2_path_len] + push 0 + push bytes_read + push eax + push d2_path_buffer + push dword [file_handle] + call _ReadFile@20 + + mov edi, d2_path_buffer + add edi, [d2_path_len] + mov byte [edi], 0 + + mov esi, d2_path_buffer + mov ecx, [d2_path_len] +.convert_slashes: + mov al, [esi] + cmp al, '\' + jne .next_char + mov byte [esi], '/' +.next_char: + inc esi + loop .convert_slashes + + call create_d2_path + call extract_d2_file + + dec dword [d2_file_count] + jmp .process_files + +.done: + mov esp, ebp + pop ebp + jmp cleanup + +create_d2_path: + push ebp + mov ebp, esp + + mov esi, input_file + mov edi, output_path +.copy_base: + lodsb + stosb + test al, al + jnz .copy_base + + dec edi + mov esi, extract_suffix + mov ecx, extract_suffix_len + rep movsb + + mov byte [edi], '/' + inc edi + + mov esi, d2_path_buffer +.copy_name: + lodsb + test al, al + jz .done + stosb + jmp .copy_name +.done: + mov byte [edi], 0 + + mov esi, output_path + mov edi, chunk_buffer +.create_dirs: + lodsb + stosb + test al, al + jz .dirs_done + cmp al, '/' + jne .create_dirs + + mov byte [edi-1], 0 + push eax + + push 0 + push chunk_buffer + call _CreateDirectoryA@8 + + pop eax + mov byte [edi-1], '/' + jmp .create_dirs + +.dirs_done: + mov esp, ebp + pop ebp + ret + +extract_d2_file: + push ebp + mov ebp, esp + + push 0 + push bytes_written + push msg_extract_len + push msg_extract + push dword [stdout_handle] + call _WriteFile@20 + + mov esi, output_path + call string_length + push 0 + push bytes_written + push eax + push output_path + push dword [stdout_handle] + call _WriteFile@20 + + push 0 + push bytes_written + push msg_newline_len + push msg_newline + push dword [stdout_handle] + call _WriteFile@20 + + push 0 + push FILE_ATTRIBUTE_NORMAL + push CREATE_ALWAYS + push 0 + push 0 + push GENERIC_WRITE + push output_path + call _CreateFileA@28 + + cmp eax, INVALID_HANDLE_VALUE + je .error + mov ebx, eax + + mov ecx, [d2_file_size] +.copy_loop: + mov eax, CHUNK_SIZE + cmp ecx, eax + jb .last_chunk + jmp .do_copy + +.last_chunk: + mov eax, ecx + +.do_copy: + push ecx + + push 0 + push bytes_read + push eax + push chunk_buffer + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .read_error + + push 0 + push bytes_written + push dword [bytes_read] + push chunk_buffer + push ebx + call _WriteFile@20 + test eax, eax + jz .write_error + + pop ecx + sub ecx, [bytes_read] + jnz .copy_loop + + push ebx + call _CloseHandle@4 + mov eax, 1 + jmp .done + +.read_error: +.write_error: + pop ecx +.error: + test ebx, ebx + jz .done + push ebx + call _CloseHandle@4 + xor eax, eax + +.done: + mov esp, ebp + pop ebp + ret \ No newline at end of file diff --git a/mar.asm b/mar.asm new file mode 100644 index 0000000..c784d58 --- /dev/null +++ b/mar.asm @@ -0,0 +1,240 @@ +section .data + mar_entry_end db 0xFF + +section .bss + mar_entry_type resb 1 + mar_filename resb 260 + mar_file_size resd 1 + +section .text +extract_mar: + push ebp + mov ebp, esp + + push FILE_CURRENT + push 0 + push 0 + push dword [file_handle] + call _SetFilePointer@16 + +.process_entry: + push 0 + push bytes_read + push 1 + push mar_entry_type + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + + mov al, [mar_entry_type] + cmp al, [mar_entry_end] + je .done + + mov edi, mar_filename +.read_filename: + push 0 + push bytes_read + push 1 + push edi + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + + mov al, [edi] + test al, al + jz .filename_done + inc edi + jmp .read_filename + +.filename_done: + mov al, [mar_entry_type] + cmp al, 1 + jne .process_entry + + push 0 + push bytes_read + push 4 + push mar_file_size + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + + call create_mar_path + + call extract_mar_file + + jmp .process_entry + +.done: + mov esp, ebp + pop ebp + jmp cleanup + +create_mar_path: + push ebp + mov ebp, esp + + mov esi, input_file + mov edi, output_path +.copy_base: + lodsb + test al, al + jz .base_done + stosb + jmp .copy_base + +.base_done: + dec edi + mov esi, extract_suffix + mov ecx, extract_suffix_len + rep movsb + + mov byte [edi], '/' + inc edi + + mov esi, mar_filename +.copy_name: + lodsb + test al, al + jz .name_done + cmp al, '\' + jne .store_char + mov al, '/' +.store_char: + stosb + jmp .copy_name + +.name_done: + mov byte [edi], 0 + + mov esi, output_path + mov edi, chunk_buffer +.create_dirs: + lodsb + stosb + test al, al + jz .dirs_done + cmp al, '/' + jne .create_dirs + + mov byte [edi-1], 0 + push eax + + push 0 + push chunk_buffer + call _CreateDirectoryA@8 + + pop eax + mov byte [edi-1], '/' + jmp .create_dirs + +.dirs_done: + mov esp, ebp + pop ebp + ret + +extract_mar_file: + push ebp + mov ebp, esp + + push 0 + push bytes_written + push msg_extract_len + push msg_extract + push dword [stdout_handle] + call _WriteFile@20 + + mov esi, output_path + xor ecx, ecx +.count_len: + lodsb + test al, al + jz .print_path + inc ecx + jmp .count_len + +.print_path: + push 0 + push bytes_written + push ecx + push output_path + push dword [stdout_handle] + call _WriteFile@20 + + push 0 + push bytes_written + push msg_newline_len + push msg_newline + push dword [stdout_handle] + call _WriteFile@20 + + push 0 + push FILE_ATTRIBUTE_NORMAL + push CREATE_ALWAYS + push 0 + push 0 + push GENERIC_WRITE + push output_path + call _CreateFileA@28 + + cmp eax, INVALID_HANDLE_VALUE + je .error + mov ebx, eax + + mov ecx, [mar_file_size] +.copy_loop: + mov eax, CHUNK_SIZE + cmp ecx, eax + jb .last_chunk + jmp .do_copy + +.last_chunk: + mov eax, ecx + +.do_copy: + push ecx + + push 0 + push bytes_read + push eax + push chunk_buffer + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .read_error + + push 0 + push bytes_written + push dword [bytes_read] + push chunk_buffer + push ebx + call _WriteFile@20 + test eax, eax + jz .write_error + + pop ecx + sub ecx, [bytes_read] + jnz .copy_loop + + push ebx + call _CloseHandle@4 + mov eax, 1 + jmp .done + +.read_error: +.write_error: + pop ecx +.error: + test ebx, ebx + jz .done + push ebx + call _CloseHandle@4 + xor eax, eax + +.done: + mov esp, ebp + pop ebp + ret \ No newline at end of file diff --git a/qar.asm b/qar.asm new file mode 100644 index 0000000..7ed15ab --- /dev/null +++ b/qar.asm @@ -0,0 +1,264 @@ +section .data + qar_filename_size equ 132 + +section .bss + qar_num_files resd 1 + qar_file_size resd 1 + qar_filename resb qar_filename_size + qar_padding resd 1 + qar_header_pad resd 1 + +section .text +extract_qar: + push ebp + mov ebp, esp + + push FILE_BEGIN + push 0 + push 0 + push dword [file_handle] + call _SetFilePointer@16 + + push FILE_CURRENT + push 0 + push 4 + push dword [file_handle] + call _SetFilePointer@16 + + push 0 + push bytes_read + push 4 + push qar_num_files + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + +.extract_loop: + mov ecx, [qar_num_files] + test ecx, ecx + jz .done + + push ecx + mov edi, qar_filename + mov ecx, qar_filename_size + xor al, al + rep stosb + pop ecx + + push 0 + push bytes_read + push qar_filename_size + push qar_filename + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + + push 0 + push bytes_read + push 4 + push qar_padding + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + + push 0 + push bytes_read + push 4 + push qar_file_size + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + + push 0 + push bytes_read + push 4 + push qar_padding + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .done + + mov al, [qar_filename] + test al, al + jz .next_file + + call create_qar_path + call extract_qar_file + +.next_file: + dec dword [qar_num_files] + jmp .extract_loop + +.done: + mov esp, ebp + pop ebp + jmp cleanup + +create_qar_path: + push ebp + mov ebp, esp + + mov esi, input_file + mov edi, output_path +.copy_base: + lodsb + stosb + test al, al + jz .base_done + jmp .copy_base + +.base_done: + dec edi + mov esi, extract_suffix + mov ecx, extract_suffix_len + rep movsb + + mov byte [edi], '/' + inc edi + + mov esi, qar_filename +.copy_name: + lodsb + test al, al + jz .name_done + cmp al, ' ' + jz .name_done + cmp al, 0x0D + je .next_char + cmp al, 0x0A + je .next_char + cmp al, '\' + jne .store_char + mov al, '/' +.store_char: + stosb +.next_char: + jmp .copy_name + +.name_done: + mov byte [edi], 0 + + mov esi, output_path + mov edi, chunk_buffer +.create_dirs: + lodsb + stosb + test al, al + jz .dirs_done + cmp al, '/' + jne .create_dirs + + mov byte [edi-1], 0 + push eax + + push 0 + push chunk_buffer + call _CreateDirectoryA@8 + + pop eax + mov byte [edi-1], '/' + jmp .create_dirs + +.dirs_done: + mov esp, ebp + pop ebp + ret + +extract_qar_file: + push ebp + mov ebp, esp + + push 0 + push bytes_written + push msg_extract_len + push msg_extract + push dword [stdout_handle] + call _WriteFile@20 + + mov esi, output_path + call string_length + push 0 + push bytes_written + push eax + push output_path + push dword [stdout_handle] + call _WriteFile@20 + + push 0 + push bytes_written + push msg_newline_len + push msg_newline + push dword [stdout_handle] + call _WriteFile@20 + + push 0 + push FILE_ATTRIBUTE_NORMAL + push CREATE_ALWAYS + push 0 + push 0 + push GENERIC_WRITE + push output_path + call _CreateFileA@28 + + cmp eax, INVALID_HANDLE_VALUE + je .error + mov ebx, eax + + mov ecx, [qar_file_size] +.copy_loop: + mov eax, CHUNK_SIZE + cmp ecx, eax + jb .last_chunk + jmp .do_copy + +.last_chunk: + mov eax, ecx + +.do_copy: + push ecx + + push 0 + push bytes_read + push eax + push chunk_buffer + push dword [file_handle] + call _ReadFile@20 + test eax, eax + jz .read_error + + push 0 + push bytes_written + push dword [bytes_read] + push chunk_buffer + push ebx + call _WriteFile@20 + test eax, eax + jz .write_error + + pop ecx + sub ecx, [bytes_read] + jnz .copy_loop + + push ebx + call _CloseHandle@4 + mov eax, 1 + jmp .done + +.read_error: +.write_error: + pop ecx +.error: + test ebx, ebx + jz .done + push ebx + call _CloseHandle@4 + xor eax, eax + +.done: + mov esp, ebp + pop ebp + ret \ No newline at end of file diff --git a/unarchive.asm b/unarchive.asm new file mode 100644 index 0000000..95e09e0 --- /dev/null +++ b/unarchive.asm @@ -0,0 +1,292 @@ +extern _ExitProcess@4 +extern _CreateFileA@28 +extern _WriteFile@20 +extern _ReadFile@20 +extern _CloseHandle@4 +extern _CreateDirectoryA@8 +extern _GetStdHandle@4 +extern _GetCommandLineA@0 +extern _SetFilePointer@16 + +global start + +section .data + CHUNK_SIZE equ 1048576 + FILENAME_SIZE equ 256 + STD_OUTPUT_HANDLE equ -11 + GENERIC_READ equ 0x80000000 + GENERIC_WRITE equ 0x40000000 + FILE_SHARE_READ equ 0x00000001 + CREATE_ALWAYS equ 2 + OPEN_EXISTING equ 3 + FILE_ATTRIBUTE_NORMAL equ 0x80 + INVALID_HANDLE_VALUE equ -1 + FILE_BEGIN equ 0 + FILE_CURRENT equ 1 + + msg_usage db "Usage: unarchive ", 13, 10 + msg_usage_len equ $ - msg_usage + msg_invalid db "Invalid archive format", 13, 10 + msg_invalid_len equ $ - msg_invalid + msg_invalid_bar db "Invalid BAR!", 13, 10 + msg_invalid_bar_len equ $ - msg_invalid_bar + msg_open_error db "Failed to open file: ", 13, 10 + msg_open_error_len equ $ - msg_open_error + msg_extract db "Extracting: " + msg_extract_len equ $ - msg_extract + msg_newline db 13, 10 + msg_newline_len equ 2 + + mar_magic db "MASMAR0", 0 + qar_magic db "QAR", 0 + + extract_suffix db "_extracted" + extract_suffix_len equ $ - extract_suffix + +section .bss + align 16 + input_file resb 260 + output_path resb 1024 + chunk_buffer resb CHUNK_SIZE + file_handle resd 1 + stdout_handle resd 1 + magic_buffer resb 8 + bytes_read resd 1 + bytes_written resd 1 + format_type resb 1 + extension resb 4 + header_buffer resb 10 + +section .text +start: + push ebp + mov ebp, esp + + push STD_OUTPUT_HANDLE + call _GetStdHandle@4 + mov [stdout_handle], eax + + call _GetCommandLineA@0 + mov esi, eax + +.skip_prog: + lodsb + test al, al + jz usage_error + cmp al, '"' + jne .not_quoted + +.skip_quoted: + lodsb + test al, al + jz usage_error + cmp al, '"' + jne .skip_quoted + inc esi + jmp .find_arg + +.not_quoted: + cmp al, ' ' + je .find_arg + test al, al + jz usage_error + jmp .skip_prog + +.find_arg: + lodsb + test al, al + jz usage_error + cmp al, ' ' + je .find_arg + dec esi + + mov edi, input_file +.copy_arg: + lodsb + test al, al + jz .arg_done + cmp al, ' ' + je .arg_done + stosb + jmp .copy_arg + +.arg_done: + mov byte [edi], 0 + + cmp byte [input_file], 0 + je usage_error + + push 0 + push FILE_ATTRIBUTE_NORMAL + push OPEN_EXISTING + push 0 + push FILE_SHARE_READ + push GENERIC_READ + push input_file + call _CreateFileA@28 + + cmp eax, INVALID_HANDLE_VALUE + je open_error + mov [file_handle], eax + + push 0 + push bytes_read + push 7 + push magic_buffer + push dword [file_handle] + call _ReadFile@20 + + mov esi, magic_buffer + mov edi, mar_magic + mov ecx, 7 + repe cmpsb + je detect_mar + + push FILE_BEGIN + push 0 + push 0 + push dword [file_handle] + call _SetFilePointer@16 + + push 0 + push bytes_read + push 3 + push magic_buffer + push dword [file_handle] + call _ReadFile@20 + + mov esi, magic_buffer + mov edi, qar_magic + mov ecx, 3 + repe cmpsb + je detect_qar + + mov esi, input_file + call get_extension + test eax, eax + jz try_bar + + mov esi, extension + mov al, 'd' + cmp byte [esi], al + jne try_bar + mov al, '2' + cmp byte [esi+1], al + je detect_d2 + +try_bar: + push FILE_BEGIN + push 0 + push 0 + push dword [file_handle] + call _SetFilePointer@16 + + mov byte [format_type], 3 + jmp process_archive + +detect_mar: + mov byte [format_type], 1 + jmp process_archive + +detect_qar: + mov byte [format_type], 2 + jmp process_archive + +detect_d2: + mov byte [format_type], 4 + jmp process_archive + +process_archive: + push FILE_BEGIN + push 0 + push 0 + push dword [file_handle] + call _SetFilePointer@16 + + movzx eax, byte [format_type] + cmp al, 1 + je extract_mar + cmp al, 2 + je extract_qar + cmp al, 3 + je extract_bar + cmp al, 4 + je extract_d2 + jmp cleanup + +string_length: + push ebp + mov ebp, esp + mov edi, esi + xor al, al + mov ecx, -1 + repne scasb + mov eax, edi + sub eax, esi + dec eax + mov esp, ebp + pop ebp + ret + +get_extension: + xor eax, eax + mov edi, extension + mov ebx, esi +.find_dot: + lodsb + test al, al + jz .not_found + cmp al, '.' + jne .find_dot +.copy_ext: + lodsb + test al, al + jz .done + stosb + jmp .copy_ext +.done: + mov eax, 1 + ret +.not_found: + xor eax, eax + ret + +cleanup: + push dword [file_handle] + call _CloseHandle@4 + xor eax, eax + push eax + call _ExitProcess@4 + +usage_error: + push 0 + push bytes_written + push msg_usage_len + push msg_usage + push dword [stdout_handle] + call _WriteFile@20 + push 1 + call _ExitProcess@4 + +open_error: + push 0 + push bytes_written + push msg_open_error_len + push msg_open_error + push dword [stdout_handle] + call _WriteFile@20 + mov esi, input_file + call string_length + push 0 + push bytes_written + push eax + push input_file + push dword [stdout_handle] + call _WriteFile@20 + push 1 + call _ExitProcess@4 + +%include "mar.asm" +%include "qar.asm" +%include "bar.asm" +%include "dtwo.asm" \ No newline at end of file