Пример #1
0
bool platform_original_game_data_exists(const utf8 *path)
{
	wchar_t *wPath = utf8_to_widechar(path);
	int len = min(MAX_PATH, utf8_length(path));
	char buffer[MAX_PATH];
	wcstombs(buffer, wPath, len);
	buffer[len] = '\0';
	free(wPath);
	char checkPath[MAX_PATH];
	sprintf(checkPath, "%s%c%s%c%s", buffer, platform_get_path_separator(), "Data", platform_get_path_separator(), "g1.dat");
	return platform_file_exists(checkPath);
}
Пример #2
0
/**
 * Default directory fallback is:
 *   - (command line argument)
 *   - <exePath>/data
 *   - <platform dependent>
 */
void platform_resolve_openrct_data_path()
{
	const char separator[2] = { platform_get_path_separator(), 0 };

	if (gCustomOpenrctDataPath[0] != 0) {
		if (realpath(gCustomOpenrctDataPath, _openrctDataDirectoryPath)) {
			log_error("Could not resolve path \"%s\"", gCustomUserDataPath);
			return;
		}

		// Ensure path ends with separator
		int len = strlen(_openrctDataDirectoryPath);
		if (_openrctDataDirectoryPath[len - 1] != separator[0]) {
			strncat(_openrctDataDirectoryPath, separator, MAX_PATH - 1);
		}
		return;
	}

	char buffer[MAX_PATH] = { 0 };
	platform_get_exe_path(buffer);

	strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
	strncat(buffer, "data", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
	log_verbose("Looking for OpenRCT2 data in %s", buffer);
	if (platform_directory_exists(buffer))
	{
		_openrctDataDirectoryPath[0] = '\0';
		safe_strcpy(_openrctDataDirectoryPath, buffer, MAX_PATH);
		log_verbose("Found OpenRCT2 data in %s", _openrctDataDirectoryPath);
		return;
	}

	platform_posix_sub_resolve_openrct_data_path(_openrctDataDirectoryPath);
	log_verbose("Trying to use OpenRCT2 data in %s", _openrctDataDirectoryPath);
}
Пример #3
0
void title_sequence_delete_preset(int preset)
{
	if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets) {
		// Delete the folder
		utf8 path[MAX_PATH];
		char separator = platform_get_path_separator();
		platform_get_user_directory(path, "title sequences");
		strcat(path, gConfigTitleSequences.presets[preset].name);
		if (!platform_directory_delete(path)) {
			log_error("Failed to delete directory: \"%s\"", path);
		}

		free(gConfigTitleSequences.presets[preset].saves);
		free(gConfigTitleSequences.presets[preset].commands);

		for (int i = preset; i < gConfigTitleSequences.num_presets - 1; i++) {
			gConfigTitleSequences.presets[i] = gConfigTitleSequences.presets[i + 1];
		}
		gConfigTitleSequences.num_presets--;
		gConfigTitleSequences.presets = realloc(gConfigTitleSequences.presets, sizeof(title_sequence) * (size_t)gConfigTitleSequences.num_presets);

		gCurrentTitleSequence--;
		if (gCurrentPreviewTitleSequence > preset)
			title_sequence_change_preset(gCurrentPreviewTitleSequence - 1);
		else if (gCurrentPreviewTitleSequence == preset)
			title_sequence_change_preset(0);
	}
}
Пример #4
0
int platform_enumerate_directories_begin(const utf8 *directory)
{
	enumerate_file_info *enumFileInfo;
	wchar_t *wpattern = utf8_to_widechar(directory);
	int length = min(utf8_length(directory), MAX_PATH);
	char *npattern = malloc(length+1);
	int converted;
	converted = wcstombs(npattern, wpattern, length);
	npattern[length - 1] = '\0';
	if (converted == MAX_PATH) {
		log_warning("truncated string %s", npattern);
	}
	log_verbose("begin directory listing, path: %s", npattern);

	// TODO: add some checking for stringness and directoryness

	int cnt;
	for (int i = 0; i < countof(_enumerateFileInfoList); i++) {
		enumFileInfo = &_enumerateFileInfoList[i];
		if (!enumFileInfo->active) {
			safe_strcpy(enumFileInfo->pattern, npattern, length);
			cnt = scandir(npattern, &enumFileInfo->fileListTemp, dirfilter, alphasort);
			if (cnt < 0)
			{
				break;
			}
			log_verbose("found %d files in dir '%s'", cnt, npattern);
			enumFileInfo->cnt = cnt;
			enumFileInfo->paths = malloc(cnt * sizeof(char *));
			char **paths = enumFileInfo->paths;
			// 256 is size of dirent.d_name
			const int buf_len = min(MAX_PATH, 256);
			const int dir_name_len = strnlen(npattern, MAX_PATH);
			char separator[] = {platform_get_path_separator(), 0};
			for (int idx = 0; idx < cnt; idx++)
			{
				struct dirent *d = enumFileInfo->fileListTemp[idx];
				const int entry_len = strnlen(d->d_name, MAX_PATH);
				// 1 for separator, 1 for trailing null
				size_t path_len = sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2);
				paths[idx] = malloc(path_len);
				paths[idx][0] = '\0';
				log_verbose("dir_name: %s", npattern);
				strncat(paths[idx], npattern, path_len - 2);
				strncat(paths[idx], separator, path_len - strnlen(paths[idx], path_len) - 1);
				strncat(paths[idx], d->d_name, path_len - strnlen(paths[idx], path_len) - 1);
				log_verbose("paths[%d] = %s", idx, paths[idx]);
			}
			enumFileInfo->handle = 0;
			enumFileInfo->active = 1;
			free(wpattern);
			free(npattern);
			return i;
		}
	}

	free(wpattern);
	free(npattern);
	return -1;
}
Пример #5
0
void title_sequence_rename_save(int preset, int index, const char *newName)
{
	if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets && index >= 0 && index < gConfigTitleSequences.presets[preset].num_saves &&
		filename_valid_characters(newName) && !title_sequence_save_exists(preset, newName)) {

		// Rename the save file
		char separator = platform_get_path_separator();
		utf8 src[MAX_PATH], dest[MAX_PATH];
		platform_get_user_directory(src, "title sequences");
		platform_get_user_directory(dest, "title sequences");
		strcat(src, gConfigTitleSequences.presets[preset].name);
		strcat(dest, gConfigTitleSequences.presets[preset].name);
		strncat(src, &separator, 1);
		strncat(dest, &separator, 1);
		strcat(src, gConfigTitleSequences.presets[preset].saves[index]);
		strcat(dest, newName);
		// Add the appropriate extension if needed
		char *extension = (char*)path_get_extension(newName);
		if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
			strcat(dest, ".sv6");
		platform_file_move(src, dest);

		safe_strncpy(gConfigTitleSequences.presets[preset].saves[index], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH);
		// Add the appropriate extension if needed
		if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
			strcat(gConfigTitleSequences.presets[preset].saves[index], ".sv6");
		title_sequence_save_preset_script(preset);
	}
}
Пример #6
0
void title_sequence_remove_save(int preset, int index)
{
	if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets && index >= 0 && index < gConfigTitleSequences.presets[preset].num_saves) {
		// Delete the save file
		char separator = platform_get_path_separator();
		utf8 path[MAX_PATH];
		platform_get_user_directory(path, "title sequences");
		strcat(path, gConfigTitleSequences.presets[preset].name);
		strncat(path, &separator, 1);
		strcat(path, gConfigTitleSequences.presets[preset].saves[index]);
		platform_file_delete(path);

		// Remove all references to this save in the commands and decrement save indecies
		for (int i = 0; i < gConfigTitleSequences.presets[preset].num_commands; i++) {
			if (gConfigTitleSequences.presets[preset].commands[i].command == TITLE_SCRIPT_LOAD) {
				if (gConfigTitleSequences.presets[preset].commands[i].saveIndex == index)
					gConfigTitleSequences.presets[preset].commands[i].saveIndex = 0xFF;
				else if (gConfigTitleSequences.presets[preset].commands[i].saveIndex > index && gConfigTitleSequences.presets[preset].commands[i].saveIndex != 0xFF)
					gConfigTitleSequences.presets[preset].commands[i].saveIndex--;
			}
		}

		for (int i = index; i < gConfigTitleSequences.presets[preset].num_saves - 1; i++) {
			safe_strncpy(gConfigTitleSequences.presets[preset].saves[i], gConfigTitleSequences.presets[preset].saves[i + 1], TITLE_SEQUENCE_MAX_SAVE_LENGTH);
		}
		gConfigTitleSequences.presets[preset].num_saves--;
		gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves);
		title_sequence_save_preset_script(preset);
	}
}
Пример #7
0
void title_sequence_add_save(int preset, const char *path, const char *newName)
{
	utf8 newPath[MAX_PATH];
	char *extension = (char*)path_get_extension(newName);
	safe_strncpy(newPath, newName, MAX_PATH);
	if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
		strcat(newPath, ".sv6");
	if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets && filename_valid_characters(newPath) && !title_sequence_save_exists(preset, newPath) && platform_file_exists(path)) {
		// Copy the save file
		char separator = platform_get_path_separator();
		platform_get_user_directory(newPath, "title sequences");
		strcat(newPath, gConfigTitleSequences.presets[preset].name);
		strncat(newPath, &separator, 1);
		strcat(newPath, newName);
		// Add the appropriate extension if needed
		if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
			strcat(newPath, ".sv6");
		platform_file_copy(path, newPath, false);

		gConfigTitleSequences.presets[preset].num_saves++;
		gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves);

		safe_strncpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH);
		// Add the appropriate extension if needed
		if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
			strcat(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], ".sv6");
	}
}
Пример #8
0
/**
 * Default directory fallback is:
 *   - (command line argument)
 *   - <platform dependent>
 */
void platform_resolve_user_data_path()
{
	const char separator[2] = { platform_get_path_separator(), 0 };

	if (gCustomUserDataPath[0] != 0) {
		if (realpath(gCustomUserDataPath, _userDataDirectoryPath) == NULL) {
			log_error("Could not resolve path \"%s\"", gCustomUserDataPath);
			return;
		}

		// Ensure path ends with separator
		int len = strlen(_userDataDirectoryPath);
		if (_userDataDirectoryPath[len - 1] != separator[0]) {
			strncat(_userDataDirectoryPath, separator, MAX_PATH - 1);
		}
		return;
	}

	char buffer[MAX_PATH];
	buffer[0] = '\0';
	log_verbose("buffer = '%s'", buffer);

	const char *homedir = getpwuid(getuid())->pw_dir;
	platform_posix_sub_user_data_path(buffer, homedir, separator);

	log_verbose("OpenRCT2 user data directory = '%s'", buffer);
	int len = strnlen(buffer, MAX_PATH);
	wchar_t *w_buffer = regular_to_wchar(buffer);
	w_buffer[len] = '\0';
	utf8 *path = widechar_to_utf8(w_buffer);
	free(w_buffer);
	safe_strcpy(_userDataDirectoryPath, path, MAX_PATH);
	free(path);
}
Пример #9
0
/**
 *
 *  rct2: 0x00683499
 */
int rct2_init_directories()
{
	// windows_get_registry_install_info((rct2_install_info*)0x009AA10C, "RollerCoaster Tycoon 2 Setup", "MS Sans Serif", 0);

	// check install directory
	if (!platform_original_game_data_exists(gConfigGeneral.game_path)) {
		log_verbose("install directory does not exist or invalid directory selected, %s", gConfigGeneral.game_path);
		if (!config_find_or_browse_install_directory()) {
			log_fatal("Invalid RCT2 installation path. Please correct in config.ini.");
			return 0;
	}
	}

	char separator[] = {platform_get_path_separator(), 0};

	strcpy(RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char), gConfigGeneral.game_path);

	strcpy(RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH_SLASH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH_SLASH, char), separator);

	strcpy(RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char), separator);
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char), "Saved Games");
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char), separator);

	strcpy(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), separator);
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), "Scenarios");
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), separator);
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), "*.SC6");

	strcpy(RCT2_ADDRESS(RCT2_ADDRESS_LANDSCAPES_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_LANDSCAPES_PATH, char), separator);
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_LANDSCAPES_PATH, char), "Landscapes");
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_LANDSCAPES_PATH, char), separator);
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_LANDSCAPES_PATH, char), "*.SC6");

	strcpy(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), separator);
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), "ObjData");
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), separator);
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), "*.DAT");

	strcpy(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char));
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), separator);
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), "Tracks");
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), separator);
	strcat(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), "*.TD?");

	strcpy(RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH_2, char), RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char));
	return 1;
}
Пример #10
0
/**
 * Default directory fallback is:
 *   - (command line argument)
 *   - $XDG_CONFIG_HOME/.config/OpenRCT2
 *   - /home/[uid]/.config/OpenRCT2
 */
void platform_resolve_user_data_path()
{
	const char separator[2] = { platform_get_path_separator(), 0 };

	if (gCustomUserDataPath[0] != 0) {
		realpath(gCustomUserDataPath, _userDataDirectoryPath);

		// Ensure path ends with separator
		int len = strlen(_userDataDirectoryPath);
		if (_userDataDirectoryPath[len - 1] != separator[0]) {
			strcat(_userDataDirectoryPath, separator);
		}
		return;
	}

	char buffer[MAX_PATH];
	buffer[0] = '\0';
	log_verbose("buffer = '%s'", buffer);
	const char *homedir = getenv("XDG_CONFIG_HOME");
	log_verbose("homedir = '%s'", homedir);
	if (homedir == NULL)
	{
		homedir = getpwuid(getuid())->pw_dir;
		log_verbose("homedir was null, used getuid, now is = '%s'", homedir);
		if (homedir == NULL)
		{
			log_fatal("Couldn't find user data directory");
			exit(-1);
			return;
		}

		strncat(buffer, homedir, MAX_PATH);
		strncat(buffer, separator, MAX_PATH);
		strncat(buffer, ".config", MAX_PATH);
	}
	else
	{
		strncat(buffer, homedir, MAX_PATH);
	}
	strncat(buffer, separator, MAX_PATH);
	strncat(buffer, "OpenRCT2", MAX_PATH);
	strncat(buffer, separator, MAX_PATH);
	log_verbose("OpenRCT2 user data directory = '%s'", buffer);
	int len = strnlen(buffer, MAX_PATH);
	wchar_t *w_buffer = regular_to_wchar(buffer);
	w_buffer[len] = '\0';
	utf8 *path = widechar_to_utf8(w_buffer);
	free(w_buffer);
	safe_strncpy(_userDataDirectoryPath, path, MAX_PATH);
	free(path);
}
Пример #11
0
static bool window_changelog_read_file()
{
	window_changelog_dispose_file();
	utf8 path[MAX_PATH];
	sprintf(path, "%s%cchangelog.txt", gExePath, platform_get_path_separator());
	if (!readentirefile(path, (void**)&_changelogText, (int*)&_changelogTextSize)) {
		log_error("Unable to read changelog.txt");
		return false;
	}
	_changelogText = realloc(_changelogText, _changelogTextSize + 1);
	_changelogText[_changelogTextSize++] = 0;

	char *start = _changelogText;
	if (_changelogTextSize >= 3 && utf8_is_bom(_changelogText))
		start += 3;

	int changelogLinesCapacity = 8;
	_changelogLines = malloc(changelogLinesCapacity * sizeof(char*));
	_changelogLines[0] = start;
	_changelogNumLines = 1;

	char *ch = start;
	while (*ch != 0) {
		unsigned char c = *ch;
		if (c == '\n') {
			*ch++ = 0;
			_changelogNumLines++;
			if (_changelogNumLines > changelogLinesCapacity) {
				changelogLinesCapacity *= 2;
				_changelogLines = realloc(_changelogLines, changelogLinesCapacity * sizeof(char*));
			}
			_changelogLines[_changelogNumLines - 1] = ch;
		} else if (c < 32 || c > 122) {
			// A character that won't be drawn or change state.
			*ch++ = FORMAT_OUTLINE_OFF;
		} else {
			ch++;
		}
	}

	_changelogLines = realloc(_changelogLines, _changelogNumLines * sizeof(char*));

	RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224;
	_changelogLongestLineWidth = 0;
	for (int i = 0; i < _changelogNumLines; i++) {
		int width = gfx_get_string_width(_changelogLines[i]);
		_changelogLongestLineWidth = max(width, _changelogLongestLineWidth);
	}
	return true;
}
Пример #12
0
// TODO move to platform
static void openrct2_set_exe_path()
{
#ifdef _WIN32
	wchar_t exePath[MAX_PATH];
	wchar_t tempPath[MAX_PATH];
	wchar_t *exeDelimiter;
	int exeDelimiterIndex;

	GetModuleFileNameW(NULL, exePath, MAX_PATH);
	exeDelimiter = wcsrchr(exePath, platform_get_path_separator());
	exeDelimiterIndex = (int)(exeDelimiter - exePath);
	lstrcpynW(tempPath, exePath, exeDelimiterIndex + 1);
	tempPath[exeDelimiterIndex] = L'\0';
	_wfullpath(exePath, tempPath, MAX_PATH);
	WideCharToMultiByte(CP_UTF8, 0, exePath, countof(exePath), gExePath, countof(gExePath), NULL, NULL);
#else
	char exePath[MAX_PATH];
	ssize_t bytesRead;
	bytesRead = readlink("/proc/self/exe", exePath, MAX_PATH);
	if (bytesRead == -1) {
		log_fatal("failed to read /proc/self/exe");
	}
	exePath[bytesRead] = '\0';
	log_verbose("######################################## Setting exe path to %s", exePath);
	char *exeDelimiter = strrchr(exePath, platform_get_path_separator());
	if (exeDelimiter == NULL)
	{
		log_error("should never happen here");
		gExePath[0] = '\0';
		return;
	}
	int exeDelimiterIndex = (int)(exeDelimiter - exePath);

	safe_strncpy(gExePath, exePath, exeDelimiterIndex + 1);
	gExePath[exeDelimiterIndex] = '\0';
#endif // _WIN32
}
Пример #13
0
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory)
{
	const char separator[2] = { platform_get_path_separator(), 0 };
	char buffer[MAX_PATH];
	safe_strncpy(buffer, _userDataDirectoryPath, sizeof(buffer));
	if (subDirectory != NULL && subDirectory[0] != 0) {
		log_verbose("adding subDirectory '%s'", subDirectory);
		strcat(buffer, subDirectory);
		strcat(buffer, separator);
	}
	int len = strnlen(buffer, MAX_PATH);
	wchar_t *w_buffer = regular_to_wchar(buffer);
	w_buffer[len] = '\0';
	utf8 *path = widechar_to_utf8(w_buffer);
	free(w_buffer);
	safe_strncpy(outPath, path, MAX_PATH);
	free(path);
	log_verbose("outPath + subDirectory = '%s'", buffer);
}
Пример #14
0
void title_sequence_duplicate_preset(int duplicate, const char *name)
{
	if (duplicate >= 0 && duplicate < gConfigTitleSequences.num_presets && filename_valid_characters(name) && !title_sequence_name_exists(name)) {
		int preset = gConfigTitleSequences.num_presets;
		gConfigTitleSequences.num_presets++;
		gConfigTitleSequences.presets = realloc(gConfigTitleSequences.presets, sizeof(title_sequence) * (size_t)gConfigTitleSequences.num_presets);
		safe_strncpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE);
		gConfigTitleSequences.presets[preset].path[0] = 0;

		size_t savesSize = sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * gConfigTitleSequences.presets[duplicate].num_saves;
		size_t commandsSize = sizeof(title_command) * gConfigTitleSequences.presets[duplicate].num_commands;
		gConfigTitleSequences.presets[preset].saves = malloc(savesSize);
		gConfigTitleSequences.presets[preset].commands = malloc(commandsSize);
		memcpy(gConfigTitleSequences.presets[preset].saves, gConfigTitleSequences.presets[duplicate].saves, savesSize);
		memcpy(gConfigTitleSequences.presets[preset].commands, gConfigTitleSequences.presets[duplicate].commands, commandsSize);
		gConfigTitleSequences.presets[preset].num_saves = gConfigTitleSequences.presets[duplicate].num_saves;
		gConfigTitleSequences.presets[preset].num_commands = gConfigTitleSequences.presets[duplicate].num_commands;

		bool loadmm = false;
		for (int i = 0; i < gConfigTitleSequences.presets[preset].num_commands; i++) {
			if (gConfigTitleSequences.presets[preset].commands[i].command == TITLE_SCRIPT_LOADMM) {
				loadmm = true;
				gConfigTitleSequences.presets[preset].commands[i].command = TITLE_SCRIPT_LOAD;
				gConfigTitleSequences.presets[preset].commands[i].saveIndex = gConfigTitleSequences.presets[duplicate].num_saves;
			}
		}

		// Create the folder
		utf8 path[MAX_PATH], srcPath[MAX_PATH];
		platform_get_user_directory(path, "title sequences");
		strcat(path, gConfigTitleSequences.presets[preset].name);
		platform_file_delete(path);
		platform_ensure_directory_exists(path);

		// Copy the saves
		char separator = platform_get_path_separator();
		for (int i = 0; i < gConfigTitleSequences.presets[preset].num_saves; i++) {
			if (gConfigTitleSequences.presets[duplicate].path[0]) {
				safe_strncpy(srcPath, gConfigTitleSequences.presets[duplicate].path, MAX_PATH);
				strcat(srcPath, gConfigTitleSequences.presets[duplicate].saves[i]);
			}
			else {
				platform_get_user_directory(srcPath, "title sequences");
				strcat(srcPath, gConfigTitleSequences.presets[duplicate].name);
				strncat(srcPath, &separator, 1);
				strcat(srcPath, gConfigTitleSequences.presets[duplicate].saves[i]);
			}
			platform_get_user_directory(path, "title sequences");
			strcat(path, gConfigTitleSequences.presets[preset].name);
			strncat(path, &separator, 1);
			strcat(path, gConfigTitleSequences.presets[preset].saves[i]);

			platform_file_copy(srcPath, path, false);
		}

		if (loadmm) {
			title_sequence_add_save(preset, get_file_path(PATH_ID_SIXFLAGS_MAGICMOUNTAIN), "Six Flags Magic Mountain.SC6");
		}

		title_sequence_save_preset_script(preset);
		gCurrentTitleSequence = preset;
	}
}
Пример #15
0
static void window_loadsave_populate_list(rct_window *w, int includeNewItem, const char *directory, const char *extension)
{
	int i;
	int sortStartIndex = 0;
	int listItemCapacity = 8;
	loadsave_list_item *listItem;
	char filter[MAX_PATH];
	
	safe_strcpy(_directory, directory, sizeof(_directory));
	if (_extension != extension) {
		safe_strcpy(_extension, extension, sizeof(_extension));
		_extension[sizeof(_extension) - 1] = '\0';
	}
	_shortenedDirectory[0] = '\0';

	safe_strcpy(filter, directory, sizeof(filter));
	strncat(filter, "*", sizeof(filter) - strnlen(filter, MAX_PATH) - 1);
	strncat(filter, extension, sizeof(filter) - strnlen(filter, MAX_PATH) - 1);

	if (_listItems != NULL)
		free(_listItems);
	_listItems = (loadsave_list_item*)malloc(listItemCapacity * sizeof(loadsave_list_item));
	_listItemsCount = 0;
	
	window_loadsave_widgets[WIDX_NEW].type = includeNewItem?WWT_CLOSEBOX:WWT_EMPTY; // Hide/Show "new" button
	if(directory[0]=='\0' && platform_get_drives()!=0) // List Windows drives
	{
		w->disabled_widgets |= (1<<WIDX_NEW) | (1<<WIDX_UP);
		for (int x = 0; x < 32; x++){
			if (listItemCapacity <= _listItemsCount) {
				listItemCapacity *= 2;
				_listItems = realloc(_listItems, listItemCapacity * sizeof(loadsave_list_item));
			}

			if (platform_get_drives() & (1 << (x))){
				listItem = &_listItems[_listItemsCount];
				memset(listItem->path, '\0', MAX_PATH);
				listItem->path[0] = 'A' + x;
				listItem->path[1] = ':';
				listItem->path[2] = platform_get_path_separator();
				strcpy(listItem->name, listItem->path);
				listItem->type = TYPE_DIRECTORY;
				_listItemsCount++;
			}
		}
	}
	else
	{
		//Get parent directory
		int directoryLength = strlen(directory);
		char separator = platform_get_path_separator();
		for(i = directoryLength-2; i>=0; i--)
		{
			if(directory[i]==separator)
				break;
		}
		safe_strcpy(_parentDirectory, directory, sizeof(_parentDirectory));
		_parentDirectory[i+1] = '\0';
		if(_parentDirectory[0]=='\0' && platform_get_drives()==0)
			w->disabled_widgets |= (1<<WIDX_UP);
		else
			w->disabled_widgets &= ~(1<<WIDX_UP);
		w->disabled_widgets &= ~(1<<WIDX_NEW);
		file_info fileInfo;
		int fileEnumHandle;
		const char *src;
		char *dst;
		char *last_dot_in_filename;
		char subDir[MAX_PATH];
		
		fileEnumHandle = platform_enumerate_directories_begin(directory);
		while (platform_enumerate_directories_next(fileEnumHandle, subDir)){
			if (listItemCapacity <= _listItemsCount) {
				listItemCapacity *= 2;
				_listItems = realloc(_listItems, listItemCapacity * sizeof(loadsave_list_item));
			}

			listItem = &_listItems[_listItemsCount];
			memset(listItem->path, '\0', MAX_PATH);
			safe_strcpy(listItem->path, directory, MAX_PATH);
			strncat(listItem->path, subDir, MAX_PATH - strnlen(listItem->path, MAX_PATH) - 1);
			safe_strcpy(listItem->name, subDir, sizeof(listItem->name));
			listItem->type = TYPE_DIRECTORY;
			_listItemsCount++;
		}
		platform_enumerate_files_end(fileEnumHandle);

		fileEnumHandle = platform_enumerate_files_begin(filter);
		while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) {
			if (listItemCapacity <= _listItemsCount) {
				listItemCapacity *= 2;
				_listItems = realloc(_listItems, listItemCapacity * sizeof(loadsave_list_item));
			}

			listItem = &_listItems[_listItemsCount];
			safe_strcpy(listItem->path, directory, sizeof(listItem->path));
			strncat(listItem->path, fileInfo.path, sizeof(listItem->path) - strnlen(listItem->path, MAX_PATH) - 1);
			listItem->type = TYPE_FILE;
			listItem->date_modified = platform_file_get_modified_time(listItem->path);

			src = fileInfo.path;
			dst = listItem->name;
			last_dot_in_filename = strrchr(fileInfo.path, '.');
			assert(last_dot_in_filename != NULL);
			i = 0;
			while (src < last_dot_in_filename && i < sizeof(listItem->name) - 1) {
				*dst++ = *src++;
				i++;
			}
			*dst = '\0';

			_listItemsCount++;
		}
		platform_enumerate_files_end(fileEnumHandle);
		window_loadsave_sort_list(sortStartIndex, _listItemsCount - 1);
	}
}
Пример #16
0
int platform_enumerate_files_begin(const utf8 *pattern)
{
	enumerate_file_info *enumFileInfo;
	wchar_t *wpattern = utf8_to_widechar(pattern);
	int length = min(utf8_length(pattern), MAX_PATH);
	char *npattern = malloc(length+1);
	int converted;
	converted = wcstombs(npattern, wpattern, length);
	npattern[length] = '\0';
	if (converted == MAX_PATH) {
		log_warning("truncated string %s", npattern);
	}
	log_verbose("begin file search, pattern: %s", npattern);

	char *file_name = strrchr(npattern, platform_get_path_separator());
	char *dir_name;
	if (file_name != NULL)
	{
		dir_name = strndup(npattern, file_name - npattern);
		file_name = &file_name[1];
	} else {
		file_name = npattern;
		dir_name = strdup(".");
	}


	int pattern_length = strlen(file_name);
	g_file_pattern = strndup(file_name, pattern_length);
	for (int j = 0; j < pattern_length; j++)
	{
		g_file_pattern[j] = (char)toupper(g_file_pattern[j]);
	}
	log_verbose("looking for file matching %s", g_file_pattern);
	int cnt;
	for (int i = 0; i < countof(_enumerateFileInfoList); i++) {
		enumFileInfo = &_enumerateFileInfoList[i];
		if (!enumFileInfo->active) {
			safe_strcpy(enumFileInfo->pattern, npattern, sizeof(enumFileInfo->pattern));
			cnt = scandir(dir_name, &enumFileInfo->fileListTemp, winfilter, alphasort);
			if (cnt < 0)
			{
				break;
			}
			log_verbose("found %d files matching in dir '%s'", cnt, dir_name);
			enumFileInfo->cnt = cnt;
			enumFileInfo->paths = malloc(cnt * sizeof(char *));
			char **paths = enumFileInfo->paths;
			// 256 is size of dirent.d_name
			const int buf_len = min(MAX_PATH, 256);
			const int dir_name_len = strnlen(dir_name, MAX_PATH);
			char separator[] = {platform_get_path_separator(), 0};
			for (int idx = 0; idx < cnt; idx++)
			{
				struct dirent *d = enumFileInfo->fileListTemp[idx];
				const int entry_len = strnlen(d->d_name, MAX_PATH);
				// 1 for separator, 1 for trailing null
				size_t path_len = sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2);
				paths[idx] = malloc(path_len);
				paths[idx][0] = '\0';
				log_verbose("dir_name: %s", dir_name);
				strncat(paths[idx], dir_name, path_len - 2);
				strncat(paths[idx], separator, path_len - strnlen(paths[idx], path_len) - 1);
				strncat(paths[idx], d->d_name, path_len - strnlen(paths[idx], path_len) - 1);
				log_verbose("paths[%d] = %s", idx, paths[idx]);
			}
			enumFileInfo->handle = 0;
			enumFileInfo->active = 1;
			free(dir_name);
			free(g_file_pattern);
			g_file_pattern = NULL;
			free(wpattern);
			free(npattern);
			return i;
		}
	}

	free(dir_name);
	free(g_file_pattern);
	g_file_pattern = NULL;
	free(wpattern);
	free(npattern);
	return -1;
}
Пример #17
0
int platform_enumerate_files_begin(const utf8 *pattern)
{
	enumerate_file_info *enumFileInfo;
	wchar_t *wpattern = utf8_to_widechar(pattern);
	int length = min(utf8_length(pattern), MAX_PATH);
	char *npattern = malloc(length);
	int converted;
	converted = wcstombs(npattern, wpattern, length);
	npattern[length - 1] = '\0';
	if (converted == MAX_PATH) {
		log_warning("truncated string %s", npattern);
	}
	log_warning("begin file search, pattern: %s", npattern);

	char *file_name = strrchr(npattern, platform_get_path_separator());
	char *dir_name;
	if (file_name != NULL)
	{
		dir_name = strndup(npattern, file_name - npattern);
		file_name = &file_name[1];
	} else {
		file_name = npattern;
		dir_name = strdup(".");
	}

	char *smatch = strchr(file_name, '*');
	if ((smatch != file_name) && (smatch != NULL))
	{
		log_error("Sorry, can only match '*' at start of filename.");
		return -1;
	} else {
		// '*' found
		if (smatch != NULL)
		{
			// some boundary checking needed
			// skip the '*'
			smatch = &smatch[1];
			char *match2 = strchr(&smatch[1], '*');
			if (match2 != NULL)
			{
				log_error("Sorry, can only match one '*' wildcard.");
				return -1;
			}
		} else {
			// '*' not found
			smatch = file_name;
		}
	}
	char *qmatch = strchr(file_name, '?');
	if ((qmatch != &npattern[length - 1]) && (qmatch != NULL))
	{
		log_error("Sorry, can only match '?' at end of filename.");
		return -1;
	} else {
		qmatch = &npattern[length];
	}
	int pattern_length = qmatch - smatch;
	g_file_pattern = strndup(smatch, pattern_length);
	for (int j = 0; j < pattern_length; j++)
	{
		g_file_pattern[j] = (char)toupper(g_file_pattern[j]);
	}
	log_warning("looking for file matching %s", g_file_pattern);
	int cnt;
	for (int i = 0; i < countof(_enumerateFileInfoList); i++) {
		enumFileInfo = &_enumerateFileInfoList[i];
		if (!enumFileInfo->active) {
			safe_strncpy(enumFileInfo->pattern, npattern, length);
			cnt = scandir(dir_name, &enumFileInfo->fileListTemp, winfilter, alphasort);
			if (cnt < 0)
			{
				break;
			}
			log_warning("found %d files matching in dir '%s'", cnt, dir_name);
			enumFileInfo->cnt = cnt;
			enumFileInfo->paths = malloc(cnt * sizeof(char *));
			char **paths = enumFileInfo->paths;
			// 256 is size of dirent.d_name
			const int buf_len = min(MAX_PATH, 256);
			const int dir_name_len = strnlen(dir_name, MAX_PATH);
			char separator[] = {platform_get_path_separator(), 0};
			for (int idx = 0; idx < cnt; idx++)
			{
				struct dirent *d = enumFileInfo->fileListTemp[idx];
				const int entry_len = strnlen(d->d_name, MAX_PATH);
				// 1 for separator, 1 for trailing null
				paths[idx] = malloc(sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2));
				paths[idx][0] = '\0';
				log_verbose("dir_name: %s", dir_name);
				strncat(paths[idx], dir_name, MAX_PATH);
				strncat(paths[idx], separator, MAX_PATH);
				strncat(paths[idx], d->d_name, MAX_PATH);
				log_verbose("paths[%d] = %s", idx, paths[idx]);
			}
			enumFileInfo->handle = 0;
			enumFileInfo->active = 1;
			free(dir_name);
			free(g_file_pattern);
			g_file_pattern = NULL;
			free(wpattern);
			free(npattern);
			return i;
		}
	}

	free(dir_name);
	free(g_file_pattern);
	g_file_pattern = NULL;
	free(wpattern);
	free(npattern);
	return -1;
}
Пример #18
0
int cmdline_for_sprite(const char **argv, int argc)
{
	if (argc == 0)
		return -1;

	if (_strcmpi(argv[0], "details") == 0) {
		if (argc < 2) {
			fprintf(stderr, "usage: sprite details <spritefile> [idx]\n");
			return -1;
		} else if (argc == 2) {
			const char *spriteFilePath = argv[1];

			if (!sprite_file_open(spriteFilePath)) {
				fprintf(stderr, "Unable to open input sprite file.\n");
				return -1;
			}

			printf("sprites: %d\n", spriteFileHeader.num_entries);
			printf("data size: %d\n", spriteFileHeader.total_size);

			sprite_file_close();
			return 1;
		} else {
			const char *spriteFilePath = argv[1];
			int spriteIndex = atoi(argv[2]);

			if (!sprite_file_open(spriteFilePath)) {
				fprintf(stderr, "Unable to open input sprite file.\n");
				return -1;
			}

			if (spriteIndex < 0 || spriteIndex >= (int)spriteFileHeader.num_entries) {
				sprite_file_close();
				fprintf(stderr, "Sprite #%d does not exist in sprite file.\n", spriteIndex);
				return -1;
			}

			rct_g1_element *g1 = &spriteFileEntries[spriteIndex];
			printf("width: %d\n", g1->width);
			printf("height: %d\n", g1->height);
			printf("x offset: %d\n", g1->x_offset);
			printf("y offset: %d\n", g1->y_offset);
			printf("data offset: 0x%X\n", g1->offset);

			sprite_file_close();
			return 1;
		}
	} else if (_strcmpi(argv[0], "export") == 0) {
		if (argc < 4) {
			fprintf(stderr, "usage: sprite export <spritefile> <idx> <output>\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];
		int spriteIndex = atoi(argv[2]);
		const char *outputPath = argv[3];

		if (!sprite_file_open(spriteFilePath)) {
			fprintf(stderr, "Unable to open input sprite file.\n");
			return -1;
		}

		if (spriteIndex < 0 || spriteIndex >= (int)spriteFileHeader.num_entries) {
			fprintf(stderr, "Sprite #%d does not exist in sprite file.\n", spriteIndex);
			return -1;
		}

		if (!sprite_file_export(spriteIndex, outputPath)) {
			fprintf(stderr, "Could not export\n");
			sprite_file_close();
			return -1;
		}

		sprite_file_close();
		return 1;
	} else if (_strcmpi(argv[0], "exportall") == 0) {
		if (argc < 3) {
			fprintf(stderr, "usage: sprite exportall <spritefile> <output directory>\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];
		char outputPath[_MAX_PATH];

		if (!sprite_file_open(spriteFilePath)) {
			fprintf(stderr, "Unable to open input sprite file.\n");
			return -1;
		}

		if (!platform_ensure_directory_exists(argv[2])){
			fprintf(stderr, "Unable to create directory.\n");
			return -1;
		}


		int maxIndex = (int)spriteFileHeader.num_entries;
		int numbers = (int)floor(log(maxIndex));
		
		strncpy(outputPath, argv[2], _MAX_PATH);
		int pathLen = strlen(outputPath);

		if (pathLen >= _MAX_PATH - numbers - 5){
			fprintf(stderr, "Path too long.\n");
			return -1;
		}

		for (int x = 0; x < numbers; x++){
			outputPath[pathLen + x] = '0';
		}
		strncpy(outputPath + pathLen + numbers, ".png", _MAX_PATH);

		for (int spriteIndex = 0; spriteIndex < maxIndex; spriteIndex++){

			if (spriteIndex % 100 == 99){
				// Status indicator
				printf("\r%d / %d, %d%%", spriteIndex, maxIndex, spriteIndex / maxIndex);
			}

			// Add to the index at the end of the file name
			char *counter = outputPath + pathLen + numbers - 1;
			(*counter)++;
			while (*counter > '9'){
				*counter = '0';
				counter--;
				(*counter)++;
			}

			if (!sprite_file_export(spriteIndex, outputPath)) {
				fprintf(stderr, "Could not export\n");
				sprite_file_close();
				return -1;
			}
		}

		sprite_file_close();
		return 1;

	} else if (_strcmpi(argv[0], "create") == 0) {
		if (argc < 2) {
			fprintf(stderr, "usage: sprite create <spritefile>\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];

		spriteFileHeader.num_entries = 0;
		spriteFileHeader.total_size = 0;
		sprite_file_save(spriteFilePath);

		sprite_file_close();
		return 1;
	} else if (_strcmpi(argv[0], "append") == 0) {
		if (argc < 3) {
			fprintf(stderr, "usage: sprite append <spritefile> <input>\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];
		const char *imagePath = argv[2];

		rct_g1_element spriteElement;
		uint8 *buffer;
		int bufferLength;
		if (!sprite_file_import(imagePath, &spriteElement, &buffer, &bufferLength, sprite_mode))
			return -1;

		if (!sprite_file_open(spriteFilePath)) {
			fprintf(stderr, "Unable to open input sprite file.\n");
			return -1;
		}
		
		spriteFileHeader.num_entries++;
		spriteFileHeader.total_size += bufferLength;
		spriteFileEntries = realloc(spriteFileEntries, spriteFileHeader.num_entries * sizeof(rct_g1_element));

		sprite_entries_make_relative();
		spriteFileData = realloc(spriteFileData, spriteFileHeader.total_size);
		sprite_entries_make_absolute();

		spriteFileEntries[spriteFileHeader.num_entries - 1] = spriteElement;
		memcpy(spriteFileData + (spriteFileHeader.total_size - bufferLength), buffer, bufferLength);
		spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData + (spriteFileHeader.total_size - bufferLength);
		
		free(buffer);
		if (!sprite_file_save(spriteFilePath))
			return -1;

		return 1;
	} else if (_strcmpi(argv[0], "build") == 0) {
		if (argc < 3) {
			fprintf(stderr, "usage: sprite build <spritefile> <resourcedir> [silent]\n");
			return -1;
		}

		const char *spriteFilePath = argv[1];
		const char *resourcePath = argv[2];
		char imagePath[MAX_PATH];
		int resourceLength = strlen(resourcePath);

		bool silent = (argc >= 4 && strcmp(argv[3], "silent") == 0);
		bool fileExists = true;
		FILE *file;

		spriteFileHeader.num_entries = 0;
		spriteFileHeader.total_size = 0;
		sprite_file_save(spriteFilePath);

		fprintf(stderr, "Building: %s\n", spriteFilePath);
		int i = 0;
		do {
			// Create image path
			strcpy(imagePath, resourcePath);
			if (resourcePath[resourceLength - 1] == '/' || resourcePath[resourceLength - 1] == '\\')
				imagePath[resourceLength - 1] = 0;
			sprintf(imagePath, "%s%c%d.png", imagePath, platform_get_path_separator(), i);

			file = fopen(imagePath, "r");
			if (file != NULL) {
				fclose(file);
				rct_g1_element spriteElement;
				uint8 *buffer;
				int bufferLength;
				if (!sprite_file_import(imagePath, &spriteElement, &buffer, &bufferLength, sprite_mode)) {
					fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath);
					return -1;
				}

				if (!sprite_file_open(spriteFilePath)) {
					fprintf(stderr, "Unable to open sprite file: %s\nCanceling\n", spriteFilePath);
					return -1;
				}

				spriteFileHeader.num_entries++;
				spriteFileHeader.total_size += bufferLength;
				spriteFileEntries = realloc(spriteFileEntries, spriteFileHeader.num_entries * sizeof(rct_g1_element));

				sprite_entries_make_relative();
				spriteFileData = realloc(spriteFileData, spriteFileHeader.total_size);
				sprite_entries_make_absolute();

				spriteFileEntries[spriteFileHeader.num_entries - 1] = spriteElement;
				memcpy(spriteFileData + (spriteFileHeader.total_size - bufferLength), buffer, bufferLength);
				spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData + (spriteFileHeader.total_size - bufferLength);

				free(buffer);

				if (!sprite_file_save(spriteFilePath)) {
					fprintf(stderr, "Could not save sprite file: %s\nCanceling\n", imagePath);
					return -1;
				}
				if (!silent)
					fprintf(stderr, "Added: %s\n", imagePath);
			}
			i++;
		} while (file != NULL);


		fprintf(stderr, "Finished\n", imagePath);
		return 1;
	} else {
		fprintf(stderr, "Unknown sprite command.");
		return 1;
	}
}