Beispiel #1
0
static exe_handle_t *
lzexe_open(const char *filename)
{
	exe_handle_t *handle;
	guint8 head[0x20];
	guint8 size[2];
	off_t fpos;

	FILE *f = sci_fopen(filename, "rb");

	if (!f)
		return NULL;

	/* Read exe header plus possible lzexe signature. */
	if (fread(head, 1, 0x20, f) != 0x20)
		return NULL;

	/* Verify "MZ" signature, header size == 2 paragraphs and number of
	** overlays == 0.
	*/
	if (UINT16(head) != 0x5a4d || UINT16(head + 8) != 2
	    || UINT16(head + 0x1a) != 0)
		return NULL;

	/* Verify that first relocation item offset is 0x1c. */
	if (UINT16(head + 0x18) != 0x1c)
		return NULL;

	/* Look for lzexe signature. */
	if (memcmp(head + 0x1c, "LZ09", 4)
            && memcmp(head + 0x1c, "LZ91", 4)) {
		return NULL;
	}

	/* Calculate code segment offset in exe file. */
	fpos = (UINT16(head + 0x16) + UINT16(head + 8)) << 4;
	/* Seek to offset 8 of info table at start of code segment. */
	if (fseek(f, fpos + 8, SEEK_SET) == -1)
		return NULL;

	/* Read size of compressed data in paragraphs. */
	if (fread(size, 1, 2, f) != 2)
		return NULL;

	/* Move file pointer to start of compressed data. */
	fpos -= UINT16(size) << 4;
	if (fseek(f, fpos, SEEK_SET) == -1)
		return NULL;

	handle = (exe_handle_t*)sci_malloc(sizeof(exe_handle_t));

	if (!lzexe_init(handle, f)) {
		sci_free(handle);
		return NULL;
	}

	return handle;
}
Beispiel #2
0
void file_open(EngineState *s, const char *filename, int mode) {
	const Common::String wrappedName = ((Sci::SciEngine*)g_engine)->wrapFilename(filename);
	Common::SeekableReadStream *inFile = 0;
	Common::WriteStream *outFile = 0;
	Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();

	if (mode == _K_FILE_MODE_OPEN_OR_FAIL) {
		// Try to open file, abort if not possible
		inFile = saveFileMan->openForLoading(wrappedName);
		// If no matching savestate exists: fall back to reading from a regular file
		if (!inFile)
			inFile = SearchMan.createReadStreamForMember(filename);
		if (!inFile)
			warning("file_open(_K_FILE_MODE_OPEN_OR_FAIL) failed to open file '%s'", filename);
	} else if (mode == _K_FILE_MODE_CREATE) {
		// Create the file, destroying any content it might have had
		outFile = saveFileMan->openForSaving(wrappedName);
		if (!outFile)
			warning("file_open(_K_FILE_MODE_CREATE) failed to create file '%s'", filename);
	} else if (mode == _K_FILE_MODE_OPEN_OR_CREATE) {
		// Try to open file, create it if it doesn't exist

		// FIXME: I am disabling this for now, as it's not quite clear what
		// should happen if the given file already exists... open it for appending?
		// Or (more likely), open it for reading *and* writing? We may have to
		// clone the file for that, etc., see also the long comment at the start
		// of this file.
		// We really need some examples on how this is used.
		error("file_open(_K_FILE_MODE_OPEN_OR_CREATE) File creation currently not supported");
	} else {
		error("file_open: unsupported mode %d", mode);
	}

	if (!inFile && !outFile) { // Failed
		debug(3, "file_open() failed");
		s->r_acc = make_reg(0, 0xffff);
		return;
	}


#if 0
	// FIXME: The old FreeSCI code for opening a file. Left as a reference, as apparently
	// the implementation below used to work well enough.

	debugC(2, kDebugLevelFile, "Opening file %s with mode %d\n", filename, mode);
	if ((mode == _K_FILE_MODE_OPEN_OR_FAIL) || (mode == _K_FILE_MODE_OPEN_OR_CREATE)) {
		file = sci_fopen(filename, "r" FO_BINARY "+"); // Attempt to open existing file
		debugC(2, kDebugLevelFile, "Opening file %s with mode %d\n", filename, mode);
		if (!file) {
			debugC(2, kDebugLevelFile, "Failed. Attempting to copy from resource dir...\n");
			file = f_open_mirrored(s, filename);
			if (file)
				debugC(2, kDebugLevelFile, "Success!\n");
			else
				debugC(2, kDebugLevelFile, "Not found.\n");
		}
	}

	if ((!file) && ((mode == _K_FILE_MODE_OPEN_OR_CREATE) || (mode == _K_FILE_MODE_CREATE))) {
		file = sci_fopen(filename, "w" FO_BINARY "+"); /* Attempt to create file */
		debugC(2, kDebugLevelFile, "Creating file %s with mode %d\n", filename, mode);
	}
	if (!file) { // Failed
		debugC(2, kDebugLevelFile, "file_open() failed\n");
		s->r_acc = make_reg(0, 0xffff);
		return;
	}
#endif

	// Find a free file handle
	uint handle = 1; // Ignore _fileHandles[0]
	while ((handle < s->_fileHandles.size()) && s->_fileHandles[handle].isOpen())
		handle++;

	if (handle == s->_fileHandles.size()) { // Hit size limit => Allocate more space
		s->_fileHandles.resize(s->_fileHandles.size() + 1);
	}

	s->_fileHandles[handle]._in = inFile;
	s->_fileHandles[handle]._out = outFile;
	s->_fileHandles[handle]._name = filename;

	s->r_acc = make_reg(0, handle);

	debug(3, " -> opened file '%s' with handle %d", filename, handle);
}