示例#1
0
/**
 * Load a standard MIDI file.
 * @param filename name of the file to load
 * @returns true if loaded was successful
 */
bool MidiFile::LoadFile(const char *filename)
{
	_midifile_instance = this;

	this->blocks.clear();
	this->tempos.clear();
	this->tickdiv = 0;

	bool success = false;
	FILE *file = FioFOpenFile(filename, "rb", Subdirectory::BASESET_DIR);
	if (file == NULL) return false;

	SMFHeader header;
	if (!ReadSMFHeader(file, header)) goto cleanup;

	/* Only format 0 (single-track) and format 1 (multi-track single-song) are accepted for now */
	if (header.format != 0 && header.format != 1) goto cleanup;
	/* Doesn't support SMPTE timecode files */
	if ((header.tickdiv & 0x8000) != 0) goto cleanup;

	this->tickdiv = header.tickdiv;

	for (; header.tracks > 0; header.tracks--) {
		if (!ReadTrackChunk(file, *this)) {
			goto cleanup;
		}
	}

	success = FixupMidiData(*this);

cleanup:
	FioFCloseFile(file);
	return success;
}
示例#2
0
/**
 * Calculate the MD5 sum for a GRF, and store it in the config.
 * @param config GRF to compute.
 * @param subdir The subdirectory to look in.
 * @return MD5 sum was successfully computed
 */
static bool CalcGRFMD5Sum(GRFConfig *config, Subdirectory subdir)
{
	FILE *f;
	Md5 checksum;
	uint8 buffer[1024];
	size_t len, size;

	/* open the file */
	f = FioFOpenFile(config->filename, "rb", subdir, &size);
	if (f == NULL) return false;

	long start = ftell(f);
	size = min(size, GRFGetSizeOfDataSection(f));

	if (start < 0 || fseek(f, start, SEEK_SET) < 0) {
		FioFCloseFile(f);
		return false;
	}

	/* calculate md5sum */
	while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
		size -= len;
		checksum.Append(buffer, len);
	}
	checksum.Finish(config->ident.md5sum);

	FioFCloseFile(f);

	return true;
}
示例#3
0
文件: debug.cpp 项目: jemmyw/openttd
static void debug_print(const char *dbg, const char *buf)
{
#if defined(ENABLE_NETWORK)
	if (_debug_socket != INVALID_SOCKET) {
		char buf2[1024 + 32];

		snprintf(buf2, lengthof(buf2), "%sdbg: [%s] %s\n", GetLogPrefix(), dbg, buf);
		send(_debug_socket, buf2, (int)strlen(buf2), 0);
		return;
	}
#endif /* ENABLE_NETWORK */
	if (strcmp(dbg, "desync") != 0) {
#if defined(WINCE)
		/* We need to do OTTD2FS twice, but as it uses a static buffer, we need to store one temporary */
		TCHAR tbuf[512];
		_sntprintf(tbuf, sizeof(tbuf), _T("%s"), OTTD2FS(dbg));
		NKDbgPrintfW(_T("dbg: [%s] %s\n"), tbuf, OTTD2FS(buf));
#else
		fprintf(stderr, "%sdbg: [%s] %s\n", GetLogPrefix(), dbg, buf);
#endif
		IConsoleDebug(dbg, buf);
	} else {
		static FILE *f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR);
		if (f == NULL) return;

		fprintf(f, "%s%s\n", GetLogPrefix(), buf);
		fflush(f);
	}
}
void FioOpenFile(int slot, const char *filename)
{
	FILE *f;

#if defined(LIMITED_FDS)
	FioFreeHandle();
#endif /* LIMITED_FDS */
	f = FioFOpenFile(filename);
	if (f == NULL) usererror("Cannot open file '%s'", filename);
	uint32 pos = ftell(f);

	FioCloseFile(slot); // if file was opened before, close it
	_fio.handles[slot] = f;
	_fio.filenames[slot] = filename;

	/* Store the filename without path and extension */
	const char *t = strrchr(filename, PATHSEPCHAR);
	_fio.shortnames[slot] = strdup(t == NULL ? filename : t);
	char *t2 = strrchr(_fio.shortnames[slot], '.');
	if (t2 != NULL) *t2 = '\0';
	strtolower(_fio.shortnames[slot]);

#if defined(LIMITED_FDS)
	_fio.usage_count[slot] = 0;
	_fio.open_handles++;
#endif /* LIMITED_FDS */
	FioSeekToFile(slot, pos);
}
	/* Add the file and calculate the md5 sum. */
	virtual bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename)
	{
		Md5 checksum;
		uint8 buffer[1024];
		size_t len, size;
		byte tmp_md5sum[16];

		/* Open the file ... */
		FILE *f = FioFOpenFile(filename, "rb", this->dir, &size);
		if (f == NULL) return false;

		/* ... calculate md5sum... */
		while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
			size -= len;
			checksum.Append(buffer, len);
		}
		checksum.Finish(tmp_md5sum);

		FioFCloseFile(f);

		/* ... and xor it to the overall md5sum. */
		for (uint i = 0; i < sizeof(md5sum); i++) this->md5sum[i] ^= tmp_md5sum[i];

		return true;
	}
/**
 * Check whether the given file exists
 * @param filename the file to try for existance
 * @param subdir the subdirectory to look in
 * @return true if and only if the file can be opened
 */
bool FioCheckFileExists(const char *filename, Subdirectory subdir)
{
	FILE *f = FioFOpenFile(filename, "rb", subdir);
	if (f == NULL) return false;

	FioFCloseFile(f);
	return true;
}
示例#7
0
/**
 * Read the header of a standard MIDI file.
 * @param[in] filename name of file to read from
 * @param[out] header filled with data read
 * @return true if the file could be opened and contained a header with correct format
 */
bool MidiFile::ReadSMFHeader(const char *filename, SMFHeader &header)
{
	FILE *file = FioFOpenFile(filename, "rb", Subdirectory::BASESET_DIR);
	if (!file) return false;
	bool result = ReadSMFHeader(file, header);
	FioFCloseFile(file);
	return result;
}
示例#8
0
/**
 * Reads the heightmap and/or size of the heightmap from a PNG file.
 * If map == NULL only the size of the PNG is read, otherwise a map
 * with grayscale pixels is allocated and assigned to *map.
 */
static bool ReadHeightmapPNG(char *filename, uint *x, uint *y, byte **map)
{
	FILE *fp;
	png_structp png_ptr = NULL;
	png_infop info_ptr  = NULL;

	fp = FioFOpenFile(filename, "rb");
	if (fp == NULL) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, WL_ERROR);
		return false;
	}

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR);
		fclose(fp);
		return false;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL || setjmp(png_jmpbuf(png_ptr))) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR);
		fclose(fp);
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return false;
	}

	png_init_io(png_ptr, fp);

	/* Allocate memory and read image, without alpha or 16-bit samples
	 * (result is either 8-bit indexed/grayscale or 24-bit RGB) */
	png_set_packing(png_ptr);
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_STRIP_16, NULL);

	/* Maps of wrong colour-depth are not used.
	 * (this should have been taken care of by stripping alpha and 16-bit samples on load) */
	if ((png_get_channels(png_ptr, info_ptr) != 1) && (png_get_channels(png_ptr, info_ptr) != 3) && (png_get_bit_depth(png_ptr, info_ptr) != 8)) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_IMAGE_TYPE, WL_ERROR);
		fclose(fp);
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return false;
	}

	if (map != NULL) {
		*map = MallocT<byte>(png_get_image_width(png_ptr, info_ptr) * png_get_image_height(png_ptr, info_ptr));
		ReadHeightmapPNGImageData(*map, png_ptr, info_ptr);
	}

	*x = png_get_image_width(png_ptr, info_ptr);
	*y = png_get_image_height(png_ptr, info_ptr);

	fclose(fp);
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	return true;
}
示例#9
0
/**
 * Reads the heightmap and/or size of the heightmap from a BMP file.
 * If map == nullptr only the size of the BMP is read, otherwise a map
 * with grayscale pixels is allocated and assigned to *map.
 */
static bool ReadHeightmapBMP(const char *filename, uint *x, uint *y, byte **map)
{
	FILE *f;
	BmpInfo info;
	BmpData data;
	BmpBuffer buffer;

	/* Init BmpData */
	memset(&data, 0, sizeof(data));

	f = FioFOpenFile(filename, "rb", HEIGHTMAP_DIR);
	if (f == nullptr) {
		ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, WL_ERROR);
		return false;
	}

	BmpInitializeBuffer(&buffer, f);

	if (!BmpReadHeader(&buffer, &info, &data)) {
		ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, WL_ERROR);
		fclose(f);
		BmpDestroyData(&data);
		return false;
	}

	/* Check if image dimensions don't overflow a size_t to avoid memory corruption. */
	if ((uint64)info.width * info.height >= (size_t)-1 / (info.bpp == 24 ? 3 : 1)) {
		ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, WL_ERROR);
		fclose(f);
		BmpDestroyData(&data);
		return false;
	}

	if (map != nullptr) {
		if (!BmpReadBitmap(&buffer, &info, &data)) {
			ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, WL_ERROR);
			fclose(f);
			BmpDestroyData(&data);
			return false;
		}

		*map = MallocT<byte>(info.width * info.height);
		ReadHeightmapBMPImageData(*map, &info, &data);
	}

	BmpDestroyData(&data);

	*x = info.width;
	*y = info.height;

	fclose(f);
	return true;
}
示例#10
0
/**
 * Calculate and check the MD5 hash of the supplied GRF.
 * @param file The file get the hash of.
 * @param subdir The sub directory to get the files from.
 * @return
 * - #CR_MATCH if the MD5 hash matches
 * - #CR_MISMATCH if the MD5 does not match
 * - #CR_NO_FILE if the file misses
 */
/* static */ MD5File::ChecksumResult GraphicsSet::CheckMD5(const MD5File *file, Subdirectory subdir)
{
	size_t size = 0;
	FILE *f = FioFOpenFile(file->filename, "rb", subdir, &size);
	if (f == NULL) return MD5File::CR_NO_FILE;

	size_t max = GRFGetSizeOfDataSection(f);

	FioFCloseFile(f);

	return file->CheckMD5(subdir, max);
}
示例#11
0
/** Opens OpenTTD files somewhere in a personal or global directory */
FILE *FioFOpenFile(const char *filename, const char *mode, Subdirectory subdir, size_t *filesize)
{
	FILE *f = NULL;
	Searchpath sp;

	assert(subdir < NUM_SUBDIRS || subdir == NO_DIRECTORY);

	FOR_ALL_SEARCHPATHS(sp) {
		f = FioFOpenFileSp(filename, mode, sp, subdir, filesize);
		if (f != NULL || subdir == NO_DIRECTORY) break;
	}

	/* We can only use .tar in case of data-dir, and read-mode */
	if (f == NULL && mode[0] == 'r') {
		static const uint MAX_RESOLVED_LENGTH = 2 * (100 + 100 + 155) + 1; // Enough space to hold two filenames plus link. See 'TarHeader'.
		char resolved_name[MAX_RESOLVED_LENGTH];

		/* Filenames in tars are always forced to be lowercase */
		strecpy(resolved_name, filename, lastof(resolved_name));
		strtolower(resolved_name);

		size_t resolved_len = strlen(resolved_name);

		/* Resolve ONE directory link */
		for (TarLinkList::iterator link = _tar_linklist.begin(); link != _tar_linklist.end(); link++) {
			const std::string &src = link->first;
			size_t len = src.length();
			if (resolved_len >= len && resolved_name[len - 1] == PATHSEPCHAR && strncmp(src.c_str(), resolved_name, len) == 0) {
				/* Apply link */
				char resolved_name2[MAX_RESOLVED_LENGTH];
				const std::string &dest = link->second;
				strecpy(resolved_name2, &(resolved_name[len]), lastof(resolved_name2));
				strecpy(resolved_name, dest.c_str(), lastof(resolved_name));
				strecpy(&(resolved_name[dest.length()]), resolved_name2, lastof(resolved_name));
				break; // Only resolve one level
			}
		}

		TarFileList::iterator it = _tar_filelist.find(resolved_name);
		if (it != _tar_filelist.end()) {
			f = FioFOpenFileTar(&((*it).second), filesize);
		}
	}

	/* Sometimes a full path is given. To support
	 * the 'subdirectory' must be 'removed'. */
	if (f == NULL && subdir != NO_DIRECTORY) {
		f = FioFOpenFile(filename, mode, NO_DIRECTORY, filesize);
	}

	return f;
}
示例#12
0
/**
 * Read all the raw language strings from the given file.
 * @param file The file to read from.
 * @return The raw strings, or NULL upon error.
 */
LanguageStrings *ReadRawLanguageStrings(const char *file)
{
	LanguageStrings *ret = NULL;
	FILE *fh = NULL;
	try {
		size_t to_read;
		fh = FioFOpenFile(file, "rb", GAME_DIR, &to_read);
		if (fh == NULL) {
			return NULL;
		}

		const char *langname = strrchr(file, PATHSEPCHAR);
		if (langname == NULL) {
			langname = file;
		} else {
			langname++;
		}

		/* Check for invalid empty filename */
		if (*langname == '.' || *langname == 0) {
			fclose(fh);
			return NULL;
		}

		ret = new LanguageStrings(langname, strchr(langname, '.'));

		char buffer[2048];
		while (to_read != 0 && fgets(buffer, sizeof(buffer), fh) != NULL) {
			size_t len = strlen(buffer);

			/* Remove trailing spaces/newlines from the string. */
			size_t i = len;
			while (i > 0 && (buffer[i - 1] == '\r' || buffer[i - 1] == '\n' || buffer[i - 1] == ' ')) i--;
			buffer[i] = '\0';

			*ret->lines.Append() = stredup(buffer, buffer + to_read - 1);

			if (len > to_read) {
				to_read = 0;
			} else {
				to_read -= len;
			}
		}

		fclose(fh);
		return ret;
	} catch (...) {
		if (fh != NULL) fclose(fh);
		delete ret;
		return NULL;
	}
}
示例#13
0
void GetOldSaveGameName(const char *file, char *title, const char *last)
{
	FILE *f = FioFOpenFile(file, "rb", NO_DIRECTORY);

	if (f == NULL) {
		*title = '\0';
		return;
	}

	DetermineOldSavegameType(f, title, last);

	fclose(f);
}
示例#14
0
bool LoadOldSaveGame(const char *file)
{
	LoadgameState ls;

	DEBUG(oldloader, 3, "Trying to load a TTD(Patch) savegame");

	InitLoading(&ls);

	/* Open file */
	ls.file = FioFOpenFile(file, "rb", NO_DIRECTORY);

	if (ls.file == NULL) {
		DEBUG(oldloader, 0, "Cannot open file '%s'", file);
		return false;
	}

	SavegameType type = DetermineOldSavegameType(ls.file, NULL, NULL);

	LoadOldMainProc *proc = NULL;

	switch (type) {
		case SGT_TTO: proc = &LoadTTOMain; break;
		case SGT_TTD: proc = &LoadTTDMain; break;
		default: break;
	}

	_savegame_type = type;

	bool game_loaded;
	try {
		game_loaded = proc != NULL && proc(&ls);
	} catch (...) {
		game_loaded = false;
	}

	if (!game_loaded) {
		SetSaveLoadError(STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED);
		fclose(ls.file);
		return false;
	}

	_pause_mode = 2;

	return true;
}
示例#15
0
/**
 * Reads the heightmap and/or size of the heightmap from a BMP file.
 * If map == NULL only the size of the BMP is read, otherwise a map
 * with grayscale pixels is allocated and assigned to *map.
 */
static bool ReadHeightmapBMP(char *filename, uint *x, uint *y, byte **map)
{
	FILE *f;
	BmpInfo info;
	BmpData data;
	BmpBuffer buffer;

	/* Init BmpData */
	memset(&data, 0, sizeof(data));

	f = FioFOpenFile(filename, "rb");
	if (f == NULL) {
		ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, WL_ERROR);
		return false;
	}

	BmpInitializeBuffer(&buffer, f);

	if (!BmpReadHeader(&buffer, &info, &data)) {
		ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, WL_ERROR);
		fclose(f);
		BmpDestroyData(&data);
		return false;
	}

	if (map != NULL) {
		if (!BmpReadBitmap(&buffer, &info, &data)) {
			ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, WL_ERROR);
			fclose(f);
			BmpDestroyData(&data);
			return false;
		}

		*map = MallocT<byte>(info.width * info.height);
		ReadHeightmapBMPImageData(*map, &info, &data);
	}

	BmpDestroyData(&data);

	*x = info.width;
	*y = info.height;

	fclose(f);
	return true;
}
/**
 * Calculate the MD5 sum for a GRF, and store it in the config.
 * @param config GRF to compute.
 * @return MD5 sum was successfully computed
 */
static bool CalcGRFMD5Sum(GRFConfig *config)
{
	FILE *f;
	Md5 checksum;
	uint8 buffer[1024];
	size_t len, size;

	/* open the file */
	f = FioFOpenFile(config->filename, "rb", DATA_DIR, &size);
	if (f == NULL) return false;

	/* calculate md5sum */
	while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
		size -= len;
		checksum.Append(buffer, len);
	}
	checksum.Finish(config->ident.md5sum);

	FioFCloseFile(f);

	return true;
}
示例#17
0
/**
 * Calculate and check the MD5 hash of the supplied filename.
 * @param subdir The sub directory to get the files from
 * @return
 * - #CR_MATCH if the MD5 hash matches
 * - #CR_MISMATCH if the MD5 does not match
 * - #CR_NO_FILE if the file misses
 */
MD5File::ChecksumResult MD5File::CheckMD5(Subdirectory subdir) const
{
	size_t size;
	FILE *f = FioFOpenFile(this->filename, "rb", subdir, &size);

	if (f == NULL) return CR_NO_FILE;

	Md5 checksum;
	uint8 buffer[1024];
	uint8 digest[16];
	size_t len;

	while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
		size -= len;
		checksum.Append(buffer, len);
	}

	FioFCloseFile(f);

	checksum.Finish(digest);
	return memcmp(this->hash, digest, sizeof(this->hash)) == 0 ? CR_MATCH : CR_MISMATCH;
}
示例#18
0
/**
 * Read all the raw language strings from the given file.
 * @param file The file to read from.
 * @return The raw strings, or NULL upon error.
 */
LanguageStrings *ReadRawLanguageStrings(const char *file)
{
	LanguageStrings *ret = NULL;
	try {
		size_t to_read;
		FILE *fh = FioFOpenFile(file, "rb", GAME_DIR, &to_read);
		if (fh == NULL) {
			return NULL;
		}

		ret = new LanguageStrings(file);

		char buffer[2048];
		while (to_read != 0 && fgets(buffer, sizeof(buffer), fh) != NULL) {
			size_t len = strlen(buffer);

			/* Remove trailing spaces/newlines from the string. */
			size_t i = len;
			while (i > 0 && (buffer[i - 1] == '\r' || buffer[i - 1] == '\n' || buffer[i - 1] == ' ')) i--;
			buffer[i] = '\0';

			*ret->lines.Append() = strndup(buffer, to_read);

			if (len > to_read) {
				to_read = 0;
			} else {
				to_read -= len;
			}
		}

		return ret;
	} catch (...) {
		delete ret;
		return NULL;
	}
}
示例#19
0
文件: ini.cpp 项目: jemmyw/openttd
void IniFile::LoadFromDisk(const char *filename)
{
	assert(this->last_group == &this->group);

	char buffer[1024];
	IniGroup *group = NULL;

	char *comment = NULL;
	uint comment_size = 0;
	uint comment_alloc = 0;

	size_t end;
	/*
	 * Now we are going to open a file that contains no more than simple
	 * plain text. That would raise the question: "why open the file as
	 * if it is a binary file?". That's simple... Microsoft, in all
	 * their greatness and wisdom decided it would be useful if ftell
	 * is aware of '\r\n' and "sees" that as a single character. The
	 * easiest way to test for that situation is by searching for '\n'
	 * and decrease the value every time you encounter a '\n'. This will
	 * thus also make ftell "see" the '\r' when it is not there, so the
	 * result of ftell will be highly unreliable. So to work around this
	 * marvel of wisdom we have to open in as a binary file.
	 */
	FILE *in = FioFOpenFile(filename, "rb", DATA_DIR, &end);
	if (in == NULL) return;

	end += ftell(in);

	/* for each line in the file */
	while ((size_t)ftell(in) < end && fgets(buffer, sizeof(buffer), in)) {
		char c, *s;
		/* trim whitespace from the left side */
		for (s = buffer; *s == ' ' || *s == '\t'; s++) {}

		/* trim whitespace from right side. */
		char *e = s + strlen(s);
		while (e > s && ((c = e[-1]) == '\n' || c == '\r' || c == ' ' || c == '\t')) e--;
		*e = '\0';

		/* skip comments and empty lines */
		if (*s == '#' || *s == ';' || *s == '\0') {
			uint ns = comment_size + (e - s + 1);
			uint a = comment_alloc;
			/* add to comment */
			if (ns > a) {
				a = max(a, 128U);
				do a *= 2; while (a < ns);
				comment = ReallocT(comment, comment_alloc = a);
			}
			uint pos = comment_size;
			comment_size += (e - s + 1);
			comment[pos + e - s] = '\n'; // comment newline
			memcpy(comment + pos, s, e - s); // copy comment contents
			continue;
		}

		/* it's a group? */
		if (s[0] == '[') {
			if (e[-1] != ']') {
				ShowInfoF("ini: invalid group name '%s'", buffer);
			} else {
				e--;
			}
			s++; // skip [
			group = new IniGroup(this, s, e - s);
			if (comment_size) {
				group->comment = strndup(comment, comment_size);
				comment_size = 0;
			}
		} else if (group) {
			char *t;
			/* find end of keyname */
			if (*s == '\"') {
				s++;
				for (t = s; *t != '\0' && *t != '\"'; t++) {}
				if (*t == '\"') *t = ' ';
			} else {
				for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++) {}
			}

			/* it's an item in an existing group */
			IniItem *item = new IniItem(group, s, t - s);
			if (comment_size) {
				item->comment = strndup(comment, comment_size);
				comment_size = 0;
			}

			/* find start of parameter */
			while (*t == '=' || *t == ' ' || *t == '\t') t++;

			bool quoted = (*t == '\"');
			/* remove starting quotation marks */
			if (*t == '\"') t++;
			/* remove ending quotation marks */
			e = t + strlen(t);
			if (e > t && e[-1] == '\"') e--;
			*e = '\0';

			/* If the value was not quoted and empty, it must be NULL */
			item->value = (!quoted && e == t) ? NULL : strndup(t, e - t);
		} else {
			/* it's an orphan item */
			ShowInfoF("ini: '%s' outside of group", buffer);
		}
	}

	if (comment_size > 0) {
		this->comment = strndup(comment, comment_size);
		comment_size = 0;
	}

	free(comment);
	fclose(in);
}
示例#20
0
void DisplaySplashImage()
{
    FILE *f = FioFOpenFile(SPLASH_IMAGE_FILE);
    if (f == NULL) return;

    png_byte header[8];
    fread(header, sizeof(png_byte), 8, f);
    if (png_sig_cmp(header, 0, 8) != 0) {
        fclose(f);
        return;
    }

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, png_my_error, png_my_warning);

    if (png_ptr == NULL) {
        fclose(f);
        return;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        fclose(f);
        return;
    }

    png_infop end_info = png_create_info_struct(png_ptr);
    if (end_info == NULL) {
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        fclose(f);
        return;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(f);
        return;
    }

    png_init_io(png_ptr, f);
    png_set_sig_bytes(png_ptr, 8);

    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    uint width      = png_get_image_width(png_ptr, info_ptr);
    uint height     = png_get_image_height(png_ptr, info_ptr);
    uint bit_depth  = png_get_bit_depth(png_ptr, info_ptr);
    uint color_type = png_get_color_type(png_ptr, info_ptr);

    if (color_type != PNG_COLOR_TYPE_PALETTE || bit_depth != 8) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(f);
        return;
    }

    if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(f);
        return;
    }

    png_colorp palette;
    int num_palette;
    png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);

    png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);

    if (width > (uint) _screen.width) width = _screen.width;
    if (height > (uint) _screen.height) height = _screen.height;

    uint xoff = (_screen.width - width) / 2;
    uint yoff = (_screen.height - height) / 2;

    switch (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth()) {
    case 8: {
        uint8 *dst_ptr = (uint8 *)_screen.dst_ptr;
        /* Initialize buffer */
        MemSetT(dst_ptr, 0xff, _screen.pitch * _screen.height);

        for (uint y = 0; y < height; y++) {
            uint8 *src = row_pointers[y];
            uint8 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;

            memcpy(dst, src, width);
        }

        for (int i = 0; i < num_palette; i++) {
            _cur_palette[i].a = i == 0 ? 0 : 0xff;
            _cur_palette[i].r = palette[i].red;
            _cur_palette[i].g = palette[i].green;
            _cur_palette[i].b = palette[i].blue;
        }

        _cur_palette[0xff].a = 0xff;
        _cur_palette[0xff].r = 0;
        _cur_palette[0xff].g = 0;
        _cur_palette[0xff].b = 0;

        _pal_first_dirty = 0;
        _pal_count_dirty = 256;
        break;
    }
    case 32: {
        uint32 *dst_ptr = (uint32 *)_screen.dst_ptr;
        /* Initialize buffer */
        MemSetT(dst_ptr, 0, _screen.pitch * _screen.height);

        for (uint y = 0; y < height; y++) {
            uint8 *src = row_pointers[y];
            uint32 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;

            for (uint x = 0; x < width; x++) {
                dst[x] = palette[src[x]].blue | (palette[src[x]].green << 8) | (palette[src[x]].red << 16) | 0xff000000;
            }
        }
        break;
    }
    }

    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    fclose(f);
    return;
}
示例#21
0
文件: ini.cpp 项目: Junky2008/OpenTTD
/* virtual */ FILE *IniFile::OpenFile(const char *filename, Subdirectory subdir, size_t *size)
{
	/* Open the text file in binary mode to prevent end-of-line translations
	 * done by ftell() and friends, as defined by K&R. */
	return FioFOpenFile(filename, "rb", subdir, size);
}
示例#22
0
/**
 * Reads the heightmap and/or size of the heightmap from a PNG file.
 * If map == nullptr only the size of the PNG is read, otherwise a map
 * with grayscale pixels is allocated and assigned to *map.
 */
static bool ReadHeightmapPNG(const char *filename, uint *x, uint *y, byte **map)
{
	FILE *fp;
	png_structp png_ptr = nullptr;
	png_infop info_ptr  = nullptr;

	fp = FioFOpenFile(filename, "rb", HEIGHTMAP_DIR);
	if (fp == nullptr) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, WL_ERROR);
		return false;
	}

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
	if (png_ptr == nullptr) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR);
		fclose(fp);
		return false;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == nullptr || setjmp(png_jmpbuf(png_ptr))) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR);
		fclose(fp);
		png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
		return false;
	}

	png_init_io(png_ptr, fp);

	/* Allocate memory and read image, without alpha or 16-bit samples
	 * (result is either 8-bit indexed/grayscale or 24-bit RGB) */
	png_set_packing(png_ptr);
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_STRIP_16, nullptr);

	/* Maps of wrong colour-depth are not used.
	 * (this should have been taken care of by stripping alpha and 16-bit samples on load) */
	if ((png_get_channels(png_ptr, info_ptr) != 1) && (png_get_channels(png_ptr, info_ptr) != 3) && (png_get_bit_depth(png_ptr, info_ptr) != 8)) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_IMAGE_TYPE, WL_ERROR);
		fclose(fp);
		png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
		return false;
	}

	uint width = png_get_image_width(png_ptr, info_ptr);
	uint height = png_get_image_height(png_ptr, info_ptr);

	/* Check if image dimensions don't overflow a size_t to avoid memory corruption. */
	if ((uint64)width * height >= (size_t)-1) {
		ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, WL_ERROR);
		fclose(fp);
		png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
		return false;
	}

	if (map != nullptr) {
		*map = MallocT<byte>(width * height);
		ReadHeightmapPNGImageData(*map, png_ptr, info_ptr);
	}

	*x = width;
	*y = height;

	fclose(fp);
	png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
	return true;
}
示例#23
0
/**
 * Try to add a fios item set with the given filename.
 * @param filename        the full path to the file to read
 * @param basepath_length amount of characters to chop of before to get a relative filename
 * @return true if the file is added.
 */
bool FiosFileScanner::AddFile(const char *filename, size_t basepath_length, const char *tar_filename)
{
	const char *ext = strrchr(filename, '.');
	if (ext == NULL) return false;

	char fios_title[64];
	fios_title[0] = '\0'; // reset the title;

	FiosType type = this->callback_proc(this->mode, filename, ext, fios_title, lastof(fios_title));
	if (type == FIOS_TYPE_INVALID) return false;

	for (const FiosItem *fios = _fios_items.Begin(); fios != _fios_items.End(); fios++) {
		if (strcmp(fios->name, filename) == 0) return false;
	}

	FiosItem *fios = _fios_items.Append();
#ifdef WIN32
	struct _stat sb;
	if (_tstat(OTTD2FS(filename), &sb) == 0) {
#else
	struct stat sb;
	if (stat(filename, &sb) == 0) {
#endif
		fios->mtime = sb.st_mtime;
	} else {
		fios->mtime = 0;
	}

	fios->type = type;
	strecpy(fios->name, filename, lastof(fios->name));

	/* If the file doesn't have a title, use its filename */
	const char *t = fios_title;
	if (StrEmpty(fios_title)) {
		t = strrchr(filename, PATHSEPCHAR);
		t = (t == NULL) ? filename : (t + 1);
	}
	strecpy(fios->title, t, lastof(fios->title));
	str_validate(fios->title, lastof(fios->title));

	return true;
}


/**
 * Fill the list of the files in a directory, according to some arbitrary rule.
 *  @param mode The mode we are in. Some modes don't allow 'parent'.
 *  @param callback_proc The function that is called where you need to do the filtering.
 *  @param subdir The directory from where to start (global) searching.
 */
static void FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_proc *callback_proc, Subdirectory subdir)
{
	struct stat sb;
	struct dirent *dirent;
	DIR *dir;
	FiosItem *fios;
	int sort_start;
	char d_name[sizeof(fios->name)];

	_fios_items.Clear();

	/* A parent directory link exists if we are not in the root directory */
	if (!FiosIsRoot(_fios_path)) {
		fios = _fios_items.Append();
		fios->type = FIOS_TYPE_PARENT;
		fios->mtime = 0;
		strecpy(fios->name, "..", lastof(fios->name));
		strecpy(fios->title, ".. (Parent directory)", lastof(fios->title));
	}

	/* Show subdirectories */
	if ((dir = ttd_opendir(_fios_path)) != NULL) {
		while ((dirent = readdir(dir)) != NULL) {
			strecpy(d_name, FS2OTTD(dirent->d_name), lastof(d_name));

			/* found file must be directory, but not '.' or '..' */
			if (FiosIsValidFile(_fios_path, dirent, &sb) && S_ISDIR(sb.st_mode) &&
					(!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
					strcmp(d_name, ".") != 0 && strcmp(d_name, "..") != 0) {
				fios = _fios_items.Append();
				fios->type = FIOS_TYPE_DIR;
				fios->mtime = 0;
				strecpy(fios->name, d_name, lastof(fios->name));
				snprintf(fios->title, lengthof(fios->title), "%s" PATHSEP " (Directory)", d_name);
				str_validate(fios->title, lastof(fios->title));
			}
		}
		closedir(dir);
	}

	/* Sort the subdirs always by name, ascending, remember user-sorting order */
	{
		SortingBits order = _savegame_sort_order;
		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
		QSortT(_fios_items.Begin(), _fios_items.Length(), CompareFiosItems);
		_savegame_sort_order = order;
	}

	/* This is where to start sorting for the filenames */
	sort_start = _fios_items.Length();

	/* Show files */
	FiosFileScanner scanner(mode, callback_proc);
	if (subdir == NO_DIRECTORY) {
		scanner.Scan(NULL, _fios_path, false);
	} else {
		scanner.Scan(NULL, subdir, true, true);
	}

	QSortT(_fios_items.Get(sort_start), _fios_items.Length() - sort_start, CompareFiosItems);

	/* Show drives */
	FiosGetDrives();

	_fios_items.Compact();
}

/**
 * Get the title of a file, which (if exists) is stored in a file named
 * the same as the data file but with '.title' added to it.
 * @param file filename to get the title for
 * @param title the title buffer to fill
 * @param last the last element in the title buffer
 * @param subdir the sub directory to search in
 */
static void GetFileTitle(const char *file, char *title, const char *last, Subdirectory subdir)
{
	char buf[MAX_PATH];
	strecpy(buf, file, lastof(buf));
	strecat(buf, ".title", lastof(buf));

	FILE *f = FioFOpenFile(buf, "r", subdir);
	if (f == NULL) return;

	size_t read = fread(title, 1, last - title, f);
	assert(title + read <= last);
	title[read] = '\0';
	str_validate(title, last);
	FioFCloseFile(f);
}