Mercurial > msvpvf
changeset 6:d1e5b8390cd3
Add Windows GUI version and a multitude of other changes
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Wed, 26 Jan 2022 20:25:08 -0500 |
parents | 92ec47e63923 |
children | bd392e82001c |
files | Makefile README.md include/common.h msvpvf.c src/gui.c src/main.c |
diffstat | 6 files changed, 437 insertions(+), 200 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Fri Jan 21 01:53:58 2022 -0500 +++ b/Makefile Wed Jan 26 20:25:08 2022 -0500 @@ -1,13 +1,16 @@ -CC=clang # clang cause gcc throws compiling errors that i don't know how to fix -CC_FLAGS=-Wall -static -O2 -LD_FLAGS=-ffunction-sections +CC=clang +CC_FLAGS=-Wall -O2 +LD_FLAGS= -%.o : %.c +src/%.o : src/%.c $(CC) -c $(CC_FLAGS) $< -o $@ -msvpvf: msvpvf.o +msvpvf: src/main.o $(CC) -o $@ $< $(CC_FLAGS) $(LD_FLAGS) +# GUI is windows-only, please use cross-compiler! +gui: src/gui.o + $(CC) -o $@ $< $(CC_FLAGS) $(LD_FLAGS) -mwindows + clean: - rm -f *.o - rm -f msvpvf msvpvf.exe + rm -f src/*.o *.exe msvpvf gui
--- a/README.md Fri Jan 21 01:53:58 2022 -0500 +++ b/README.md Wed Jan 26 20:25:08 2022 -0500 @@ -1,2 +1,15 @@ # msvpvf-c -C port of msvpvf +C/C++ port of msvpvf + +## What is this?? +msvpvf is a tool used to "downgrade" VEGAS Pro project files, written entirely in C. + +Currently, it doesn't look that great. Making pretty apps with `windows.h` is not the easiest job in the world. If someone is willing enough to make it look prettier, be my guest. + +## Compilation +``` +git clone https://github.com/mrpapersonic/msvpvf-c +cd msvpvf-c +make +``` +NOTE: if you are using Windows, there is a GUI available. To compile it, use `make gui`.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/common.h Wed Jan 26 20:25:08 2022 -0500 @@ -0,0 +1,7 @@ +#include <unistd.h> +#include <getopt.h> + +static struct option options_long[5]; +char* strremove(char* str, const char* sub); +void set_data(unsigned char magic[], uint16_t version, FILE* target); +int copy_file(char* source_file, char* target_file);
--- a/msvpvf.c Fri Jan 21 01:53:58 2022 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -/* Movie Studio / Vegas Pro version spoofer - * by Paper -*/ - -#include <stdio.h> -#include <unistd.h> -#include <getopt.h> -#include <inttypes.h> -#include <string.h> -#include <stdlib.h> -#if __STDC_VERSION__ >= 199901L -#include <stdbool.h> -#else -typedef enum { false, true } bool; /* less than C99 */ -#endif -#ifdef _MSC_VER -#define strdup(p) _strdup(p) -#endif - -static struct option options_long[] = { - {"input", required_argument, NULL, 'i'}, - {"output", required_argument, NULL, 'o'}, - {"version", required_argument, NULL, 'v'}, - {"type", required_argument, NULL, 't'}, - {"help", 0, NULL, 'h'} -}; - -char* strremove(char* str, const char* sub) { - size_t len = strlen(sub); - if (len > 0) { - char *p = str; - while ((p = strstr(p, sub)) != NULL) { - memmove(p, p + len, strlen(p + len) + 1); - } - } - return str; -} - -void set_data(unsigned char magic[], uint16_t version, FILE* target) { - int i; - fseek(target, 0x46, SEEK_SET); - fputc(version, target); - for (i=0; i<=sizeof(*magic); ++i) { - fseek(target, 0x18+i, SEEK_SET); - fputc(magic[i], target); - } -} - -int copy_file(char* source_file, char* target_file) { - FILE *source, *target; - - source = fopen(source_file, "rb"); - if (source == NULL) { - return 1; - } - target = fopen(target_file, "wb"); - if (target == NULL) { - return 1; - } - - size_t n, m; - unsigned char buff[8192]; - do { - n = fread(buff, 1, sizeof(buff), source); - if (n) m = fwrite(buff, 1, n, target); - else m = 0; - } while ((n > 0) && (n == m)); - - fclose(target); - fclose(source); - return 0; -} - -int main(int argc, char *argv[]) { - int c, option_index = 0; - unsigned char magic[16]; - FILE* outfile; - struct arguments { - char input[128]; - char output[128]; - int version; - char type[128]; - } args; - strcpy(args.input, " "); - strcpy(args.output, " "); - args.version = -1; - strcpy(args.type, " "); - - while ((c = getopt_long(argc, argv, "i:o:v:t:h", options_long, &option_index)) != -1) - switch(c) { - case 'i': - strncpy(args.input, optarg, sizeof(args.input)-1); /* subtract 1 to make sure it's "null-safe" */ - break; - case 'o': - strncpy(args.output, optarg, sizeof(args.input)-1); - break; - case 'v': - args.version = abs(atoi(strdup(optarg))); /* abs() for possible negative inputs */ - break; - case 't': - strncpy(args.type, optarg, sizeof(args.input)-1); - break; - case 'h': - default: - printf("msvpvf by Paper\nusage: %s (-i/--input) infile [(-o/--output) outfile] (-v/--version) version (-t/--type) [vf, veg]", argv[0]); - return 0; - } - if (strcmp(args.input, " ") == 0) { - printf("Input file name?\n"); - fflush(stdout); - fgets(args.input, sizeof(args.input)-1, stdin); - args.input[strcspn(args.input, "\r\n")] = 0; - } - if (access(args.input, F_OK) != 0) { - fprintf(stderr, "Input file \"%s\" doesn't exist! Exiting.", args.input); - return 1; - } - if (fgetc(fopen(args.input, "r")) == EOF) { - fprintf(stderr, "Input file \"%s\" is empty.", args.input); - return 1; - } - FILE* input_file = fopen(args.input, "r"); - fseek(input_file, 0x46, SEEK_SET); - printf("Input file version: %d\n", fgetc(input_file)); - fseek(input_file, 0x18, SEEK_SET); - int file_version = fgetc(input_file); - printf("Input file type: "); - if (file_version == 0xEF) { - printf("VEGAS Pro\n\n"); - } else if (file_version == 0xF6) { - printf("Movie Studio\n\n"); - } else { - printf("Unknown\n\n"); - } - int* ptr = &args.version; - if (args.version == -1) { - printf("What version of VEGAS would you like to spoof to?: "); - fflush(stdout); - scanf("%d", ptr); - } - if (strcmp(args.type, " ") == 0) { - printf("Would you like it to be VEGAS Pro or Movie Studio? [veg/vf]: "); - fflush(stdout); - scanf("%3s", args.type); - } - fflush(stdout); - if (strcmp(args.output, " ") == 0) { /* string manipulation hell */ - char temp[128] = {'V'}; - char str_version[16] = {}; - sprintf(str_version, "%d", args.version); - strncat(temp, str_version, 2); - strncat(temp, "_", 1); - strncat(temp, args.input, 120); - strcpy(temp, strremove(temp, strrchr(args.input, ('.')))); /* remove file extension */ - strncat(temp, ".", 1); - strncat(temp, args.type, 3); - strncpy(args.output, temp, 127); - } - if (strcmp(args.type, "veg") == 0) { - unsigned char T[] = {0xEF, 0x29, 0xC4, 0x46, 0x4A, 0x90, 0xD2, 0x11, 0x87, 0x22, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A}; - for (option_index = 0; option_index <= 15; option_index++) { - magic[option_index] = T[option_index]; - } - } else if (strcmp(args.type, "vf") == 0) { - unsigned char T[] = {0xF6, 0x1B, 0x3C, 0x53, 0x35, 0xD6, 0xF3, 0x43, 0x8A, 0x90, 0x64, 0xB8, 0x87, 0x23, 0x1F, 0x7F}; - for (option_index = 0; option_index <= 15; option_index++) { - magic[option_index] = T[option_index]; - } - } else { - fprintf(stderr, "Type %s is invalid!", args.type); - return 1; - } - copy_file(args.input, args.output); -#ifdef _WIN32 - if (strcspn(args.input, "<>:\"/\\|?*") == strlen(args.input)+1) { -#elif defined(__unix__) - if (strcspn(args.input, "/") == strlen(args.input)+1) { -#else - if (NULL) { -#endif - fprintf(stderr, "Invalid output filename detected! Exiting..."); - return 1; - } - outfile = fopen(args.output, "r+b"); - if (outfile == NULL) { - fprintf(stderr, "Failed to open file %s! Is the filename invalid?", args.output); - return 1; - } - set_data(magic, args.version, outfile); - fclose(outfile); - return 0; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gui.c Wed Jan 26 20:25:08 2022 -0500 @@ -0,0 +1,212 @@ +#include <stdio.h> +#include <windows.h> +#include <stdint.h> +#include <stdbool.h> +#include <commdlg.h> +#include "../include/common.h" +#define OPEN_FILE_BUTTON 0 +#define COMBOBOX 1 +#define LISTBOX 2 +#define SAVE_FILE_BUTTON 3 + +HWND hWndListBox, hWndComboBox; +int16_t version = 11, type = 1; /* type: 0 is vf, 1 is veg */ +char* file_name = " "; /* initialize as a space, a filename cannot literally just be a space */ + +void set_data(unsigned char magic[], uint16_t version, FILE* target) { + int i; + fseek(target, 0x46, SEEK_SET); + fputc(version, target); + for (i=0; i<=sizeof(*magic); ++i) { + fseek(target, 0x18+i, SEEK_SET); + fputc(magic[i], target); + } +} + +int copy_file(char* source_file, char* target_file) { + FILE *source, *target; + + source = fopen(source_file, "rb"); + if (source == NULL) return 1; + target = fopen(target_file, "wb"); + if (target == NULL) { + fclose(source); + return 1; + } + + size_t n, m; + unsigned char buff[8192]; + do { + n = fread(buff, 1, sizeof(buff), source); + if (n) m = fwrite(buff, 1, n, target); + else m = 0; + } while ((n > 0) && (n == m)); + + fclose(target); + fclose(source); + return 0; +} + +void display_file(char* path) { + /* Read the file to memory */ + FILE* file; + file = fopen(path, "rb"); + fseek(file, 0, SEEK_END); + int _size = ftell(file); + rewind(file); + char* data = calloc(_size+1, sizeof(char*)); + fread(data, _size, 1, file); + data[_size] = '\0'; + + free(data); + fclose(file); +} + +char* open_file(HWND hWnd) { + OPENFILENAME ofn; + char filename[127]; + + ZeroMemory(&ofn, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hWnd; + ofn.lpstrFile = filename; + ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = 127; + ofn.lpstrFilter = "Project files\0*.veg;*.vf\0All files\0*.*\0"; + ofn.nFilterIndex = 1; + + GetOpenFileName(&ofn); + + display_file(filename); + + return _strdup(filename); +} + +void save_file(HWND hWnd, char* input_file) { + if (strcmp(input_file, " ") == 0) { + MessageBoxW(hWnd, L"Please open a file first!", L"Invalid input file!", MB_ICONEXCLAMATION); + return; + } + OPENFILENAME ofn; + char output_file[127]; + + ZeroMemory(&ofn, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hWnd; + ofn.lpstrFile = output_file; + ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = 127; + ofn.lpstrFilter = "Project files\0*.veg\0All files\0*.*\0"; + ofn.nFilterIndex = 1; + + GetSaveFileName(&ofn); + + copy_file(input_file, output_file); + FILE* output = fopen(output_file, "r+b"); + if (output == NULL) { + MessageBoxW(hWnd, L"Failed to save project file!", L"Saving project failed!", MB_ICONEXCLAMATION); + return; + } + + if (type == 1) { + unsigned char magic[] = {0xEF, 0x29, 0xC4, 0x46, 0x4A, 0x90, 0xD2, 0x11, 0x87, 0x22, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A}; + set_data(magic, version, output); + } else { + unsigned char magic[] = {0xF6, 0x1B, 0x3C, 0x53, 0x35, 0xD6, 0xF3, 0x43, 0x8A, 0x90, 0x64, 0xB8, 0x87, 0x23, 0x1F, 0x7F}; + set_data(magic, version, output); + } + + fclose(output); +} + +void AddControls(HWND hWnd) { + /* versions */ + hWndComboBox = CreateWindowW(L"ComboBox", NULL, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_VSCROLL, (int)((225 - 50)/2), 30, 50, 200, hWnd, (HMENU)COMBOBOX, NULL, NULL); + TCHAR versions[][10] = {TEXT("8"), TEXT("9"), TEXT("10"), TEXT("11"), TEXT("12"), TEXT("13"), TEXT("14"), TEXT("15"), TEXT("16"), TEXT("17"), TEXT("18"), TEXT("19")}; + + TCHAR A[16]; + + memset(&A,0,sizeof(A)); + int i = 0; + for (i = 0; i <= 11; i++) { + wcscpy_s((WCHAR*)A, sizeof(A)/sizeof(TCHAR), (WCHAR*)versions[i]); + SendMessage(hWndComboBox, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A); + } + SendMessage(hWndComboBox, CB_SETCURSEL, (WPARAM)3, (LPARAM)0); + /* open file */ + HWND open_button = CreateWindowW(L"Button", L"Open", WS_VISIBLE | WS_CHILD, (int)((225 - 50)/2), 5, 50, 20, hWnd, (HMENU)OPEN_FILE_BUTTON, NULL, NULL); + /* type */ + TCHAR listbox_items[][13] = {TEXT("VEGAS Pro"), TEXT("Movie Studio")}; + hWndListBox = CreateWindowW(L"Listbox", NULL, WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY, (int)((225 - 100)/2), 55, 100, 40, hWnd, (HMENU)LISTBOX, NULL, NULL); + for (i = 0; i < ARRAYSIZE(listbox_items); i++) { + int pos = (int)SendMessage(hWndListBox, LB_ADDSTRING, i, (LPARAM) listbox_items[i]); + SendMessage(hWndListBox, LB_SETITEMDATA, pos, (LPARAM) i); + } + SendMessage(hWndListBox, LB_SETCURSEL, (WPARAM)0, (LPARAM)0); + /* save file */ + HWND save_button = CreateWindowW(L"Button", L"Save", WS_VISIBLE | WS_CHILD, (int)((225 - 50)/2), 90, 50, 20, hWnd, (HMENU)SAVE_FILE_BUTTON, NULL, NULL); + if (open_button == NULL || save_button == NULL || hWndListBox == NULL || hWndComboBox == NULL) + MessageBoxW(hWnd, L"how did you even trigger this", L"GUI could not be initialized!", MB_ICONEXCLAMATION); +} + +bool CALLBACK SetFont(HWND child, LPARAM font) { + SendMessage(child, WM_SETFONT, font, true); + return true; +} + +LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { + switch(msg) { + case WM_COMMAND: + if(HIWORD(wParam) == CBN_SELCHANGE) { + if (LOWORD(wParam) == COMBOBOX) + version = (int16_t)(8+SendMessage((HWND) lParam, (UINT) CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0)); + if (LOWORD(wParam) == LISTBOX) + type = SendMessage((HWND) lParam, (UINT) LB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); + } + switch(wParam) { + case OPEN_FILE_BUTTON: + file_name = open_file(hWnd); + break; + case COMBOBOX: + break; /* NOTE: remove these 4 lines if we don't end up doing anything with them */ + case LISTBOX: + break; + case SAVE_FILE_BUTTON: + save_file(hWnd, file_name); + break; + } + break; + case WM_CREATE: { + AddControls(hWnd); + EnumChildWindows(hWnd, (WNDENUMPROC)SetFont, (LPARAM)GetStockObject(DEFAULT_GUI_FONT)); + break; + } + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProcW(hWnd, msg, wParam, lParam); + } + return false; +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR args, int ncmdshow) { + WNDCLASSW wc = {0}; + + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hInstance = hInstance; + wc.lpszClassName = L"msvpvf"; + wc.lpfnWndProc = WindowProcedure; + + if (!RegisterClassW(&wc)) return -1; + + CreateWindowW(L"msvpvf", L"Movie Studio / Vegas Pro version spoofer", WS_OVERLAPPED | WS_VISIBLE | WS_MINIMIZEBOX | WS_SYSMENU, 100, 100, 225, 200, NULL, NULL, hInstance, NULL); + + MSG msg = {0}; + + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.c Wed Jan 26 20:25:08 2022 -0500 @@ -0,0 +1,194 @@ +/* Movie Studio / Vegas Pro version spoofer + * by Paper +*/ + +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "../include/common.h" +#ifdef _MSC_VER +#define strdup(p) _strdup(p) +#endif + +static struct option options_long[] = { + {"input", required_argument, NULL, 'i'}, + {"output", required_argument, NULL, 'o'}, + {"version", required_argument, NULL, 'v'}, + {"type", required_argument, NULL, 't'}, + {"help", 0, NULL, 'h'} +}; + +char* strremove(char* str, const char* sub) { + size_t len = strlen(sub); + if (len > 0) { + char *p = str; + while ((p = strstr(p, sub)) != NULL) { + memmove(p, p + len, strlen(p + len) + 1); + } + } + return str; +} + +void set_data(unsigned char magic[], uint16_t version, FILE* target) { + int i; + fseek(target, 0x46, SEEK_SET); + fputc(version, target); + for (i=0; i<=sizeof(*magic); ++i) { + fseek(target, 0x18+i, SEEK_SET); + fputc(magic[i], target); + } +} + +int copy_file(char* source_file, char* target_file) { + FILE *source, *target; + + source = fopen(source_file, "rb"); + + if (source == NULL) return 1; + + target = fopen(target_file, "wb"); + + if (target == NULL) { + fclose(source); + return 1; + } + + size_t n, m; + unsigned char buff[8192]; + do { + n = fread(buff, 1, sizeof(buff), source); + if (n) m = fwrite(buff, 1, n, target); + else m = 0; + } while ((n > 0) && (n == m)); + + fclose(target); + fclose(source); + return 0; +} + +int main(int argc, char *argv[]) { + int c, option_index = 0; + unsigned char magic[16]; + FILE* outfile; + struct arguments { + char input[128]; + char output[128]; + int version; + char type[128]; + } args; + strcpy(args.input, " "); + strcpy(args.output, " "); + args.version = -1; + strcpy(args.type, " "); + + while ((c = getopt_long(argc, argv, "i:o:v:t:h", options_long, &option_index)) != -1) + switch(c) { + case 'i': + strncpy(args.input, optarg, sizeof(args.input)-1); /* subtract 1 to make sure it's "null-safe" */ + break; + case 'o': + strncpy(args.output, optarg, sizeof(args.input)-1); + break; + case 'v': + args.version = abs(atoi(strcpy(optarg))); /* abs() for possible negative inputs */ + break; + case 't': + strncpy(args.type, optarg, sizeof(args.input)-1); + break; + case 'h': + default: + printf("msvpvf by Paper\nusage: %s (-i/--input) infile [(-o/--output) outfile] (-v/--version) version (-t/--type) [vf, veg]\n", argv[0]); + return 0; + } + if (argc == 1) { + printf("msvpvf by Paper\nusage: %s (-i/--input) infile [(-o/--output) outfile] (-v/--version) version (-t/--type) [vf, veg]\n", argv[0]); + return 0; + } + if (strcmp(args.input, " ") == 0) { + printf("Input file name?\n"); + fflush(stdout); + fgets(args.input, sizeof(args.input)-1, stdin); + args.input[strcspn(args.input, "\r\n")] = 0; + } + if (access(args.input, F_OK) != 0) { + fprintf(stderr, "Input file \"%s\" doesn't exist! Exiting.", args.input); + return 1; + } + FILE* input_file = fopen(args.input, "r"); + if (fgetc() == EOF) { + fprintf(stderr, "Input file \"%s\" is empty.", args.input); + fclose(input_file); + return 1; + } + fseek(input_file, 0x46, SEEK_SET); + printf("Input file version: %d\n", fgetc(input_file)); + fseek(input_file, 0x18, SEEK_SET); + int file_version = fgetc(input_file); + printf("Input file type: "); + if (file_version == 0xEF) { + printf("VEGAS Pro\n\n"); + } else if (file_version == 0xF6) { + printf("Movie Studio\n\n"); + } else { + printf("Unknown\n\n"); + } + int* ptr = &args.version; + if (args.version == -1) { + printf("What version of VEGAS would you like to spoof to?: "); + fflush(stdout); + scanf("%d", ptr); + } + if (strcmp(args.type, " ") == 0) { + printf("Would you like it to be VEGAS Pro or Movie Studio? [veg/vf]: "); + fflush(stdout); + scanf("%3s", args.type); + } + fflush(stdout); + if (strcmp(args.output, " ") == 0) { /* string manipulation hell */ + char temp[128] = {'V'}; + char str_version[16] = {}; + sprintf(str_version, "%d", args.version); + strncat(temp, str_version, 2); + strncat(temp, "_", 1); + strncat(temp, args.input, 120); + strcpy(temp, strremove(temp, strrchr(args.input, ('.')))); /* remove file extension */ + strncat(temp, ".", 1); + strncat(temp, args.type, 3); + strncpy(args.output, temp, 127); + } + if (strcmp(args.type, "veg") == 0) { + const unsigned char T[] = {0xEF, 0x29, 0xC4, 0x46, 0x4A, 0x90, 0xD2, 0x11, 0x87, 0x22, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A}; + for (option_index = 0; option_index <= 15; option_index++) { + magic[option_index] = T[option_index]; + } + } else if (strcmp(args.type, "vf") == 0) { + const unsigned char T[] = {0xF6, 0x1B, 0x3C, 0x53, 0x35, 0xD6, 0xF3, 0x43, 0x8A, 0x90, 0x64, 0xB8, 0x87, 0x23, 0x1F, 0x7F}; + for (option_index = 0; option_index <= 15; option_index++) { + magic[option_index] = T[option_index]; + } + } else { + fprintf(stderr, "Type %s is invalid!", args.type); + return 1; + } + copy_file(args.input, args.output); +#ifdef _WIN32 + if (strcspn(args.input, "<>:\"/\\|?*") == strlen(args.input)+1) { +#elif defined(__unix__) + if (strcspn(args.input, "/") == strlen(args.input)+1) { +#else + if (NULL) { +#endif + fprintf(stderr, "Invalid output filename detected! Exiting..."); + return 1; + } + outfile = fopen(args.output, "r+b"); + if (outfile == NULL) { + fprintf(stderr, "Failed to open file %s! Do you have write permissions?", args.output); + return 1; + } + set_data(magic, args.version, outfile); + fclose(outfile); + return 0; +}