aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/config-file.cpp386
-rw-r--r--common/config-file.h57
-rw-r--r--common/gameDetector.cpp632
-rw-r--r--common/gameDetector.h79
-rw-r--r--common/main.cpp150
-rw-r--r--common/scummsys.h366
-rw-r--r--common/stdafx.cpp1
-rw-r--r--common/stdafx.h169
-rw-r--r--common/system.h199
-rw-r--r--common/timer.cpp157
-rw-r--r--common/timer.h66
-rw-r--r--common/util.cpp312
-rw-r--r--common/util.h183
13 files changed, 2757 insertions, 0 deletions
diff --git a/common/config-file.cpp b/common/config-file.cpp
new file mode 100644
index 0000000000..b56630f5c5
--- /dev/null
+++ b/common/config-file.cpp
@@ -0,0 +1,386 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "stdafx.h"
+#include "config-file.h"
+#include "scumm.h"
+
+#define MAXLINELEN 256
+
+#define xfree(p) {if (p) free(p);}
+
+
+static char *ltrim(char *t)
+{
+ for (; *t && (*t == ' '); t++);
+ return t;
+}
+
+static char *rtrim(char *t)
+{
+ int l;
+
+ for (l = strlen(t) - 1; l; l--) {
+ if (t[l] == ' ') {
+ *t = 0;
+ } else {
+ return t;
+ }
+ }
+ return t;
+}
+
+class hashconfig {
+public:
+ hashconfig (const char *);
+ ~hashconfig ();
+ bool is_domain(const char *) const;
+ const char *get(const char *) const;
+ const char *set(const char *, const char *);
+ const char *getdomain() const;
+ void flush(FILE *) const;
+ void rename(const char *);
+ void merge(const hashconfig *);
+private:
+ char *domain;
+ char **keys, **values;
+ int nkeys;
+};
+
+hashconfig::hashconfig (const char *dom):domain(dom ? strdup(dom) : 0),
+keys(0), values(0), nkeys(0)
+{
+}
+
+hashconfig::~hashconfig () {
+ xfree(domain);
+}
+
+bool hashconfig::is_domain(const char *d) const
+{
+ return d && domain && !strcmp(d, domain);
+}
+
+const char *hashconfig::get(const char *key) const
+{
+ int i;
+
+ for (i = 0; i < nkeys; i++) {
+ if (!strcmp(key, keys[i])) {
+ return values[i];
+ }
+ }
+
+ return 0;
+}
+
+const char *hashconfig::set(const char *key, const char *value)
+{
+ int i;
+
+ for (i = 0; i < nkeys; i++) {
+ if (!strcmp(key, keys[i])) {
+ xfree(values[i]);
+ return values[i] = value ? strdup(value) : 0;
+ }
+ }
+
+ nkeys++;
+ keys = (char **)realloc(keys, nkeys * sizeof(char *));
+ values = (char **)realloc(values, nkeys * sizeof(char *));
+ keys[nkeys - 1] = strdup(key);
+ return values[nkeys - 1] = value ? strdup(value) : 0;
+}
+
+const char *hashconfig::getdomain() const
+{
+ return domain;
+}
+
+void hashconfig::flush(FILE *cfg_file) const
+{
+ int i;
+
+ if (!domain)
+ return;
+
+ fprintf(cfg_file, "[%s]\n", domain);
+
+ for (i = 0; i < nkeys; i++) {
+ if (values[i]) {
+ fprintf(cfg_file, "%s=%s\n", keys[i], values[i]);
+ }
+ }
+ fprintf(cfg_file, "\n");
+}
+
+void hashconfig::rename(const char *d)
+{
+ xfree(domain);
+ domain = d ? strdup(d) : 0;
+}
+
+void hashconfig::merge(const hashconfig *h)
+{
+ int i;
+
+ for (i = 0; i < h->nkeys; i++) {
+ set(h->keys[i], h->values[i]);
+ }
+}
+
+// The config-class itself.
+
+Config::Config (const char *cfg, const char *d)
+: filename(strdup(cfg)), domain(d ? strdup(d) : 0), hash(0), ndomains(0), willwrite(false)
+{
+ FILE *cfg_file;
+ char t[MAXLINELEN];
+
+ if (!(cfg_file = fopen(cfg, "r"))) {
+ debug(1, "Unable to open configuration file: %s.\n", filename);
+ } else {
+ while (!feof(cfg_file)) {
+ if (!fgets(t, MAXLINELEN, cfg_file))
+ continue;
+ if (t[0] != '#') {
+ if (t[0] == '[') {
+ // It's a new domain which begins here.
+ char *p = strchr(t, ']');
+ if (!p) {
+ debug(1, "Config file buggy: no ] at the end of the domain name.\n");
+ } else {
+ *p = 0;
+ set_domain(t + 1);
+ }
+ } else {
+ // It's a new key in the domain.
+ if (!domain) {
+ debug(1, "Config file buggy: we have a key without a domain first.\n");
+ }
+ char *p = strchr(t, '\n');
+ if (p)
+ *p = 0;
+ p = strchr(t, '\r');
+ if (p)
+ *p = 0;
+
+ if (!(p = strchr(t, '='))) {
+ if (strlen(t))
+ debug(1, "Config file buggy: there is junk: %s\n", t);
+ } else {
+ char *key, *value;
+ *p = 0;
+ key = ltrim(rtrim(t));
+ value = ltrim(p + 1);
+ set(key, value);
+ }
+ }
+ }
+ }
+ set_domain(d);
+ fclose(cfg_file);
+ }
+}
+
+Config::~Config () {
+ int i;
+
+ xfree(filename);
+ xfree(domain);
+
+ for (i = 0; i < ndomains; i++) {
+ delete hash[i];
+ }
+ xfree(hash);
+}
+
+const char *Config::get(const char *key, const char *d) const
+{
+ int i;
+
+ if (!d)
+ d = domain;
+
+ for (i = 0; i < ndomains; i++) {
+ if (hash[i]->is_domain(d)) {
+ return hash[i]->get(key);
+ }
+ }
+
+ return 0;
+}
+
+const int Config::getInt(const char *key, int def, const char *d) const
+{
+ const char *value = get(key, d);
+
+ if (value)
+ return atoi(value);
+ return def;
+}
+
+const bool Config::getBool(const char *key, bool def, const char *d) const
+{
+ const char *value = get(key, d);
+
+ if (value)
+ return !scumm_stricmp(value, "true");
+ return def;
+}
+
+const char *Config::set(const char *key, const char *value, const char *d)
+{
+ int i;
+
+ if (!d)
+ d = domain;
+
+ for (i = 0; i < ndomains; i++) {
+ if (hash[i]->is_domain(d)) {
+ return hash[i]->set(key, value);
+ }
+ }
+
+ ndomains++;
+ hash = (hashconfig **)realloc(hash, ndomains * sizeof(hashconfig *));
+ hash[ndomains - 1] = new hashconfig (d);
+
+ return hash[ndomains - 1]->set(key, value);
+}
+
+const char *Config::set(const char *key, int value_i, const char *d)
+{
+ char value[MAXLINELEN];
+ sprintf(value, "%i", value_i);
+ return set(key, value, d);
+}
+
+const char *Config::set(const char *key, bool value_b, const char *d)
+{
+ const char *value = value_b ? "true" : "false";
+ return set(key, value, d);
+}
+
+void Config::set_domain(const char *d)
+{
+ int i;
+ xfree(domain);
+ domain = d ? strdup(d) : 0;
+
+ for (i = 0; i < ndomains; i++) {
+ if (hash[i]->is_domain(domain))
+ return;
+ }
+ ndomains++;
+ hash = (hashconfig **)realloc(hash, ndomains * sizeof(hashconfig *));
+ hash[ndomains - 1] = new hashconfig (domain);
+}
+
+void Config::flush() const
+{
+ FILE *cfg_file;
+ int i;
+
+ if (!willwrite)
+ return;
+
+ if (!(cfg_file = fopen(filename, "w"))) {
+ debug(1, "Unable to write configuration file: %s.\n", filename);
+ } else {
+ for (i = 0; i < ndomains; i++) {
+ hash[i]->flush(cfg_file);
+ }
+ fclose(cfg_file);
+ }
+}
+
+void Config::rename_domain(const char *d)
+{
+ int i, index = -1;
+
+ for (i = 0; i < ndomains; i++) {
+ if (hash[i]->is_domain(d)) {
+ index = i;
+ }
+ }
+
+ for (i = 0; i < ndomains; i++) {
+ if (hash[i]->is_domain(domain)) {
+ if (index >= 0) {
+ hash[i]->merge(hash[index]);
+ hash[index]->rename(0);
+ rename_domain(d);
+ } else {
+ hash[i]->rename(d);
+ set_domain(d);
+ }
+ }
+ }
+}
+
+void Config::delete_domain(const char *d)
+{
+ int i;
+
+ for (i = 0; i < ndomains; i++) {
+ if (hash[i]->is_domain(d)) {
+ hash[i]->rename(0);
+ }
+ }
+}
+
+void Config::change_filename(const char *f)
+{
+ xfree(filename);
+ filename = f ? strdup(f) : 0;
+}
+
+void Config::merge_config(const Config *c)
+{
+ int i, j;
+ bool found;
+
+ for (i = 0; i < c->ndomains; i++) {
+ found = false;
+ for (j = 0; j < ndomains; j++) {
+ if (hash[j]->is_domain(c->hash[i]->getdomain())) {
+ hash[j]->merge(c->hash[i]);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ndomains++;
+ hash = (hashconfig **)realloc(hash, ndomains * sizeof(hashconfig *));
+ hash[ndomains - 1] = new hashconfig (domain);
+ hash[ndomains - 1]->merge(c->hash[i]);
+ }
+ }
+}
+
+void Config::set_writing(bool w)
+{
+ willwrite = w;
+}
diff --git a/common/config-file.h b/common/config-file.h
new file mode 100644
index 0000000000..eee4cfde59
--- /dev/null
+++ b/common/config-file.h
@@ -0,0 +1,57 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef CONFIG_FILE_H
+#define CONFIG_FILE_H
+
+class hashconfig;
+
+class Config {
+public:
+ Config (const char * = "config.cfg", const char * = "default");
+ ~Config ();
+ const char *get(const char *key, const char *dom = 0) const;
+ const int getInt(const char *key, int def = 0, const char *dom = 0) const;
+ const bool getBool(const char *key, bool def = false, const char *dom = 0) const;
+
+ const char *set(const char *key, const char *value, const char *dom = 0);
+ const char *set(const char *key, int value, const char *dom = 0);
+ const char *set(const char *key, bool value, const char *dom = 0);
+
+ void set_domain(const char *);
+ void flush() const;
+ void rename_domain(const char *);
+ void delete_domain(const char *);
+ void change_filename(const char *);
+ void merge_config(const Config *);
+ void set_writing(bool);
+private:
+ char *filename, *domain;
+ hashconfig **hash;
+ int ndomains;
+ bool willwrite;
+};
+
+// The global config object
+extern Config *scummcfg;
+
+#endif
diff --git a/common/gameDetector.cpp b/common/gameDetector.cpp
new file mode 100644
index 0000000000..421dfd782e
--- /dev/null
+++ b/common/gameDetector.cpp
@@ -0,0 +1,632 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+
+#include "stdafx.h"
+#include "scumm/scumm.h"
+#include "sound/mididrv.h"
+#include "scumm/imuse.h"
+#include "common/gameDetector.h"
+#include "common/config-file.h"
+
+
+#define CHECK_OPTION() if ((current_option != NULL) || (*s != '\0')) goto ShowHelpAndExit
+#define HANDLE_OPTION() if ((*s == '\0') && (current_option == NULL)) goto ShowHelpAndExit; \
+ if ((*s != '\0') && (current_option != NULL)) goto ShowHelpAndExit; \
+ option = (*s == '\0' ? current_option : s); \
+ current_option = NULL
+#define HANDLE_OPT_OPTION() if ((*s != '\0') && (current_option != NULL)) goto ShowHelpAndExit; \
+ if ((*s == '\0') && (current_option == NULL)) option = NULL; \
+ else option = (*s == '\0' ? current_option : s); \
+ current_option = NULL
+
+static const char USAGE_STRING[] =
+ "ScummVM - Scumm Interpreter\n"
+ "Syntax:\n"
+ "\tscummvm [-v] [-d[<num>]] [-n] [-b<num>] [-t<num>] [-s<num>] [-p<path>] [-m<num>] [-f] game\n"
+ "Flags:\n"
+ "\t-a - specify game is amiga version\n"
+ "\t-b<num> - start in room <num>\n"
+ "\t-c<num> - use cdrom <num> for cd audio\n"
+ "\t-d[<num>] - enable debug output (debug level [1])\n"
+ "\t-e<mode> - set music engine (see readme.txt for details)\n"
+ "\t-f - fullscreen mode\n"
+ "\t-g<mode> - graphics mode (normal,2x,3x,2xsai,super2xsai,supereagle,advmame2x)\n"
+ "\t-l<file> - load config file instead of default\n"
+ "\t-m<num> - set music volume to <num> (0-100)\n"
+ "\t-n - no subtitles for speech\n"
+ "\t-p<path> - look for game in <path>\n"
+ "\t-s<num> - set sfx volume to <num> (0-255)\n"
+ "\t-t<num> - set music tempo (default- adlib: 0x1F0000, midi: 0x460000)\n"
+ "\t-v - show version info and exit\n"
+#if defined(UNIX)
+ "\t-w[<file>] - write to config file [~/.scummvmrc]\n"
+#else
+ "\t-w[<file>] - write to config file [scummvm.ini]\n"
+#endif
+ "\t-x[<num>] - save game slot to load (default: autosave)\n"
+ "\t-y - set text speed (default: 60)\n"
+;
+
+void GameDetector::updateconfig()
+{
+ const char * val;
+
+ _amiga = scummcfg->getBool("amiga", _amiga);
+
+ _save_slot = scummcfg->getInt("save_slot", _save_slot);
+
+ _cdrom = scummcfg->getInt("cdrom", _cdrom);
+
+ if ((val = scummcfg->get("music_driver")))
+ if (!parseMusicDriver(val)) {
+ printf("Error in the config file: invalid music_driver.\n");
+ printf(USAGE_STRING);
+ exit(-1);
+ }
+
+ _fullScreen = scummcfg->getBool("fullscreen", _fullScreen);
+
+ if ((val = scummcfg->get("gfx_mode")))
+ if ((_gfx_mode = parseGraphicsMode(val)) == -1) {
+ printf("Error in the config file: invalid gfx_mode.\n");
+ printf(USAGE_STRING);
+ exit(-1);
+ }
+
+ _music_volume = scummcfg->getInt("music_volume", _music_volume);
+
+ _noSubtitles = scummcfg->getBool("nosubtitles", _noSubtitles);
+
+ if ((val = scummcfg->get("path")))
+ _gameDataPath = strdup(val);
+
+ _sfx_volume = scummcfg->getInt("sfx_volume", _sfx_volume);
+
+ // We use strtol for the tempo to allow it to be specified in hex.
+ if ((val = scummcfg->get("tempo")))
+ _gameTempo = strtol(val, NULL, 0);
+
+ _talkSpeed = scummcfg->getInt("talkspeed", _talkSpeed);
+}
+
+void GameDetector::parseCommandLine(int argc, char **argv)
+{
+ int i;
+ char *s;
+ char *current_option = NULL;
+ char *option = NULL;
+ char c;
+ _save_slot = -1;
+
+ // check for arguments
+ if (argc < 2) {
+ printf(USAGE_STRING);
+ //exit(1);
+ }
+
+ scummcfg->set_domain("game-specific");
+ /* Parse the arguments */
+ for (i = argc - 1; i >= 1; i--) {
+ s = argv[i];
+
+ if (s[0] == '-') {
+ s++;
+ c = *s++;
+ switch (tolower(c)) {
+ case 'a':
+ CHECK_OPTION();
+ _amiga = (c == 'a');
+ scummcfg->set("amiga", _amiga);
+ break;
+ case 'b':
+ HANDLE_OPTION();
+ _bootParam = atoi(option);
+ break;
+ case 'c':
+ HANDLE_OPTION();
+ _cdrom = atoi(option);
+ scummcfg->set("cdrom", _cdrom);
+ break;
+ case 'd':
+ _debugMode = true;
+ HANDLE_OPT_OPTION();
+ if (option != NULL)
+ _debugLevel = atoi(option);
+ debug(1,"Debugmode (level %d) on", _debugLevel);
+ break;
+ case 'e':
+ HANDLE_OPTION();
+ if (!parseMusicDriver(option))
+ goto ShowHelpAndExit;
+ scummcfg->set("music_driver", option);
+ break;
+ case 'f':
+ CHECK_OPTION();
+ _fullScreen = (c == 'f');
+ scummcfg->set("fullscreen", _fullScreen, "scummvm");
+ break;
+ case 'g':
+ HANDLE_OPTION();
+ _gfx_mode = parseGraphicsMode(option);
+ if (_gfx_mode == -1)
+ goto ShowHelpAndExit;
+ scummcfg->set("gfx_mode", option, "scummvm");
+ break;
+ case 'l':
+ HANDLE_OPTION();
+ {
+ Config * newconfig = new Config(option, "scummvm");
+ scummcfg->merge_config(newconfig);
+ delete newconfig;
+ updateconfig();
+ break;
+ }
+ break;
+ case 'm':
+ HANDLE_OPTION();
+ _music_volume = atoi(option);
+ scummcfg->set("music_volume", _music_volume);
+ break;
+ case 'n':
+ CHECK_OPTION();
+ _noSubtitles = (c == 'n');
+ scummcfg->set("nosubtitles", _noSubtitles);
+ break;
+ case 'p':
+ HANDLE_OPTION();
+ _gameDataPath = option;
+ scummcfg->set("path", _gameDataPath);
+ break;
+ case 'r':
+ HANDLE_OPTION();
+ // Ignore -r for now, to ensure backward compatibility.
+ break;
+ case 's':
+ HANDLE_OPTION();
+ _sfx_volume = atoi(option);
+ scummcfg->set("sfx_volume", _sfx_volume);
+ break;
+ case 't':
+ HANDLE_OPTION();
+ _gameTempo = strtol(option, 0, 0);
+ scummcfg->set("tempo", option);
+ break;
+ case 'v':
+ CHECK_OPTION();
+ printf("ScummVM " SCUMMVM_VERSION "\nBuilt on " __DATE__ " "
+ __TIME__ "\n");
+#ifdef SCUMMVM_PLATFORM_VERSION
+ printf(" " SCUMMVM_PLATFORM_VERSION "\n");
+#endif
+ exit(1);
+ case 'w':
+ _saveconfig = true;
+ scummcfg->set_writing(true);
+ HANDLE_OPT_OPTION();
+ if (option != NULL)
+ scummcfg->change_filename(option);
+ break;
+ case 'x':
+ _save_slot = 0;
+ HANDLE_OPT_OPTION();
+ if (option != NULL) {
+ _save_slot = atoi(option);
+ scummcfg->set("save_slot", _save_slot);
+ }
+ break;
+ case 'y':
+ HANDLE_OPTION();
+ _talkSpeed = atoi(option);
+ scummcfg->set("talkspeed", _talkSpeed);
+ break;
+ default:
+ goto ShowHelpAndExit;
+ }
+ } else {
+ if (i == (argc - 1)) {
+ _exe_name = s;
+ scummcfg->set_domain(s);
+ scummcfg->rename_domain("game-specific");
+ scummcfg->rename_domain(s);
+ updateconfig();
+ } else {
+ if (current_option == NULL)
+ current_option = s;
+ else
+ goto ShowHelpAndExit;
+ }
+ }
+ }
+
+ if (_exe_name)
+ scummcfg->flush();
+
+ return;
+
+ ShowHelpAndExit:
+ printf(USAGE_STRING);
+ exit(1);
+}
+
+int GameDetector::parseGraphicsMode(const char *s) {
+ struct GraphicsModes {
+ const char *name;
+ int id;
+ };
+
+ const struct GraphicsModes gfx_modes[] = {
+ {"normal",GFX_NORMAL},
+ {"1x",GFX_NORMAL},
+ {"2x",GFX_DOUBLESIZE},
+ {"3x",GFX_TRIPLESIZE},
+ {"2xsai",GFX_2XSAI},
+ {"super2xsai",GFX_SUPER2XSAI},
+ {"supereagle",GFX_SUPEREAGLE},
+ {"advmame2x",GFX_ADVMAME2X}
+ };
+
+ const GraphicsModes *gm = gfx_modes;
+ int i;
+ for(i=0; i!=ARRAYSIZE(gfx_modes); i++,gm++) {
+ if (!scumm_stricmp(gm->name, s))
+ return gm->id;
+ }
+
+ return -1;
+}
+
+bool GameDetector::parseMusicDriver(const char *s) {
+ struct MusicDrivers {
+ const char *name;
+ int id;
+ };
+
+ const struct MusicDrivers music_drivers[] = {
+ {"auto",MD_AUTO},
+ {"null",MD_NULL},
+ {"windows",MD_WINDOWS},
+ {"seq",MD_SEQ},
+ {"qt",MD_QTMUSIC},
+ {"core",MD_COREAUDIO},
+ {"amidi",MD_AMIDI},
+ {"midiemu",MD_MIDIEMU},
+ {"alsa", MD_ALSA},
+ {"adlib",-1},
+ };
+
+ const MusicDrivers *md = music_drivers;
+ int i;
+
+ _use_adlib = false;
+
+ for(i=0; i!=ARRAYSIZE(music_drivers); i++,md++) {
+ if (!scumm_stricmp(md->name, s)) {
+ if (md->id == -1) {
+ _use_adlib = true;
+ }
+ _midi_driver = md->id;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+struct VersionSettings {
+ const char *filename;
+ const char *gamename;
+ byte id, major, middle, minor;
+ uint32 features;
+};
+
+/*
+ This is a list of all known SCUMM games. Commented games are not
+ supported at this time */
+
+static const VersionSettings version_settings[] = {
+ /* Scumm Version 1 */
+// {"maniac", "Maniac Mansion (C64)", GID_MANIAC64, 1, 0, 0,},
+// {"zak", "Zak McKracken and the Alien Mindbenders (C64)", GID_ZAK64, 1, 0, 0,},
+
+ /* Scumm Version 2 */
+// {"maniac", "Maniac Mansion", GID_MANIAC, 2, 0, 0,},
+// {"zak", "Zak McKracken and the Alien Mindbenders", GID_ZAK, 2, 0, 0,},
+// {"indy3", "Indiana Jones and the Last Crusade", GID_INDY3, 2, 0, 0,},
+
+ /* Scumm Version 3 */
+ {"indy3", "Indiana Jones and the Last Crusade (256)", GID_INDY3_256, 3, 0, 22,
+ GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD256 | GF_NO_SCALLING},
+ {"zak256", "Zak McKracken and the Alien Mindbenders (256)", GID_ZAK256, 3, 0, 0,
+ GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD256 | GF_AUDIOTRACKS | GF_NO_SCALLING},
+ {"loom", "Loom", GID_LOOM, 3, 5, 40,
+ GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD_BUNDLE | GF_16COLOR | GF_NO_SCALLING},
+
+ /* Scumm Version 4 */
+ {"monkeyEGA", "Monkey Island 1 (EGA)", GID_MONKEY_EGA, 4, 0, 67,
+ GF_SMALL_HEADER | GF_USE_KEY | GF_16COLOR}, // EGA version
+
+ /* Scumm version 5 */
+ {"monkeyVGA", "Monkey Island 1 (256 color Floppy version)", GID_MONKEY_VGA, 5, 0, 16,
+ GF_SMALL_HEADER | GF_USE_KEY | GF_AUDIOTRACKS | GF_ADLIB_DEFAULT},
+ {"loomcd", "Loom (256 color CD version)", GID_LOOM256, 5, 1, 42,
+ GF_SMALL_HEADER | GF_USE_KEY | GF_AUDIOTRACKS | GF_ADLIB_DEFAULT},
+ {"monkey", "Monkey Island 1", GID_MONKEY, 5, 2, 2,
+ GF_USE_KEY | GF_AUDIOTRACKS | GF_ADLIB_DEFAULT},
+ {"monkey1", "Monkey Island 1 (alt)", GID_MONKEY, 5, 2, 2,
+ GF_USE_KEY | GF_AUDIOTRACKS | GF_ADLIB_DEFAULT},
+ {"monkey2", "Monkey Island 2: LeChuck's revenge", GID_MONKEY2, 5, 2, 2,
+ GF_USE_KEY | GF_ADLIB_DEFAULT},
+ {"atlantis", "Indiana Jones and the Fate of Atlantis", GID_INDY4, 5, 5, 0,
+ GF_USE_KEY | GF_ADLIB_DEFAULT},
+ {"playfate", "Indiana Jones and the Fate of Atlantis (Demo)", GID_INDY4, 5, 5, 0,
+ GF_USE_KEY | GF_ADLIB_DEFAULT},
+ {"fate", "Indiana Jones and the Fate of Atlantis (Demo)", GID_INDY4, 5, 5, 0,
+ GF_USE_KEY | GF_ADLIB_DEFAULT},
+
+ /* Scumm Version 6 */
+ {"tentacle", "Day Of The Tentacle", GID_TENTACLE, 6, 4, 2,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_USE_KEY | GF_ADLIB_DEFAULT},
+ {"dottdemo", "Day Of The Tentacle (Demo)", GID_TENTACLE, 6, 3, 2,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_USE_KEY | GF_ADLIB_DEFAULT},
+ {"samnmax", "Sam & Max", GID_SAMNMAX, 6, 4, 2,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_USE_KEY | GF_DRAWOBJ_OTHER_ORDER},
+ {"samdemo", "Sam & Max (Demo)", GID_SAMNMAX, 6, 3, 0,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_USE_KEY | GF_DRAWOBJ_OTHER_ORDER | GF_ADLIB_DEFAULT},
+ {"snmdemo", "Sam & Max (Demo)", GID_SAMNMAX, 6, 3, 0,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_USE_KEY | GF_DRAWOBJ_OTHER_ORDER | GF_ADLIB_DEFAULT},
+
+ {"puttdemo", "Putt Putt joins the parade (demo)", GID_SAMNMAX, 6, 3, 0,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_USE_KEY | GF_ADLIB_DEFAULT | GF_HUMONGOUS},
+ {"moondemo", "Putt Putt goes to the moon (demo)", GID_SAMNMAX, 6, 3, 0,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_USE_KEY | GF_ADLIB_DEFAULT | GF_HUMONGOUS},
+
+ {"test", "Test demo game", GID_SAMNMAX, 6, 6, 6, GF_NEW_OPCODES | GF_AFTER_V6},
+
+ /* Scumm Version 7 */
+ {"ft", "Full Throttle", GID_FT, 7, 3, 0,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_AFTER_V7},
+ {"dig", "The Dig", GID_DIG, 7, 5, 0,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_AFTER_V7},
+
+ /* Simon the Sorcerer 1 & 2 (not SCUMM games) */
+ {"simon1dos", "Simon the Sorcerer 1 for DOS", GID_SIMON_FIRST+0, 99, 99, 99, 0},
+ {"simon2dos", "Simon the Sorcerer 2 for DOS", GID_SIMON_FIRST+1, 99, 99, 99, 0},
+ {"simon1win", "Simon the Sorcerer 1 for Windows", GID_SIMON_FIRST+2, 99, 99, 99, 0},
+ {"simon2win", "Simon the Sorcerer 2 for Windows", GID_SIMON_FIRST+3, 99, 99, 99, 0},
+
+ /* Scumm Version 8 */
+ {"comi", "The Curse of Monkey Island", GID_CMI, 8, 1, 0,
+ GF_NEW_OPCODES | GF_AFTER_V6 | GF_AFTER_V7 | GF_AFTER_V8},
+
+ {NULL, NULL}
+};
+
+bool GameDetector::detectGame()
+{
+ const VersionSettings *gnl = version_settings;
+
+ _gameId = 0;
+ _gameText = NULL;
+ do {
+ if (!scumm_stricmp(_exe_name, gnl->filename)) {
+ _gameId = gnl->id;
+ _scummVersion = gnl->major;
+
+ _features = gnl->features;
+ _gameText = gnl->gamename;
+ debug(1, "Detected game '%s', version %d.%d.%d",
+ gnl->gamename, gnl->major, gnl->middle, gnl->minor);
+ return true;
+ }
+ } while ((++gnl)->filename);
+
+ debug(1, "Failed game detection");
+
+ return true;
+}
+
+char *GameDetector::getGameName()
+{
+ if (_gameText == NULL) {
+ char buf[256];
+ sprintf(buf, "Unknown game: \"%s\"", _exe_name);
+ return strdup(buf);
+ }
+ return strdup(_gameText);
+}
+
+int GameDetector::detectMain(int argc, char **argv)
+{
+ _debugMode = 0; // off by default...
+
+ _noSubtitles = 0; // use by default - should this depend on soundtrack?
+
+ _talkSpeed = 60;
+
+#ifndef _WIN32_WCE
+ _gfx_mode = GFX_DOUBLESIZE;
+#else
+ _gfx_mode = GFX_NORMAL;
+#endif
+ _sfx_volume = kDefaultSFXVolume;
+ _music_volume = kDefaultMusicVolume;
+
+#if defined(USE_NULL_DRIVER)
+ _gfx_driver = GD_NULL;
+#elif defined(__DC__)
+ _gfx_driver = GD_DC;
+#elif defined(X11_BACKEND)
+ _gfx_driver = GD_X;
+#elif defined(__MORPHOS__)
+ _gfx_driver = GD_MORPHOS;
+#elif defined(_WIN32_WCE)
+ _gfx_driver = GD_WINCE;
+#elif defined(MACOS_CARBON)
+ _gfx_driver = GD_MAC;
+#else
+ /* SDL is the default driver for now */
+ _gfx_driver = GD_SDL;
+#endif
+
+ _gameDataPath = NULL;
+ _gameTempo = 0;
+ _soundCardType = 3;
+
+
+
+ _midi_driver = MD_AUTO;
+
+#if defined(__DC__)
+ extern int dc_setup(GameDetector &detector);
+ dc_setup(*this);
+#elif defined(MACOS_CARBON)
+ extern char* SelectGame();
+ char *game_name = SelectGame();
+ printf(game_name);
+#else
+ _saveconfig = false;
+ updateconfig();
+ parseCommandLine(argc, argv);
+#endif
+
+ if (_exe_name == NULL) {
+ //launcherLoop();
+ //setWindowName(this);
+ warning("No game was specified...");
+ return (-1);
+ }
+
+
+ if (!detectGame()) {
+ warning("Game detection failed. Using default settings");
+ _features = GF_DEFAULT;
+ _gameText = "Please choose a game";
+ }
+
+ /* Use the adlib sound driver if auto mode is selected,
+ * and the game is one of those that want adlib as
+ * default */
+ if (_midi_driver == MD_AUTO && _features&GF_ADLIB_DEFAULT) {
+ _use_adlib = true;
+ }
+
+ if (!_gameDataPath) {
+ warning("No path was provided. Assuming the data files are in the current directory");
+ _gameDataPath = strdup("");
+ } else if (_gameDataPath[strlen(_gameDataPath)-1] != '/'
+#ifdef __MORPHOS__
+ && _gameDataPath[strlen(_gameDataPath)-1] != ':'
+#endif
+ && _gameDataPath[strlen(_gameDataPath)-1] != '\\') {
+ char slashless[1024]; /* Append slash to path */
+ strcpy(slashless, _gameDataPath);
+ _gameDataPath = (char *)malloc((strlen(slashless) + 1) * sizeof(char));
+ sprintf(_gameDataPath, "%s/", slashless);
+ }
+
+ if (_amiga)
+ _features = _features | GF_AMIGA;
+
+ return (0);
+}
+
+OSystem *GameDetector::createSystem() {
+ /* auto is to use SDL */
+ switch(_gfx_driver) {
+#if defined(X11_BACKEND)
+ case GD_X:
+ return OSystem_X11_create();
+#elif defined(__DC__)
+ case GD_DC:
+ return OSystem_Dreamcast_create();
+#elif defined(_WIN32_WCE)
+ case GD_WINCE:
+ return OSystem_WINCE3_create();
+#elif defined(__MORPHOS__)
+ case GD_MORPHOS:
+ return OSystem_MorphOS_create(_gameId, _gfx_mode, _fullScreen);
+#elif defined(MACOS_CARBON)
+ case GD_MAC:
+ return OSystem_MAC_create(_gfx_mode, _fullScreen);
+#elif defined(USE_NULL_DRIVER)
+ case GD_NULL:
+ return OSystem_NULL_create();
+#else
+ case GD_SDL:
+ return OSystem_SDL_create(_gfx_mode, _fullScreen);
+#endif
+ }
+
+ error("Invalid graphics driver");
+ return NULL;
+}
+
+MidiDriver *GameDetector::createMidi() {
+ int drv = _midi_driver;
+
+#if defined (_WIN32_WCE)
+ /* Always use MIDI emulation on CE devices */
+ if (drv == MD_AUTO) drv = MD_MIDIEMU;
+#endif
+
+#if defined (WIN32) && !defined(_WIN32_WCE)
+ /* MD_WINDOWS is default MidiDriver on windows targets */
+ if (drv == MD_AUTO) drv = MD_WINDOWS;
+#elif defined(__APPLE__) || defined(macintosh)
+ /* MD_QTMUSIC is default MidiDriver on MacOS targets */
+ if (drv == MD_AUTO) drv = MD_QTMUSIC;
+#elif defined(UNIX) || defined(X11_BACKEND)
+ /* MD_MIDIEMU is default MidiDriver on UNIX targets. */
+ /* FIXME: Attempt to detect if sequencer is available,
+ and use it in preference. */
+ if (drv == MD_AUTO) drv = MD_MIDIEMU;
+#endif
+
+ switch(drv) {
+ case MD_AUTO:
+ case MD_NULL: return MidiDriver_NULL_create();
+ case MD_MIDIEMU: return MidiDriver_MIDIEMU_create();
+#if defined(WIN32) && !defined(_WIN32_WCE)
+ case MD_WINDOWS: return MidiDriver_WIN_create();
+#endif
+#if defined(__MORPHOS__)
+ case MD_AMIDI: return MidiDriver_AMIDI_create();
+#endif
+#if defined(UNIX) && !defined(__BEOS__)
+ case MD_SEQ: return MidiDriver_SEQ_create();
+#endif
+#if defined(__APPLE__) || defined(macintosh)
+ case MD_QTMUSIC: return MidiDriver_QT_create();
+#endif
+#if defined(MACOSX)
+ case MD_COREAUDIO: return MidiDriver_CORE_create();
+#endif
+#if defined(UNIX) && defined(USE_ALSA)
+ case MD_ALSA: return MidiDriver_ALSA_create();
+#endif
+ }
+
+ error("Invalid midi driver selected");
+ return NULL;
+}
diff --git a/common/gameDetector.h b/common/gameDetector.h
new file mode 100644
index 0000000000..4cbfa3453f
--- /dev/null
+++ b/common/gameDetector.h
@@ -0,0 +1,79 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef GAMEDETECTOR_H
+#define GAMEDETECTOR_H
+
+class OSystem;
+class MidiDriver;
+
+class GameDetector {
+public:
+ int detectMain(int argc, char **argv);
+ void parseCommandLine(int argc, char **argv);
+ bool detectGame(void);
+ char *getGameName(void);
+
+ bool _fullScreen;
+ byte _gameId;
+ bool _simon;
+
+ bool _use_adlib;
+
+ int _music_volume;
+ int _sfx_volume;
+ bool _amiga;
+
+ uint16 _talkSpeed;
+ uint16 _debugMode;
+ uint16 _noSubtitles;
+ uint16 _bootParam;
+ uint16 _soundCardType;
+
+ char *_gameDataPath;
+ int _gameTempo;
+ int _midi_driver;
+ char *_exe_name;
+ const char *_gameText;
+ uint32 _features;
+
+ int _gfx_driver;
+ int _gfx_mode;
+
+ int _scummVersion;
+ int _cdrom;
+ int _save_slot;
+
+ bool _saveconfig;
+
+ int parseGraphicsMode(const char *s);
+
+ bool parseMusicDriver(const char *s);
+
+ void updateconfig();
+
+public:
+ OSystem *createSystem();
+ MidiDriver *createMidi();
+};
+
+#endif
diff --git a/common/main.cpp b/common/main.cpp
new file mode 100644
index 0000000000..43fd2e4563
--- /dev/null
+++ b/common/main.cpp
@@ -0,0 +1,150 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "stdafx.h"
+#include "engine.h"
+#include "scumm.h"
+#include "sound/mididrv.h"
+#include "gameDetector.h"
+#include "simon/simon.h"
+#include "config-file.h"
+
+GameDetector detector;
+
+Config *scummcfg = 0;
+
+
+#if defined(QTOPIA)
+// FIXME - why exactly is this needed?
+extern "C" int main(int argc, char *argv[]);
+#endif
+
+#if defined(MACOSX) || defined(QTOPIA)
+#include <SDL.h>
+#elif !defined(__MORPHOS__)
+#undef main
+#endif
+
+#if defined(UNIX)
+#include <sys/param.h>
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 256
+#endif
+#define DEFAULT_CONFIG_FILE ".scummvmrc"
+#else
+#define DEFAULT_CONFIG_FILE "scummvm.ini"
+#endif
+
+#if defined(UNIX)
+#include <signal.h>
+
+#ifndef SCUMM_NEED_ALIGNMENT
+static void handle_errors(int sig_num) {
+ error("Your system does not support unaligned memory accesses. Please rebuild with SCUMM_NEED_ALIGNMENT ");
+}
+#endif
+
+/* This function is here to test if the endianness / alignement compiled it is matching
+ with the one at run-time. */
+static void do_memory_test(void) {
+ unsigned char test[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
+ unsigned int value;
+ /* First test endianness */
+#ifdef SCUMM_LITTLE_ENDIAN
+ if (*((int *) test) != 0x44332211) {
+ error("Compiled as LITTLE_ENDIAN on a big endian system. Please rebuild ");
+ }
+ value = 0x55443322;
+#else
+ if (*((int *) test) != 0x11223344) {
+ error("Compiled as BIG_ENDIAN on a little endian system. Please rebuild ");
+ }
+ value = 0x22334455;
+#endif
+ /* Then check if one really supports unaligned memory accesses */
+#ifndef SCUMM_NEED_ALIGNMENT
+ signal(SIGBUS, handle_errors);
+ signal(SIGABRT, handle_errors);
+ signal(SIGSEGV, handle_errors);
+ if (*((unsigned int *) ((char *) test + 1)) != value) {
+ error("Your system does not support unaligned memory accesses. Please rebuild with SCUMM_NEED_ALIGNMENT ");
+ }
+ signal(SIGBUS, SIG_DFL);
+ signal(SIGABRT, SIG_DFL);
+ signal(SIGSEGV, SIG_DFL);
+#endif
+}
+
+#endif
+
+int main(int argc, char *argv[])
+{
+#ifdef __DC__
+ extern void dc_init_hardware();
+ dc_init_hardware();
+#endif
+
+#if defined(UNIX)
+ /* On Unix, do a quick endian / alignement check before starting */
+ do_memory_test();
+
+ char scummhome[MAXPATHLEN];
+ if(getenv("HOME") != NULL)
+ sprintf(scummhome,"%s/%s", getenv("HOME"), DEFAULT_CONFIG_FILE);
+ else strcpy(scummhome,DEFAULT_CONFIG_FILE);
+#else
+ char scummhome[255];
+ #if defined (WIN32) && !defined(_WIN32_WCE)
+ GetWindowsDirectory(scummhome, 255);
+ strcat(scummhome, "\\");
+ strcat(scummhome, DEFAULT_CONFIG_FILE);
+ #else
+ strcpy(scummhome,DEFAULT_CONFIG_FILE);
+ #endif
+#endif
+
+ scummcfg = new Config(scummhome, "scummvm");
+ scummcfg->set("versioninfo", SCUMMVM_VERSION);
+ if (detector.detectMain(argc, argv))
+ return (-1);
+
+ OSystem *system = detector.createSystem();
+
+ {
+ char *s = detector.getGameName();
+ OSystem::Property prop;
+
+ prop.caption = s;
+ system->property(OSystem::PROP_SET_WINDOW_CAPTION, &prop);
+ free(s);
+ }
+
+ // Create the game engine
+ Engine *engine = Engine::createFromDetector(&detector, system);
+
+ // Run the game engine
+ engine->go();
+
+ delete scummcfg;
+
+ return 0;
+}
diff --git a/common/scummsys.h b/common/scummsys.h
new file mode 100644
index 0000000000..74fcfbcb84
--- /dev/null
+++ b/common/scummsys.h
@@ -0,0 +1,366 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+#ifndef __SCUMMSYS_H_
+#define __SCUMMSYS_H_
+
+#include <stdlib.h>
+
+#if defined(HAVE_NO_BOOL)
+typedef int bool;
+const bool true(1), false(0);
+#endif /* HAVE_NO_BOOL */
+
+#if defined(_MSC_VER)
+
+//#pragma warning (disable: 4244)
+//#pragma warning (disable: 4101)
+
+#define scumm_stricmp stricmp
+
+#if defined(CHECK_HEAP)
+#undef CHECK_HEAP
+#define CHECK_HEAP checkHeap();
+#else
+#define CHECK_HEAP
+#endif
+
+#define SCUMM_LITTLE_ENDIAN
+
+#define FORCEINLINE __forceinline
+#define NORETURN _declspec(noreturn)
+
+typedef unsigned char byte;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned long uint32;
+typedef unsigned int uint;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed long int32;
+
+#define START_PACK_STRUCTS pack (push,1)
+#define END_PACK_STRUCTS pack(pop)
+#define GCC_PACK
+
+#elif defined(__MINGW32__)
+
+#define scumm_stricmp stricmp
+#define CHECK_HEAP
+#define SCUMM_LITTLE_ENDIAN
+
+#define FORCEINLINE inline
+#define NORETURN __attribute__((__noreturn__))
+#define GCC_PACK __attribute__((packed))
+#define _HEAPOK 0
+
+typedef unsigned char byte;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned long uint32;
+typedef unsigned int uint;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed long int32;
+
+#define START_PACK_STRUCTS pack (push,1)
+#define END_PACK_STRUCTS pack(pop)
+
+#elif defined(UNIX) || defined(__APPLE__)
+
+#define scumm_stricmp strcasecmp
+
+#define CHECK_HEAP
+
+#ifdef X11_BACKEND
+
+/* You need to set those manually */
+#define SCUMM_LITTLE_ENDIAN
+/* #define SCUMM_NEED_ALIGNMENT */
+
+#else
+/* need this for the SDL_BYTEORDER define */
+#include <SDL_byteorder.h>
+
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define SCUMM_LITTLE_ENDIAN
+#elif SDL_BYTEORDER == SDL_BIG_ENDIAN
+#define SCUMM_BIG_ENDIAN
+#define SCUMM_NEED_ALIGNMENT
+#else
+#error Neither SDL_BIG_ENDIAN nor SDL_LITTLE_ENDIAN is set.
+#endif
+#endif
+
+#define FORCEINLINE inline
+#define CDECL
+
+typedef unsigned char byte;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint;
+typedef signed char int8;
+typedef signed short int16;
+
+# if defined(__DECCXX) // Assume alpha architecture
+
+# define INVERSE_MKID
+# define SCUMM_NEED_ALIGNMENT
+
+typedef unsigned int uint32;
+typedef signed int int32;
+
+# else
+
+typedef unsigned long uint32;
+typedef signed long int32;
+
+# endif
+
+
+#if defined(__GNUC__)
+#define START_PACK_STRUCTS
+#define END_PACK_STRUCTS
+#define GCC_PACK __attribute__((packed))
+#define NORETURN __attribute__((__noreturn__))
+#else
+#define START_PACK_STRUCTS pack (1)
+#define END_PACK_STRUCTS pack ()
+#define GCC_PACK
+#define NORETURN
+#endif
+
+#elif defined(macintosh)
+#include <stdio.h>
+
+#include "macos.h"
+
+#define scumm_stricmp strcmp
+inline char* strdup(char *buf) {return (char*)buf;};
+
+#define CHECK_HEAP
+#define SCUMM_BIG_ENDIAN
+
+#define FORCEINLINE inline
+#define CDECL
+
+typedef unsigned char byte;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned long uint32;
+typedef unsigned int uint;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed long int32;
+
+#define START_PACK_STRUCTS pack (1)
+#define END_PACK_STRUCTS pack ()
+#define GCC_PACK
+#define NORETURN
+#define USE_QTMUSIC
+#define NEED_STRDUP
+
+#elif defined(__MORPHOS__)
+#define scumm_stricmp stricmp
+#define CHECK_HEAP
+
+#define SCUMM_BIG_ENDIAN
+#define SCUMM_NEED_ALIGNMENT
+
+#define FORCEINLINE inline
+#define CDECL
+
+typedef unsigned char byte;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned long uint32;
+typedef unsigned int uint;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed long int32;
+
+#if defined(__GNUC__)
+ #define START_PACK_STRUCTS
+ #define END_PACK_STRUCTS
+ #define GCC_PACK __attribute__((packed))
+ #define NORETURN __attribute__((__noreturn__))
+#else
+ #define START_PACK_STRUCTS pack (1)
+ #define END_PACK_STRUCTS pack ()
+ #define GCC_PACK
+ #define NORETURN
+#endif
+#define main morphos_main
+#elif defined(__DC__)
+
+#define scumm_stricmp strcasecmp
+#define CHECK_HEAP
+#define SCUMM_LITTLE_ENDIAN
+#define SCUMM_NEED_ALIGNMENT
+
+#define FORCEINLINE inline
+#define NORETURN __attribute__((__noreturn__))
+#define GCC_PACK __attribute__((packed))
+#define CDECL
+
+typedef unsigned char byte;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned long uint32;
+typedef unsigned int uint;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed long int32;
+
+#define START_PACK_STRUCTS pack (push,1)
+#define END_PACK_STRUCTS pack(pop)
+
+#else
+#error No system type defined
+#endif
+
+
+#if defined(SCUMM_LITTLE_ENDIAN)
+
+//#if defined(SCUMM_NEED_ALIGNMENT)
+//#error Little endian processors that need alignment is not implemented
+//#endif
+
+
+#define PROTO_MKID(a) ((((a)>>24)&0xFF) | (((a)>>8)&0xFF00) | (((a)<<8)&0xFF0000) | (((a)<<24)&0xFF000000))
+#define PROTO_MKID_BE(a) (a & 0xffffffff)
+
+#if defined(INVERSE_MKID)
+# define MKID(a) PROTO_MKID_BE(a)
+# define MKID_BE(a) PROTO_MKID(a)
+#else
+# define MKID(a) PROTO_MKID(a)
+# define MKID_BE(a) PROTO_MKID_BE(a)
+#endif
+
+
+#if defined(SCUMM_NEED_ALIGNMENT)
+ FORCEINLINE uint READ_LE_UINT16(void *ptr) {
+ return (((byte*)ptr)[1]<<8)|((byte*)ptr)[0];
+ }
+#else
+ FORCEINLINE uint READ_LE_UINT16(void *ptr) {
+ return *(uint16*)(ptr);
+ }
+#endif
+
+FORCEINLINE uint READ_BE_UINT16(void *ptr) {
+ return (((byte*)ptr)[0]<<8)|((byte*)ptr)[1];
+}
+
+#if defined(SCUMM_NEED_ALIGNMENT)
+ FORCEINLINE uint32 READ_LE_UINT32(void *ptr) {
+ byte *b = (byte*)ptr;
+ return (b[3]<<24)+(b[2]<<16)+(b[1]<<8)+(b[0]);
+ }
+#else
+ FORCEINLINE uint32 READ_LE_UINT32(void *ptr) {
+ return *(uint32*)(ptr);
+ }
+#endif
+
+FORCEINLINE uint32 READ_BE_UINT32(void *ptr) {
+ byte *b = (byte*)ptr;
+ return (b[0]<<24)+(b[1]<<16)+(b[2]<<8)+(b[3]);
+}
+
+#define READ_BE_UINT32_UNALIGNED READ_BE_UINT32
+#define READ_BE_UINT16_UNALIGNED READ_BE_UINT16
+
+#define READ_UINT32_UNALIGNED(a) READ_LE_UINT32(a)
+
+#define FROM_LE_32(__a__) __a__
+#define FROM_LE_16(__a__) __a__
+
+#define TO_LE_32(__a__) __a__
+#define TO_LE_16(__a__) __a__
+
+#define TO_BE_32(a) ((((a)>>24)&0xFF) | (((a)>>8)&0xFF00) | (((a)<<8)&0xFF0000) | (((a)<<24)&0xFF000000))
+
+uint16 FORCEINLINE TO_BE_16(uint16 a) { return (a>>8) | (a<<8); }
+
+#elif defined(SCUMM_BIG_ENDIAN)
+
+#define MKID(a) (a)
+#define MKID_BE(a) (a)
+//#define MKID_BE(a) ((((a)>>24)&0xFF) | (((a)>>8)&0xFF00) | (((a)<<8)&0xFF0000) | (((a)<<24)&0xFF000000))
+
+uint32 FORCEINLINE FROM_LE_32(uint32 a) {
+ return ((a>>24)&0xFF) + ((a>>8)&0xFF00) + ((a<<8)&0xFF0000) + ((a<<24)&0xFF000000);
+}
+
+uint16 FORCEINLINE FROM_LE_16(uint16 a) {
+ return ((a>>8)&0xFF) + ((a<<8)&0xFF00);
+}
+
+#define TO_LE_32 FROM_LE_32
+#define TO_LE_16 FROM_LE_16
+
+uint32 FORCEINLINE READ_LE_UINT32(void *ptr) {
+ byte *b = (byte*)ptr;
+ return (b[3]<<24)+(b[2]<<16)+(b[1]<<8)+(b[0]);
+}
+
+uint32 FORCEINLINE READ_BE_UINT32(void *ptr) {
+ return *(uint32*)(ptr);
+}
+
+uint FORCEINLINE READ_LE_UINT16(void *ptr) {
+ byte *b = (byte*)ptr;
+ return (b[1]<<8) + b[0];
+}
+
+uint FORCEINLINE READ_BE_UINT16(void *ptr) {
+ return *(uint16*)(ptr);
+}
+
+uint FORCEINLINE READ_BE_UINT16_UNALIGNED(void *ptr) {
+ return (((byte*)ptr)[0]<<8)|((byte*)ptr)[1];
+}
+
+uint32 FORCEINLINE READ_BE_UINT32_UNALIGNED(void *ptr) {
+ byte *b = (byte*)ptr;
+ return (b[0]<<24)+(b[1]<<16)+(b[2]<<8)+(b[3]);
+}
+
+#define READ_UINT32_UNALIGNED READ_BE_UINT32_UNALIGNED
+
+#define TO_BE_32(a) (a)
+#define TO_BE_16(a) (a)
+#else
+
+#error No endianness defined
+
+#endif
+
+
+#ifdef NEED_STRDUP
+char *strdup(const char *s);
+#endif
+
+/* Initialized operator new */
+void * operator new(size_t size);
+
+#endif
diff --git a/common/stdafx.cpp b/common/stdafx.cpp
new file mode 100644
index 0000000000..fd4f341c7b
--- /dev/null
+++ b/common/stdafx.cpp
@@ -0,0 +1 @@
+#include "stdafx.h"
diff --git a/common/stdafx.h b/common/stdafx.h
new file mode 100644
index 0000000000..de4f0156ce
--- /dev/null
+++ b/common/stdafx.h
@@ -0,0 +1,169 @@
+/*
+ * $Id$
+ *
+ * $Log$
+ * Revision 1.1 2002/08/21 16:07:23 fingolfin
+ * Initial revision
+ *
+ * Revision 1.18 2002/07/08 13:33:10 fingolfin
+ * two more small QNX fixes
+ *
+ * Revision 1.17 2002/06/02 20:28:09 bbrox
+ * Small warning fix + double inclusion protection (can always be useful
+ * :) ).
+ *
+ * Revision 1.16 2002/05/05 20:04:25 fingolfin
+ * cleaning up the mess drigo left... <sigh>
+ *
+ * Revision 1.15 2002/05/05 19:06:51 drigo
+ * Fixed some things for Macintosh ports
+ *
+ * Revision 1.14 2002/04/18 21:40:23 tomjoad
+ * Reenable MorphOS Midi driver, small updates to CD open code (only when CD audio is requested) and start options
+ *
+ * Revision 1.13 2002/04/12 21:26:34 strigeus
+ * new video engine (expect broken non-sdl builds),
+ * simon the sorcerer 1 & 2 support (non SCUMM games)
+ *
+ * Revision 1.12 2002/03/14 22:45:22 arisme
+ * Minor changes to compile WinCE port
+ *
+ * Revision 1.11 2002/03/09 13:48:53 drigo
+ * Support for MacOS classic port
+ *
+ * Revision 1.10 2002/03/08 17:05:09 mutle
+ * Some changes, need to be done to get the Mac Port running. For example Point is now called ScummPoint, as the name Point is already in use by Apple.
+ *
+ * Revision 1.9 2002/03/06 12:24:56 ender
+ * Applied cleanup and scaling patch by Rob.
+ *
+ * Revision 1.8 2001/11/20 07:13:01 vasyl
+ * Added ability for ports to override all includes in stdafx.h. To use this feature
+ * port must define symbol NONSTANDARD_PORT. Port must also provide
+ * port-specific portdefs.h with all includes, symbol defines and everything else
+ * port needs.
+ *
+ * Revision 1.7 2001/11/11 16:54:45 strigeus
+ * implemented some sam&max specific features,
+ * fixed some bugs
+ *
+ * Revision 1.6 2001/11/06 22:59:59 cmatsuoka
+ * Re-added changes to allow cygwin and beos cross-compilation.
+ *
+ */
+
+#ifndef _STDAFX_H
+#define _STDAFX_H
+
+#if defined(NONSTANDARD_PORT)
+
+#include <portdefs.h>
+
+#elif defined(WIN32)
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+#if !defined(_WIN32_WCE)
+
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define NOGDICAPMASKS
+#define OEMRESOURCE
+#define NONLS
+#define NOICONS
+#define NOMCX
+#define NOPROFILER
+#define NOKANJI
+#define NOSERVICE
+#define NOMETAFILE
+#define NOCOMM
+#define NOCRYPT
+#define NOIME
+#define NOATOM
+#define NOCTLMGR
+#define NOCLIPBOARD
+#define NOMEMMGR
+#define NOSYSMETRICS
+#define NOMENUS
+#define NOOPENFILE
+#define NOWH
+#define NOSOUND
+#define NODRAWTEXT
+
+
+#endif
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <conio.h>
+#include <malloc.h>
+#include <assert.h>
+#include <mmsystem.h>
+#include <ctype.h>
+#include <Winuser.h>
+#include <direct.h>
+
+#else
+
+#if defined(__MORPHOS__)
+#include <devices/timer.h>
+#undef CMD_INVALID
+#endif
+#if !defined(macintosh)
+#include <sys/types.h>
+#include <sys/uio.h>
+#endif
+#if !defined (__BEOS__)
+#include <unistd.h>
+#endif
+#if defined(__QNXNTO__)
+#include <strings.h> /* For strcasecmp */
+#endif
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+
+
+#endif
+
+
+/* Semi-Platform-specific version info */
+#ifdef ALLOW_GDI
+/* Assume Win32 GDI is used, then... */
+#define SCUMMVM_PLATFORM_VERSION "Win32 GDI version"
+
+#else
+#ifdef ALLOW_X11
+/* Assume pure X11 is used, then... */
+#define SCUMMVM_PLATFORM_VERSION "X11 version"
+
+#else
+
+#ifdef MACOS_CARBON
+#define SCUMMVM_PLATFORM_VERSION "Macintosh version"
+#else
+
+#ifdef SDL_COMPILEDVERSION
+#define SCUMMVM_PLATFORM_VERSION "SDL version"
+//SDL_COMPILEDVERSION is a number... :(
+//SDL_Linked_Version returns an SDL_Version structure...
+
+#endif
+#endif
+#endif
+#endif
+
+#endif
diff --git a/common/system.h b/common/system.h
new file mode 100644
index 0000000000..b8255eff48
--- /dev/null
+++ b/common/system.h
@@ -0,0 +1,199 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef _SYSTEM_H
+#define _SYSTEM_H
+
+/* Interface to what's below ScummVM */
+
+class OSystem {
+public:
+ typedef int ThreadProc(void *param);
+ typedef void SoundProc(void *param, byte *buf, int len);
+
+ struct Event {
+ int event_code;
+ struct {
+ uint16 ascii;
+ byte flags;
+ int keycode;
+ } kbd;
+ struct {
+ int x,y;
+ } mouse;
+ };
+
+ enum {
+ EVENT_KEYDOWN = 1,
+ EVENT_KEYUP = 2,
+ EVENT_MOUSEMOVE = 3,
+ EVENT_LBUTTONDOWN = 4,
+ EVENT_LBUTTONUP = 5,
+ EVENT_RBUTTONDOWN = 6,
+ EVENT_RBUTTONUP = 7,
+ };
+
+ enum {
+ KBD_CTRL = 1,
+ KBD_ALT = 2,
+ KBD_SHIFT = 4,
+ };
+
+ enum {
+ PROP_TOGGLE_FULLSCREEN = 1,
+ PROP_SET_WINDOW_CAPTION = 2,
+ PROP_OPEN_CD = 3,
+ PROP_SET_GFX_MODE = 4,
+ PROP_SHOW_DEFAULT_CURSOR = 5,
+ PROP_GET_SAMPLE_RATE = 6,
+ PROP_GET_FULLSCREEN = 7
+ };
+ union Property {
+ char *caption;
+ int cd_num;
+ int gfx_mode;
+ bool show_cursor;
+ };
+
+ enum {
+ SOUND_8BIT = 0,
+ SOUND_16BIT = 1,
+ };
+
+ // Set colors of the palette
+ virtual void set_palette(const byte *colors, uint start, uint num) = 0;
+
+ // Set the size of the video bitmap.
+ // Typically, 320x200
+ virtual void init_size(uint w, uint h) = 0;
+
+ // Draw a bitmap to screen.
+ // The screen will not be updated to reflect the new bitmap
+ virtual void copy_rect(const byte *buf, int pitch, int x, int y, int w, int h) = 0;
+
+ // Update the dirty areas of the screen
+ virtual void update_screen() = 0;
+
+ // Either show or hide the mouse cursor
+ virtual bool show_mouse(bool visible) = 0;
+
+ // Set the position of the mouse cursor
+ virtual void set_mouse_pos(int x, int y) = 0;
+
+ // Set the bitmap that's used when drawing the cursor.
+ virtual void set_mouse_cursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y) = 0;
+
+ // Shaking is used in SCUMM. Set current shake position.
+ virtual void set_shake_pos(int shake_pos) = 0;
+
+ // Get the number of milliseconds since the program was started.
+ virtual uint32 get_msecs() = 0;
+
+ // Delay for a specified amount of milliseconds
+ virtual void delay_msecs(uint msecs) = 0;
+
+ // Create a thread
+ virtual void *create_thread(ThreadProc *proc, void *param) = 0;
+
+ // Get the next event.
+ // Returns true if an event was retrieved.
+ virtual bool poll_event(Event *event) = 0;
+
+ // Set the function to be invoked whenever samples need to be generated
+ // Format is the sample type format.
+ // Only 16-bit signed mode is needed for simon & scumm
+ virtual bool set_sound_proc(void *param, SoundProc *proc, byte format) = 0;
+
+ // Get or set a property
+ virtual uint32 property(int param, Property *value) = 0;
+
+ // Poll cdrom status
+ // Returns true if cd audio is playing
+ virtual bool poll_cdrom() = 0;
+
+ // Play cdrom audio track
+ virtual void play_cdrom(int track, int num_loops, int start_frame, int end_frame) = 0;
+
+ // Stop cdrom audio track
+ virtual void stop_cdrom() = 0;
+
+ // Update cdrom audio status
+ virtual void update_cdrom() = 0;
+
+ // Add a new callback timer
+ virtual void set_timer(int timer, int (*callback)(int)) = 0;
+
+ // Mutex handling
+ virtual void *create_mutex(void) = 0;
+ virtual void lock_mutex(void *mutex) = 0;
+ virtual void unlock_mutex(void *mutex) = 0;
+ virtual void delete_mutex(void *mutex) = 0;
+
+ // Quit
+ virtual void quit() = 0;
+};
+
+
+/* Factory functions. This means we don't have to include the
+ * OSystem_SDL header file. (which in turn would require the SDL headers)
+ */
+
+/* OSystem_SDL */
+extern OSystem *OSystem_SDL_create(int gfx_driver, bool full_screen);
+extern OSystem *OSystem_NULL_create();
+extern OSystem *OSystem_MorphOS_create(int game_id, int gfx_driver, bool full_screen);
+extern OSystem *OSystem_Dreamcast_create();
+extern OSystem *OSystem_WINCE3_create();
+extern OSystem *OSystem_X11_create();
+extern OSystem *OSystem_MAC_create(int gfx_mode, bool full_screen);
+
+enum {
+ GFX_NORMAL = 0,
+ GFX_DOUBLESIZE = 1,
+ GFX_TRIPLESIZE = 2,
+ GFX_2XSAI = 3,
+ GFX_SUPER2XSAI = 4,
+ GFX_SUPEREAGLE = 5,
+ GFX_ADVMAME2X = 6
+};
+
+
+/* Graphics drivers */
+enum {
+ GD_NULL = 0,
+ GD_SDL,
+ GD_X,
+ GD_MORPHOS,
+ GD_WINCE,
+ GD_MAC,
+ GD_DC
+};
+
+enum {
+#ifdef _WIN32_WCE
+ SAMPLES_PER_SEC = 11025
+#else
+ SAMPLES_PER_SEC = 22050
+#endif
+};
+
+#endif
diff --git a/common/timer.cpp b/common/timer.cpp
new file mode 100644
index 0000000000..2a3fc74024
--- /dev/null
+++ b/common/timer.cpp
@@ -0,0 +1,157 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "scumm.h"
+#include "scummsys.h"
+#include "timer.h"
+
+static Scumm * scumm;
+
+Timer::Timer(Scumm * parent) {
+ _initialized = false;
+ _timerRunning = false;
+ scumm = _scumm = parent;
+}
+
+Timer::~Timer() {
+ release ();
+}
+
+static int timer_handler (int t)
+{
+ scumm->_timer->handler (&t);
+ return t;
+}
+
+int Timer::handler(int * t) {
+ uint32 interval, l;
+
+ if (_timerRunning) {
+ _lastTime = _thisTime;
+ _thisTime = _osystem->get_msecs();
+ interval = _thisTime - _lastTime;
+
+ for (l = 0; l < MAX_TIMERS; l++) {
+ if ((_timerSlots[l].procedure) && (_timerSlots[l].interval > 0)) {
+ _timerSlots[l].counter -= interval;
+ if (_timerSlots[l].counter <= 0) {
+ _timerSlots[l].counter += _timerSlots[l].interval;
+ _timerSlots[l].procedure (_scumm);
+ }
+ }
+ }
+ }
+
+ return *t;
+}
+
+bool Timer::init() {
+ int32 l;
+
+ _osystem = _scumm->_system;
+ if (_osystem == NULL) {
+ printf("Timer: OSystem not initialized !\n");
+ return false;
+ }
+
+ if (_initialized == true)
+ return true;
+
+ for (l = 0; l < MAX_TIMERS; l++) {
+ _timerSlots[l].procedure = NULL;
+ _timerSlots[l].interval = 0;
+ _timerSlots[l].counter = 0;
+ }
+
+ _thisTime = _osystem->get_msecs();
+ _osystem->set_timer (10, &timer_handler);
+
+ _timerRunning = true;
+ _initialized = true;
+ return true;
+}
+
+void Timer::release() {
+ int32 l;
+
+ if (_initialized == false)
+ return;
+
+ _timerRunning = false;
+ _osystem->set_timer (0, NULL);
+ _initialized = false;
+
+ for (l = 0; l < MAX_TIMERS; l++) {
+ _timerSlots[l].procedure = NULL;
+ _timerSlots[l].interval = 0;
+ _timerSlots[l].counter = 0;
+ }
+}
+
+bool Timer::installProcedure (TimerProc procedure, int32 interval) {
+ int32 l;
+ bool found = false;
+
+ if (_initialized == false) {
+ printf ("Timer: is not initialized !");
+ return false;
+ }
+
+ _timerRunning = false;
+ for (l = 0; l < MAX_TIMERS; l++) {
+ if (!_timerSlots[l].procedure) {
+ _timerSlots[l].procedure = procedure;
+ _timerSlots[l].interval = interval;
+ _timerSlots[l].counter = interval;
+ found = true;
+ break;
+ }
+ }
+
+ _timerRunning = true;
+ if (!found) {
+ printf ("Can't find free slot !");
+ return false;
+ }
+
+ return true;
+}
+
+void Timer::releaseProcedure (TimerProc procedure) {
+ int32 l;
+
+ if (_initialized == false) {
+ printf ("Timer: is not initialized !");
+ return;
+ }
+
+ _timerRunning = false;
+ for (l = 0; l < MAX_TIMERS; l++) {
+ if (_timerSlots[l].procedure == procedure) {
+ _timerSlots[l].procedure = 0;
+ _timerSlots[l].interval = 0;
+ _timerSlots[l].counter = 0;
+ }
+ }
+ _timerRunning = true;
+}
+
+
diff --git a/common/timer.h b/common/timer.h
new file mode 100644
index 0000000000..a4f4c7080d
--- /dev/null
+++ b/common/timer.h
@@ -0,0 +1,66 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+#include "scummsys.h"
+
+#define MAX_TIMERS 5
+
+typedef void (*TimerProc)(Scumm *);
+
+#ifdef __MORPHOS__
+#include "morphos/morphos_timer.h"
+#else
+
+class OSystem;
+
+class Timer {
+
+private:
+ OSystem *_osystem;
+ Scumm *_scumm;
+ bool _initialized;
+ bool _timerRunning;
+ void *_timerHandler;
+ int32 _thisTime;
+ int32 _lastTime;
+
+ struct TimerSlots {
+ TimerProc procedure;
+ int32 interval;
+ int32 counter;
+ } _timerSlots[MAX_TIMERS];
+
+public:
+ Timer(Scumm *system);
+ ~Timer();
+
+ int handler(int *t);
+ bool init();
+ void release();
+ bool installProcedure(TimerProc procedure, int32 interval);
+ void releaseProcedure(TimerProc procedure);
+};
+
+#endif
+
+#endif
diff --git a/common/util.cpp b/common/util.cpp
new file mode 100644
index 0000000000..4a5d50e369
--- /dev/null
+++ b/common/util.cpp
@@ -0,0 +1,312 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "util.h"
+
+// 8-bit alpha blending routines
+int BlendCache[256][256];
+
+int RGBMatch(byte *palette, int r, int g, int b)
+{
+ int i, bestidx = 0, besterr = 0xFFFFFF;
+ int error = 0;
+
+ for (i = 0;i < 256;i++) {
+ byte *pal = palette + (i * 3);
+ int r_diff = r - (int)*pal++;
+ int g_diff = g - (int)*pal++;
+ int b_diff = b - (int)*pal++;
+ r_diff *= r_diff; g_diff *= g_diff; b_diff *= b_diff;
+
+ error = r_diff + g_diff + b_diff;
+ if (error < besterr) {
+ besterr = error;
+ bestidx = i;
+ }
+ }
+ return bestidx;
+}
+
+int Blend(int src, int dst, byte *palette)
+{
+ int r, g, b;
+ int alpha = 128; // Level of transparency [0-256]
+ byte *srcpal = palette + (dst * 3);
+ byte *dstpal = palette + (src * 3);
+
+ if (BlendCache[dst][src] > -1)
+ return BlendCache[dst][src];
+
+ r = (*srcpal++ * alpha);
+ r += (*dstpal++ * (256-alpha));
+ r /= 256;
+
+ g = (*srcpal++ * alpha);
+ g += (*dstpal++ * (256-alpha));
+ g /= 256;
+
+ b = (*srcpal++ * alpha);
+ b += (*dstpal++ * (256-alpha));
+ b /= 256;
+
+ return (BlendCache[dst][src] = RGBMatch(palette, r , g , b ));
+}
+
+void ClearBlendCache(byte *palette, int weight)
+{
+ for (int i = 0; i < 256; i++)
+ for (int j = 0 ; j < 256 ; j++)
+// BlendCache[i][j] = i; // No alphablending
+// BlendCache[i][j] = j; // 100% translucent
+ BlendCache[i][j] = -1; // Enable alphablending
+}
+
+
+#pragma mark -
+
+/*
+ * Print hexdump of the data passed in, 8 bytes a row
+ */
+void hexdump(const byte * data, int len)
+{
+ int i;
+ byte c;
+ while (len >= 8) {
+ for (i = 0; i < 8; i++)
+ printf("%02x ", data[i]);
+ printf(" |");
+ for (i = 0; i < 8; i++) {
+ c = data[i];
+ if (c < 32 || c > 127)
+ c = '.';
+ printf("%c", c);
+ }
+ printf("|\n");
+ data += 8;
+ len -= 8;
+ }
+
+ if (len <= 0)
+ return;
+
+ for (i = 0; i < len; i++)
+ printf("%02x ", data[i]);
+ for (; i < 8; i++)
+ printf(" ");
+ printf(" |");
+ for (i = 0; i < len; i++) {
+ c = data[i];
+ if (c < 32 || c > 127)
+ c = '.';
+ printf("%c", c);
+ }
+ for (; i < 8; i++)
+ printf(" ");
+ printf("|\n");
+}
+
+
+#pragma mark -
+
+
+namespace ScummVM {
+
+String::String(const char *str)
+{
+ _refCount = new int(1);
+ _capacity = _len = strlen(str);
+ _str = (char *)calloc(1, _capacity+1);
+ memcpy(_str, str, _len+1);
+}
+
+String::String(const String &str)
+{
+ ++(*str._refCount);
+
+ _refCount = str._refCount;
+ _capacity = str._capacity;
+ _len = str._capacity;
+ _str = str._str;
+}
+
+String::~String()
+{
+ decRefCount();
+}
+
+void String::decRefCount()
+{
+ --(*_refCount);
+ if (*_refCount <= 0) {
+ delete _refCount;
+ if (_str)
+ free(_str);
+ }
+}
+
+String& String::operator =(const char* str)
+{
+ int len = strlen(str);
+ if (len > 0) {
+ ensureCapacity(len, false);
+
+ _len = len;
+ memcpy(_str, str, _len + 1);
+ } else if (_len > 0) {
+ decRefCount();
+
+ _refCount = new int(1);
+ _capacity = 0;
+ _len = 0;
+ _str = 0;
+ }
+ return *this;
+}
+
+String& String::operator =(const String& str)
+{
+ ++(*str._refCount);
+
+ decRefCount();
+
+ _refCount = str._refCount;
+ _capacity = str._capacity;
+ _len = str._len;
+ _str = str._str;
+
+ return *this;
+}
+
+String& String::operator +=(const char* str)
+{
+ int len = strlen(str);
+ if (len > 0) {
+ ensureCapacity(_len + len, true);
+
+ memcpy(_str + _len, str, len + 1);
+ _len += len;
+ }
+ return *this;
+}
+
+String& String::operator +=(const String& str)
+{
+ int len = str._len;
+ if (len > 0) {
+ ensureCapacity(_len + len, true);
+
+ memcpy(_str + _len, str._str, len + 1);
+ _len += len;
+ }
+ return *this;
+}
+
+String& String::operator +=(char c)
+{
+ ensureCapacity(_len + 1, true);
+
+ _str[_len++] = c;
+ _str[_len] = 0;
+
+ return *this;
+}
+
+bool String::operator ==(const String& x)
+{
+ return (_len == x._len) && ((_len == 0) || (0 == strcmp(_str, x._str)));
+}
+
+bool String::operator ==(const char* x)
+{
+ if (_str == 0)
+ return (x == 0) || (*x == 0);
+ if (x == 0)
+ return (_len == 0);
+ return (0 != strcmp(_str, x));
+}
+
+bool String::operator !=(const String& x)
+{
+ return (_len != x._len) || ((_len != 0) && (0 != strcmp(_str, x._str)));
+}
+
+bool String::operator !=(const char* x)
+{
+ if (_str == 0)
+ return (x != 0) && (*x != 0);
+ if (x == 0)
+ return (_len != 0);
+ return (0 == strcmp(_str, x));
+}
+
+
+void String::deleteLastChar() {
+ if (_len > 0) {
+ ensureCapacity(_len - 1, true);
+ _str[--_len] = 0;
+ }
+}
+
+void String::clear()
+{
+ if (_capacity) {
+ decRefCount();
+
+ _refCount = new int(1);
+ _capacity = 0;
+ _len = 0;
+ _str = 0;
+ }
+}
+
+void String::ensureCapacity(int new_len, bool keep_old)
+{
+ // If there is not enough space, or if we are not the only owner
+ // of the current data, then we have to reallocate it.
+ if (new_len <= _capacity && *_refCount == 1)
+ return;
+
+ int newCapacity = (new_len <= _capacity) ? _capacity : new_len + 32;
+ char *newStr = (char *)calloc(1, newCapacity+1);
+
+ if (keep_old && _str)
+ memcpy(newStr, _str, _len + 1);
+ else
+ _len = 0;
+
+ decRefCount();
+
+ _refCount = new int(1);
+ _capacity = newCapacity;
+ _str = newStr;
+}
+
+bool operator == (const char* y, const String& x)
+{
+ return x == y;
+}
+
+bool operator != (const char* y, const String& x)
+{
+ return x != y;
+}
+
+}; // End of namespace ScummVM
diff --git a/common/util.h b/common/util.h
new file mode 100644
index 0000000000..0f74ede00f
--- /dev/null
+++ b/common/util.h
@@ -0,0 +1,183 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "scummsys.h"
+
+int RGBMatch(byte *palette, int r, int g, int b);
+int Blend(int src, int dst, byte *palette);
+void ClearBlendCache(byte *palette, int weight);
+
+/*
+ * Print hexdump of the data passed in, 8 bytes a row
+ */
+void hexdump(const byte * data, int len);
+
+
+namespace ScummVM {
+
+template <class T>
+class List {
+protected:
+ int _capacity;
+ int _size;
+ T *_data;
+
+public:
+ List<T>() : _capacity(0), _size(0), _data(0) {}
+ List<T>(const List<T>& list) : _capacity(0), _size(0), _data(0)
+ {
+ _size = list._size;
+ _capacity = _size + 32;
+ _data = new T[_capacity];
+ for (int i = 0; i < _size; i++)
+ _data[i] = list._data[i];
+ }
+
+ ~List<T>()
+ {
+ if (_data)
+ delete [] _data;
+ }
+
+ void push_back(const T& str)
+ {
+ ensureCapacity(_size + 1);
+ _data[_size++] = str;
+ }
+
+ // TODO: insert, remove, ...
+
+ T& operator [](int idx)
+ {
+ assert(idx >= 0 && idx < _size);
+ return _data[idx];
+ }
+
+ const T& operator [](int idx) const
+ {
+ assert(idx >= 0 && idx < _size);
+ return _data[idx];
+ }
+
+ List<T>& operator =(const List<T>& list)
+ {
+ if (_data)
+ delete [] _data;
+ _size = list._size;
+ _capacity = _size + 32;
+ _data = new T[_capacity];
+ for (int i = 0; i < _size; i++)
+ _data[i] = list._data[i];
+
+ return *this;
+ }
+
+ int size() const { return _size; }
+
+ void clear()
+ {
+ if (_data) {
+ delete [] _data;
+ _data = 0;
+ }
+ _size = 0;
+ _capacity = 0;
+ }
+
+ bool isEmpty() const { return (_size == 0); }
+
+protected:
+ void ensureCapacity(int new_len)
+ {
+ if (new_len <= _capacity)
+ return;
+
+ T *old_data = _data;
+ _capacity = new_len + 32;
+ _data = new T[_capacity];
+
+ if (old_data) {
+ // Copy old data
+ for (int i = 0; i < _size; i++)
+ _data[i] = old_data[i];
+ delete [] old_data;
+ }
+ }
+};
+
+
+class String {
+protected:
+ int *_refCount;
+ int _capacity;
+ int _len;
+ char *_str;
+public:
+ String() : _capacity(0), _len(0), _str(0) { _refCount = new int(1); }
+ String(const char *str);
+ String(const String &str);
+ ~String();
+
+ String& operator =(const char* str);
+ String& operator =(const String& str);
+ String& operator +=(const char* str);
+ String& operator +=(const String& str);
+ String& operator +=(char c);
+
+ bool operator ==(const String& x);
+ bool operator ==(const char* x);
+ bool operator !=(const String& x);
+ bool operator !=(const char* x);
+
+// operator char *() { return _str; }
+ operator const char *() const { return _str; }
+ const char *c_str() const { return _str; }
+ int size() const { return _len; }
+
+ void deleteLastChar();
+ void clear();
+
+ bool isEmpty() const { return (_len == 0); }
+
+protected:
+ void ensureCapacity(int new_len, bool keep_old);
+ void decRefCount();
+};
+
+// Some useful additional comparision operators for Strings
+bool operator == (const char* x, const String& y);
+bool operator != (const char* x, const String& y);
+
+class StringList : public List<String> {
+public:
+ void push_back(const char* str)
+ {
+ ensureCapacity(_size + 1);
+ _data[_size] = str;
+ _size++;
+ }
+};
+
+}; // End of namespace ScummVM
+
+#endif