Ejemplo n.º 1
0
int extract_iso(uniso_status_t *s, struct archive *iso, const char *dst,
        distro_filter_f filter, uniso_progress_t total, uniso_progress_cb cb,
        void *cb_data) {
    struct archive_entry *e;
    uniso_progress_t current = 0;

    make_dir_parents(dst);

    if(cb)
        cb(current, total, cb_data);

    while(archive_read_next_header(iso, &e) == ARCHIVE_OK) {
        char *name = unix_path(strdup2(archive_entry_pathname(e)));
        if(archive_entry_filetype(e) == AE_IFDIR
                || !filter(name)) {
            free(name);
            continue;
        }
        s->files = new_string_node_t(name, s->files);
        char *dest = unix_path(create_dest(dst, "/", name));
        if(!extract_file(s, iso, dest)) {
            free(dest);
            return 0;
        }
        ++current;
        if(cb)
            cb(current, total, cb_data);
        free(dest);
    }

    return 1;
}
Ejemplo n.º 2
0
int install_grub2(lickdir_t *lick) {
    char *grub_cfg_lick = unix_path(concat_strs(2, lick->drive, "/lickgrub.cfg"));
    if(!path_exists(grub_cfg_lick)) {
        char *grub_cfg_header = unix_path(concat_strs(2, lick->res, "/lickgrub.cfg"));
        if(!copy_file(grub_cfg_lick, grub_cfg_header)) {
            free(grub_cfg_lick);
            free(grub_cfg_header);
            if(!lick->err)
                lick->err = strdup2("Error writing to grub menu.");
            return 0;
        }
        free(grub_cfg_header);
    }
    free(grub_cfg_lick);
    return 1;
}
Ejemplo n.º 3
0
char *open_file_dialog(void)
{
	OPENFILENAME ofn;
	static char szFile[MAX_PATH];
	static char szOldDir[MAX_PATH];
	static int old_dir_set = 0;
	ZeroMemory( &ofn , sizeof( ofn));
	ofn.lStructSize = sizeof ( ofn );
	ofn.hwndOwner = NULL ;
	ofn.lpstrFile = szFile ;
	ofn.lpstrFile[0] = '\0';
	ofn.nMaxFile = sizeof( szFile );
	ofn.lpstrFilter = "*.*\0*.*\0main.lua;*.zip;*.idf\0main.lua;*.zip;*.idf\0\0";
	ofn.nFilterIndex = 2;
	ofn.lpstrFileTitle = NULL;
	ofn.nMaxFileTitle = 0;
	if (!old_dir_set)
		ofn.lpstrInitialDir = NULL;
	else
		ofn.lpstrInitialDir = szOldDir;
	ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_READONLY;
	if (!GetOpenFileName(&ofn))
		return NULL;
	old_dir_set = 1;
	strcpy(szOldDir, ofn.lpstrFile);
	dirname(szOldDir);
	unix_path(ofn.lpstrFile);
	return ofn.lpstrFile;
}
Ejemplo n.º 4
0
int uninstall_grub2(lickdir_t *lick) {
    char drive = mount_uefi_partition();
    if(drive == '\0') {
        if(!lick->err)
            lick->err = strdup2("Could not mount EFI partition.");
        return 0;
    }

    if(!fix_grub2_inner(lick, GRUB2_FIX_UNINSTALL, drive)) {
        unmount_uefi_partition(drive);
        if(!lick->err)
            lick->err = strdup2("Could not revert boot fix.");
        return 0;
    }

    char *grub_cfg = unix_path(concat_strs(2, lick->drive, "/lickgrub.cfg"));
    if(!has_valuable_info(grub_cfg)) {
        unlink_file(grub_cfg);
    }
    free(grub_cfg);

    char *lick_cert = strdup2("?:/lick.cer");
    lick_cert[0] = drive;
    unlink_file(lick_cert);
    free(lick_cert);

    char lick_dir[] = "?:/EFI/LICK";
    lick_dir[0] = drive;
    unlink_recursive(lick_dir);
    unmount_uefi_partition(drive);

    return 1;
}
Ejemplo n.º 5
0
char *sdl_path(char *p)
{
	char *r = mbs2utf8(p);
	if (p)
		free(p);
	unix_path(r);
	return r;
}
Ejemplo n.º 6
0
uniso_status_t *undir(const char *src, const char *dst, distro_filter_f filter,
        uniso_progress_cb cb, void *cb_data) {
    uniso_status_t *s = new_status();

    make_dir_parents(dst);

    struct dirent **e;
    const int len = scandir2(src, &e, NULL, NULL);
    if (len == -1)
      return s;
    int failed = 0;

    if(cb)
        cb(0, len, cb_data);

    for(uniso_progress_t i = 0; i < (unsigned int)len; /* Updated in loop. */) {
        if(!failed) {
            char *path = unix_path(concat_strs(3, src, "/", e[i]->d_name));
            if(file_type(path) != FILE_TYPE_DIR && filter(e[i]->d_name)) {
                char *dst_path = unix_path(concat_strs(3, dst, "/", e[i]->d_name));
                if(copy_file(dst_path, path)) {
                    s->files = new_string_node_t(strdup(e[i]->d_name), s->files);
                    // If we are copying directly from a CD, the file will be
                    // read-only. This causes problems when we try to delete
                    // the files.
                    attrib_open(dst_path);
                } else {
                    failed = 1;
                }
                free(dst_path);
            }
            free(path);
        }
        free(e[i]);
        ++i;
        if(cb)
            cb(i, len, cb_data);
    }
    free(e);

    s->finished = 1;
    return s;
}
Ejemplo n.º 7
0
char *dirpath(const char *path)
{
	static char fp[PATH_MAX * 4];
	if (path[0] == '/')
		return (char*)path;
	snprintf(fp, sizeof(fp), "%s/%s", curdir, path);
	fp[sizeof(fp) - 1] = 0;
	unix_path(fp);
	return fp;
}
Ejemplo n.º 8
0
char *home_dir( void )
{
	static char homedir[PATH_MAX]="";
	SHGetFolderPath( NULL, 
		CSIDL_FLAG_CREATE | CSIDL_PROFILE,
		NULL,
		0, 
		(LPTSTR)homedir );
	unix_path(homedir);
	return homedir;
}
Ejemplo n.º 9
0
char *game_tmp_path(void)
{
	DWORD dwRetVal = 0;
	static TCHAR lpTempPathBuffer[MAX_PATH];
	  //  Gets the temp path env string (no guarantee it's a valid path).
	dwRetVal = GetTempPath(MAX_PATH,          // length of the buffer
		lpTempPathBuffer); // buffer for path 
	if (dwRetVal > MAX_PATH || (dwRetVal == 0)) {
		return NULL;
	}
	strcat((char*)lpTempPathBuffer, "/instead-games");
	if (mkdir((char*)lpTempPathBuffer) && errno != EEXIST)
		return NULL;
	unix_path((char*)lpTempPathBuffer);
	return (char*)lpTempPathBuffer;
}
Ejemplo n.º 10
0
char *getfilepath(const char *d, const char *n)
{
	int i = ((d)?strlen(d):0) + ((n)?strlen(n):0) + 3;
	char *p = malloc(i);
	if (p) {
		p[0] = 0;
		if (d && d[0]) { /* non empty string */
			strcpy(p, d);
			if (p[strlen(d) - 1] != '/')
				strcat(p, "/");
		}
		if (n)
			strcat(p, n);
		unix_path(p);
	}
	return p;
}
Ejemplo n.º 11
0
static int run_game(const char *path)
{
	char *p, *ep, *d;
	static char gp[PATH_MAX + 1];
	static char *cd = "./";
	if (!path)
		return -1;
	if (!path[0])
		return -1;
	if (strlen(path) >= PATH_MAX)
		return -1;
	strcpy(gp, path);
	p = gp;
	unix_path(p);
	ep = p + strlen(p) - 1;
	while (*ep == '/' && ep != p)
		*ep-- = 0;
	if (!p[0])
		return -1;
	ep = p + strlen(p) - 1;
	while (ep != p) {
		if (*ep == '/') {
			*ep ++ = 0;
			break;
		}
		ep --;
	}
	if (ep == p)
		d = cd;
	else
		d = p;

	if (!is_game(d, ep)) {
		fprintf(stderr, "%s/%s is not a game path.\n", d, ep);
		return -1;
	}
	game_sw = ep;
	games_sw = d;
	return 0;
}
Ejemplo n.º 12
0
char *app_dir( void )
{
	static char appdir[PATH_MAX]="";
#ifdef _LOCAL_APPDATA
	if (appdata_sw)
		strcpy(appdir, appdata_sw);
	else {
		strcpy(appdir, game_cwd);
		strcat(appdir, "/appdata");
	}
	if (!access(appdir, W_OK))
		return appdir;
#endif

	SHGetFolderPath( NULL, 
		CSIDL_FLAG_CREATE | CSIDL_LOCAL_APPDATA,
		NULL,
		0, 
		(LPTSTR)appdir );
	unix_path(appdir);
	strcat(appdir, "/instead");
	return appdir;
}
Ejemplo n.º 13
0
int remove_grub2(const char *id, lickdir_t *lick) {
    char *menu_path = unix_path(concat_strs(2, lick->drive, "/lickgrub.cfg"));
    int ret = flat_remove_section(menu_path, id, lick);
    free(menu_path);
    return ret;
}
Ejemplo n.º 14
0
void wince_init(char *path)
{
	unix_path(path);
	strcpy(game_cwd, getcurdir(path));
}
Ejemplo n.º 15
0
char *getrealpath(const char *path, char *resolved)
{
	const char *q;
	char *p, *fres;
	size_t len;
#if defined(unix) && !defined(S60)
	struct stat sb;
	ssize_t n;
	int idx = 0, nlnk = 0;
	char wbuf[2][PATH_MAX];
#endif
	/* POSIX sez we must test for this */
	if (path == NULL) {
		return NULL;
	}

	if (resolved == NULL) {
		fres = resolved = malloc(PATH_MAX);
		if (resolved == NULL)
			return NULL;
	} else
		fres = NULL;


	/*
	 * Build real path one by one with paying an attention to .,
	 * .. and symbolic link.
	 */

	/*
	 * `p' is where we'll put a new component with prepending
	 * a delimiter.
	 */
	p = resolved;

	if (*path == '\0') {
		*p = '\0';
		goto out;
	}

	/* If relative path, start from current working directory. */
	if (!is_absolute_path(path)) {
		/* check for resolved pointer to appease coverity */
		if (getdir(resolved, PATH_MAX) == NULL) {
			p[0] = '.';
			p[1] = '\0';
			goto out;
		}
		unix_path(resolved);
		len = strlen(resolved);
		if (len > 1)
			p += len;
	}

loop:
	/* Skip any slash. */
	while (*path == '/')
		path++;

	if (*path == '\0') {
		if (p == resolved)
			*p++ = '/';
		*p = '\0';
		return resolved;
	}

	/* Find the end of this component. */
	q = path;
	do
		q++;
	while (*q != '/' && *q != '\0');

	/* Test . or .. */
	if (path[0] == '.') {
		if (q - path == 1) {
			path = q;
			goto loop;
		}
		if (path[1] == '.' && q - path == 2) {
			/* Trim the last component. */
			if (p != resolved)
				while (*--p != '/' && p != resolved)
					continue;
			path = q;
			goto loop;
		}
	}

	/* Append this component. */
	if (p - resolved + 1 + q - path + 1 > PATH_MAX) {
		if (p == resolved)
			*p++ = '/';
		*p = '\0';
		goto out;
	}
	if (p == resolved
		&& is_absolute_path(path)
			&& path[0] != '/') { /* win? */
		memcpy(&p[0], path,
		    q - path);
		p[q - path] = '\0';
		p += q - path;
		path = q;
		goto loop;
	} else {
		p[0] = '/';
		memcpy(&p[1], path,
		    /* LINTED We know q > path. */
		    q - path);
		p[1 + q - path] = '\0';
	}
#if defined(unix) && !defined(S60)
	/*
	 * If this component is a symlink, toss it and prepend link
	 * target to unresolved path.
	 */
	if (lstat(resolved, &sb) != -1 && S_ISLNK(sb.st_mode)) {
		if (nlnk++ >= 16) {
			goto out;
		}
		n = readlink(resolved, wbuf[idx], sizeof(wbuf[0]) - 1);
		if (n < 0)
			goto out;
		if (n == 0) {
			goto out;
		}

		/* Append unresolved path to link target and switch to it. */
		if (n + (len = strlen(q)) + 1 > sizeof(wbuf[0])) {
			goto out;
		}
		memcpy(&wbuf[idx][n], q, len + 1);
		path = wbuf[idx];
		idx ^= 1;

		/* If absolute symlink, start from root. */
		if (*path == '/')
			p = resolved;
		goto loop;
	}
#endif
	/* Advance both resolved and unresolved path. */
	p += 1 + q - path;
	path = q;
	goto loop;
out:
	free(fres);
	return NULL;
}
Ejemplo n.º 16
0
int fix_grub2_inner(lickdir_t *lick, grub2_fix_function function, char original_drive) {
    char drive = original_drive;
    if(!drive) {
        drive = mount_uefi_partition();
        if(!drive) {
            lick->err = strdup2("Could not mount UEFI partition.");
            return 0;
        }
    }

    char *lick_grub = strdup2("?:/efi/lick/" GRUB2_EFI);
    char *lick_shim = strdup2("?:/efi/lick/shim.efi");
    char *lick_mokmanager = strdup2("?:/efi/lick/" MOKMANAGER_EFI);
    char *boot_grub = strdup2("?:/efi/boot/" GRUB2_EFI);
    char *boot_shim = strdup2("?:/efi/boot/shim.efi");
    char *boot_mokmanager = strdup2("?:/efi/boot/" MOKMANAGER_EFI);
    char *boot_file = strdup("?:/efi/boot/bootx64.efi");
    char *boot_file_backup = strdup2("?:/efi/boot/bootx64-orig.efi");
    char *ms_loader = strdup2("?:/efi/microsoft/boot/bootmgfw.efi");
    char *ms_loader_backup = strdup2("?:/efi/microsoft/boot/bootmgfw-backup.efi");
    char *grub_cfg = unix_path(concat_strs(2, lick->drive, "/lickgrub.cfg"));
    char *grub_menu = NULL;

    lick_grub[0] = drive;
    lick_shim[0] = drive;
    lick_mokmanager[0] = drive;
    boot_grub[0] = drive;
    boot_shim[0] = drive;
    boot_mokmanager[0] = drive;
    ms_loader[0] = drive;
    ms_loader_backup[0] = drive;
    boot_file[0] = drive;
    boot_file_backup[0] = drive;

    const char *fatal_warning =
        "WARNING! The fix has only been half applied.\n"
        "The system may not boot when rebooted.\n"
        "Find out why renaming files on the UEFI partition is not working,\n"
        "then move `/EFI/Microsoft` to `/EFI/Microsoft-backup`.";

    grub2_fix_status status = GRUB2_FIX_UNINSTALLED;

    if(path_exists(boot_grub) || path_exists(boot_mokmanager)
            || path_exists(ms_loader_backup)
            || path_exists(boot_file_backup)) {
        if(path_exists(boot_grub) && path_exists(boot_mokmanager)
                && path_exists(ms_loader_backup)
                && path_exists(boot_file_backup))
            status = GRUB2_FIX_INSTALLED;
        else
            status = GRUB2_FIX_PARTLY_INSTALLED;
    }

    int ret = 0;

    if(function == GRUB2_FIX_CHECK) {
        if(status == GRUB2_FIX_INSTALLED)
            ret = 1;
    } else if(status == GRUB2_FIX_PARTLY_INSTALLED)
        lick->err = strdup2("Partial boot fix applied.");
    else if(function == GRUB2_FIX_INSTALL && status == GRUB2_FIX_INSTALLED)
        lick->err = strdup2("Boot fix already applied!");
    else if(function == GRUB2_FIX_UNINSTALL && status == GRUB2_FIX_UNINSTALLED)
        ret = 1;
    else if(function == GRUB2_FIX_INSTALL) {
        /* Steps:
         * 1) Copy `/EFI/LICK/{grubx64,shim,MokManager}.efi` to `/EFI/Boot/`
         * 2) Rename `/EFI/Boot/bootx64.efi` to `bootx64-orig.efi`
         * 3) Rename `/EFI/Boot/shim.efi` to `bootx64.efi`
         * 4) Rename `/EFI/Microsoft/Boot/bootmgfw.efi` to `bootmgfw-backup.efi`
         */
        do {
            int fail = 1;
            do {
                if(!copy_file(boot_grub, lick_grub))
                    break;
                if(!copy_file(boot_shim, lick_shim))
                    break;
                if(!copy_file(boot_mokmanager, lick_mokmanager))
                    break;
                if(!copy_file(boot_file_backup, boot_file))
                    break;

                attrib_t boot_attrs = attrib_open(boot_file);
                if(!replace_file(boot_file, boot_shim)) {
                    attrib_save(boot_file, boot_attrs);
                    lick->err = strdup2("Could not overwrite boot file.");
                    break;
                }
                if(!rename_file(ms_loader_backup, ms_loader)) {
                    // Try to restore the backup.
                    if(!replace_file(boot_file, boot_file_backup)) {
                        // At this point we are stuck with the fix being
                        // half applied. Realistically, this should never occur.
                        attrib_save(boot_file, boot_attrs);
                        lick->err = strdup2(fatal_warning);
                        fail = 0;
                        break;
                    }
                    lick->err = strdup2("Could not rename directory.");
                    break;
                }

                attrib_save(boot_file_backup, boot_attrs);
                fail = 0;
            } while(0);

            if(fail) {
                unlink_file(boot_grub);
                unlink_file(boot_shim);
                unlink_file(boot_mokmanager);
                unlink_file(boot_file_backup);
                if(!lick->err)
                    lick->err = strdup2("Could not copy files on EFI partition.");
                break;
            }

            // Edit grub menu.
            FILE *f = fopen(grub_cfg, "r");
            if(!f) {
                if(!lick->err)
                    lick->err = strdup2("Successfully installed, but could not modify configuration file.");
                break;
            }
            grub_menu = file_to_str(f);
            fclose(f);
            char *grub_menu_lower = lower_str(strdup2(grub_menu));

            // Search for `/efi/microsoft` (case insensitive)
            // and replace with `/efi/microsoft-backup`
            // First, find the number of `/efi/microsoft`
            size_t cnt = 0;
            const char *str = grub_menu_lower;
            const char *needle = "/efi/microsoft/boot/bootmgfw.efi";
            const char *replacement = "/efi/microsoft/boot/bootmgfw-backup.efi";
            for(;;) {
                str = strstr(str, needle);
                if(!str)
                    break;
                ++cnt;
                ++str; // Increment string to find the next occurrance.
            }

            if(cnt > 0) {
                /* Here, there are 3 strings:
                 * - The original menu, grub_menu.
                 *   This is pointed to by start and str_normal.
                 * - The lowercase menu, grub_menu_lower.
                 *   This is pointed to by str.
                 * - The new menu, new_grub_menu.
                 *   This is pointed to by dst.
                 */
                size_t newsize = strlen(grub_menu)
                    + cnt * (strlen(replacement) - strlen(needle))
                    + 1;
                char *new_grub_menu = malloc(newsize);
                char *dst = new_grub_menu;

                const char *start = grub_menu;
                str = grub_menu_lower;
                for(size_t i = 0; i < cnt; ++i) {
                    str = strstr(str, needle);
                    const char *str_normal = str - grub_menu_lower + grub_menu;
                    // Print everything from start to str.
                    size_t len = str_normal - start;
                    memcpy(dst, start, len);
                    dst += len;
                    strcpy(dst, replacement);
                    str += strlen(needle);
                    dst += strlen(replacement);

                    start = str_normal + strlen(needle);
                }
                strcpy(dst, start);
                grub_menu[newsize - 1] = '\0';

                f = fopen(grub_cfg, "w");
                if(!f) {
                    if(!lick->err)
                        lick->err = strdup2("Successfully installed, but could not modify configuration file.");
                    free(new_grub_menu);
                    free(grub_menu_lower);
                    break;
                }
                fprintf(f, "%s", new_grub_menu);
                fclose(f);
                free(new_grub_menu);
                free(grub_menu_lower);
            }
            ret = 1;
        } while(0);
    } else {
        /* Steps:
         * 1) Rename `/EFI/Microsoft/Boot/bootmgfw-backup.efi` to `bootmgfw.efi`
         * 2) Rename `/EFI/Boot/bootx64-orig.efi` to `bootx64.efi`
         * 3) Delete `/EFI/Boot/{grubx64,MokManager}.efi`
         */
        do {
            if(!rename_file(ms_loader, ms_loader_backup)) {
                lick->err = strdup2("Could not rename directory.");
                break;
            }
            attrib_t boot_attrs = attrib_open(boot_file_backup);
            if(!replace_file(boot_file, boot_file_backup)) {
                attrib_save(boot_file_backup, boot_attrs);
                if(!rename_file(ms_loader_backup, ms_loader)) {
                    lick->err = strdup2(fatal_warning);
                    break;
                }
                lick->err = strdup2("Could not replace boot file.");
                break;
            }
            attrib_save(boot_file, boot_attrs);

            unlink_file(boot_grub);
            unlink_file(boot_mokmanager);
            ret = 1;
        } while(0);
    }

    if(!original_drive)
        unmount_uefi_partition(drive);
    free(lick_grub);
    free(lick_shim);
    free(lick_mokmanager);
    free(boot_grub);
    free(boot_shim);
    free(boot_mokmanager);
    free(ms_loader);
    free(ms_loader_backup);
    free(boot_file);
    free(boot_file_backup);
    free(grub_cfg);
    free(grub_menu);
    return ret;
}
Ejemplo n.º 17
0
Archivo: nt.c Proyecto: noryb009/lick
char *boot_ini_path_with_drive(const char *boot_drive) {
    return unix_path(concat_strs(3, boot_drive, "/", BOOT_FILE));
}
Ejemplo n.º 18
0
int main(int argc, char *argv[])
{
#ifdef _USE_UNPACK
	int clean_tmp = 0;
#endif
	int err = 0;
	int i;
#ifdef __APPLE__
	macosx_init();
#endif
#ifndef S60
	putenv("SDL_MOUSE_RELATIVE=0"); /* test this! */
#endif

#ifdef _WIN32_WCE
	libwince_init(argv[0], 1);
	wince_init(argv[0]);
#else
#ifdef S60
	extern char s60_data[];
	strcpy(game_cwd, s60_data);
#else
#ifdef _WIN32
	strcpy(game_cwd, dirname(argv[0]));
#else
	if (!getcwd(game_cwd, sizeof(game_cwd)))
		fprintf(stderr,"Warning: can not get current dir\n.");
#endif
#endif
#endif
	unix_path(game_cwd);
	setdir(game_cwd);

	for (i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "-vsync"))
			vsync_sw = 1;
		else if (!strcmp(argv[i], "-nosound"))
			nosound_sw = 1;
		else if (!strcmp(argv[i], "-fullscreen"))
			fullscreen_sw = 1;
		else if (!strcmp(argv[i], "-mode")) {	
			if ((i + 1) < argc)
				mode_sw = argv[++i];
			else
				mode_sw = "-1x-1";
		} else if (!strcmp(argv[i], "-window"))
			window_sw = 1;
		else if (!strcmp(argv[i], "-debug")) {
			if (!debug_sw)
				debug_init();
			debug_sw = 1;
		} else if (!strcmp(argv[i], "-owntheme"))
			owntheme_sw = 1;
		else if (!strcmp(argv[i], "-noautosave"))
			noauto_sw = 1;
		else if (!strcmp(argv[i], "-game")) {
			if ((i + 1) < argc)
				game_sw = argv[++i];
			else
				game_sw = "";
		} else if (!strcmp(argv[i], "-theme")) {
			if ((i + 1) < argc)
				theme_sw = argv[++i];
			else
				theme_sw = "";
		} else if (!strcmp(argv[i], "-nostdgames")) {
			nostdgames_sw = 1;
#ifdef _LOCAL_APPDATA
		} else if (!strcmp(argv[i], "-appdata")) {
			if ((i + 1) < argc)
				appdata_sw = argv[++i];
			else
				appdata_sw = "";
#endif
		} else if (!strcmp(argv[i], "-chunksize")) {
			if ((i + 1) < argc)
				chunksize_sw = atoi(argv[++i]);
			else
				chunksize_sw = DEFAULT_CHUNKSIZE;
		} else if (!strcmp(argv[i], "-gamespath")) {
			if ((i + 1) < argc)
				games_sw = argv[++i];
			else
				games_sw = "";
		} else if (!strcmp(argv[i], "-themespath")) {
			if ((i + 1) < argc)
				themes_sw = argv[++i];
			else
				themes_sw = "";
		} else if (!strcmp(argv[i], "-idf")) {	
			if ((i + 1) < argc)
				idf_sw = argv[++i];
			else {
				fprintf(stderr,"No data directory specified.\n");
				err = 1;
				goto out;
			}
		} else if (!strcmp(argv[i], "-encode")) {	
			if ((i + 1) < argc)
				encode_sw = argv[++i];
			else {
				fprintf(stderr,"No lua file specified.\n");
				err = 1;
				goto out;
			}
			if ((i + 1) < argc)
				encode_output = argv[++i];
			else
				encode_output = "lua.enc";
		} else if (!strcmp(argv[i], "-version")) {
			version_sw = 1;
		} else if (!strcmp(argv[i], "-nopause")) {
			nopause_sw = 1;
		} else if (!strcmp(argv[i], "-software")) {
			software_sw = 1;
#ifdef _USE_UNPACK
		} else if (!strcmp(argv[i], "-install")) {
			if ((i + 1) < argc) {
				char *file = argv[++i];
				char *p;
				if (games_sw)
					p = games_sw;
				else
					p = game_local_games_path(1);
				if (setup_zip(file, p)) {
					err = 1;
					goto out;
				}
			}
#endif
		} else if (!strcmp(argv[i], "-quit")) {
			exit(0);
		} else if (!strcmp(argv[i], "-hinting")) {
			if ((i + 1) < argc)
				hinting_sw = atoi(argv[++i]);
			else
				hinting_sw = 1;
		} else if (!strcmp(argv[i], "-lua") || !strcmp(argv[i], "-luac")) {
			if ((i + 1) < argc) {
				lua_exec = !strcmp(argv[i], "-lua");
				lua_sw = argv[++ i];
				opt_index = i + 1;
				break;
			} else {
				fprintf(stderr, "No lua script.\n");
				err = 1;
				goto out;
			}
		} else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help")
			|| !strcmp(argv[i], "--help")) {
			usage();
			goto out;
		} else if (argv[i][0] == '-') {
			fprintf(stderr,"Unknown option: %s\n", argv[i]);
			usage();
			err = 1;
			goto out;
		} else if (!start_idf(argv[i])) {
			fprintf(stderr, "Adding idf: %s\n", argv[i]);
		} else if (!run_game(argv[i])) {
			fprintf(stderr, "Opening game: %s\n", argv[i]);
		}
#ifdef _USE_UNPACK
		else {
			char *p;
			if (games_sw)
				p = games_sw;
			else
				p = game_tmp_path();
			if (setup_zip(argv[i], p)) {
				err = 1;
				goto out;
			}
			clean_tmp = 1;
		}
#endif
	}
	cfg_load();

	if (opt_debug == 1 && debug_sw == 0) {
		debug_sw = 1;
		debug_init();
	}

	if (opt_vsync == 1 && vsync_sw == 0)
		vsync_sw = 1;

	if (version_sw) {
		fprintf(stdout, VERSION"\n");
		goto out;
	}

	if (lua_sw) {
		err = instead_init_lua(dirname(lua_sw));
		if (err)
			goto out;
		if (!err)
			err = instead_loadscript(lua_sw,
				argc - opt_index,
				argv + opt_index,
				lua_exec);
		instead_done();
		goto out;
	}

	if (encode_sw) {
		err = instead_encode(encode_sw, encode_output);
		goto out;
	}

	if (idf_sw) {
		char *p = malloc(strlen(idf_sw) + 5);
		if (p) {
			char *b;
			strcpy(p, idf_sw);
			b = basename(p);
			strcat(b, ".idf");
			idf_create(b, idf_sw);
			free(p);
		} else
			idf_create("data.idf", idf_sw);
		goto out;
	}
	menu_langs_lookup(dirpath(LANG_PATH));
	
	if (!langs_nr) {
		fprintf(stderr, "No languages found in: %s.\n", dirpath(LANG_PATH));
		err = 1;
		goto out;
	}
	if (!opt_lang || !opt_lang[0])
		opt_lang = game_locale();
	
	if (menu_lang_select(opt_lang) && menu_lang_select(LANG_DEF)) {
		fprintf(stderr, "Can not load default language.\n");
		err = 1;
		goto out;
	}
	
	if (games_sw)
		games_lookup(games_sw);

	if (owntheme_sw && !opt_owntheme) {
		opt_owntheme = 2;
	}

	if (!nostdgames_sw && games_lookup(dirpath(GAMES_PATH)))
		fprintf(stderr, "No games found in: %s.\n", GAMES_PATH);

	if (themes_sw)
		themes_lookup(themes_sw);

	if (!nostdthemes_sw) {
		themes_lookup(dirpath(THEMES_PATH));
		themes_lookup(game_local_themes_path());
	}
	
	if (!nostdgames_sw)
		games_lookup(game_local_games_path(0));

	if (start_idf_sw) {
		char *d, *b;
		char *dd, *bb;
		static char idf_game[255];
		d = strdup(start_idf_sw);
		b = strdup(start_idf_sw);
		if (d && b) {
			dd = dirname(d);
			bb = basename(b);
			if (!games_replace(dirpath(dd), bb)) {
				game_sw = idf_game;
				strncpy(idf_game, bb, sizeof(idf_game) - 1);
				idf_game[sizeof(idf_game) - 1] = 0;
			}
		}
		if (d)
			free(d); 
		if (b)
			free(b);
	}

	if (noauto_sw && opt_autosave)
		opt_autosave = 2;
	if (window_sw)
		opt_fs = 0;
	if (fullscreen_sw)
		opt_fs = 1;
	
	if (mode_sw)
		parse_mode(mode_sw, opt_mode);
	
	if (game_sw) {
		FREE(opt_game);
		opt_game = game_sw;
	}	

	if (theme_sw) {
		FREE(opt_theme);
		opt_theme = theme_sw;
	}	
	
	if (opt_theme)
		game_theme_select(opt_theme);
	if (!curtheme_dir)
		game_theme_select(DEFAULT_THEME);
	
	/* Initialize SDL */
	if (gfx_init() < 0)
		return -1;
#ifdef _USE_GTK
	gtk_init(&argc, &argv); /* must be called AFTER SDL_Init when using SDL2 */
#endif
	if (gfx_video_init() || input_init())
		return -1;

	if (game_init(opt_game)) {
		game_error();
	}

	game_loop();
	cfg_save();
	game_done(0);

	gfx_video_done();

#ifndef ANDROID
	gfx_done();
#endif
out:
	if (debug_sw)
		debug_done();
#ifdef _USE_GTK
/*	gtk_main_quit (); */
#endif
#ifdef _USE_UNPACK
	if (clean_tmp)
		remove_dir(game_tmp_path());
#endif
#if defined(ANDROID) || defined(IOS)
	exit(err);
#endif
	return err;
}