aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/tools.cpp
diff options
context:
space:
mode:
authorMax Horn2009-02-21 18:28:38 +0000
committerMax Horn2009-02-21 18:28:38 +0000
commit0d41ca8d38ce6c604a2a7c9c763b9bf92dd5a9c9 (patch)
tree2ff210eb071c2a9e2ba97c13adbab7261cbf5415 /engines/sci/tools.cpp
parentb6c9b12e64426e57c24dc4742bed641546bbe395 (diff)
downloadscummvm-rg350-0d41ca8d38ce6c604a2a7c9c763b9bf92dd5a9c9.tar.gz
scummvm-rg350-0d41ca8d38ce6c604a2a7c9c763b9bf92dd5a9c9.tar.bz2
scummvm-rg350-0d41ca8d38ce6c604a2a7c9c763b9bf92dd5a9c9.zip
SCI: Moved scicore/tools.cpp to tools.cpp, and include/resource.h to tools.h
svn-id: r38720
Diffstat (limited to 'engines/sci/tools.cpp')
-rw-r--r--engines/sci/tools.cpp478
1 files changed, 478 insertions, 0 deletions
diff --git a/engines/sci/tools.cpp b/engines/sci/tools.cpp
new file mode 100644
index 0000000000..b1d0829bd6
--- /dev/null
+++ b/engines/sci/tools.cpp
@@ -0,0 +1,478 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#ifdef WIN32
+# include <windows.h>
+# include <errno.h>
+# include <mmsystem.h>
+# include <sys/timeb.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# undef ARRAYSIZE
+#endif
+
+#ifdef UNIX
+#include <fnmatch.h>
+#endif
+
+#include "common/archive.h"
+#include "common/file.h"
+#include "common/util.h"
+#include "common/str.h"
+
+#include "sci/include/engine.h"
+
+namespace Sci {
+
+// FIXME: Get rid of G_DIR_SEPARATOR / G_DIR_SEPARATOR_S
+#if _MSC_VER
+# define G_DIR_SEPARATOR_S "\\"
+# define G_DIR_SEPARATOR '\\'
+#else
+# define G_DIR_SEPARATOR_S "/"
+# define G_DIR_SEPARATOR '/'
+#endif
+
+
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+int script_debug_flag = 0; // Defaulting to running mode
+int sci_debug_flags = 0; // Special flags
+
+#ifndef con_file
+# define con_file 0
+#endif
+
+int sci_ffs(int _mask) {
+ int retval = 0;
+
+ if (!_mask)
+ return 0;
+ retval++;
+ while (!(_mask & 1)) {
+ retval++;
+ _mask >>= 1;
+ }
+
+ return retval;
+}
+
+//******************* Debug functions *******************
+
+// Functions for internal macro use
+void _SCIkvprintf(FILE *file, const char *format, va_list args);
+
+void _SCIkvprintf(FILE *file, const char *format, va_list args) {
+ vfprintf(file, format, args);
+ if (con_file) vfprintf(con_file, format, args);
+}
+
+
+void _SCIkwarn(EngineState *s, const char *file, int line, int area, const char *format, ...) {
+ va_list args;
+
+ if (area == SCIkERROR_NR)
+ fprintf(stderr, "ERROR: ");
+ else
+ fprintf(stderr, "Warning: ");
+
+ va_start(args, format);
+ _SCIkvprintf(stderr, format, args);
+ va_end(args);
+ fflush(NULL);
+
+ if (sci_debug_flags & _DEBUG_FLAG_BREAK_ON_WARNINGS) script_debug_flag = 1;
+}
+
+void _SCIkdebug(EngineState *s, const char *file, int line, int area, const char *format, ...) {
+ va_list args;
+
+ if (s->debug_mode & (1 << area)) {
+ fprintf(stdout, " kernel: (%s L%d): ", file, line);
+ va_start(args, format);
+ _SCIkvprintf(stdout, format, args);
+ va_end(args);
+ fflush(NULL);
+ }
+}
+
+void _SCIGNUkdebug(const char *funcname, EngineState *s, const char *file, int line, int area, const char *format, ...) {
+ va_list xargs;
+ int error = ((area == SCIkWARNING_NR) || (area == SCIkERROR_NR));
+
+ if (error || (s->debug_mode & (1 << area))) { // Is debugging enabled for this area?
+
+ fprintf(stderr, "FSCI: ");
+
+ if (area == SCIkERROR_NR)
+ fprintf(stderr, "ERROR in %s ", funcname);
+ else if (area == SCIkWARNING_NR)
+ fprintf(stderr, "%s: Warning ", funcname);
+ else
+ fprintf(stderr, funcname);
+
+ fprintf(stderr, "(%s L%d): ", file, line);
+
+ va_start(xargs, format);
+ _SCIkvprintf(stderr, format, xargs);
+ va_end(xargs);
+
+ }
+}
+
+
+#if defined(HAVE_GETTIMEOFDAY)
+void sci_gettime(long *seconds, long *useconds) {
+ struct timeval tv;
+
+ assert(!gettimeofday(&tv, NULL));
+ *seconds = tv.tv_sec;
+ *useconds = tv.tv_usec;
+}
+#elif defined (WIN32)
+
+/*WARNING(Incorrect)*/
+/* Warning: This function only retrieves the amount of mseconds since the start of
+** the Win32 kernel; it does /not/ provide the number of seconds since the epoch!
+** There are no known cases where this causes problems, though. */
+void sci_gettime(long *seconds, long *useconds) {
+ DWORD tm;
+
+ if (TIMERR_NOERROR != timeBeginPeriod(1)) {
+ fprintf(stderr, "timeBeginPeriod(1) failed in sci_gettime\n");
+ }
+
+ tm = timeGetTime();
+
+ if (TIMERR_NOERROR != timeEndPeriod(1)) {
+ fprintf(stderr, "timeEndPeriod(1) failed in sci_gettime\n");
+ }
+
+ *seconds = tm / 1000;
+ *useconds = (tm % 1000) * 1000;
+}
+#else
+# error "You need to provide a microsecond resolution sci_gettime implementation for your platform!"
+#endif
+
+
+void sci_get_current_time(GTimeVal *val) {
+ long foo, bar;
+ sci_gettime(&foo, &bar);
+ val->tv_sec = foo;
+ val->tv_usec = bar;
+}
+
+#if defined(WIN32)
+void sci_init_dir(sci_dir_t *dir) {
+ dir->search = -1;
+}
+
+char *sci_find_first(sci_dir_t *dir, const char *mask) {
+ dir->search = _findfirst(mask, &(dir->fileinfo));
+
+ if (dir->search != -1) {
+ if (dir->fileinfo.name == NULL) {
+ return NULL;
+ }
+
+ if (strcmp(dir->fileinfo.name, ".") == 0 ||
+ strcmp(dir->fileinfo.name, "..") == 0) {
+ if (sci_find_next(dir) == NULL) {
+ return NULL;
+ }
+ }
+
+ return dir->fileinfo.name;
+ } else {
+ switch (errno) {
+ case ENOENT: {
+#ifdef _DEBUG
+ printf("_findfirst errno = ENOENT: no match\n");
+
+ if (mask)
+ printf(" in: %s\n", mask);
+ else
+ printf(" - searching in undefined directory\n");
+#endif
+ break;
+ }
+ case EINVAL: {
+ printf("_findfirst errno = EINVAL: invalid filename\n");
+ break;
+ }
+ default:
+ printf("_findfirst errno = unknown (%d)", errno);
+ }
+ }
+
+ return NULL;
+}
+
+char *sci_find_next(sci_dir_t *dir) {
+ if (dir->search == -1)
+ return NULL;
+
+ if (_findnext(dir->search, &(dir->fileinfo)) < 0) {
+ _findclose(dir->search);
+ dir->search = -1;
+ return NULL;
+ }
+
+ if (strcmp(dir->fileinfo.name, ".") == 0 ||
+ strcmp(dir->fileinfo.name, "..") == 0) {
+ if (sci_find_next(dir) == NULL) {
+ return NULL;
+ }
+ }
+
+ return dir->fileinfo.name;
+}
+
+void sci_finish_find(sci_dir_t *dir) {
+ if (dir->search != -1) {
+ _findclose(dir->search);
+ dir->search = -1;
+ }
+}
+
+#else
+
+void sci_init_dir(sci_dir_t *dir) {
+ dir->dir = NULL;
+ dir->mask_copy = NULL;
+}
+
+char *sci_find_first(sci_dir_t *dir, const char *mask) {
+ if (dir->dir)
+ closedir(dir->dir);
+
+ if (!(dir->dir = opendir("."))) {
+ sciprintf("%s, L%d: opendir(\".\") failed!\n", __FILE__, __LINE__);
+ return NULL;
+ }
+
+ dir->mask_copy = sci_strdup(mask);
+
+ return sci_find_next(dir);
+}
+
+#ifndef FNM_CASEFOLD
+#define FNM_CASEFOLD 0
+#warning "File searches will not be case-insensitive!"
+#endif
+
+char *sci_find_next(sci_dir_t *dir) {
+ struct dirent *match;
+
+ while ((match = readdir(dir->dir))) {
+ if (match->d_name[0] == '.')
+ continue;
+
+ if (!fnmatch(dir->mask_copy, match->d_name, FNM_CASEFOLD))
+ return match->d_name;
+ }
+
+ sci_finish_find(dir);
+
+ return NULL;
+}
+
+void sci_finish_find(sci_dir_t *dir) {
+ if (dir->dir) {
+ closedir(dir->dir);
+ dir->dir = NULL;
+ free(dir->mask_copy);
+ dir->mask_copy = NULL;
+ }
+}
+
+#endif
+
+int sci_mkpath(const char *path) {
+ const char *path_position = path;
+ char *next_separator = NULL;
+
+ if (chdir(G_DIR_SEPARATOR_S)) { // Go to root
+ sciprintf("Error: Could not change to root directory '%s'", G_DIR_SEPARATOR_S);
+ return -1;
+ }
+
+ do {
+ if (next_separator)
+ *next_separator = G_DIR_SEPARATOR_S[0];
+ next_separator = (char *)strchr(path_position, G_DIR_SEPARATOR_S[0]);
+
+ if (next_separator)
+ *next_separator = 0;
+
+ if (*path_position) { // Unless we're at the first slash...
+ if (chdir(path_position)) {
+ if (scimkdir(path_position, 0700) || chdir(path_position)) {
+ sciprintf("Error: Could not create subdirectory '%s' in", path_position);
+ if (next_separator)
+ *next_separator = G_DIR_SEPARATOR_S[0];
+ sciprintf(" '%s'!\n", path);
+ return -2;
+ }
+ }
+ }
+ path_position = next_separator + 1;
+
+ } while (next_separator);
+
+ return 0;
+}
+
+
+/* Returns the case-sensitive filename of a file.
+** Expects *dir to be uninitialized and the caller to free it afterwards.
+** Parameters: (const char *) fname: Name of file to get case-sensitive.
+** (sci_dir_t *) dir: Directory to find file within.
+** Returns : (char *) Case-sensitive filename of the file.
+*/
+Common::String _fcaseseek(const char *fname) {
+ // Expects *dir to be uninitialized and the caller to
+ // free it afterwards */
+
+ if (strchr(fname, G_DIR_SEPARATOR)) {
+ fprintf(stderr, "_fcaseseek() does not support subdirs\n");
+ BREAKPOINT();
+ }
+
+ // Look up the file, ignoring case
+ Common::ArchiveMemberList files;
+ SearchMan.listMatchingMembers(files, fname);
+
+ for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
+ const Common::String name = (*x)->getName();
+ if (name.equalsIgnoreCase(fname))
+ return name;
+ }
+
+ return Common::String();
+}
+
+FILE *sci_fopen(const char *fname, const char *mode) {
+ Common::String name = _fcaseseek(fname);
+ FILE *file = NULL;
+
+ if (!name.empty())
+ file = fopen(name.c_str(), mode);
+ else if (strchr(mode, 'w'))
+ file = fopen(fname, mode);
+
+ return file;
+}
+
+int sci_open(const char *fname, int flags) {
+ int file = SCI_INVALID_FD;
+ Common::String name = _fcaseseek(fname);
+ if (!name.empty())
+ file = open(name.c_str(), flags);
+
+ return file;
+}
+
+char *sci_getcwd() {
+ int size = 0;
+ char *cwd = NULL;
+
+ while (size < 8192) {
+ size += 256;
+ cwd = (char*)sci_malloc(size);
+ if (getcwd(cwd, size - 1))
+ return cwd;
+
+ free(cwd);
+ }
+
+ fprintf(stderr, "Could not determine current working directory!\n");
+
+ return NULL;
+}
+
+#ifdef __DC__
+
+int sci_fd_size(int fd) {
+ return fs_total(fd);
+}
+
+int sci_file_size(const char *fname) {
+ int fd = fs_open(fname, O_RDONLY);
+ int retval = -1;
+
+ if (fd != 0) {
+ retval = sci_fd_size(fd);
+ fs_close(fd);
+ }
+
+ return retval;
+}
+
+#else
+
+int sci_fd_size(int fd) {
+ struct stat fd_stat;
+
+ if (fstat(fd, &fd_stat))
+ return -1;
+
+ return fd_stat.st_size;
+}
+
+int sci_file_size(const char *fname) {
+ struct stat fn_stat;
+
+ if (stat(fname, &fn_stat))
+ return -1;
+
+ return fn_stat.st_size;
+}
+
+#endif
+
+/* Simple heuristic to work around array handling peculiarity in SQ4:
+It uses StrAt() to read the individual elements, so we must determine
+whether a string is really a string or an array. */
+int is_print_str(char *str) {
+ int printable = 0;
+ int len = strlen(str);
+
+ if (len == 0) return 1;
+
+ while (*str) {
+ if (isprint(*str)) printable++;
+ str++;
+ }
+
+ return ((float)printable / (float)len >= 0.5);
+}
+
+} // End of namespace Sci