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; }
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); }