From 8e2ab87455b75fffef1feeb7bc3a95a62d3a949e Mon Sep 17 00:00:00 2001 From: Pawel Kolodziejski Date: Sun, 25 Mar 2012 11:41:48 +0200 Subject: [PATCH] ALL: synced with scummvm --- COPYRIGHT | 1 + Makefile.common | 5 +- audio/mididrv.cpp | 1 + audio/softsynth/mt32/Structures.h | 4 +- audio/softsynth/opl/mame.cpp | 4 +- backends/keymapper/action.cpp | 16 +- backends/keymapper/action.h | 10 +- .../hardware-input.cpp} | 172 ++++++++-- backends/keymapper/hardware-input.h | 160 +++++++++ backends/keymapper/hardware-key.h | 187 ---------- backends/keymapper/keymap.cpp | 100 +++--- backends/keymapper/keymap.h | 28 +- backends/keymapper/keymapper-defaults.h | 8 +- backends/keymapper/keymapper.cpp | 196 ++++++++--- backends/keymapper/keymapper.h | 56 ++- backends/keymapper/remap-dialog.cpp | 80 ++--- backends/keymapper/remap-dialog.h | 4 +- backends/midi/stmidi.cpp | 2 +- backends/midi/windows.cpp | 40 ++- backends/module.mk | 1 + backends/platform/sdl/module.mk | 1 - backends/vkeybd/virtual-keyboard-parser.cpp | 14 +- base/commandLine.cpp | 11 +- base/main.cpp | 4 +- common/EventDispatcher.cpp | 6 + common/EventMapper.cpp | 38 +++ common/endian.h | 10 +- common/events.h | 19 +- common/gui_options.cpp | 115 +++++++ common/gui_options.h | 85 +++++ common/language.cpp | 125 +++++++ common/language.h | 86 +++++ common/macresman.cpp | 21 ++ common/macresman.h | 7 + common/math.h | 2 +- common/module.mk | 4 + common/platform.cpp | 109 ++++++ common/platform.h | 82 +++++ common/ptr.h | 4 +- common/rect.h | 6 +- common/rendermode.cpp | 122 +++++++ common/rendermode.h | 73 ++++ common/scummsys.h | 7 +- common/singleton.h | 2 +- common/stream.cpp | 2 +- common/substream.h | 17 +- common/system.h | 8 +- common/translation.cpp | 5 +- common/util.cpp | 319 ------------------ common/util.h | 182 ---------- configure | 8 +- devtools/create_project/xcode.cpp | 246 +++++++------- engines/advancedDetector.h | 10 +- engines/engine.h | 2 + engines/game.cpp | 1 + engines/game.h | 3 +- engines/grim/update/lang_filter.h | 2 +- engines/myst3/cursor.cpp | 5 +- engines/myst3/myst3.cpp | 2 +- engines/myst3/node.cpp | 9 +- engines/myst3/node.h | 6 +- engines/myst3/nodecube.cpp | 5 +- engines/myst3/nodeframe.cpp | 5 +- graphics/decoders/bmp.cpp | 159 +++++++++ graphics/{imagedec.h => decoders/bmp.h} | 40 +-- graphics/decoders/image_decoder.h | 85 +++++ graphics/{ => decoders}/jpeg.cpp | 112 +++--- graphics/{ => decoders}/jpeg.h | 24 +- graphics/fonts/ttf.cpp | 8 +- graphics/imagedec.cpp | 181 ---------- graphics/module.mk | 2 + graphics/surface.cpp | 79 +++++ graphics/surface.h | 11 + graphics/yuv_to_rgb.cpp | 46 +++ graphics/yuv_to_rgb.h | 15 + gui/ThemeEngine.cpp | 15 +- gui/debugger.cpp | 5 +- gui/dialog.cpp | 27 +- gui/dialog.h | 9 + gui/gui-manager.cpp | 10 +- gui/launcher.cpp | 1 + gui/object.cpp | 20 ++ gui/object.h | 2 + gui/options.cpp | 71 ++-- gui/options.h | 6 +- gui/themes/modern.zip | Bin 1439345 -> 1442047 bytes gui/themes/modern/modern_gfx.stx | 7 +- gui/widgets/edittext.cpp | 2 + test/common/memoryreadstream.h | 16 + test/common/subreadstream.h | 18 + 90 files changed, 2414 insertions(+), 1422 deletions(-) rename backends/{platform/sdl/hardwarekeys.cpp => keymapper/hardware-input.cpp} (55%) create mode 100644 backends/keymapper/hardware-input.h delete mode 100644 backends/keymapper/hardware-key.h create mode 100644 common/gui_options.cpp create mode 100644 common/gui_options.h create mode 100644 common/language.cpp create mode 100644 common/language.h create mode 100644 common/platform.cpp create mode 100644 common/platform.h create mode 100644 common/rendermode.cpp create mode 100644 common/rendermode.h create mode 100644 graphics/decoders/bmp.cpp rename graphics/{imagedec.h => decoders/bmp.h} (53%) create mode 100644 graphics/decoders/image_decoder.h rename graphics/{ => decoders}/jpeg.cpp (88%) rename graphics/{ => decoders}/jpeg.h (85%) delete mode 100644 graphics/imagedec.cpp diff --git a/COPYRIGHT b/COPYRIGHT index d56434bc393..2a462e13a06 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -252,3 +252,4 @@ Xanathar "xanathar" Grant Yeager "glo_kidd" Benjamin W. Zale "junior_aepi" Yotam Barnoy "bluddy" +Tom Frost "TomFrost" diff --git a/Makefile.common b/Makefile.common index 94af95c7a69..b99ebcec586 100644 --- a/Makefile.common +++ b/Makefile.common @@ -12,7 +12,7 @@ all: $(EXECUTABLE) plugins ###################################################################### # Module settings ###################################################################### -#ResidualVM: do not include 'test' but add 'math': +#ResidualVM: added 'math': PLUGINS := MODULES := test devtools base $(MODULES) @@ -155,7 +155,8 @@ endif # Get the current version information ###################################################################### -VERSION = $(shell grep SCUMMVM_VERSION "${srcdir}/base/internal_version.h" | cut -d\" -f2) +# AmigaOS4's grep has a problem with "./" in pathnames, so use cat piped into grep. +VERSION = $(shell cat "${srcdir}/base/internal_version.h" | grep SCUMMVM_VERSION | cut -d\" -f2) VER_MAJOR = $(shell echo $(VERSION) | cut -d. -f 1) VER_MINOR = $(shell echo $(VERSION) | cut -d. -f 2) VER_PATCH = $(shell echo $(VERSION) | cut -d. -f 3 | cut -c1) diff --git a/audio/mididrv.cpp b/audio/mididrv.cpp index 6817791c6bb..0518915e81a 100644 --- a/audio/mididrv.cpp +++ b/audio/mididrv.cpp @@ -22,6 +22,7 @@ #include "common/config-manager.h" #include "common/error.h" +#include "common/gui_options.h" #include "common/str.h" #include "common/system.h" #include "common/textconsole.h" diff --git a/audio/softsynth/mt32/Structures.h b/audio/softsynth/mt32/Structures.h index e4d98ad1fc1..cbce89ae188 100644 --- a/audio/softsynth/mt32/Structures.h +++ b/audio/softsynth/mt32/Structures.h @@ -42,7 +42,7 @@ typedef signed char Bit8s; // Since sysex allows this memory to be written to in blocks of bytes, // we keep this packed so that we can copy data into the various // banks directly -#if defined(_MSC_VER) || defined (__MINGW32__) +#if defined(_MSC_VER) || defined(__MINGW32__) #pragma pack(push, 1) #else #pragma pack(1) @@ -172,7 +172,7 @@ struct MemParams { } MT32EMU_ALIGN_PACKED system; }; -#if defined(_MSC_VER) || defined (__MINGW32__) +#if defined(_MSC_VER) || defined(__MINGW32__) #pragma pack(pop) #else #pragma pack() diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp index dd3c3540456..c54f620a108 100644 --- a/audio/softsynth/opl/mame.cpp +++ b/audio/softsynth/opl/mame.cpp @@ -33,7 +33,7 @@ #include "common/textconsole.h" #include "common/util.h" -#if defined (_WIN32_WCE) || defined (__SYMBIAN32__) || defined(__GP32__) || defined(GP2X) || defined (__MAEMO__) || defined(__DS__) || defined (__MINT__) || defined(__N64__) +#if defined(_WIN32_WCE) || defined(__SYMBIAN32__) || defined(__GP32__) || defined(GP2X) || defined(__MAEMO__) || defined(__DS__) || defined(__MINT__) || defined(__N64__) #include "common/config-manager.h" #endif @@ -1226,7 +1226,7 @@ FM_OPL *makeAdLibOPL(int rate) { // We need to emulate one YM3812 chip int env_bits = FMOPL_ENV_BITS_HQ; int eg_ent = FMOPL_EG_ENT_HQ; -#if defined (_WIN32_WCE) || defined(__SYMBIAN32__) || defined(__GP32__) || defined (GP2X) || defined(__MAEMO__) || defined(__DS__) || defined (__MINT__) || defined(__N64__) +#if defined(_WIN32_WCE) || defined(__SYMBIAN32__) || defined(__GP32__) || defined(GP2X) || defined(__MAEMO__) || defined(__DS__) || defined(__MINT__) || defined(__N64__) if (ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) { env_bits = FMOPL_ENV_BITS_HQ; eg_ent = FMOPL_EG_ENT_HQ; diff --git a/backends/keymapper/action.cpp b/backends/keymapper/action.cpp index e5b2d9415a8..33f5c423b07 100644 --- a/backends/keymapper/action.cpp +++ b/backends/keymapper/action.cpp @@ -29,7 +29,7 @@ namespace Common { Action::Action(Keymap *boss, const char *i, String des) - : _boss(boss), description(des), _hwKey(0) { + : _boss(boss), description(des), _hwInput(0) { assert(i); assert(_boss); @@ -38,18 +38,18 @@ Action::Action(Keymap *boss, const char *i, String des) _boss->addAction(this); } -void Action::mapKey(const HardwareKey *key) { - if (_hwKey) +void Action::mapInput(const HardwareInput *input) { + if (_hwInput) _boss->unregisterMapping(this); - _hwKey = key; + _hwInput = input; - if (_hwKey) - _boss->registerMapping(this, _hwKey); + if (_hwInput) + _boss->registerMapping(this, _hwInput); } -const HardwareKey *Action::getMappedKey() const { - return _hwKey; +const HardwareInput *Action::getMappedInput() const { + return _hwInput; } } // End of namespace Common diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h index 3132260512f..5e69ed3918d 100644 --- a/backends/keymapper/action.h +++ b/backends/keymapper/action.h @@ -34,7 +34,7 @@ namespace Common { -struct HardwareKey; +struct HardwareInput; class Keymap; #define ACTION_ID_SIZE (4) @@ -55,8 +55,8 @@ struct Action { List events; private: - /** Hardware key that is mapped to this Action */ - const HardwareKey *_hwKey; + /** Hardware input that is mapped to this Action */ + const HardwareInput *_hwInput; Keymap *_boss; public: @@ -97,8 +97,8 @@ public: return _boss; } - void mapKey(const HardwareKey *key); - const HardwareKey *getMappedKey() const; + void mapInput(const HardwareInput *input); + const HardwareInput *getMappedInput() const; }; diff --git a/backends/platform/sdl/hardwarekeys.cpp b/backends/keymapper/hardware-input.cpp similarity index 55% rename from backends/platform/sdl/hardwarekeys.cpp rename to backends/keymapper/hardware-input.cpp index 5fb4473ebd2..d1f8822ac08 100644 --- a/backends/platform/sdl/hardwarekeys.cpp +++ b/backends/keymapper/hardware-input.cpp @@ -1,34 +1,34 @@ /* 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. +* +* 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. +* +*/ - * 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. - * - */ - -#include "backends/platform/sdl/sdl.h" -#include "backends/keymapper/keymapper.h" -#include "common/keyboard.h" +#include "backends/keymapper/hardware-input.h" #ifdef ENABLE_KEYMAPPER -using namespace Common; +#include "backends/keymapper/keymapper.h" -static const KeyTableEntry sdlKeys[] = { +namespace Common { + +static const KeyTableEntry defaultKeys[] = { {"BACKSPACE", KEYCODE_BACKSPACE, ASCII_BACKSPACE, "Backspace", false}, {"TAB", KEYCODE_TAB, ASCII_TAB, "Tab", false}, {"CLEAR", KEYCODE_CLEAR, 0, "Clear", false}, @@ -164,7 +164,7 @@ static const KeyTableEntry sdlKeys[] = { {0, KEYCODE_INVALID, 0, 0, false} }; -static const ModifierTableEntry sdlModifiers[] = { +static const ModifierTableEntry defaultModifiers[] = { { 0, "", "", false }, { KBD_CTRL, "C+", "Ctrl+", false }, { KBD_ALT, "A+", "Alt+", false }, @@ -175,7 +175,121 @@ static const ModifierTableEntry sdlModifiers[] = { { 0, 0, 0, false } }; -Common::HardwareKeySet *OSystem_SDL::getHardwareKeySet() { - return new HardwareKeySet(sdlKeys, sdlModifiers); +HardwareInputSet::HardwareInputSet(bool useDefault, const KeyTableEntry *keys, const ModifierTableEntry *modifiers) { + if (useDefault) + addHardwareInputs(defaultKeys, defaultModifiers); + if (keys) + addHardwareInputs(keys, modifiers ? modifiers : defaultModifiers); } -#endif + +HardwareInputSet::~HardwareInputSet() { + List::const_iterator it; + + for (it = _inputs.begin(); it != _inputs.end(); ++it) + delete *it; +} + +void HardwareInputSet::addHardwareInput(const HardwareInput *input) { + assert(input); + + debug(8, "Adding hardware input [%s][%s]", input->id.c_str(), input->description.c_str()); + + removeHardwareInput(input); + + _inputs.push_back(input); +} + +const HardwareInput *HardwareInputSet::findHardwareInput(String id) const { + List::const_iterator it; + + for (it = _inputs.begin(); it != _inputs.end(); ++it) { + if ((*it)->id == id) + return (*it); + } + return 0; +} + +const HardwareInput *HardwareInputSet::findHardwareInput(const HardwareInputCode code) const { + List::const_iterator it; + + for (it = _inputs.begin(); it != _inputs.end(); ++it) { + const HardwareInput *entry = *it; + if (entry->type == kHardwareInputTypeGeneric && entry->inputCode == code) + return entry; + } + return 0; +} + +const HardwareInput *HardwareInputSet::findHardwareInput(const KeyState& keystate) const { + List::const_iterator it; + + for (it = _inputs.begin(); it != _inputs.end(); ++it) { + const HardwareInput *entry = *it; + if (entry->type == kHardwareInputTypeKeyboard && entry->key == keystate) + return entry; + } + return 0; +} + +void HardwareInputSet::addHardwareInputs(const HardwareInputTableEntry inputs[]) { + for (const HardwareInputTableEntry *entry = inputs; entry->hwId; ++entry) + addHardwareInput(new HardwareInput(entry->hwId, entry->code, entry->desc)); +} + +void HardwareInputSet::addHardwareInputs(const KeyTableEntry keys[], const ModifierTableEntry modifiers[]) { + const KeyTableEntry *key; + const ModifierTableEntry *mod; + char fullKeyId[50]; + char fullKeyDesc[100]; + uint16 ascii; + + for (mod = modifiers; mod->id; mod++) { + for (key = keys; key->hwId; key++) { + ascii = key->ascii; + + if (mod->shiftable && key->shiftable) { + snprintf(fullKeyId, 50, "%s%c", mod->id, toupper(key->hwId[0])); + snprintf(fullKeyDesc, 100, "%s%c", mod->desc, toupper(key->desc[0])); + ascii = toupper(key->ascii); + } else if (mod->shiftable) { + snprintf(fullKeyId, 50, "S+%s%s", mod->id, key->hwId); + snprintf(fullKeyDesc, 100, "Shift+%s%s", mod->desc, key->desc); + } else { + snprintf(fullKeyId, 50, "%s%s", mod->id, key->hwId); + snprintf(fullKeyDesc, 100, "%s%s", mod->desc, key->desc); + } + + addHardwareInput(new HardwareInput(fullKeyId, KeyState(key->keycode, ascii, mod->flag), fullKeyDesc)); + } + } +} + +void HardwareInputSet::removeHardwareInput(const HardwareInput *input) { + if (!input) + return; + + List::iterator it; + + for (it = _inputs.begin(); it != _inputs.end(); ++it) { + const HardwareInput *entry = (*it); + bool match = false; + if (entry->id == input->id) + match = true; + else if (input->type == entry->type) { + if (input->type == kHardwareInputTypeGeneric && input->inputCode == entry->inputCode) + match = true; + else if (input->type == kHardwareInputTypeKeyboard && input->key == entry->key) + match = true; + } + if (match) { + debug(7, "Removing hardware input [%s] (%s) because it matches [%s] (%s)", entry->id.c_str(), entry->description.c_str(), input->id.c_str(), input->description.c_str()); + delete entry; + _inputs.erase(it); + } + } +} + +} //namespace Common + +#endif // #ifdef ENABLE_KEYMAPPER + diff --git a/backends/keymapper/hardware-input.h b/backends/keymapper/hardware-input.h new file mode 100644 index 00000000000..51d4accb5b3 --- /dev/null +++ b/backends/keymapper/hardware-input.h @@ -0,0 +1,160 @@ +/* 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. +* +*/ + +#ifndef COMMON_HARDWARE_KEY_H +#define COMMON_HARDWARE_KEY_H + +#include "common/scummsys.h" + +#ifdef ENABLE_KEYMAPPER + +#include "common/keyboard.h" +#include "common/list.h" +#include "common/str.h" +#include "common/textconsole.h" + +namespace Common { + +typedef uint32 HardwareInputCode; + +enum HardwareInputType { + /** Input that sends single events */ + kHardwareInputTypeGeneric, + /** Input that usually send -up and -down events */ + kHardwareInputTypeKeyboard +}; + +/** +* Describes an available hardware input +*/ +struct HardwareInput { + /** unique id used for saving/loading to config */ + String id; + + /** Human readable description */ + String description; + + const HardwareInputType type; + + /** + * A platform specific unique identifier for an input event + * generated when this input is triggered. + * This is only relevant when type == kHardwareInputTypeGeneric + */ + HardwareInputCode inputCode; + + /** + * The KeyState that is generated by the back-end + * when this hardware key is pressed. + * This is only relevant when type == kHardwareInputTypeKeyboard + */ + KeyState key; + + HardwareInput(String i, HardwareInputCode ic = 0, String desc = "") + : id(i), inputCode(ic), description(desc), type(kHardwareInputTypeGeneric) { } + + HardwareInput(String i, KeyState ky, String desc = "") + : id(i), key(ky), description(desc), type(kHardwareInputTypeKeyboard) { } +}; + +struct HardwareInputTableEntry { + const char *hwId; + HardwareInputCode code; + const char *desc; +}; + +/** + * Entry in a static table of available non-modifier keys + */ +struct KeyTableEntry { + const char *hwId; + KeyCode keycode; + uint16 ascii; + const char *desc; + bool shiftable; +}; + +/** + * Entry in a static table of available key modifiers + */ +struct ModifierTableEntry { + byte flag; + const char *id; + const char *desc; + bool shiftable; +}; + +/** + * Simple class to encapsulate a device's set of HardwareInputs. + * Each device should instantiate this and call addHardwareInput a number of times + * in its constructor to define the device's available keys. + */ +class HardwareInputSet { +public: + + /** + * Add hardware input keys to the set out of key and modifier tables. + * @param useDefault auto-add the built-in default inputs + * @param keys table of available keys + * @param modifiers table of available modifiers + */ + HardwareInputSet(bool useDefault = false, const KeyTableEntry keys[] = 0, const ModifierTableEntry modifiers[] = 0); + + virtual ~HardwareInputSet(); + + void addHardwareInput(const HardwareInput *input); + + const HardwareInput *findHardwareInput(String id) const; + + const HardwareInput *findHardwareInput(const HardwareInputCode code) const; + + const HardwareInput *findHardwareInput(const KeyState& keystate) const; + + const List &getHardwareInputs() const { return _inputs; } + + uint size() const { return _inputs.size(); } + + /** + * Add hardware inputs to the set out of a table. + * @param inputs table of available inputs + */ + void addHardwareInputs(const HardwareInputTableEntry inputs[]); + + /** + * Add hardware inputs to the set out of key and modifier tables. + * @param keys table of available keys + * @param modifiers table of available modifiers + */ + void addHardwareInputs(const KeyTableEntry keys[], const ModifierTableEntry modifiers[]); + + void removeHardwareInput(const HardwareInput *input); + +private: + + List _inputs; +}; + +} // End of namespace Common + +#endif // #ifdef ENABLE_KEYMAPPER + +#endif // #ifndef COMMON_HARDWARE_KEY_H diff --git a/backends/keymapper/hardware-key.h b/backends/keymapper/hardware-key.h deleted file mode 100644 index 9fd8d1981a5..00000000000 --- a/backends/keymapper/hardware-key.h +++ /dev/null @@ -1,187 +0,0 @@ -/* 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. -* -*/ - -#ifndef COMMON_HARDWARE_KEY_H -#define COMMON_HARDWARE_KEY_H - -#include "common/scummsys.h" - -#ifdef ENABLE_KEYMAPPER - -#include "common/textconsole.h" - -namespace Common { - -/** -* Describes an available hardware key -*/ -struct HardwareKey { - /** unique id used for saving/loading to config */ - String id; - - /** Human readable description */ - String description; - - /** - * The KeyState that is generated by the back-end - * when this hardware key is pressed. - */ - KeyState key; - - HardwareKey(String i, KeyState ky = KeyState(), String desc = "") - : id(i), key(ky), description(desc) { } -}; - -/** - * Entry in a static table of available non-modifier keys - */ -struct KeyTableEntry { - const char *hwId; - KeyCode keycode; - uint16 ascii; - const char *desc; - bool shiftable; -}; - -/** - * Entry in a static table of available key modifiers - */ -struct ModifierTableEntry { - byte flag; - const char *id; - const char *desc; - bool shiftable; -}; - -/** - * Simple class to encapsulate a device's set of HardwareKeys. - * Each device should instantiate this and call addHardwareKey a number of times - * in its constructor to define the device's available keys. - */ -class HardwareKeySet { -public: - - /** - * Add hardware keys to the set out of key and modifier tables. - * @param keys table of available keys - * @param modifiers table of available modifiers - */ - HardwareKeySet(const KeyTableEntry keys[], const ModifierTableEntry modifiers[]) { - addHardwareKeys(keys, modifiers); - } - - HardwareKeySet() { } - - virtual ~HardwareKeySet() { - List::const_iterator it; - - for (it = _keys.begin(); it != _keys.end(); it++) - delete *it; - } - - void addHardwareKey(const HardwareKey *key) { - checkForKey(key); - _keys.push_back(key); - } - - const HardwareKey *findHardwareKey(String id) const { - List::const_iterator it; - - for (it = _keys.begin(); it != _keys.end(); it++) { - if ((*it)->id == id) - return (*it); - } - return 0; - } - - const HardwareKey *findHardwareKey(const KeyState& keystate) const { - List::const_iterator it; - - for (it = _keys.begin(); it != _keys.end(); it++) { - if ((*it)->key == keystate) - return (*it); - } - return 0; - } - - const List &getHardwareKeys() const { - return _keys; - } - - uint size() const { - return _keys.size(); - } - - /** - * Add hardware keys to the set out of key and modifier tables. - * @param keys table of available keys - * @param modifiers table of available modifiers - */ - void addHardwareKeys(const KeyTableEntry keys[], const ModifierTableEntry modifiers[]) { - const KeyTableEntry *key; - const ModifierTableEntry *mod; - char fullKeyId[50]; - char fullKeyDesc[100]; - uint16 ascii; - - for (mod = modifiers; mod->id; mod++) { - for (key = keys; key->hwId; key++) { - ascii = key->ascii; - - if (mod->shiftable && key->shiftable) { - snprintf(fullKeyId, 50, "%s%c", mod->id, toupper(key->hwId[0])); - snprintf(fullKeyDesc, 100, "%s%c", mod->desc, toupper(key->desc[0])); - ascii = toupper(key->ascii); - } else if (mod->shiftable) { - snprintf(fullKeyId, 50, "S+%s%s", mod->id, key->hwId); - snprintf(fullKeyDesc, 100, "Shift+%s%s", mod->desc, key->desc); - } else { - snprintf(fullKeyId, 50, "%s%s", mod->id, key->hwId); - snprintf(fullKeyDesc, 100, "%s%s", mod->desc, key->desc); - } - - addHardwareKey(new HardwareKey(fullKeyId, KeyState(key->keycode, ascii, mod->flag), fullKeyDesc)); - } - } - } - -private: - - void checkForKey(const HardwareKey *key) { - List::iterator it; - - for (it = _keys.begin(); it != _keys.end(); it++) { - if ((*it)->id == key->id) - error("Error adding HardwareKey '%s' - id of %s already in use!", key->description.c_str(), key->id.c_str()); - else if ((*it)->key == key->key) - error("Error adding HardwareKey '%s' - key already in use!", key->description.c_str()); - } - } - - List _keys; -}; - -} // End of namespace Common - -#endif // #ifdef ENABLE_KEYMAPPER - -#endif // #ifndef COMMON_HARDWARE_KEY_H diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp index 3913fd149e2..e95dd6afb5f 100644 --- a/backends/keymapper/keymap.cpp +++ b/backends/keymapper/keymap.cpp @@ -26,21 +26,24 @@ #include "common/system.h" -#include "backends/keymapper/hardware-key.h" +#include "backends/keymapper/hardware-input.h" #include "backends/keymapper/keymapper-defaults.h" #define KEYMAP_KEY_PREFIX "keymap_" namespace Common { -Keymap::Keymap(const Keymap& km) : _actions(km._actions), _keymap(), _configDomain(0) { +Keymap::Keymap(const Keymap& km) : _actions(km._actions), _keymap(), _nonkeymap(), _configDomain(0) { List::iterator it; for (it = _actions.begin(); it != _actions.end(); ++it) { - const HardwareKey *hwKey = (*it)->getMappedKey(); + const HardwareInput *hwInput = (*it)->getMappedInput(); - if (hwKey) { - _keymap[hwKey->key] = *it; + if (hwInput) { + if (hwInput->type == kHardwareInputTypeKeyboard) + _keymap[hwInput->key] = *it; + else if (hwInput->type == kHardwareInputTypeGeneric) + _nonkeymap[hwInput->inputCode] = *it; } } } @@ -59,24 +62,32 @@ void Keymap::addAction(Action *action) { _actions.push_back(action); } -void Keymap::registerMapping(Action *action, const HardwareKey *hwKey) { - HashMap::iterator it; - - it = _keymap.find(hwKey->key); - - // if key is already mapped to a different action then un-map it - if (it != _keymap.end() && action != it->_value) { - it->_value->mapKey(0); +void Keymap::registerMapping(Action *action, const HardwareInput *hwInput) { + if (hwInput->type == kHardwareInputTypeKeyboard) { + HashMap::iterator it = _keymap.find(hwInput->key); + // if input is already mapped to a different action then unmap it from there + if (it != _keymap.end() && action != it->_value) + it->_value->mapInput(0); + // now map it + _keymap[hwInput->key] = action; + } else if (hwInput->type == kHardwareInputTypeGeneric) { + HashMap::iterator it = _nonkeymap.find(hwInput->inputCode); + // if input is already mapped to a different action then unmap it from there + if (it != _nonkeymap.end() && action != it->_value) + it->_value->mapInput(0); + // now map it + _nonkeymap[hwInput->inputCode] = action; } - - _keymap[hwKey->key] = action; } void Keymap::unregisterMapping(Action *action) { - const HardwareKey *hwKey = action->getMappedKey(); + const HardwareInput *hwInput = action->getMappedInput(); - if (hwKey) { - _keymap.erase(hwKey->key); + if (hwInput) { + if (hwInput->type == kHardwareInputTypeKeyboard) + _keymap.erase(hwInput->key); + else if (hwInput->type == kHardwareInputTypeGeneric) + _nonkeymap.erase(hwInput->inputCode); } } @@ -116,11 +127,22 @@ Action *Keymap::getMappedAction(const KeyState& ks) const { return it->_value; } +Action *Keymap::getMappedAction(const HardwareInputCode code) const { + HashMap::iterator it; + + it = _nonkeymap.find(code); + + if (it == _nonkeymap.end()) + return 0; + else + return it->_value; +} + void Keymap::setConfigDomain(ConfigManager::Domain *dom) { _configDomain = dom; } -void Keymap::loadMappings(const HardwareKeySet *hwKeys) { +void Keymap::loadMappings(const HardwareInputSet *hwKeys) { if (!_configDomain) return; @@ -129,7 +151,7 @@ void Keymap::loadMappings(const HardwareKeySet *hwKeys) { Common::KeymapperDefaultBindings *defaults = g_system->getKeymapperDefaultBindings(); - HashMap mappedKeys; + HashMap mappedInputs; List::iterator it; String prefix = KEYMAP_KEY_PREFIX + _name + "_"; @@ -138,37 +160,37 @@ void Keymap::loadMappings(const HardwareKeySet *hwKeys) { String actionId(ua->id); String confKey = prefix + actionId; - String hwKeyId = _configDomain->getVal(confKey); + String hwInputId = _configDomain->getVal(confKey); bool defaulted = false; // fall back to the platform-specific defaults - if (hwKeyId.empty() && defaults) { - hwKeyId = defaults->getDefaultBinding(_name, actionId); - if (!hwKeyId.empty()) + if (hwInputId.empty() && defaults) { + hwInputId = defaults->getDefaultBinding(_name, actionId); + if (!hwInputId.empty()) defaulted = true; } // there's no mapping - if (hwKeyId.empty()) + if (hwInputId.empty()) continue; - const HardwareKey *hwKey = hwKeys->findHardwareKey(hwKeyId.c_str()); + const HardwareInput *hwInput = hwKeys->findHardwareInput(hwInputId.c_str()); - if (!hwKey) { - warning("HardwareKey with ID '%s' not known", hwKeyId.c_str()); + if (!hwInput) { + warning("HardwareInput with ID '%s' not known", hwInputId.c_str()); continue; } if (defaulted) { - if (mappedKeys.contains(hwKeyId)) { - debug(1, "Action [%s] not falling back to hardcoded default value [%s] because the key is in use", confKey.c_str(), hwKeyId.c_str()); + if (mappedInputs.contains(hwInputId)) { + debug(1, "Action [%s] not falling back to hardcoded default value [%s] because the hardware input is in use", confKey.c_str(), hwInputId.c_str()); continue; } - warning("Action [%s] fell back to hardcoded default value [%s]", confKey.c_str(), hwKeyId.c_str()); + warning("Action [%s] fell back to hardcoded default value [%s]", confKey.c_str(), hwInputId.c_str()); } - mappedKeys.setVal(hwKeyId, hwKey); + mappedInputs.setVal(hwInputId, hwInput); // map the key - ua->mapKey(hwKey); + ua->mapInput(hwInput); } } @@ -187,27 +209,27 @@ void Keymap::saveMappings() { String actId((*it)->id, (*it)->id + actIdLen); String hwId = ""; - if ((*it)->getMappedKey()) { - hwId = (*it)->getMappedKey()->id; + if ((*it)->getMappedInput()) { + hwId = (*it)->getMappedInput()->id; } _configDomain->setVal(prefix + actId, hwId); } } -bool Keymap::isComplete(const HardwareKeySet *hwKeys) { +bool Keymap::isComplete(const HardwareInputSet *hwInputs) { List::iterator it; bool allMapped = true; uint numberMapped = 0; for (it = _actions.begin(); it != _actions.end(); ++it) { - if ((*it)->getMappedKey()) { - numberMapped++; + if ((*it)->getMappedInput()) { + ++numberMapped; } else { allMapped = false; } } - return allMapped || (numberMapped == hwKeys->size()); + return allMapped || (numberMapped == hwInputs->size()); } } // End of namespace Common diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h index 2e9f08533e1..6eaec7dcaf2 100644 --- a/backends/keymapper/keymap.h +++ b/backends/keymapper/keymap.h @@ -33,12 +33,10 @@ #include "common/keyboard.h" #include "common/list.h" #include "backends/keymapper/action.h" +#include "backends/keymapper/hardware-input.h" namespace Common { -struct HardwareKey; -class HardwareKeySet; - /** * Hash function for KeyState */ @@ -76,13 +74,20 @@ public: */ Action *getMappedAction(const KeyState& ks) const; + /** + * Find the Action that a generic input is mapped to + * @param code the input code that is mapped to the required Action + * @return a pointer to the Action or 0 if no + */ + Action *getMappedAction(const HardwareInputCode code) const; + void setConfigDomain(ConfigManager::Domain *dom); /** * Load this keymap's mappings from the config manager. - * @param hwKeys the set to retrieve hardware key pointers from + * @param hwInputs the set to retrieve hardware input pointers from */ - void loadMappings(const HardwareKeySet *hwKeys); + void loadMappings(const HardwareInputSet *hwInputs); /** * Save this keymap's mappings to the config manager @@ -93,9 +98,9 @@ public: /** * Returns true if all UserAction's in Keymap are mapped, or, - * all HardwareKey's from the given set have been used up. + * all HardwareInputs from the given set have been used up. */ - bool isComplete(const HardwareKeySet *hwKeys); + bool isComplete(const HardwareInputSet *hwInputs); const String& getName() { return _name; } @@ -110,15 +115,15 @@ private: void addAction(Action *action); /** - * Registers a HardwareKey to the given Action + * Registers a HardwareInput to the given Action * @param action Action in this Keymap - * @param key pointer to HardwareKey to map + * @param key pointer to HardwareInput to map * @see Action::mapKey */ - void registerMapping(Action *action, const HardwareKey *key); + void registerMapping(Action *action, const HardwareInput *input); /** - * Unregisters a HardwareKey from the given Action (if one is mapped) + * Unregisters a HardwareInput from the given Action (if one is mapped) * @param action Action in this Keymap * @see Action::mapKey */ @@ -130,6 +135,7 @@ private: String _name; List _actions; HashMap _keymap; + HashMap _nonkeymap; ConfigManager::Domain *_configDomain; }; diff --git a/backends/keymapper/keymapper-defaults.h b/backends/keymapper/keymapper-defaults.h index 5b84ebeaa9b..bd4afd4e3a5 100644 --- a/backends/keymapper/keymapper-defaults.h +++ b/backends/keymapper/keymapper-defaults.h @@ -35,17 +35,17 @@ namespace Common { class KeymapperDefaultBindings : HashMap { public: /** - * This sets a default hwKey for a given Keymap Action + * This sets a default hwInput for a given Keymap Action * @param keymapId String representing Keymap id (Keymap.name) * @param actionId String representing Action id (Action.id) - * @param hwKeyId String representing the HardwareKey id (HardwareKey.hwKeyId) + * @param hwInputId String representing the HardwareInput id (HardwareInput.id) */ - void setDefaultBinding(String keymapId, String actionId, String hwKeyId) { setVal(keymapId + "_" + actionId, hwKeyId); } + void setDefaultBinding(String keymapId, String actionId, String hwInputId) { setVal(keymapId + "_" + actionId, hwInputId); } /** * This retrieves the assigned default hwKey for a given Keymap Action * @param keymapId String representing Keymap id (Keymap.name) * @param actionId String representing Action id (Action.id) - * @return hwKeyId String representing the HardwareKey id (HardwareKey.hwKeyId) + * @return String representing the HardwareInput id (HardwareInput.id) */ String getDefaultBinding(String keymapId, String actionId) { return getVal(keymapId + "_" + actionId); } }; diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp index 189f8624697..dcb021f2d87 100644 --- a/backends/keymapper/keymapper.cpp +++ b/backends/keymapper/keymapper.cpp @@ -25,9 +25,14 @@ #ifdef ENABLE_KEYMAPPER #include "common/config-manager.h" +#include "common/system.h" namespace Common { +// These magic numbers are provided by fuzzie and WebOS +static const uint32 kDelayKeyboardEventMillis = 250; +static const uint32 kDelayMouseEventMillis = 50; + void Keymapper::Domain::addKeymap(Keymap *map) { iterator it = find(map->getName()); @@ -54,26 +59,26 @@ Keymap *Keymapper::Domain::getKeymap(const String& name) { } Keymapper::Keymapper(EventManager *evtMgr) - : _eventMan(evtMgr), _enabled(true), _hardwareKeys(0) { + : _eventMan(evtMgr), _enabled(true), _remapping(false), _hardwareInputs(0), _actionToRemap(0) { ConfigManager::Domain *confDom = ConfMan.getDomain(ConfigManager::kKeymapperDomain); _globalDomain.setConfigDomain(confDom); } Keymapper::~Keymapper() { - delete _hardwareKeys; + delete _hardwareInputs; } -void Keymapper::registerHardwareKeySet(HardwareKeySet *keys) { - if (_hardwareKeys) - error("Hardware key set already registered"); +void Keymapper::registerHardwareInputSet(HardwareInputSet *inputs) { + if (_hardwareInputs) + error("Hardware input set already registered"); - if (!keys) { - warning("No hardware keys are supplied"); - return; + if (!inputs) { + warning("No hardware input were defined, using defaults"); + inputs = new HardwareInputSet(true); } - _hardwareKeys = keys; + _hardwareInputs = inputs; } void Keymapper::addGlobalKeymap(Keymap *keymap) { @@ -95,15 +100,15 @@ void Keymapper::addGameKeymap(Keymap *keymap) { } void Keymapper::initKeymap(Domain &domain, Keymap *map) { - if (!_hardwareKeys) { - warning("No hardware keys were registered yet (%s)", map->getName().c_str()); + if (!_hardwareInputs) { + warning("No hardware inputs were registered yet (%s)", map->getName().c_str()); return; } map->setConfigDomain(domain.getConfigDomain()); - map->loadMappings(_hardwareKeys); + map->loadMappings(_hardwareInputs); - if (map->isComplete(_hardwareKeys) == false) { + if (map->isComplete(_hardwareInputs) == false) { map->saveMappings(); ConfMan.flushToDisk(); } @@ -183,13 +188,16 @@ List Keymapper::mapEvent(const Event &ev, EventSource *source) { if (source && !source->allowMapping()) { return DefaultEventMapper::mapEvent(ev, source); } - List mappedEvents; - if (ev.type == Common::EVENT_KEYDOWN) + if (_remapping) + mappedEvents = remap(ev); + else if (ev.type == Common::EVENT_KEYDOWN) mappedEvents = mapKeyDown(ev.kbd); else if (ev.type == Common::EVENT_KEYUP) mappedEvents = mapKeyUp(ev.kbd); + else if (ev.type == Common::EVENT_CUSTOM_BACKEND_HARDWARE) + mappedEvents = mapNonKey(ev.customType); if (!mappedEvents.empty()) return mappedEvents; @@ -197,6 +205,13 @@ List Keymapper::mapEvent(const Event &ev, EventSource *source) { return DefaultEventMapper::mapEvent(ev, source); } +void Keymapper::startRemappingMode(Action *actionToRemap) { + assert(!_remapping); + + _remapping = true; + _actionToRemap = actionToRemap; +} + List Keymapper::mapKeyDown(const KeyState& key) { return mapKey(key, true); } @@ -236,7 +251,30 @@ List Keymapper::mapKey(const KeyState& key, bool keyDown) { if (!action) return List(); - return executeAction(action, keyDown); + return executeAction(action, keyDown ? kIncomingKeyDown : kIncomingKeyUp); +} + + +List Keymapper::mapNonKey(const HardwareInputCode code) { + if (!_enabled || _activeMaps.empty()) + return List(); + + Action *action = 0; + + // Search for nonkey in active keymap stack + for (int i = _activeMaps.size() - 1; i >= 0; --i) { + MapRecord mr = _activeMaps[i]; + debug(5, "Keymapper::mapKey keymap: %s", mr.keymap->getName().c_str()); + action = mr.keymap->getMappedAction(code); + + if (action || !mr.transparent) + break; + } + + if (!action) + return List(); + + return executeAction(action); } Action *Keymapper::getAction(const KeyState& key) { @@ -245,54 +283,106 @@ Action *Keymapper::getAction(const KeyState& key) { return action; } -List Keymapper::executeAction(const Action *action, bool keyDown) { +List Keymapper::executeAction(const Action *action, IncomingEventType incomingType) { List mappedEvents; List::const_iterator it; - + Event evt; for (it = action->events.begin(); it != action->events.end(); ++it) { - Event evt = *it; + evt = Event(*it); + EventType convertedType = convertDownToUp(evt.type); - switch (evt.type) { - case EVENT_KEYDOWN: - if (!keyDown) evt.type = EVENT_KEYUP; - break; - case EVENT_KEYUP: - if (keyDown) evt.type = EVENT_KEYDOWN; - break; - case EVENT_LBUTTONDOWN: - if (!keyDown) evt.type = EVENT_LBUTTONUP; - break; - case EVENT_LBUTTONUP: - if (keyDown) evt.type = EVENT_LBUTTONDOWN; - break; - case EVENT_RBUTTONDOWN: - if (!keyDown) evt.type = EVENT_RBUTTONUP; - break; - case EVENT_RBUTTONUP: - if (keyDown) evt.type = EVENT_RBUTTONDOWN; - break; - case EVENT_MBUTTONDOWN: - if (!keyDown) evt.type = EVENT_MBUTTONUP; - break; - case EVENT_MBUTTONUP: - if (keyDown) evt.type = EVENT_MBUTTONDOWN; - break; - case EVENT_MAINMENU: - if (!keyDown) evt.type = EVENT_MAINMENU; - break; - default: - // don't deliver other events on key up - if (!keyDown) continue; + // hardware keys need to send up instead when they are up + if (incomingType == kIncomingKeyUp) { + if (convertedType == EVENT_INVALID) + continue; // don't send any non-down-converted events on up they were already sent on down + evt.type = convertedType; } evt.mouse = _eventMan->getMousePos(); - mappedEvents.push_back(evt); + + // Check if the event is coming from a non-key hardware event + // that is mapped to a key event + if (incomingType == kIncomingNonKey && convertedType != EVENT_INVALID) + // WORKAROUND: Delay the down events coming from non-key hardware events + // with a zero delay. This is to prevent DOWN1 DOWN2 UP1 UP2. + addDelayedEvent(0, evt); + else + mappedEvents.push_back(evt); + + // non-keys need to send up as well + if (incomingType == kIncomingNonKey && convertedType != EVENT_INVALID) { + // WORKAROUND: Delay the up events coming from non-key hardware events + // This is for engines that run scripts that check on key being down + evt.type = convertedType; + const uint32 delay = (convertedType == EVENT_KEYUP ? kDelayKeyboardEventMillis : kDelayMouseEventMillis); + addDelayedEvent(delay, evt); + } } return mappedEvents; } -const HardwareKey *Keymapper::findHardwareKey(const KeyState& key) { - return (_hardwareKeys) ? _hardwareKeys->findHardwareKey(key) : 0; +EventType Keymapper::convertDownToUp(EventType type) { + EventType result = EVENT_INVALID; + switch (type) { + case EVENT_KEYDOWN: + result = EVENT_KEYUP; + break; + case EVENT_LBUTTONDOWN: + result = EVENT_LBUTTONUP; + break; + case EVENT_RBUTTONDOWN: + result = EVENT_RBUTTONUP; + break; + case EVENT_MBUTTONDOWN: + result = EVENT_MBUTTONUP; + break; + default: + break; + } + return result; +} + +const HardwareInput *Keymapper::findHardwareInput(const KeyState& key) { + return (_hardwareInputs) ? _hardwareInputs->findHardwareInput(key) : 0; +} + +const HardwareInput *Keymapper::findHardwareInput(const HardwareInputCode code) { + return (_hardwareInputs) ? _hardwareInputs->findHardwareInput(code) : 0; +} + +List Keymapper::remap(const Event &ev) { + assert(_remapping); + assert(_actionToRemap); + + List list; + + const HardwareInput *hwInput = 0; + Event mappedEvent; + + switch (ev.type) { + case EVENT_KEYDOWN: + // eat the event by returning an event invalid + mappedEvent.type = EVENT_INVALID; + list.push_back(mappedEvent); + break; + case EVENT_KEYUP: + hwInput = findHardwareInput(ev.kbd); + break; + case EVENT_CUSTOM_BACKEND_HARDWARE: + hwInput = findHardwareInput(ev.customType); + break; + default: + break; + } + if (hwInput) { + _actionToRemap->mapInput(hwInput); + _actionToRemap->getParent()->saveMappings(); + _remapping = false; + _actionToRemap = 0; + mappedEvent.type = EVENT_GUI_REMAP_COMPLETE_ACTION; + list.push_back(mappedEvent); + } + return list; } } // End of namespace Common diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h index 31bfcbc0801..1e8d1c08c32 100644 --- a/backends/keymapper/keymapper.h +++ b/backends/keymapper/keymapper.h @@ -31,7 +31,7 @@ #include "common/list.h" #include "common/hashmap.h" #include "common/stack.h" -#include "backends/keymapper/hardware-key.h" +#include "backends/keymapper/hardware-input.h" #include "backends/keymapper/keymap.h" namespace Common { @@ -81,17 +81,17 @@ public: virtual List mapEvent(const Event &ev, EventSource *source); /** - * Registers a HardwareKeySet with the Keymapper + * Registers a HardwareInputSet with the Keymapper * @note should only be called once (during backend initialisation) */ - void registerHardwareKeySet(HardwareKeySet *keys); + void registerHardwareInputSet(HardwareInputSet *inputs); /** - * Get a list of all registered HardwareKeys + * Get a list of all registered HardwareInputs */ - const List &getHardwareKeys() const { - assert(_hardwareKeys); - return _hardwareKeys->getHardwareKeys(); + const List &getHardwareInputs() const { + assert(_hardwareInputs); + return _hardwareInputs->getHardwareInputs(); } /** @@ -149,6 +149,7 @@ public: * @return mapped events */ List mapKey(const KeyState& key, bool keyDown); + List mapNonKey(const HardwareInputCode code); /** * @brief Map a key down event. @@ -168,9 +169,32 @@ public: void setEnabled(bool enabled) { _enabled = enabled; } /** - * Return a HardwareKey pointer for the given key state + * @brief Activate remapping mode + * While this mode is active, any mappable event will be bound to the action + * provided. + * @param actionToRemap Action that is the target of the remap */ - const HardwareKey *findHardwareKey(const KeyState& key); + void startRemappingMode(Action *actionToRemap); + + /** + * @brief Force-stop the remapping mode + */ + void stopRemappingMode() { _remapping = false; } + + /** + * Query whether the keymapper is currently in the remapping mode + */ + bool isRemapping() const { return _remapping; } + + /** + * Return a HardwareInput pointer for the given key state + */ + const HardwareInput *findHardwareInput(const KeyState& key); + + /** + * Return a HardwareInput pointer for the given input code + */ + const HardwareInput *findHardwareInput(const HardwareInputCode code); Domain& getGlobalDomain() { return _globalDomain; } Domain& getGameDomain() { return _gameDomain; } @@ -178,22 +202,32 @@ public: private: + enum IncomingEventType { + kIncomingKeyDown, + kIncomingKeyUp, + kIncomingNonKey + }; + void initKeymap(Domain &domain, Keymap *keymap); Domain _globalDomain; Domain _gameDomain; - HardwareKeySet *_hardwareKeys; + HardwareInputSet *_hardwareInputs; void pushKeymap(Keymap *newMap, bool transparent, bool global); Action *getAction(const KeyState& key); - List executeAction(const Action *act, bool keyDown); + List executeAction(const Action *act, IncomingEventType incomingType = kIncomingNonKey); + EventType convertDownToUp(EventType eventType); + List remap(const Event &ev); EventManager *_eventMan; bool _enabled; + bool _remapping; + Action *_actionToRemap; Stack _activeMaps; HashMap _keysDown; diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp index a8699091965..009c2201a95 100644 --- a/backends/keymapper/remap-dialog.cpp +++ b/backends/keymapper/remap-dialog.cpp @@ -39,7 +39,7 @@ enum { }; RemapDialog::RemapDialog() - : Dialog("KeyMapper"), _keymapTable(0), _activeRemapAction(0), _topAction(0), _remapTimeout(0), _topKeymapIsGui(false) { + : Dialog("KeyMapper"), _keymapTable(0), _topAction(0), _remapTimeout(0), _topKeymapIsGui(false) { _keymapper = g_system->getEventManager()->getKeymapper(); assert(_keymapper); @@ -243,16 +243,14 @@ void RemapDialog::clearMapping(uint i) { return; debug(3, "clear the mapping %u", i); - _activeRemapAction = _currentActions[_topAction + i].action; - _activeRemapAction->mapKey(0); - _activeRemapAction->getParent()->saveMappings(); + Action *activeRemapAction = _currentActions[_topAction + i].action; + activeRemapAction->mapInput(0); + activeRemapAction->getParent()->saveMappings(); _changes = true; // force refresh - _topAction = -1; + stopRemapping(true); refreshKeymap(); - - _activeRemapAction = 0; } void RemapDialog::startRemapping(uint i) { @@ -260,57 +258,56 @@ void RemapDialog::startRemapping(uint i) { return; _remapTimeout = g_system->getMillis() + kRemapTimeoutDelay; - _activeRemapAction = _currentActions[_topAction + i].action; + Action *activeRemapAction = _currentActions[_topAction + i].action; _keymapWidgets[i].keyButton->setLabel("..."); _keymapWidgets[i].keyButton->draw(); - _keymapper->setEnabled(false); + _keymapper->startRemappingMode(activeRemapAction); } -void RemapDialog::stopRemapping() { +void RemapDialog::stopRemapping(bool force) { _topAction = -1; refreshKeymap(); - _activeRemapAction = 0; - - _keymapper->setEnabled(true); + if (force) + _keymapper->stopRemappingMode(); } void RemapDialog::handleKeyDown(Common::KeyState state) { - if (_activeRemapAction) + if (_keymapper->isRemapping()) return; GUI::Dialog::handleKeyDown(state); } void RemapDialog::handleKeyUp(Common::KeyState state) { - if (_activeRemapAction) { - const HardwareKey *hwkey = _keymapper->findHardwareKey(state); + if (_keymapper->isRemapping()) + return; - debug(4, "RemapDialog::handleKeyUp Key: %d, %d (%c), %x", state.keycode, state.ascii, (state.ascii ? state.ascii : ' '), state.flags); + GUI::Dialog::handleKeyUp(state); +} - if (hwkey) { - _activeRemapAction->mapKey(hwkey); - _activeRemapAction->getParent()->saveMappings(); - _changes = true; - stopRemapping(); - } +void RemapDialog::handleOtherEvent(Event ev) { + if (ev.type == EVENT_GUI_REMAP_COMPLETE_ACTION) { + // _keymapper is telling us that something changed + _changes = true; + stopRemapping(); } else { - GUI::Dialog::handleKeyUp(state); + GUI::Dialog::handleOtherEvent(ev); } } void RemapDialog::handleMouseDown(int x, int y, int button, int clickCount) { - if (_activeRemapAction) + if (_keymapper->isRemapping()) stopRemapping(); else Dialog::handleMouseDown(x, y, button, clickCount); } void RemapDialog::handleTickle() { - if (_activeRemapAction && g_system->getMillis() > _remapTimeout) - stopRemapping(); + if (_keymapper->isRemapping() && g_system->getMillis() > _remapTimeout) + stopRemapping(true); Dialog::handleTickle(); } @@ -325,7 +322,7 @@ void RemapDialog::loadKeymap() { // - all of the topmost keymap action // - all mapped actions that are reachable - List freeKeys(_keymapper->getHardwareKeys()); + List freeInputs(_keymapper->getHardwareInputs()); int topIndex = activeKeymaps.size() - 1; @@ -344,8 +341,8 @@ void RemapDialog::loadKeymap() { _currentActions.push_back(info); - if (act->getMappedKey()) - freeKeys.remove(act->getMappedKey()); + if (act->getMappedInput()) + freeInputs.remove(act->getMappedInput()); } // loop through remaining finding mappings for unmapped keys @@ -353,21 +350,26 @@ void RemapDialog::loadKeymap() { for (int i = topIndex - 1; i >= 0; --i) { Keymapper::MapRecord mr = activeKeymaps[i]; debug(3, "RemapDialog::loadKeymap keymap: %s", mr.keymap->getName().c_str()); - List::iterator keyIt = freeKeys.begin(); + List::iterator inputIt = freeInputs.begin(); + const HardwareInput *input = *inputIt; + while (inputIt != freeInputs.end()) { - while (keyIt != freeKeys.end()) { - Action *act = mr.keymap->getMappedAction((*keyIt)->key); + Action *act = 0; + if (input->type == kHardwareInputTypeKeyboard) + act = mr.keymap->getMappedAction(input->key); + else if (input->type == kHardwareInputTypeGeneric) + act = mr.keymap->getMappedAction(input->inputCode); if (act) { ActionInfo info = {act, true, act->description + " (" + mr.keymap->getName() + ")"}; _currentActions.push_back(info); - freeKeys.erase(keyIt++); + freeInputs.erase(inputIt); } else { - ++keyIt; + ++inputIt; } } - if (mr.transparent == false || freeKeys.empty()) + if (mr.transparent == false || freeInputs.empty()) break; } } @@ -420,10 +422,10 @@ void RemapDialog::refreshKeymap() { widg.actionText->setLabel(info.description); widg.actionText->setEnabled(!info.inherited); - const HardwareKey *mappedKey = info.action->getMappedKey(); + const HardwareInput *mappedInput = info.action->getMappedInput(); - if (mappedKey) - widg.keyButton->setLabel(mappedKey->description); + if (mappedInput) + widg.keyButton->setLabel(mappedInput->description); else widg.keyButton->setLabel("-"); diff --git a/backends/keymapper/remap-dialog.h b/backends/keymapper/remap-dialog.h index 143deca4cfc..82c68405db0 100644 --- a/backends/keymapper/remap-dialog.h +++ b/backends/keymapper/remap-dialog.h @@ -50,6 +50,7 @@ public: virtual void handleKeyUp(Common::KeyState state); virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual void handleTickle(); + virtual void handleOtherEvent(Common::Event ev); protected: struct ActionWidgets { @@ -67,7 +68,7 @@ protected: void refreshKeymap(); void clearMapping(uint i); void startRemapping(uint i); - void stopRemapping(); + void stopRemapping(bool force = false); Keymapper *_keymapper; Keymap** _keymapTable; @@ -85,7 +86,6 @@ protected: uint _rowCount; Array _keymapWidgets; - Action *_activeRemapAction; uint32 _remapTimeout; static const uint32 kRemapTimeoutDelay = 3000; diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp index 53302f8a809..5a6326877e0 100644 --- a/backends/midi/stmidi.cpp +++ b/backends/midi/stmidi.cpp @@ -36,7 +36,7 @@ #include "common/scummsys.h" -#if defined __MINT__ +#if defined(__MINT__) #include #include "audio/mpu401.h" diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp index 828411cd22c..f4c5431d6e3 100644 --- a/backends/midi/windows.cpp +++ b/backends/midi/windows.cpp @@ -177,13 +177,49 @@ MusicDevices WindowsMusicPlugin::getDevices() const { int numDevs = midiOutGetNumDevs(); MIDIOUTCAPS tmp; + Common::StringArray deviceNames; for (int i = 0; i < numDevs; i++) { if (midiOutGetDevCaps(i, &tmp, sizeof(MIDIOUTCAPS)) != MMSYSERR_NOERROR) break; + deviceNames.push_back(tmp.szPname); + } + + // Check for non-unique device names. This may happen if someone has devices with identical + // names (e. g. more than one USB device of the exact same hardware type). It seems that this + // does happen in reality sometimes. We generate index numbers for these devices. + // This is not an ideal solution, since this index could change whenever another USB + // device gets plugged in or removed, switched off or just plugged into a different port. + // Unfortunately midiOutGetDevCaps() does not generate any other unique information + // that could be used. Our index numbers which match the device order should at least be + // a little more stable than just using the midiOutGetDevCaps() device ID, since a missing + // device (e.g. switched off) should actually not be harmful to our indices (as it would be + // when using the device IDs). The cases where users have devices with identical names should + // be rare enough anyway. + Common::Array nonUniqueIndex; + for (int i = 0; i < numDevs; i++) { + int match = -1; + for (int ii = 0; ii < i; ii++) { + if (deviceNames[i] == deviceNames[ii]) { + if (nonUniqueIndex[ii] == -1) + nonUniqueIndex[ii] = 0; + if (++match == 0) + ++match; + } + } + nonUniqueIndex.push_back(match); + } + + // We now add the index number to the non-unique device names to make them unique. + for (int i = 0; i < numDevs; i++) { + if (nonUniqueIndex[i] != -1) + deviceNames[i] = Common::String::format("%s - #%.02d", deviceNames[i].c_str(), nonUniqueIndex[i]); + } + + for (Common::StringArray::iterator i = deviceNames.begin(); i != deviceNames.end(); ++i) // There is no way to detect the "MusicType" so I just set it to MT_GM // The user will have to manually select his MT32 type device and his GM type device. - devices.push_back(MusicDevice(this, tmp.szPname, MT_GM)); - } + devices.push_back(MusicDevice(this, *i, MT_GM)); + return devices; } diff --git a/backends/module.mk b/backends/module.mk index 3c74329cba3..53d17a3ee4d 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -33,6 +33,7 @@ endif ifdef ENABLE_KEYMAPPER MODULE_OBJS += \ keymapper/action.o \ + keymapper/hardware-input.o \ keymapper/keymap.o \ keymapper/keymapper.o \ keymapper/remap-dialog.o diff --git a/backends/platform/sdl/module.mk b/backends/platform/sdl/module.mk index f1afe373490..98a82653019 100644 --- a/backends/platform/sdl/module.mk +++ b/backends/platform/sdl/module.mk @@ -1,7 +1,6 @@ MODULE := backends/platform/sdl MODULE_OBJS := \ - hardwarekeys.o \ main.o \ sdl.o diff --git a/backends/vkeybd/virtual-keyboard-parser.cpp b/backends/vkeybd/virtual-keyboard-parser.cpp index 19581135788..bb8286d1f57 100644 --- a/backends/vkeybd/virtual-keyboard-parser.cpp +++ b/backends/vkeybd/virtual-keyboard-parser.cpp @@ -34,7 +34,7 @@ #include "common/tokenizer.h" #include "common/stream.h" -#include "graphics/imagedec.h" +#include "graphics/decoders/bmp.h" namespace Common { @@ -266,11 +266,15 @@ bool VirtualKeyboardParser::parserCallback_layout(ParserNode *node) { const Graphics::PixelFormat format = g_system->getOverlayFormat(); - _mode->image = Graphics::ImageDecoder::loadFile(*file, format); - delete file; + { + Graphics::BitmapDecoder bmp; + if (!bmp.loadStream(*file)) + return parserError("Error loading bitmap '" + _mode->bitmapName + "'"); - if (!_mode->image) - return parserError("Error loading bitmap '" + _mode->bitmapName + "'"); + _mode->image = bmp.getSurface()->convertTo(format); + } + + delete file; int r, g, b; if (node->values.contains("transparent_color")) { diff --git a/base/commandLine.cpp b/base/commandLine.cpp index cbdb0fef705..2da8966014d 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -33,9 +33,10 @@ #include "base/version.h" #include "common/config-manager.h" +#include "common/fs.h" +#include "common/rendermode.h" #include "common/system.h" #include "common/textconsole.h" -#include "common/fs.h" #include "gui/ThemeEngine.h" @@ -67,7 +68,7 @@ static const char HELP_STRING[] = " -z, --list-games Display list of supported games and exit\n" " -t, --list-targets Display list of configured targets and exit\n" " --list-saves=TARGET Display a list of savegames for the game (TARGET) specified\n" -#if defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) +#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) " --console Enable the console window (default:enabled)\n" #endif "\n" @@ -134,7 +135,7 @@ static void usage(const char *s, ...) { vsnprintf(buf, STRINGBUFLEN, s, va); va_end(va); -#if !(defined(__GP32__) || defined (__SYMBIAN32__) || defined(__DS__)) +#if !(defined(__GP32__) || defined(__SYMBIAN32__) || defined(__DS__)) printf(USAGE_STRING, s_appName, buf, s_appName, s_appName); #endif exit(1); @@ -238,12 +239,12 @@ void registerDefaults() { // Use this for boolean options; this distinguishes between "-x" and "-X", // resp. between "--some-option" and "--no-some-option". #define DO_OPTION_BOOL(shortCmd, longCmd) \ - if (isLongCmd ? (!strcmp(s+2, longCmd) || !strcmp(s+2, "no-"longCmd)) : (tolower(s[1]) == shortCmd)) { \ + if (isLongCmd ? (!strcmp(s+2, longCmd) || !strcmp(s+2, "no-" longCmd)) : (tolower(s[1]) == shortCmd)) { \ bool boolValue = (Common::isLower(s[1]) != 0); \ s += 2; \ if (isLongCmd) { \ boolValue = !strcmp(s, longCmd); \ - s += boolValue ? (sizeof(longCmd) - 1) : (sizeof("no-"longCmd) - 1); \ + s += boolValue ? (sizeof(longCmd) - 1) : (sizeof("no-" longCmd) - 1); \ } \ if (*s != '\0') goto unknownOption; \ const char *option = boolValue ? "true" : "false"; \ diff --git a/base/main.cpp b/base/main.cpp index 677d30377ae..4af86758570 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -265,10 +265,10 @@ static void setupKeymapper(OSystem &system) { Keymapper *mapper = system.getEventManager()->getKeymapper(); - HardwareKeySet *keySet = system.getHardwareKeySet(); + HardwareInputSet *inputSet = system.getHardwareInputSet(); // Query backend for hardware keys and register them - mapper->registerHardwareKeySet(keySet); + mapper->registerHardwareInputSet(inputSet); // Now create the global keymap Keymap *primaryGlobalKeymap = new Keymap(kGlobalKeymapName); diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp index 4c7286bbb5f..012a2dfce5b 100644 --- a/common/EventDispatcher.cpp +++ b/common/EventDispatcher.cpp @@ -60,6 +60,12 @@ void EventDispatcher::dispatch() { } } } + + List delayedEvents = _mapper->getDelayedEvents(); + for (List::iterator k = delayedEvents.begin(); k != delayedEvents.end(); ++k) { + const Event delayedEvent = *k; + dispatchEvent(delayedEvent); + } } void EventDispatcher::registerMapper(EventMapper *mapper) { diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp index 2808a7b5fd6..5f6771a71d9 100644 --- a/common/EventMapper.cpp +++ b/common/EventMapper.cpp @@ -22,6 +22,9 @@ #include "common/events.h" +#include "common/system.h" +#include "common/textconsole.h" + namespace Common { List DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) { @@ -46,9 +49,44 @@ List DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) { // if it didn't get mapped, just pass it through if (mappedEvent.type == EVENT_INVALID) mappedEvent = ev; + +#ifdef ENABLE_KEYMAPPER + // TODO: this check is not needed post-split + if (mappedEvent.type == EVENT_CUSTOM_BACKEND_HARDWARE) { + warning("EVENT_CUSTOM_BACKEND_HARDWARE was not mapped"); + return List(); + } +#endif + events.push_back(mappedEvent); return events; } +void DefaultEventMapper::addDelayedEvent(uint32 millis, Event ev) { + if (_delayedEvents.empty()) { + _delayedEffectiveTime = g_system->getMillis() + millis; + millis = 0; + } + DelayedEventsEntry entry = DelayedEventsEntry(millis, ev); + _delayedEvents.push(entry); +} + +List DefaultEventMapper::getDelayedEvents() { + List events; + + if (_delayedEvents.empty()) + return events; + + uint32 now = g_system->getMillis(); + + while (!_delayedEvents.empty() && now >= _delayedEffectiveTime) { + DelayedEventsEntry entry = _delayedEvents.pop(); + if (!_delayedEvents.empty()) + _delayedEffectiveTime += _delayedEvents.front().timerOffset; + events.push_back(entry.event); + } + return events; +} + } // namespace Common diff --git a/common/endian.h b/common/endian.h index 5fc54e97b83..28020451c6c 100644 --- a/common/endian.h +++ b/common/endian.h @@ -86,7 +86,7 @@ } // Test for GCC >= 4.3.0 as this version added the bswap builtin -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +#elif GCC_ATLEAST(4, 3) FORCEINLINE uint32 SWAP_BYTES_32(uint32 a) { return __builtin_bswap32(a); @@ -156,7 +156,7 @@ // // Moreover, we activate this code for GCC >= 3.3 but *only* if unaligned access // is allowed. -#if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3 && !defined(SCUMM_NEED_ALIGNMENT))) +#if GCC_ATLEAST(4, 0) || (GCC_ATLEAST(3, 3) && !defined(SCUMM_NEED_ALIGNMENT)) FORCEINLINE uint16 READ_UINT16(const void *ptr) { struct Unaligned16 { uint16 val; } __attribute__ ((__packed__, __may_alias__)); @@ -396,6 +396,12 @@ inline uint32 READ_BE_UINT24(const void *ptr) { return (b[0] << 16) | (b[1] << 8) | (b[2]); } +#ifdef SCUMM_LITTLE_ENDIAN +#define READ_UINT24(a) READ_LE_UINT24(a) +#else +#define READ_UINT24(a) READ_BE_UINT24(a) +#endif + // ResidualVM specific: #if defined(SCUMM_BIG_ENDIAN) diff --git a/common/events.h b/common/events.h index d4e03facb0f..3455300a770 100644 --- a/common/events.h +++ b/common/events.h @@ -78,7 +78,9 @@ enum EventType { , // IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use // this, please talk to tsoliman and/or LordHoto. - EVENT_CUSTOM_BACKEND = 18, + EVENT_CUSTOM_BACKEND_ACTION = 18, + EVENT_CUSTOM_BACKEND_HARDWARE = 21, + EVENT_GUI_REMAP_COMPLETE_ACTION = 22, EVENT_KEYMAPPER_REMAP = 19 #endif #ifdef ENABLE_VKEYBD @@ -237,12 +239,27 @@ public: * Map an incoming event to one or more action events */ virtual List mapEvent(const Event &ev, EventSource *source) = 0; + + virtual List getDelayedEvents() = 0; }; class DefaultEventMapper : public EventMapper { public: + DefaultEventMapper() : _delayedEvents(), _delayedEffectiveTime(0) {} // EventMapper interface virtual List mapEvent(const Event &ev, EventSource *source); + virtual List getDelayedEvents(); +protected: + virtual void addDelayedEvent(uint32 millis, Event ev); + + struct DelayedEventsEntry { + const uint32 timerOffset; + const Event event; + DelayedEventsEntry(const uint32 offset, const Event ev) : timerOffset(offset), event(ev) { } + }; + + Queue _delayedEvents; + uint32 _delayedEffectiveTime; }; /** diff --git a/common/gui_options.cpp b/common/gui_options.cpp new file mode 100644 index 00000000000..32a7cc9c414 --- /dev/null +++ b/common/gui_options.cpp @@ -0,0 +1,115 @@ +/* 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. + * + */ + +#include "common/gui_options.h" + +#include "common/config-manager.h" +#include "common/str.h" + +namespace Common { + +const struct GameOpt { + const char *option; + const char *desc; +} g_gameOptions[] = { + { GUIO_NOSUBTITLES, "sndNoSubs" }, + { GUIO_NOMUSIC, "sndNoMusic" }, + { GUIO_NOSPEECH, "sndNoSpeech" }, + { GUIO_NOSFX, "sndNoSFX" }, + { GUIO_NOMIDI, "sndNoMIDI" }, + + { GUIO_NOLAUNCHLOAD, "launchNoLoad" }, + + { GUIO_MIDIPCSPK, "midiPCSpk" }, + { GUIO_MIDICMS, "midiCMS" }, + { GUIO_MIDIPCJR, "midiPCJr" }, + { GUIO_MIDIADLIB, "midiAdLib" }, + { GUIO_MIDIC64, "midiC64" }, + { GUIO_MIDIAMIGA, "midiAmiga" }, + { GUIO_MIDIAPPLEIIGS,"midiAppleIIgs" }, + { GUIO_MIDITOWNS, "midiTowns" }, + { GUIO_MIDIPC98, "midiPC98" }, + { GUIO_MIDIMT32, "midiMt32" }, + { GUIO_MIDIGM, "midiGM" }, + + { GUIO_NOASPECT, "noAspect" }, + { GUIO_EGAUNDITHER, "egaUndither" }, + + { GUIO_RENDERHERCGREEN, "hercGreen" }, + { GUIO_RENDERHERCAMBER, "hercAmber" }, + { GUIO_RENDERCGA, "cga" }, + { GUIO_RENDEREGA, "ega" }, + { GUIO_RENDERVGA, "vga" }, + { GUIO_RENDERAMIGA, "amiga" }, + { GUIO_RENDERFMTOWNS, "fmtowns" }, + { GUIO_RENDERPC9821, "pc9821" }, + { GUIO_RENDERPC9801, "pc9801" }, + + { GUIO_NONE, 0 } +}; + +bool checkGameGUIOption(const String &option, const String &str) { + for (int i = 0; g_gameOptions[i].desc; i++) { + if (option.contains(g_gameOptions[i].option)) { + if (str.contains(g_gameOptions[i].desc)) + return true; + else + return false; + } + } + return false; +} + +String parseGameGUIOptions(const String &str) { + String res; + + for (int i = 0; g_gameOptions[i].desc; i++) + if (str.contains(g_gameOptions[i].desc)) + res += g_gameOptions[i].option; + + return res; +} + +const String getGameGUIOptionsDescription(const String &options) { + String res; + + for (int i = 0; g_gameOptions[i].desc; i++) + if (options.contains(g_gameOptions[i].option[0])) + res += String(g_gameOptions[i].desc) + " "; + + res.trim(); + + return res; +} + +void updateGameGUIOptions(const String &options, const String &langOption) { + const String newOptionString = getGameGUIOptionsDescription(options) + " " + langOption; + + if ((!options.empty() && !ConfMan.hasKey("guioptions")) || + (ConfMan.hasKey("guioptions") && ConfMan.get("guioptions") != newOptionString)) { + ConfMan.set("guioptions", newOptionString); + ConfMan.flushToDisk(); + } +} + + +} // End of namespace Common diff --git a/common/gui_options.h b/common/gui_options.h new file mode 100644 index 00000000000..33ecccad634 --- /dev/null +++ b/common/gui_options.h @@ -0,0 +1,85 @@ +/* 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. + * + */ + +#ifndef COMMON_GUI_OPTIONS_H +#define COMMON_GUI_OPTIONS_H + +#define GUIO_NONE "\000" +#define GUIO_NOSUBTITLES "\001" +#define GUIO_NOMUSIC "\002" +#define GUIO_NOSPEECH "\003" +#define GUIO_NOSFX "\004" +#define GUIO_NOMIDI "\005" +#define GUIO_NOLAUNCHLOAD "\006" + +#define GUIO_MIDIPCSPK "\007" +#define GUIO_MIDICMS "\010" +#define GUIO_MIDIPCJR "\011" +#define GUIO_MIDIADLIB "\012" +#define GUIO_MIDIC64 "\013" +#define GUIO_MIDIAMIGA "\014" +#define GUIO_MIDIAPPLEIIGS "\015" +#define GUIO_MIDITOWNS "\016" +#define GUIO_MIDIPC98 "\017" +#define GUIO_MIDIMT32 "\020" +#define GUIO_MIDIGM "\021" + +#define GUIO_NOASPECT "\022" +#define GUIO_EGAUNDITHER "\023" + +#define GUIO_RENDERHERCGREEN "\030" +#define GUIO_RENDERHERCAMBER "\031" +#define GUIO_RENDERCGA "\032" +#define GUIO_RENDEREGA "\033" +#define GUIO_RENDERVGA "\034" +#define GUIO_RENDERAMIGA "\035" +#define GUIO_RENDERFMTOWNS "\036" +#define GUIO_RENDERPC9821 "\037" +#define GUIO_RENDERPC9801 "\040" + +#define GUIO0() (GUIO_NONE) +#define GUIO1(a) (a) +#define GUIO2(a,b) (a b) +#define GUIO3(a,b,c) (a b c) +#define GUIO4(a,b,c,d) (a b c d) +#define GUIO5(a,b,c,d,e) (a b c d e) +#define GUIO6(a,b,c,d,e,f) (a b c d e f) + +namespace Common { + +class String; + +bool checkGameGUIOption(const String &option, const String &str); +String parseGameGUIOptions(const String &str); +const String getGameGUIOptionsDescription(const String &options); + +/** + * Updates the GUI options of the current config manager + * domain, when they differ to the ones passed as + * parameter. + */ +void updateGameGUIOptions(const String &options, const String &langOption); + + +} // End of namespace Common + +#endif diff --git a/common/language.cpp b/common/language.cpp new file mode 100644 index 00000000000..898adf8d0e5 --- /dev/null +++ b/common/language.cpp @@ -0,0 +1,125 @@ +/* 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. + */ + +#include "common/language.h" +#include "common/gui_options.h" +#include "common/str.h" + +namespace Common { + +const LanguageDescription g_languages[] = { + { "zh-cn", "zh_CN", "Chinese (China)", ZH_CNA }, + { "zh", "zh_TW", "Chinese (Taiwan)", ZH_TWN }, + { "cz", "cs_CZ", "Czech", CZ_CZE }, + { "nl", "nl_NL", "Dutch", NL_NLD }, + { "en", "en", "English", EN_ANY }, // Generic English (when only one game version exist) + { "gb", "en_GB", "English (GB)", EN_GRB }, + { "us", "en_US", "English (US)", EN_USA }, + { "fr", "fr_FR", "French", FR_FRA }, + { "de", "de_DE", "German", DE_DEU }, + { "gr", "el_GR", "Greek", GR_GRE }, + { "he", "he_IL", "Hebrew", HE_ISR }, + { "hb", "he_IL", "Hebrew", HE_ISR }, // Deprecated + { "hr", "hr_HR", "Croatian", HR_HRV }, + { "hu", "hu_HU", "Hungarian", HU_HUN }, + { "it", "it_IT", "Italian", IT_ITA }, + { "jp", "ja_JP", "Japanese", JA_JPN }, + { "kr", "ko_KR", "Korean", KO_KOR }, + { "nb", "nb_NO", "Norwegian Bokm\xE5l", NB_NOR }, // TODO Someone should verify the unix locale + { "pl", "pl_PL", "Polish", PL_POL }, + { "br", "pt_BR", "Portuguese", PT_BRA }, + { "ru", "ru_RU", "Russian", RU_RUS }, + { "es", "es_ES", "Spanish", ES_ESP }, + { "se", "sv_SE", "Swedish", SE_SWE }, + { 0, 0, 0, UNK_LANG } +}; + +Language parseLanguage(const String &str) { + if (str.empty()) + return UNK_LANG; + + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (str.equalsIgnoreCase(l->code)) + return l->id; + } + + return UNK_LANG; +} + +Language parseLanguageFromLocale(const char *locale) { + if (!locale || !*locale) + return UNK_LANG; + + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (!strcmp(l->unixLocale, locale)) + return l->id; + } + + return UNK_LANG; +} + +const char *getLanguageCode(Language id) { + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (l->id == id) + return l->code; + } + return 0; +} + +const char *getLanguageLocale(Language id) { + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (l->id == id) + return l->unixLocale; + } + return 0; +} + +const char *getLanguageDescription(Language id) { + const LanguageDescription *l = g_languages; + for (; l->code; ++l) { + if (l->id == id) + return l->description; + } + return 0; +} + +bool checkGameGUIOptionLanguage(Language lang, const String &str) { + if (!str.contains("lang_")) // If no languages are specified + return true; + + if (str.contains(getGameGUIOptionsDescriptionLanguage(lang))) + return true; + + return false; +} + +const String getGameGUIOptionsDescriptionLanguage(Language lang) { + if (lang == UNK_LANG) + return ""; + + return String("lang_") + getLanguageDescription(lang); +} + +} // End of namespace Common diff --git a/common/language.h b/common/language.h new file mode 100644 index 00000000000..db552fc9c45 --- /dev/null +++ b/common/language.h @@ -0,0 +1,86 @@ +/* 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. + */ + +#ifndef COMMON_LANGUAGE_H +#define COMMON_LANGUAGE_H + +#include "common/scummsys.h" + +namespace Common { + +class String; + +/** + * List of game language. + */ +enum Language { + ZH_CNA, + ZH_TWN, + CZ_CZE, + NL_NLD, + EN_ANY, // Generic English (when only one game version exist) + EN_GRB, + EN_USA, + FR_FRA, + DE_DEU, + GR_GRE, + HE_ISR, + HR_HRV, + HU_HUN, + IT_ITA, + JA_JPN, + KO_KOR, + NB_NOR, + PL_POL, + PT_BRA, + RU_RUS, + ES_ESP, + SE_SWE, + + UNK_LANG = -1 // Use default language (i.e. none specified) +}; + +struct LanguageDescription { + const char *code; + const char *unixLocale; + const char *description; + Language id; +}; + +extern const LanguageDescription g_languages[]; + + +/** Convert a string containing a language name into a Language enum value. */ +extern Language parseLanguage(const String &str); +extern Language parseLanguageFromLocale(const char *locale); +extern const char *getLanguageCode(Language id); +extern const char *getLanguageLocale(Language id); +extern const char *getLanguageDescription(Language id); + +// TODO: Document this GUIO related function +const String getGameGUIOptionsDescriptionLanguage(Common::Language lang); + +// TODO: Document this GUIO related function +bool checkGameGUIOptionLanguage(Common::Language lang, const String &str); + +} // End of namespace Common + +#endif diff --git a/common/macresman.cpp b/common/macresman.cpp index 1317600cb7f..14bdfa70806 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -238,6 +238,27 @@ bool MacResManager::open(FSNode path, String filename) { return false; } +bool MacResManager::exists(const String &filename) { + // Try the file name by itself + if (Common::File::exists(filename)) + return true; + + // Try the .rsrc extension + if (Common::File::exists(filename + ".rsrc")) + return true; + + // Check if we have a MacBinary file + Common::File tempFile; + if (tempFile.open(filename + ".bin") && isMacBinary(tempFile)) + return true; + + // Check if we have an AppleDouble file + if (tempFile.open("._" + filename) && tempFile.readUint32BE() == 0x00051607) + return true; + + return false; +} + bool MacResManager::loadFromAppleDouble(SeekableReadStream &stream) { if (stream.readUint32BE() != 0x00051607) // tag return false; diff --git a/common/macresman.h b/common/macresman.h index 4d86e46d114..68201069255 100644 --- a/common/macresman.h +++ b/common/macresman.h @@ -68,6 +68,13 @@ public: */ bool open(FSNode path, String filename); + /** + * See if a Mac data/resource fork pair exists. + * @param filename The base file name of the file + * @return True if either a data fork or resource fork with this name exists + */ + static bool exists(const String &filename); + /** * Close the Mac data/resource fork pair. */ diff --git a/common/math.h b/common/math.h index f787b84fa6c..b85ec0d22a9 100644 --- a/common/math.h +++ b/common/math.h @@ -75,7 +75,7 @@ struct Complex { float re, im; }; -#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +#if GCC_ATLEAST(3, 4) inline int intLog2(uint32 v) { // This is a slightly optimized implementation of log2 for natural numbers // targeting gcc. It also saves some binary size over our fallback diff --git a/common/module.mk b/common/module.mk index 084237c504d..0d8e79a9501 100644 --- a/common/module.mk +++ b/common/module.mk @@ -12,13 +12,17 @@ MODULE_OBJS := \ EventRecorder.o \ file.o \ fs.o \ + gui_options.o \ hashmap.o \ + language.o \ macresman.o \ memorypool.o \ md5.o \ mutex.o \ + platform.o \ random.o \ rational.o \ + rendermode.o \ str.o \ stream.o \ system.o \ diff --git a/common/platform.cpp b/common/platform.cpp new file mode 100644 index 00000000000..a3a02c60ec7 --- /dev/null +++ b/common/platform.cpp @@ -0,0 +1,109 @@ +/* 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. + */ + +#include "common/platform.h" +#include "common/str.h" + +namespace Common { + +const PlatformDescription g_platforms[] = { + { "2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS }, + { "3do", "3do", "3do", "3DO", kPlatform3DO }, + { "acorn", "acorn", "acorn", "Acorn", kPlatformAcorn }, + { "amiga", "ami", "amiga", "Amiga", kPlatformAmiga }, + { "atari", "atari-st", "st", "Atari ST", kPlatformAtariST }, + { "c64", "c64", "c64", "Commodore 64", kPlatformC64 }, + { "pc", "dos", "ibm", "DOS", kPlatformPC }, + { "pc98", "pc98", "pc98", "PC-98", kPlatformPC98 }, + { "wii", "wii", "wii", "Nintendo Wii", kPlatformWii }, + { "coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3 }, + + // The 'official' spelling seems to be "FM-TOWNS" (e.g. in the Indy4 demo). + // However, on the net many variations can be seen, like "FMTOWNS", + // "FM TOWNS", "FmTowns", etc. + { "fmtowns", "towns", "fm", "FM-TOWNS", kPlatformFMTowns }, + + { "linux", "linux", "linux", "Linux", kPlatformLinux }, + { "macintosh", "mac", "mac", "Macintosh", kPlatformMacintosh }, + { "pce", "pce", "pce", "PC-Engine", kPlatformPCEngine }, + { "nes", "nes", "nes", "NES", kPlatformNES }, + { "segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD }, + { "windows", "win", "win", "Windows", kPlatformWindows }, + { "playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX }, + //ResidualVM: playstation2 + { "playstation2", "ps2", "ps2", "Sony PlayStation 2", kPlatformPS2 }, + { "cdi", "cdi", "cdi", "Philips CD-i", kPlatformCDi }, + { "ios", "ios", "ios", "Apple iOS", kPlatformIOS }, + + { 0, 0, 0, "Default", kPlatformUnknown } +}; + +Platform parsePlatform(const String &str) { + if (str.empty()) + return kPlatformUnknown; + + // Handle some special case separately, for compatibility with old config + // files. + if (str == "1") + return kPlatformAmiga; + else if (str == "2") + return kPlatformAtariST; + else if (str == "3") + return kPlatformMacintosh; + + const PlatformDescription *l = g_platforms; + for (; l->code; ++l) { + if (str.equalsIgnoreCase(l->code) || str.equalsIgnoreCase(l->code2) || str.equalsIgnoreCase(l->abbrev)) + return l->id; + } + + return kPlatformUnknown; +} + + +const char *getPlatformCode(Platform id) { + const PlatformDescription *l = g_platforms; + for (; l->code; ++l) { + if (l->id == id) + return l->code; + } + return 0; +} + +const char *getPlatformAbbrev(Platform id) { + const PlatformDescription *l = g_platforms; + for (; l->code; ++l) { + if (l->id == id) + return l->abbrev; + } + return 0; +} + +const char *getPlatformDescription(Platform id) { + const PlatformDescription *l = g_platforms; + for (; l->code; ++l) { + if (l->id == id) + return l->description; + } + return l->description; +} + +} // End of namespace Common diff --git a/common/platform.h b/common/platform.h new file mode 100644 index 00000000000..b972850029a --- /dev/null +++ b/common/platform.h @@ -0,0 +1,82 @@ +/* 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. + */ + +#ifndef COMMON_PLATFORM_H +#define COMMON_PLATFORM_H + +#include "common/scummsys.h" + +namespace Common { + +class String; + +/** + * List of game platforms. Specifying a platform for a target can be used to + * give the game engines a hint for which platform the game data file are. + * This may be optional or required, depending on the game engine and the + * game in question. + */ +enum Platform { + kPlatformPC, + kPlatformAmiga, + kPlatformAtariST, + kPlatformMacintosh, + kPlatformFMTowns, + kPlatformWindows, + kPlatformNES, + kPlatformC64, + kPlatformCoCo3, + kPlatformLinux, + kPlatformAcorn, + kPlatformSegaCD, + kPlatform3DO, + kPlatformPCEngine, + kPlatformApple2GS, + kPlatformPC98, + kPlatformWii, + kPlatformPSX, + //ResidualVM: playstation2 + kPlatformPS2, + kPlatformCDi, + kPlatformIOS, + + kPlatformUnknown = -1 +}; + +struct PlatformDescription { + const char *code; + const char *code2; + const char *abbrev; + const char *description; + Platform id; +}; + +extern const PlatformDescription g_platforms[]; + +/** Convert a string containing a platform name into a Platform enum value. */ +extern Platform parsePlatform(const String &str); +extern const char *getPlatformCode(Platform id); +extern const char *getPlatformAbbrev(Platform id); +extern const char *getPlatformDescription(Platform id); + +} // End of namespace Common + +#endif diff --git a/common/ptr.h b/common/ptr.h index 2b0670caae8..f734ec133f7 100644 --- a/common/ptr.h +++ b/common/ptr.h @@ -103,7 +103,7 @@ private: */ template class SharedPtr { -#if !((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)) +#if !defined(__GNUC__) || GCC_ATLEAST(3, 0) template friend class SharedPtr; #endif public: @@ -200,7 +200,7 @@ public: * This should just be used for debugging purposes. */ RefValue refCount() const { return _refCount ? *_refCount : 0; } -#if !((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)) +#if !defined(__GNUC__) || GCC_ATLEAST(3, 0) private: #endif void decRef() { diff --git a/common/rect.h b/common/rect.h index 768d1ebbb96..2bd3affafee 100644 --- a/common/rect.h +++ b/common/rect.h @@ -244,11 +244,11 @@ struct Rect { /** * Create a rectangle around the given center. + * @note the center point is rounded up and left when given an odd width and height */ static Rect center(int16 cx, int16 cy, int16 w, int16 h) { - w /= 2; - h /= 2; - return Rect(cx - w, cy - h, cx + w, cy + h); + int x = cx - w / 2, y = cy - h / 2; + return Rect(x, y, x + w, y + h); } }; diff --git a/common/rendermode.cpp b/common/rendermode.cpp new file mode 100644 index 00000000000..e8f31466305 --- /dev/null +++ b/common/rendermode.cpp @@ -0,0 +1,122 @@ +/* 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. + * + */ + +#include "common/rendermode.h" + +#include "common/gui_options.h" +#include "common/str.h" +#include "common/translation.h" + + +namespace Common { + + +const RenderModeDescription g_renderModes[] = { + // I18N: Hercules is graphics card name + { "hercGreen", _s("Hercules Green"), kRenderHercG }, + { "hercAmber", _s("Hercules Amber"), kRenderHercA }, + { "cga", "CGA", kRenderCGA }, + { "ega", "EGA", kRenderEGA }, + { "vga", "VGA", kRenderVGA }, + { "amiga", "Amiga", kRenderAmiga }, + { "fmtowns", "FM-Towns", kRenderFMTowns }, + { "pc9821", "PC-9821 (256 Colors)", kRenderPC9821 }, + { "pc9801", "PC-9801 (16 Colors)", kRenderPC9801 }, + {0, 0, kRenderDefault} +}; + +struct RenderGUIOMapping { + RenderMode id; + const char *guio; +}; + +// TODO: Merge s_renderGUIOMapping into g_renderModes? the kRenderDefault +// could be used to indicate "any" mode when passed to renderMode2GUIO (if +// we wanted to merge allRenderModesGUIOs back into) +static const RenderGUIOMapping s_renderGUIOMapping[] = { + { kRenderHercG, GUIO_RENDERHERCGREEN }, + { kRenderHercA, GUIO_RENDERHERCAMBER }, + { kRenderCGA, GUIO_RENDERCGA }, + { kRenderEGA, GUIO_RENDEREGA }, + { kRenderVGA, GUIO_RENDERVGA }, + { kRenderAmiga, GUIO_RENDERAMIGA }, + { kRenderFMTowns, GUIO_RENDERFMTOWNS }, + { kRenderPC9821, GUIO_RENDERPC9821 }, + { kRenderPC9801, GUIO_RENDERPC9801 } +}; + +DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Green", "lowres") +DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Amber", "lowres") + +RenderMode parseRenderMode(const String &str) { + if (str.empty()) + return kRenderDefault; + + const RenderModeDescription *l = g_renderModes; + for (; l->code; ++l) { + if (str.equalsIgnoreCase(l->code)) + return l->id; + } + + return kRenderDefault; +} + +const char *getRenderModeCode(RenderMode id) { + const RenderModeDescription *l = g_renderModes; + for (; l->code; ++l) { + if (l->id == id) + return l->code; + } + return 0; +} + +const char *getRenderModeDescription(RenderMode id) { + const RenderModeDescription *l = g_renderModes; + for (; l->code; ++l) { + if (l->id == id) + return l->description; + } + return 0; +} + +String renderMode2GUIO(RenderMode id) { + String res; + + for (int i = 0; i < ARRAYSIZE(s_renderGUIOMapping); i++) { + if (id == s_renderGUIOMapping[i].id) + res += s_renderGUIOMapping[i].guio; + } + + return res; +} + +String allRenderModesGUIOs() { + String res; + + for (int i = 0; i < ARRAYSIZE(s_renderGUIOMapping); i++) { + res += s_renderGUIOMapping[i].guio; + } + + return res; +} + +} // End of namespace Common diff --git a/common/rendermode.h b/common/rendermode.h new file mode 100644 index 00000000000..945c4e7d9d3 --- /dev/null +++ b/common/rendermode.h @@ -0,0 +1,73 @@ +/* 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. + * + */ + +#ifndef COMMON_RENDERMODE_H +#define COMMON_RENDERMODE_H + +#include "common/scummsys.h" + +namespace Common { + +class String; + +/** + * List of render modes. It specifies which original graphics mode + * to use. Some targets used postprocessing dithering routines for + * reducing color depth of final image which let it to be rendered on + * such low-level adapters as CGA or Hercules. + */ +enum RenderMode { + kRenderDefault = 0, + kRenderVGA = 1, + kRenderEGA = 2, + kRenderCGA = 3, + kRenderHercG = 4, + kRenderHercA = 5, + kRenderAmiga = 6, + kRenderFMTowns = 7, + kRenderPC9821 = 8, + kRenderPC9801 = 9 +}; + +struct RenderModeDescription { + const char *code; + const char *description; + RenderMode id; +}; + +extern const RenderModeDescription g_renderModes[]; + +/** Convert a string containing a render mode name into a RenderingMode enum value. */ +extern RenderMode parseRenderMode(const String &str); +extern const char *getRenderModeCode(RenderMode id); +extern const char *getRenderModeDescription(RenderMode id); + +// TODO: Rename the following to something better; also, document it +extern String renderMode2GUIO(RenderMode id); + +// TODO: Rename the following to something better; also, document it +extern String allRenderModesGUIOs(); + + +} // End of namespace Common + +#endif diff --git a/common/scummsys.h b/common/scummsys.h index 1c24b361b5f..368c1ec1cf3 100644 --- a/common/scummsys.h +++ b/common/scummsys.h @@ -23,6 +23,9 @@ #ifndef COMMON_SCUMMSYS_H #define COMMON_SCUMMSYS_H +// This is a convenience macro to test whether the compiler used is a GCC +// version, which is at least major.minor. +#define GCC_ATLEAST(major, minor) (defined(__GNUC__) && (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))) #if defined(_WIN32_WCE) && _WIN32_WCE < 300 #define NONSTANDARD_PORT @@ -268,7 +271,7 @@ #ifndef FORCEINLINE #if defined(_MSC_VER) #define FORCEINLINE __forceinline - #elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) + #elif GCC_ATLEAST(3, 1) #define FORCEINLINE inline __attribute__((__always_inline__)) #else #define FORCEINLINE inline @@ -320,7 +323,7 @@ #define scumm_va_copy va_copy #elif defined(__va_copy) #define scumm_va_copy __va_copy - #elif defined(_MSC_VER) || defined (__SYMBIAN32__) + #elif defined(_MSC_VER) || defined(__SYMBIAN32__) #define scumm_va_copy(dst, src) ((dst) = (src)) #else #error scumm_va_copy undefined for this port diff --git a/common/singleton.h b/common/singleton.h index a4f106c9d3a..d7078360f38 100644 --- a/common/singleton.h +++ b/common/singleton.h @@ -44,7 +44,7 @@ private: * and you specialise makeInstance to return an instance of a subclass. */ //template -#if defined (_WIN32_WCE) || defined (_MSC_VER) || defined (__WINS__) +#if defined(_WIN32_WCE) || defined(_MSC_VER) || defined(__WINS__) //FIXME evc4 and msvc7 doesn't like it as private member public: #endif diff --git a/common/stream.cpp b/common/stream.cpp index 30b3bca4973..85647bfe3a4 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -240,7 +240,7 @@ bool SeekableSubReadStream::seek(int32 offset, int whence) { return ret; } -uint32 SafeSubReadStream::read(void *dataPtr, uint32 dataSize) { +uint32 SafeSeekableSubReadStream::read(void *dataPtr, uint32 dataSize) { // Make sure the parent stream is at the right position seek(0, SEEK_CUR); diff --git a/common/substream.h b/common/substream.h index 7e67389da1b..01686529aad 100644 --- a/common/substream.h +++ b/common/substream.h @@ -99,21 +99,24 @@ public: * normal SeekableSubReadStream, at the cost of seek()ing the parent stream * before each read(). * - * More than one SafeSubReadStream to the same parent stream can be used + * More than one SafeSeekableSubReadStream to the same parent stream can be used * at the same time; they won't mess up each other. They will, however, * reposition the parent stream, so don't depend on its position to be - * the same after a read() or seek() on one of its SafeSubReadStream. + * the same after a read() or seek() on one of its SafeSeekableSubReadStream. + * + * Note that this stream is *not* threading safe. Calling read from the audio + * thread and from the main thread might mess up the data retrieved. */ -class SafeSubReadStream : public SeekableSubReadStream { +class SafeSeekableSubReadStream : public SeekableSubReadStream { public: - SafeSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO) : - SeekableSubReadStream(parentStream, begin, end, disposeParentStream) { + SafeSeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO) + : SeekableSubReadStream(parentStream, begin, end, disposeParentStream) { } - virtual uint32 read(void *dataPtr, uint32 dataSize); + virtual uint32 read(void *dataPtr, uint32 dataSize); }; -} // End of namespace Common +} // End of namespace Common #endif diff --git a/common/system.h b/common/system.h index 79804db6cb7..bcb4fed307d 100644 --- a/common/system.h +++ b/common/system.h @@ -54,7 +54,7 @@ class TimerManager; class SeekableReadStream; class WriteStream; #ifdef ENABLE_KEYMAPPER -class HardwareKeySet; +class HardwareInputSet; class Keymap; class KeymapperDefaultBindings; #endif @@ -1013,15 +1013,15 @@ public: #ifdef ENABLE_KEYMAPPER /** - * Register hardware keys with keymapper + * Register hardware inputs with keymapper * IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use * this, please talk to tsoliman and/or LordHoto. * - * @return HardwareKeySet with all keys and recommended mappings + * @return HardwareInputSet with all keys and recommended mappings * * See keymapper documentation for further reference. */ - virtual Common::HardwareKeySet *getHardwareKeySet() { return 0; } + virtual Common::HardwareInputSet *getHardwareInputSet() { return 0; } /** * Return a platform-specific global keymap diff --git a/common/translation.cpp b/common/translation.cpp index db443cf18e7..b11cb6c40dd 100644 --- a/common/translation.cpp +++ b/common/translation.cpp @@ -232,8 +232,9 @@ bool TranslationManager::openTranslationsFile(File &inFile) { ArchiveMemberList fileList; SearchMan.listMatchingMembers(fileList, "translations.dat"); for (ArchiveMemberList::iterator it = fileList.begin(); it != fileList.end(); ++it) { - SeekableReadStream *stream = it->get()->createReadStream(); - if (stream && inFile.open(stream, it->get()->getName())) { + ArchiveMember const &m = **it; + SeekableReadStream *const stream = m.createReadStream(); + if (stream && inFile.open(stream, m.getName())) { if (checkHeader(inFile)) return true; inFile.close(); diff --git a/common/util.cpp b/common/util.cpp index 4ba22aa95c5..4d9ff11c5c1 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -29,8 +29,6 @@ #include "common/util.h" -#include "common/translation.h" -#include "common/config-manager.h" #include "common/debug.h" namespace Common { @@ -112,323 +110,6 @@ bool parseBool(const String &val, bool &valAsBool) { #pragma mark - -const LanguageDescription g_languages[] = { - { "zh-cn", "zh_CN", "Chinese (China)", ZH_CNA }, - { "zh", "zh_TW", "Chinese (Taiwan)", ZH_TWN }, - { "cz", "cs_CZ", "Czech", CZ_CZE }, - { "nl", "nl_NL", "Dutch", NL_NLD }, - { "en", "en", "English", EN_ANY }, // Generic English (when only one game version exist) - { "gb", "en_GB", "English (GB)", EN_GRB }, - { "us", "en_US", "English (US)", EN_USA }, - { "fr", "fr_FR", "French", FR_FRA }, - { "de", "de_DE", "German", DE_DEU }, - { "gr", "el_GR", "Greek", GR_GRE }, - { "he", "he_IL", "Hebrew", HE_ISR }, - { "hb", "he_IL", "Hebrew", HE_ISR }, // Deprecated - { "hr", "hr_HR", "Croatian", HR_HRV }, - { "hu", "hu_HU", "Hungarian", HU_HUN }, - { "it", "it_IT", "Italian", IT_ITA }, - { "jp", "ja_JP", "Japanese", JA_JPN }, - { "kr", "ko_KR", "Korean", KO_KOR }, - { "nb", "nb_NO", "Norwegian Bokm\xE5l", NB_NOR }, // TODO Someone should verify the unix locale - { "pl", "pl_PL", "Polish", PL_POL }, - { "br", "pt_BR", "Portuguese", PT_BRA }, - { "ru", "ru_RU", "Russian", RU_RUS }, - { "es", "es_ES", "Spanish", ES_ESP }, - { "se", "sv_SE", "Swedish", SE_SWE }, - { 0, 0, 0, UNK_LANG } -}; - -Language parseLanguage(const String &str) { - if (str.empty()) - return UNK_LANG; - - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (str.equalsIgnoreCase(l->code)) - return l->id; - } - - return UNK_LANG; -} - -Language parseLanguageFromLocale(const char *locale) { - if (!locale || !*locale) - return UNK_LANG; - - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (!strcmp(l->unixLocale, locale)) - return l->id; - } - - return UNK_LANG; -} - -const char *getLanguageCode(Language id) { - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (l->id == id) - return l->code; - } - return 0; -} - -const char *getLanguageLocale(Language id) { - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (l->id == id) - return l->unixLocale; - } - return 0; -} - -const char *getLanguageDescription(Language id) { - const LanguageDescription *l = g_languages; - for (; l->code; ++l) { - if (l->id == id) - return l->description; - } - return 0; -} - - -#pragma mark - - - -const PlatformDescription g_platforms[] = { - { "2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS }, - { "3do", "3do", "3do", "3DO", kPlatform3DO }, - { "acorn", "acorn", "acorn", "Acorn", kPlatformAcorn }, - { "amiga", "ami", "amiga", "Amiga", kPlatformAmiga }, - { "atari", "atari-st", "st", "Atari ST", kPlatformAtariST }, - { "c64", "c64", "c64", "Commodore 64", kPlatformC64 }, - { "pc", "dos", "ibm", "DOS", kPlatformPC }, - { "pc98", "pc98", "pc98", "PC-98", kPlatformPC98 }, - { "wii", "wii", "wii", "Nintendo Wii", kPlatformWii }, - { "coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3 }, - - // The 'official' spelling seems to be "FM-TOWNS" (e.g. in the Indy4 demo). - // However, on the net many variations can be seen, like "FMTOWNS", - // "FM TOWNS", "FmTowns", etc. - { "fmtowns", "towns", "fm", "FM-TOWNS", kPlatformFMTowns }, - - { "linux", "linux", "linux", "Linux", kPlatformLinux }, - { "macintosh", "mac", "mac", "Macintosh", kPlatformMacintosh }, - { "pce", "pce", "pce", "PC-Engine", kPlatformPCEngine }, - { "nes", "nes", "nes", "NES", kPlatformNES }, - { "segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD }, - { "windows", "win", "win", "Windows", kPlatformWindows }, - { "playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX }, - //ResidualVM: playstation2 - { "playstation2", "ps2", "ps2", "Sony PlayStation 2", kPlatformPS2 }, - { "cdi", "cdi", "cdi", "Philips CD-i", kPlatformCDi }, - { "ios", "ios", "ios", "Apple iOS", kPlatformIOS }, - - { 0, 0, 0, "Default", kPlatformUnknown } -}; - -Platform parsePlatform(const String &str) { - if (str.empty()) - return kPlatformUnknown; - - // Handle some special case separately, for compatibility with old config - // files. - if (str == "1") - return kPlatformAmiga; - else if (str == "2") - return kPlatformAtariST; - else if (str == "3") - return kPlatformMacintosh; - - const PlatformDescription *l = g_platforms; - for (; l->code; ++l) { - if (str.equalsIgnoreCase(l->code) || str.equalsIgnoreCase(l->code2) || str.equalsIgnoreCase(l->abbrev)) - return l->id; - } - - return kPlatformUnknown; -} - - -const char *getPlatformCode(Platform id) { - const PlatformDescription *l = g_platforms; - for (; l->code; ++l) { - if (l->id == id) - return l->code; - } - return 0; -} - -const char *getPlatformAbbrev(Platform id) { - const PlatformDescription *l = g_platforms; - for (; l->code; ++l) { - if (l->id == id) - return l->abbrev; - } - return 0; -} - -const char *getPlatformDescription(Platform id) { - const PlatformDescription *l = g_platforms; - for (; l->code; ++l) { - if (l->id == id) - return l->description; - } - return l->description; -} - - -#pragma mark - - - -const RenderModeDescription g_renderModes[] = { - // I18N: Hercules is graphics card name - { "hercGreen", _s("Hercules Green"), kRenderHercG }, - { "hercAmber", _s("Hercules Amber"), kRenderHercA }, - { "cga", "CGA", kRenderCGA }, - { "ega", "EGA", kRenderEGA }, - { "vga", "VGA", kRenderVGA }, - { "amiga", "Amiga", kRenderAmiga }, - { "fmtowns", "FM-Towns", kRenderFMTowns }, - { "pc98", "PC-98", kRenderPC98 }, - {0, 0, kRenderDefault} -}; - -DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Green", "lowres") -DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Amber", "lowres") - -RenderMode parseRenderMode(const String &str) { - if (str.empty()) - return kRenderDefault; - - const RenderModeDescription *l = g_renderModes; - for (; l->code; ++l) { - if (str.equalsIgnoreCase(l->code)) - return l->id; - } - - return kRenderDefault; -} - -const char *getRenderModeCode(RenderMode id) { - const RenderModeDescription *l = g_renderModes; - for (; l->code; ++l) { - if (l->id == id) - return l->code; - } - return 0; -} - -const char *getRenderModeDescription(RenderMode id) { - const RenderModeDescription *l = g_renderModes; - for (; l->code; ++l) { - if (l->id == id) - return l->description; - } - return 0; -} - -const struct GameOpt { - const char *option; - const char *desc; -} g_gameOptions[] = { - { GUIO_NOSUBTITLES, "sndNoSubs" }, - { GUIO_NOMUSIC, "sndNoMusic" }, - { GUIO_NOSPEECH, "sndNoSpeech" }, - { GUIO_NOSFX, "sndNoSFX" }, - { GUIO_NOMIDI, "sndNoMIDI" }, - - { GUIO_NOLAUNCHLOAD, "launchNoLoad" }, - - { GUIO_MIDIPCSPK, "midiPCSpk" }, - { GUIO_MIDICMS, "midiCMS" }, - { GUIO_MIDIPCJR, "midiPCJr" }, - { GUIO_MIDIADLIB, "midiAdLib" }, - { GUIO_MIDIC64, "midiC64" }, - { GUIO_MIDIAMIGA, "midiAmiga" }, - { GUIO_MIDIAPPLEIIGS,"midiAppleIIgs" }, - { GUIO_MIDITOWNS, "midiTowns" }, - { GUIO_MIDIPC98, "midiPC98" }, - { GUIO_MIDIMT32, "midiMt32" }, - { GUIO_MIDIGM, "midiGM" }, - - { GUIO_NOASPECT, "noAspect" }, - { GUIO_EGAUNDITHER, "egaUndither" }, - - { GUIO_RENDERHERCGREEN, "hercGreen" }, - { GUIO_RENDERHERCAMBER, "hercAmber" }, - { GUIO_RENDERCGA, "cga" }, - { GUIO_RENDEREGA, "ega" }, - { GUIO_RENDERVGA, "vga" }, - { GUIO_RENDERAMIGA, "amiga" }, - { GUIO_RENDERFMTOWNS, "fmtowns" }, - { GUIO_RENDERPC98, "pc98" }, - - { GUIO_NONE, 0 } -}; - -bool checkGameGUIOption(const String &option, const String &str) { - for (int i = 0; g_gameOptions[i].desc; i++) { - if (option.contains(g_gameOptions[i].option)) { - if (str.contains(g_gameOptions[i].desc)) - return true; - else - return false; - } - } - return false; -} - -bool checkGameGUIOptionLanguage(Language lang, const String &str) { - if (!str.contains("lang_")) // If no languages are specified - return true; - - if (str.contains(getGameGUIOptionsDescriptionLanguage(lang))) - return true; - - return false; -} - -const String getGameGUIOptionsDescriptionLanguage(Language lang) { - if (lang == UNK_LANG) - return ""; - - return String(String("lang_") + getLanguageDescription(lang)); -} - -String parseGameGUIOptions(const String &str) { - Common::String res; - - for (int i = 0; g_gameOptions[i].desc; i++) - if (str.contains(g_gameOptions[i].desc)) - res += g_gameOptions[i].option; - - return res; -} - -const String getGameGUIOptionsDescription(const String &options) { - String res; - - for (int i = 0; g_gameOptions[i].desc; i++) - if (options.contains(g_gameOptions[i].option[0])) - res += String(g_gameOptions[i].desc) + " "; - - res.trim(); - - return res; -} - -void updateGameGUIOptions(const String &options, const String &langOption) { - const String newOptionString = getGameGUIOptionsDescription(options) + " " + langOption; - - if ((!options.empty() && !ConfMan.hasKey("guioptions")) || - (ConfMan.hasKey("guioptions") && ConfMan.get("guioptions") != newOptionString)) { - ConfMan.set("guioptions", newOptionString); - ConfMan.flushToDisk(); - } -} - #define ENSURE_ASCII_CHAR(c) \ if (c < 0 || c > 127) \ return false diff --git a/common/util.h b/common/util.h index 8352912c6f1..b90be0675b4 100644 --- a/common/util.h +++ b/common/util.h @@ -25,7 +25,6 @@ #include "common/scummsys.h" #include "common/str.h" - /** * Check whether a given pointer is aligned correctly. * Note that 'alignment' must be a power of two! @@ -78,46 +77,6 @@ template inline void SWAP(T &a, T &b) { T tmp = a; a = b; b = tmp; } # define SCUMMVM_CURRENT_FUNCTION "" #endif -#define GUIO_NONE "\000" -#define GUIO_NOSUBTITLES "\001" -#define GUIO_NOMUSIC "\002" -#define GUIO_NOSPEECH "\003" -#define GUIO_NOSFX "\004" -#define GUIO_NOMIDI "\005" -#define GUIO_NOLAUNCHLOAD "\006" - -#define GUIO_MIDIPCSPK "\007" -#define GUIO_MIDICMS "\010" -#define GUIO_MIDIPCJR "\011" -#define GUIO_MIDIADLIB "\012" -#define GUIO_MIDIC64 "\013" -#define GUIO_MIDIAMIGA "\014" -#define GUIO_MIDIAPPLEIIGS "\015" -#define GUIO_MIDITOWNS "\016" -#define GUIO_MIDIPC98 "\017" -#define GUIO_MIDIMT32 "\020" -#define GUIO_MIDIGM "\021" - -#define GUIO_NOASPECT "\022" -#define GUIO_EGAUNDITHER "\023" - -#define GUIO_RENDERHERCGREEN "\030" -#define GUIO_RENDERHERCAMBER "\031" -#define GUIO_RENDERCGA "\032" -#define GUIO_RENDEREGA "\033" -#define GUIO_RENDERVGA "\034" -#define GUIO_RENDERAMIGA "\035" -#define GUIO_RENDERFMTOWNS "\036" -#define GUIO_RENDERPC98 "\037" - -#define GUIO0() (GUIO_NONE) -#define GUIO1(a) (a) -#define GUIO2(a,b) (a b) -#define GUIO3(a,b,c) (a b c) -#define GUIO4(a,b,c,d) (a b c d) -#define GUIO5(a,b,c,d,e) (a b c d e) -#define GUIO6(a,b,c,d,e,f) (a b c d e f) - namespace Common { /** @@ -206,147 +165,6 @@ bool isSpace(int c); */ bool isUpper(int c); - -/** - * List of game language. - */ -enum Language { - ZH_CNA, - ZH_TWN, - CZ_CZE, - NL_NLD, - EN_ANY, // Generic English (when only one game version exist) - EN_GRB, - EN_USA, - FR_FRA, - DE_DEU, - GR_GRE, - HE_ISR, - HR_HRV, - HU_HUN, - IT_ITA, - JA_JPN, - KO_KOR, - NB_NOR, - PL_POL, - PT_BRA, - RU_RUS, - ES_ESP, - SE_SWE, - - UNK_LANG = -1 // Use default language (i.e. none specified) -}; - -struct LanguageDescription { - const char *code; - const char *unixLocale; - const char *description; - Language id; -}; - -extern const LanguageDescription g_languages[]; - - -/** Convert a string containing a language name into a Language enum value. */ -extern Language parseLanguage(const String &str); -extern Language parseLanguageFromLocale(const char *locale); -extern const char *getLanguageCode(Language id); -extern const char *getLanguageLocale(Language id); -extern const char *getLanguageDescription(Language id); - -/** - * List of game platforms. Specifying a platform for a target can be used to - * give the game engines a hint for which platform the game data file are. - * This may be optional or required, depending on the game engine and the - * game in question. - */ -enum Platform { - kPlatformPC, - kPlatformAmiga, - kPlatformAtariST, - kPlatformMacintosh, - kPlatformFMTowns, - kPlatformWindows, - kPlatformNES, - kPlatformC64, - kPlatformCoCo3, - kPlatformLinux, - kPlatformAcorn, - kPlatformSegaCD, - kPlatform3DO, - kPlatformPCEngine, - kPlatformApple2GS, - kPlatformPC98, - kPlatformWii, - kPlatformPSX, - //ResidualVM: playstation2 - kPlatformPS2, - kPlatformCDi, - kPlatformIOS, - - kPlatformUnknown = -1 -}; - -struct PlatformDescription { - const char *code; - const char *code2; - const char *abbrev; - const char *description; - Platform id; -}; - -extern const PlatformDescription g_platforms[]; - -/** Convert a string containing a platform name into a Platform enum value. */ -extern Platform parsePlatform(const String &str); -extern const char *getPlatformCode(Platform id); -extern const char *getPlatformAbbrev(Platform id); -extern const char *getPlatformDescription(Platform id); - -/** - * List of render modes. It specifies which original graphics mode - * to use. Some targets used postprocessing dithering routines for - * reducing color depth of final image which let it to be rendered on - * such low-level adapters as CGA or Hercules. - */ -enum RenderMode { - kRenderDefault = 0, - kRenderVGA = 1, - kRenderEGA = 2, - kRenderCGA = 3, - kRenderHercG = 4, - kRenderHercA = 5, - kRenderAmiga = 6, - kRenderFMTowns = 7, - kRenderPC98 = 8 -}; - -struct RenderModeDescription { - const char *code; - const char *description; - RenderMode id; -}; - -extern const RenderModeDescription g_renderModes[]; - -/** Convert a string containing a render mode name into a RenderingMode enum value. */ -extern RenderMode parseRenderMode(const String &str); -extern const char *getRenderModeCode(RenderMode id); -extern const char *getRenderModeDescription(RenderMode id); - -bool checkGameGUIOption(const String &option, const String &str); -bool checkGameGUIOptionLanguage(Language lang, const String &str); -String parseGameGUIOptions(const String &str); -const String getGameGUIOptionsDescription(const String &options); -const String getGameGUIOptionsDescriptionLanguage(Language lang); - -/** - * Updates the GUI options of the current config manager - * domain, when they differ to the ones passed as - * parameter. - */ -void updateGameGUIOptions(const String &options, const String &langOption); - } // End of namespace Common #endif diff --git a/configure b/configure index 1fa54fbdf06..5b4c707da6f 100755 --- a/configure +++ b/configure @@ -2300,8 +2300,10 @@ if test -n "$_host"; then iphone) DEFINES="$DEFINES -DIPHONE" _backend="iphone" - _build_hq_scalers=no + _build_scalers=no + _mt32emu=no _seq_midi=no + _timidity=no ;; m68k-atari-mint) DEFINES="$DEFINES -DSYSTEM_NOT_SUPPORTING_D_TYPE" @@ -2573,7 +2575,6 @@ case $_backend in gph) ;; iphone) - OBJCFLAGS="$OBJCFLAGS --std=c99" LIBS="$LIBS -lobjc -framework UIKit -framework CoreGraphics -framework OpenGLES" LIBS="$LIBS -framework QuartzCore -framework GraphicsServices -framework CoreFoundation" LIBS="$LIBS -framework Foundation -framework AudioToolbox -framework CoreAudio" @@ -2690,7 +2691,7 @@ esac # Enable 16bit support only for backends which support it # case $_backend in - android | bada | dingux | dreamcast | gph | maemo | openpandora | psp | samsungtv | sdl | webos | wii) + android | bada | dingux | dreamcast | gph | iphone | maemo | openpandora | psp | samsungtv | sdl | webos | wii) if test "$_16bit" = auto ; then _16bit=yes else @@ -3566,6 +3567,7 @@ fi define_in_config_if_yes "$_opengl" "USE_OPENGL" define_in_config_if_yes "$_opengles" "USE_GLES" + # # Check for nasm # diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp index cf3e762e44d..b28dd89e7de 100644 --- a/devtools/create_project/xcode.cpp +++ b/devtools/create_project/xcode.cpp @@ -524,7 +524,7 @@ void XCodeProvider::setupBuildConfiguration() { // ****************************************/ // Debug - Object *iPhone_Debug_Object = new Object(this, "XCBuildConfiguration_ResidualVM-iPhone_Debug", _targets[0] /* ResidualVM-iPhone */, "XCBuildConfiguration", "PBXNativeTarget", "Debug"); + Object *iPhone_Debug_Object = new Object(this, "XCBuildConfiguration_ResidualVM-iPhone_Debug", _targets[0] /* ScummVM-iPhone */, "XCBuildConfiguration", "PBXNativeTarget", "Debug"); Property iPhone_Debug; ADD_SETTING_QUOTE(iPhone_Debug, "ARCHS", "$(ARCHS_UNIVERSAL_IPHONE_OS)"); ADD_SETTING_QUOTE(iPhone_Debug, "CODE_SIGN_IDENTITY", "iPhone Developer"); @@ -566,7 +566,7 @@ void XCodeProvider::setupBuildConfiguration() { iPhone_Debug_Object->properties["buildSettings"] = iPhone_Debug; // Release - Object *iPhone_Release_Object = new Object(this, "XCBuildConfiguration_ResidualVM-iPhone_Release", _targets[0] /* ResidualVM-iPhone */, "XCBuildConfiguration", "PBXNativeTarget", "Release"); + Object *iPhone_Release_Object = new Object(this, "XCBuildConfiguration_ResidualVM-iPhone_Release", _targets[0] /* ScummVM-iPhone */, "XCBuildConfiguration", "PBXNativeTarget", "Release"); Property iPhone_Release(iPhone_Debug); ADD_SETTING(iPhone_Release, "GCC_OPTIMIZATION_LEVEL", "3"); ADD_SETTING(iPhone_Release, "COPY_PHASE_STRIP", "YES"); @@ -584,153 +584,153 @@ void XCodeProvider::setupBuildConfiguration() { ****************************************/ // Debug - Object *residualvm_Debug_Object = new Object(this, "XCBuildConfiguration_residualvm_Debug", "residualvm", "XCBuildConfiguration", "PBXProject", "Debug"); - Property residualvm_Debug; - ADD_SETTING(residualvm_Debug, "ALWAYS_SEARCH_USER_PATHS", "NO"); - ADD_SETTING_QUOTE(residualvm_Debug, "ARCHS", "$(ARCHS_STANDARD_32_BIT)"); - ADD_SETTING_QUOTE(residualvm_Debug, "CODE_SIGN_IDENTITY", "Don't Code Sign"); - ADD_SETTING_QUOTE_VAR(residualvm_Debug, "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "Don't Code Sign"); - ADD_SETTING_QUOTE(residualvm_Debug, "FRAMEWORK_SEARCH_PATHS", ""); - ADD_SETTING(residualvm_Debug, "GCC_C_LANGUAGE_STANDARD", "c99"); - ADD_SETTING(residualvm_Debug, "GCC_ENABLE_CPP_EXCEPTIONS", "NO"); - ADD_SETTING(residualvm_Debug, "GCC_ENABLE_CPP_RTTI", "NO"); - ADD_SETTING(residualvm_Debug, "GCC_INPUT_FILETYPE", "automatic"); - ADD_SETTING(residualvm_Debug, "GCC_OPTIMIZATION_LEVEL", "0"); - ValueList residualvm_defines(_defines); - ADD_DEFINE(residualvm_defines, "IPHONE"); - ADD_DEFINE(residualvm_defines, "XCODE"); - ADD_DEFINE(residualvm_defines, "IPHONE_OFFICIAL"); - ADD_SETTING_LIST(residualvm_Debug, "GCC_PREPROCESSOR_DEFINITIONS", residualvm_defines, SettingsNoQuote|SettingsAsList, 5); - ADD_SETTING(residualvm_Debug, "GCC_THUMB_SUPPORT", "NO"); - ADD_SETTING(residualvm_Debug, "GCC_USE_GCC3_PFE_SUPPORT", "NO"); - ADD_SETTING(residualvm_Debug, "GCC_WARN_ABOUT_RETURN_TYPE", "YES"); - ADD_SETTING(residualvm_Debug, "GCC_WARN_UNUSED_VARIABLE", "YES"); - ValueList residualvm_HeaderPaths; - residualvm_HeaderPaths.push_back("include/"); - residualvm_HeaderPaths.push_back("../../engines/"); - residualvm_HeaderPaths.push_back("../../"); - ADD_SETTING_LIST(residualvm_Debug, "HEADER_SEARCH_PATHS", residualvm_HeaderPaths, SettingsNoQuote|SettingsAsList, 5); - ADD_SETTING_QUOTE(residualvm_Debug, "LIBRARY_SEARCH_PATHS", ""); - ADD_SETTING(residualvm_Debug, "ONLY_ACTIVE_ARCH", "YES"); - ADD_SETTING_QUOTE(residualvm_Debug, "OTHER_CFLAGS", ""); - ADD_SETTING_QUOTE(residualvm_Debug, "OTHER_LDFLAGS", "-lz"); - ADD_SETTING(residualvm_Debug, "PREBINDING", "NO"); - ADD_SETTING(residualvm_Debug, "SDKROOT", "macosx10.6"); + Object *scummvm_Debug_Object = new Object(this, "XCBuildConfiguration_residualvm_Debug", "residualvm", "XCBuildConfiguration", "PBXProject", "Debug"); + Property scummvm_Debug; + ADD_SETTING(scummvm_Debug, "ALWAYS_SEARCH_USER_PATHS", "NO"); + ADD_SETTING_QUOTE(scummvm_Debug, "ARCHS", "$(ARCHS_STANDARD_32_BIT)"); + ADD_SETTING_QUOTE(scummvm_Debug, "CODE_SIGN_IDENTITY", "Don't Code Sign"); + ADD_SETTING_QUOTE_VAR(scummvm_Debug, "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "Don't Code Sign"); + ADD_SETTING_QUOTE(scummvm_Debug, "FRAMEWORK_SEARCH_PATHS", ""); + ADD_SETTING(scummvm_Debug, "GCC_C_LANGUAGE_STANDARD", "c99"); + ADD_SETTING(scummvm_Debug, "GCC_ENABLE_CPP_EXCEPTIONS", "NO"); + ADD_SETTING(scummvm_Debug, "GCC_ENABLE_CPP_RTTI", "NO"); + ADD_SETTING(scummvm_Debug, "GCC_INPUT_FILETYPE", "automatic"); + ADD_SETTING(scummvm_Debug, "GCC_OPTIMIZATION_LEVEL", "0"); + ValueList scummvm_defines(_defines); + ADD_DEFINE(scummvm_defines, "IPHONE"); + ADD_DEFINE(scummvm_defines, "XCODE"); + ADD_DEFINE(scummvm_defines, "IPHONE_OFFICIAL"); + ADD_SETTING_LIST(scummvm_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvm_defines, SettingsNoQuote|SettingsAsList, 5); + ADD_SETTING(scummvm_Debug, "GCC_THUMB_SUPPORT", "NO"); + ADD_SETTING(scummvm_Debug, "GCC_USE_GCC3_PFE_SUPPORT", "NO"); + ADD_SETTING(scummvm_Debug, "GCC_WARN_ABOUT_RETURN_TYPE", "YES"); + ADD_SETTING(scummvm_Debug, "GCC_WARN_UNUSED_VARIABLE", "YES"); + ValueList scummvm_HeaderPaths; + scummvm_HeaderPaths.push_back("include/"); + scummvm_HeaderPaths.push_back("../../engines/"); + scummvm_HeaderPaths.push_back("../../"); + ADD_SETTING_LIST(scummvm_Debug, "HEADER_SEARCH_PATHS", scummvm_HeaderPaths, SettingsNoQuote|SettingsAsList, 5); + ADD_SETTING_QUOTE(scummvm_Debug, "LIBRARY_SEARCH_PATHS", ""); + ADD_SETTING(scummvm_Debug, "ONLY_ACTIVE_ARCH", "YES"); + ADD_SETTING_QUOTE(scummvm_Debug, "OTHER_CFLAGS", ""); + ADD_SETTING_QUOTE(scummvm_Debug, "OTHER_LDFLAGS", "-lz"); + ADD_SETTING(scummvm_Debug, "PREBINDING", "NO"); + ADD_SETTING(scummvm_Debug, "SDKROOT", "macosx10.6"); - residualvm_Debug_Object->addProperty("name", "Debug", "", SettingsNoValue); - residualvm_Debug_Object->properties["buildSettings"] = residualvm_Debug; + scummvm_Debug_Object->addProperty("name", "Debug", "", SettingsNoValue); + scummvm_Debug_Object->properties["buildSettings"] = scummvm_Debug; // Release - Object *residualvm_Release_Object = new Object(this, "XCBuildConfiguration_residualvm_Release", "residualvm", "XCBuildConfiguration", "PBXProject", "Release"); - Property residualvm_Release(residualvm_Debug); - REMOVE_SETTING(residualvm_Release, "GCC_C_LANGUAGE_STANDARD"); // Not sure why we remove that, or any of the other warnings - REMOVE_SETTING(residualvm_Release, "GCC_WARN_ABOUT_RETURN_TYPE"); - REMOVE_SETTING(residualvm_Release, "GCC_WARN_UNUSED_VARIABLE"); - REMOVE_SETTING(residualvm_Release, "ONLY_ACTIVE_ARCH"); + Object *scummvm_Release_Object = new Object(this, "XCBuildConfiguration_scummvm_Release", "residualvm", "XCBuildConfiguration", "PBXProject", "Release"); + Property scummvm_Release(scummvm_Debug); + REMOVE_SETTING(scummvm_Release, "GCC_C_LANGUAGE_STANDARD"); // Not sure why we remove that, or any of the other warnings + REMOVE_SETTING(scummvm_Release, "GCC_WARN_ABOUT_RETURN_TYPE"); + REMOVE_SETTING(scummvm_Release, "GCC_WARN_UNUSED_VARIABLE"); + REMOVE_SETTING(scummvm_Release, "ONLY_ACTIVE_ARCH"); - residualvm_Release_Object->addProperty("name", "Release", "", SettingsNoValue); - residualvm_Release_Object->properties["buildSettings"] = residualvm_Release; + scummvm_Release_Object->addProperty("name", "Release", "", SettingsNoValue); + scummvm_Release_Object->properties["buildSettings"] = scummvm_Release; - _buildConfiguration.add(residualvm_Debug_Object); - _buildConfiguration.add(residualvm_Release_Object); + _buildConfiguration.add(scummvm_Debug_Object); + _buildConfiguration.add(scummvm_Release_Object); /**************************************** * ScummVM-OS X ****************************************/ // Debug - Object *residualvmOSX_Debug_Object = new Object(this, "XCBuildConfiguration_ResidualVM-OSX_Debug", _targets[1] /* ResidualVM-OS X */, "XCBuildConfiguration", "PBXNativeTarget", "Debug"); - Property residualvmOSX_Debug; - ADD_SETTING_QUOTE(residualvmOSX_Debug, "ARCHS", "$(NATIVE_ARCH)"); - ADD_SETTING(residualvmOSX_Debug, "COMPRESS_PNG_FILES", "NO"); - ADD_SETTING(residualvmOSX_Debug, "COPY_PHASE_STRIP", "NO"); - ADD_SETTING_QUOTE(residualvmOSX_Debug, "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym"); - ADD_SETTING_QUOTE(residualvmOSX_Debug, "FRAMEWORK_SEARCH_PATHS", ""); - ADD_SETTING(residualvmOSX_Debug, "GCC_C_LANGUAGE_STANDARD", "c99"); - ADD_SETTING(residualvmOSX_Debug, "GCC_ENABLE_CPP_EXCEPTIONS", "NO"); - ADD_SETTING(residualvmOSX_Debug, "GCC_ENABLE_CPP_RTTI", "NO"); - ADD_SETTING(residualvmOSX_Debug, "GCC_DYNAMIC_NO_PIC", "NO"); - ADD_SETTING(residualvmOSX_Debug, "GCC_ENABLE_FIX_AND_CONTINUE", "NO"); - ADD_SETTING(residualvmOSX_Debug, "GCC_OPTIMIZATION_LEVEL", "0"); - ADD_SETTING(residualvmOSX_Debug, "GCC_PRECOMPILE_PREFIX_HEADER", "NO"); - ADD_SETTING_QUOTE(residualvmOSX_Debug, "GCC_PREFIX_HEADER", ""); - ValueList residualvmOSX_defines(_defines); - ADD_DEFINE(residualvmOSX_defines, "SDL_BACKEND"); - ADD_DEFINE(residualvmOSX_defines, "MACOSX"); - ADD_SETTING_LIST(residualvmOSX_Debug, "GCC_PREPROCESSOR_DEFINITIONS", residualvmOSX_defines, SettingsNoQuote|SettingsAsList, 5); - ADD_SETTING_QUOTE(residualvmOSX_Debug, "GCC_VERSION", ""); - ValueList residualvmOSX_HeaderPaths; - residualvmOSX_HeaderPaths.push_back("/opt/local/include/SDL"); - residualvmOSX_HeaderPaths.push_back("/opt/local/include"); - residualvmOSX_HeaderPaths.push_back("include/"); - residualvmOSX_HeaderPaths.push_back("../../engines/"); - residualvmOSX_HeaderPaths.push_back("../../"); - ADD_SETTING_LIST(residualvmOSX_Debug, "HEADER_SEARCH_PATHS", residualvmOSX_HeaderPaths, SettingsNoQuote|SettingsAsList, 5); - ADD_SETTING_QUOTE(residualvmOSX_Debug, "INFOPLIST_FILE", "$(SRCROOT)/../macosx/Info.plist"); - ValueList residualvmOSX_LibPaths; - residualvmOSX_LibPaths.push_back("/sw/lib"); - residualvmOSX_LibPaths.push_back("/opt/local/lib"); - residualvmOSX_LibPaths.push_back("\"$(inherited)\""); - residualvmOSX_LibPaths.push_back("\"\\\\\\\"$(SRCROOT)/lib\\\\\\\"\""); // mmmh, all those slashes, it's almost Christmas \o/ - ADD_SETTING_LIST(residualvmOSX_Debug, "LIBRARY_SEARCH_PATHS", residualvmOSX_LibPaths, SettingsNoQuote|SettingsAsList, 5); - ADD_SETTING_QUOTE(residualvmOSX_Debug, "OTHER_CFLAGS", ""); - ValueList residualvmOSX_LdFlags; - residualvmOSX_LdFlags.push_back("-lSDLmain"); - residualvmOSX_LdFlags.push_back("-logg"); - residualvmOSX_LdFlags.push_back("-lvorbisfile"); - residualvmOSX_LdFlags.push_back("-lvorbis"); - residualvmOSX_LdFlags.push_back("-lmad"); - residualvmOSX_LdFlags.push_back("-lFLAC"); - residualvmOSX_LdFlags.push_back("-lSDL"); - residualvmOSX_LdFlags.push_back("-lz"); - ADD_SETTING_LIST(residualvmOSX_Debug, "OTHER_LDFLAGS", residualvmOSX_LdFlags, SettingsAsList, 5); - ADD_SETTING(residualvmOSX_Debug, "PREBINDING", "NO"); - ADD_SETTING(residualvmOSX_Debug, "PRODUCT_NAME", "ResidualVM"); + Object *scummvmOSX_Debug_Object = new Object(this, "XCBuildConfiguration_ResidualVM-OSX_Debug", _targets[1] /* ScummVM-OS X */, "XCBuildConfiguration", "PBXNativeTarget", "Debug"); + Property scummvmOSX_Debug; + ADD_SETTING_QUOTE(scummvmOSX_Debug, "ARCHS", "$(NATIVE_ARCH)"); + ADD_SETTING(scummvmOSX_Debug, "COMPRESS_PNG_FILES", "NO"); + ADD_SETTING(scummvmOSX_Debug, "COPY_PHASE_STRIP", "NO"); + ADD_SETTING_QUOTE(scummvmOSX_Debug, "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym"); + ADD_SETTING_QUOTE(scummvmOSX_Debug, "FRAMEWORK_SEARCH_PATHS", ""); + ADD_SETTING(scummvmOSX_Debug, "GCC_C_LANGUAGE_STANDARD", "c99"); + ADD_SETTING(scummvmOSX_Debug, "GCC_ENABLE_CPP_EXCEPTIONS", "NO"); + ADD_SETTING(scummvmOSX_Debug, "GCC_ENABLE_CPP_RTTI", "NO"); + ADD_SETTING(scummvmOSX_Debug, "GCC_DYNAMIC_NO_PIC", "NO"); + ADD_SETTING(scummvmOSX_Debug, "GCC_ENABLE_FIX_AND_CONTINUE", "NO"); + ADD_SETTING(scummvmOSX_Debug, "GCC_OPTIMIZATION_LEVEL", "0"); + ADD_SETTING(scummvmOSX_Debug, "GCC_PRECOMPILE_PREFIX_HEADER", "NO"); + ADD_SETTING_QUOTE(scummvmOSX_Debug, "GCC_PREFIX_HEADER", ""); + ValueList scummvmOSX_defines(_defines); + ADD_DEFINE(scummvmOSX_defines, "SDL_BACKEND"); + ADD_DEFINE(scummvmOSX_defines, "MACOSX"); + ADD_SETTING_LIST(scummvmOSX_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvmOSX_defines, SettingsNoQuote|SettingsAsList, 5); + ADD_SETTING_QUOTE(scummvmOSX_Debug, "GCC_VERSION", ""); + ValueList scummvmOSX_HeaderPaths; + scummvmOSX_HeaderPaths.push_back("/opt/local/include/SDL"); + scummvmOSX_HeaderPaths.push_back("/opt/local/include"); + scummvmOSX_HeaderPaths.push_back("include/"); + scummvmOSX_HeaderPaths.push_back("../../engines/"); + scummvmOSX_HeaderPaths.push_back("../../"); + ADD_SETTING_LIST(scummvmOSX_Debug, "HEADER_SEARCH_PATHS", scummvmOSX_HeaderPaths, SettingsNoQuote|SettingsAsList, 5); + ADD_SETTING_QUOTE(scummvmOSX_Debug, "INFOPLIST_FILE", "$(SRCROOT)/../macosx/Info.plist"); + ValueList scummvmOSX_LibPaths; + scummvmOSX_LibPaths.push_back("/sw/lib"); + scummvmOSX_LibPaths.push_back("/opt/local/lib"); + scummvmOSX_LibPaths.push_back("\"$(inherited)\""); + scummvmOSX_LibPaths.push_back("\"\\\\\\\"$(SRCROOT)/lib\\\\\\\"\""); // mmmh, all those slashes, it's almost Christmas \o/ + ADD_SETTING_LIST(scummvmOSX_Debug, "LIBRARY_SEARCH_PATHS", scummvmOSX_LibPaths, SettingsNoQuote|SettingsAsList, 5); + ADD_SETTING_QUOTE(scummvmOSX_Debug, "OTHER_CFLAGS", ""); + ValueList scummvmOSX_LdFlags; + scummvmOSX_LdFlags.push_back("-lSDLmain"); + scummvmOSX_LdFlags.push_back("-logg"); + scummvmOSX_LdFlags.push_back("-lvorbisfile"); + scummvmOSX_LdFlags.push_back("-lvorbis"); + scummvmOSX_LdFlags.push_back("-lmad"); + scummvmOSX_LdFlags.push_back("-lFLAC"); + scummvmOSX_LdFlags.push_back("-lSDL"); + scummvmOSX_LdFlags.push_back("-lz"); + ADD_SETTING_LIST(scummvmOSX_Debug, "OTHER_LDFLAGS", scummvmOSX_LdFlags, SettingsAsList, 5); + ADD_SETTING(scummvmOSX_Debug, "PREBINDING", "NO"); + ADD_SETTING(scummvmOSX_Debug, "PRODUCT_NAME", "ResidualVM"); - residualvmOSX_Debug_Object->addProperty("name", "Debug", "", SettingsNoValue); - residualvmOSX_Debug_Object->properties["buildSettings"] = residualvmOSX_Debug; + scummvmOSX_Debug_Object->addProperty("name", "Debug", "", SettingsNoValue); + scummvmOSX_Debug_Object->properties["buildSettings"] = scummvmOSX_Debug; // Release - Object *residualvmOSX_Release_Object = new Object(this, "XCBuildConfiguration_ResidualVMOSX_Release", _targets[1] /* ResidualVM-OS X */, "XCBuildConfiguration", "PBXNativeTarget", "Release"); - Property residualvmOSX_Release(residualvmOSX_Debug); - ADD_SETTING(residualvmOSX_Release, "COPY_PHASE_STRIP", "YES"); - REMOVE_SETTING(residualvmOSX_Release, "GCC_DYNAMIC_NO_PIC"); - REMOVE_SETTING(residualvmOSX_Release, "GCC_OPTIMIZATION_LEVEL"); - ADD_SETTING(residualvmOSX_Release, "WRAPPER_EXTENSION", "app"); + Object *scummvmOSX_Release_Object = new Object(this, "XCBuildConfiguration_ResidualVMOSX_Release", _targets[1] /* ScummVM-OS X */, "XCBuildConfiguration", "PBXNativeTarget", "Release"); + Property scummvmOSX_Release(scummvmOSX_Debug); + ADD_SETTING(scummvmOSX_Release, "COPY_PHASE_STRIP", "YES"); + REMOVE_SETTING(scummvmOSX_Release, "GCC_DYNAMIC_NO_PIC"); + REMOVE_SETTING(scummvmOSX_Release, "GCC_OPTIMIZATION_LEVEL"); + ADD_SETTING(scummvmOSX_Release, "WRAPPER_EXTENSION", "app"); - residualvmOSX_Release_Object->addProperty("name", "Release", "", SettingsNoValue); - residualvmOSX_Release_Object->properties["buildSettings"] = residualvmOSX_Release; + scummvmOSX_Release_Object->addProperty("name", "Release", "", SettingsNoValue); + scummvmOSX_Release_Object->properties["buildSettings"] = scummvmOSX_Release; - _buildConfiguration.add(residualvmOSX_Debug_Object); - _buildConfiguration.add(residualvmOSX_Release_Object); + _buildConfiguration.add(scummvmOSX_Debug_Object); + _buildConfiguration.add(scummvmOSX_Release_Object); /**************************************** - * ResidualVM-Simulator + * ScummVM-Simulator ****************************************/ // Debug - Object *residualvmSimulator_Debug_Object = new Object(this, "XCBuildConfiguration_ResidualVM-Simulator_Debug", _targets[2] /* ResidualVM-Simulator */, "XCBuildConfiguration", "PBXNativeTarget", "Debug"); - Property residualvmSimulator_Debug(iPhone_Debug); - ADD_SETTING_QUOTE(residualvmSimulator_Debug, "FRAMEWORK_SEARCH_PATHS", "$(inherited)"); - ADD_SETTING_LIST(residualvmSimulator_Debug, "GCC_PREPROCESSOR_DEFINITIONS", residualvm_defines, SettingsNoQuote|SettingsAsList, 5); - ADD_SETTING(residualvmSimulator_Debug, "SDKROOT", "iphonesimulator3.2"); - REMOVE_SETTING(residualvmSimulator_Debug, "TARGETED_DEVICE_FAMILY"); + Object *scummvmSimulator_Debug_Object = new Object(this, "XCBuildConfiguration_ResidualVM-Simulator_Debug", _targets[2] /* ScummVM-Simulator */, "XCBuildConfiguration", "PBXNativeTarget", "Debug"); + Property scummvmSimulator_Debug(iPhone_Debug); + ADD_SETTING_QUOTE(scummvmSimulator_Debug, "FRAMEWORK_SEARCH_PATHS", "$(inherited)"); + ADD_SETTING_LIST(scummvmSimulator_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvm_defines, SettingsNoQuote|SettingsAsList, 5); + ADD_SETTING(scummvmSimulator_Debug, "SDKROOT", "iphonesimulator3.2"); + REMOVE_SETTING(scummvmSimulator_Debug, "TARGETED_DEVICE_FAMILY"); - residualvmSimulator_Debug_Object->addProperty("name", "Debug", "", SettingsNoValue); - residualvmSimulator_Debug_Object->properties["buildSettings"] = residualvmSimulator_Debug; + scummvmSimulator_Debug_Object->addProperty("name", "Debug", "", SettingsNoValue); + scummvmSimulator_Debug_Object->properties["buildSettings"] = scummvmSimulator_Debug; // Release - Object *residualvmSimulator_Release_Object = new Object(this, "XCBuildConfiguration_ResidualVM-Simulator_Release", _targets[2] /* ResidualVM-Simulator */, "XCBuildConfiguration", "PBXNativeTarget", "Release"); - Property residualvmSimulator_Release(residualvmSimulator_Debug); - ADD_SETTING(residualvmSimulator_Release, "COPY_PHASE_STRIP", "YES"); - REMOVE_SETTING(residualvmSimulator_Release, "GCC_DYNAMIC_NO_PIC"); - ADD_SETTING(residualvmSimulator_Release, "WRAPPER_EXTENSION", "app"); + Object *scummvmSimulator_Release_Object = new Object(this, "XCBuildConfiguration_ResidualVM-Simulator_Release", _targets[2] /* ScummVM-Simulator */, "XCBuildConfiguration", "PBXNativeTarget", "Release"); + Property scummvmSimulator_Release(scummvmSimulator_Debug); + ADD_SETTING(scummvmSimulator_Release, "COPY_PHASE_STRIP", "YES"); + REMOVE_SETTING(scummvmSimulator_Release, "GCC_DYNAMIC_NO_PIC"); + ADD_SETTING(scummvmSimulator_Release, "WRAPPER_EXTENSION", "app"); - residualvmSimulator_Release_Object->addProperty("name", "Release", "", SettingsNoValue); - residualvmSimulator_Release_Object->properties["buildSettings"] = residualvmSimulator_Release; + scummvmSimulator_Release_Object->addProperty("name", "Release", "", SettingsNoValue); + scummvmSimulator_Release_Object->properties["buildSettings"] = scummvmSimulator_Release; - _buildConfiguration.add(residualvmSimulator_Debug_Object); - _buildConfiguration.add(residualvmSimulator_Release_Object); + _buildConfiguration.add(scummvmSimulator_Debug_Object); + _buildConfiguration.add(scummvmSimulator_Release_Object); ////////////////////////////////////////////////////////////////////////// // Configuration List diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index c31c8bd66e7..0cec039b5ed 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -26,6 +26,8 @@ #include "engines/metaengine.h" #include "engines/engine.h" +#include "common/gui_options.h" // FIXME: Temporary hack? + namespace Common { class Error; class FSList; @@ -169,7 +171,13 @@ protected: /** * Name of single gameid (optional). * - * @todo Properly explain this -- what does it do? + * Used to override gameid. + * This is a recommended setting to prevent global gameid pollution. + * With this option set, the gameid effectively turns into engineid. + * + * FIXME: This field actually removes a feature (gameid) in order to + * address a more generic problem. We should find a better way to + * disambiguate gameids. */ const char *_singleid; diff --git a/engines/engine.h b/engines/engine.h index a020dc4951b..4f4223384a3 100644 --- a/engines/engine.h +++ b/engines/engine.h @@ -24,6 +24,8 @@ #include "common/scummsys.h" #include "common/str.h" +#include "common/language.h" +#include "common/platform.h" class OSystem; diff --git a/engines/game.cpp b/engines/game.cpp index be15240745b..4bfd8f3bf22 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -21,6 +21,7 @@ */ #include "engines/game.h" +#include "common/gui_options.h" const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list) { diff --git a/engines/game.h b/engines/game.h index d5136936bc1..3417203ea7f 100644 --- a/engines/game.h +++ b/engines/game.h @@ -26,7 +26,8 @@ #include "common/array.h" #include "common/hash-str.h" #include "common/str.h" -#include "common/util.h" +#include "common/language.h" +#include "common/platform.h" /** * A simple structure used to map gameids (like "monkey", "sword1", ...) to diff --git a/engines/grim/update/lang_filter.h b/engines/grim/update/lang_filter.h index 43aedc85c29..f615d83bb8e 100644 --- a/engines/grim/update/lang_filter.h +++ b/engines/grim/update/lang_filter.h @@ -24,7 +24,7 @@ #define LANGFILTER_H #include "common/archive.h" -#include "common/util.h" +#include "common/language.h" namespace Grim { diff --git a/engines/myst3/cursor.cpp b/engines/myst3/cursor.cpp index a41179af410..14330396865 100644 --- a/engines/myst3/cursor.cpp +++ b/engines/myst3/cursor.cpp @@ -27,7 +27,7 @@ #include "engines/myst3/state.h" #include "graphics/surface.h" -#include "graphics/imagedec.h" +#include "graphics/decoders/image_decoder.h" namespace Myst3 { @@ -77,7 +77,8 @@ void Cursor::loadAvailableCursors() { error("Cursor %d does not exist", availableCursors[i].nodeID); Common::MemoryReadStream *bmpStream = cursorDesc->getData(); - Graphics::Surface *surface = Graphics::ImageDecoder::loadFile(*bmpStream, Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)); + // FIXME: + Graphics::Surface *surface;// = Graphics::ImageDecoder::loadFile(*bmpStream, Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)); delete bmpStream; // Apply the colorkey for transparency diff --git a/engines/myst3/myst3.cpp b/engines/myst3/myst3.cpp index a41c45b8df0..ce094d4e048 100644 --- a/engines/myst3/myst3.cpp +++ b/engines/myst3/myst3.cpp @@ -44,7 +44,7 @@ #include "engines/myst3/menu.h" #include "engines/myst3/sound.h" -#include "graphics/jpeg.h" +#include "graphics/decoders/jpeg.h" #include "graphics/conversion.h" #include "graphics/pixelbuffer.h" diff --git a/engines/myst3/node.cpp b/engines/myst3/node.cpp index 7ac11b4633c..e39c2076a5c 100644 --- a/engines/myst3/node.cpp +++ b/engines/myst3/node.cpp @@ -33,7 +33,7 @@ namespace Myst3 { -void Face::setTextureFromJPEG(Graphics::JPEG *jpeg) { +void Face::setTextureFromJPEG(Graphics::JPEGDecoder *jpeg) { _bitmap = new Graphics::Surface(); _bitmap->create(jpeg->getComponent(1)->w, jpeg->getComponent(1)->h, Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0)); @@ -168,8 +168,9 @@ void Node::loadSpotItem(uint16 id, uint16 condition, bool fade) { Common::MemoryReadStream *jpegStream = jpegDesc->getData(); - Graphics::JPEG jpeg; - jpeg.read(jpegStream); + Graphics::JPEGDecoder jpeg; + //FIXME + //jpeg.read(jpegStream); spotItemFace->loadData(&jpeg); @@ -300,7 +301,7 @@ void SpotItemFace::initBlack(uint16 width, uint16 height) { initNotDrawn(width, height); } -void SpotItemFace::loadData(Graphics::JPEG *jpeg) { +void SpotItemFace::loadData(Graphics::JPEGDecoder *jpeg) { // Convert active SpotItem image to raw data _bitmap = new Graphics::Surface(); _bitmap->create(jpeg->getComponent(1)->w, jpeg->getComponent(1)->h, Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0)); diff --git a/engines/myst3/node.h b/engines/myst3/node.h index b3d5701da91..bd5e5b01d1c 100644 --- a/engines/myst3/node.h +++ b/engines/myst3/node.h @@ -29,7 +29,7 @@ #include "common/rect.h" #include "graphics/surface.h" -#include "graphics/jpeg.h" +#include "graphics/decoders/jpeg.h" namespace Myst3 { @@ -45,7 +45,7 @@ class Face { Face(Myst3Engine *vm); ~Face(); - void setTextureFromJPEG(Graphics::JPEG *jpeg); + void setTextureFromJPEG(Graphics::JPEGDecoder *jpeg); void markTextureDirty() { _textureDirty = true; } void uploadTexture(); @@ -61,7 +61,7 @@ class SpotItemFace { ~SpotItemFace(); void initBlack(uint16 width, uint16 height); - void loadData(Graphics::JPEG *jpeg); + void loadData(Graphics::JPEGDecoder *jpeg); void updateData(const uint8 *data); void clear(); diff --git a/engines/myst3/nodecube.cpp b/engines/myst3/nodecube.cpp index 09883701df9..a7ffbbadd89 100644 --- a/engines/myst3/nodecube.cpp +++ b/engines/myst3/nodecube.cpp @@ -39,8 +39,9 @@ NodeCube::NodeCube(Myst3Engine *vm, uint16 id) : Common::MemoryReadStream *jpegStream = jpegDesc->getData(); if (jpegStream) { - Graphics::JPEG jpeg; - jpeg.read(jpegStream); + Graphics::JPEGDecoder jpeg; + //FIXME + //jpeg.read(jpegStream); _faces[i] = new Face(_vm); _faces[i]->setTextureFromJPEG(&jpeg); diff --git a/engines/myst3/nodeframe.cpp b/engines/myst3/nodeframe.cpp index 1f42001d0fe..3190bd4bb34 100644 --- a/engines/myst3/nodeframe.cpp +++ b/engines/myst3/nodeframe.cpp @@ -44,8 +44,9 @@ NodeFrame::NodeFrame(Myst3Engine *vm, uint16 id) : Common::MemoryReadStream *jpegStream = jpegDesc->getData(); if (jpegStream) { - Graphics::JPEG jpeg; - jpeg.read(jpegStream); + Graphics::JPEGDecoder jpeg; + //FIXME + //jpeg.read(jpegStream); _faces[0] = new Face(_vm); _faces[0]->setTextureFromJPEG(&jpeg); diff --git a/graphics/decoders/bmp.cpp b/graphics/decoders/bmp.cpp new file mode 100644 index 00000000000..0d44881d7ce --- /dev/null +++ b/graphics/decoders/bmp.cpp @@ -0,0 +1,159 @@ +/* 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. + */ + +#include "common/stream.h" +#include "common/textconsole.h" + +#include "graphics/pixelformat.h" +#include "graphics/surface.h" +#include "graphics/decoders/bmp.h" + +namespace Graphics { + +BitmapDecoder::BitmapDecoder() { + _surface = 0; + _palette = 0; +} + +BitmapDecoder::~BitmapDecoder() { + destroy(); +} + +void BitmapDecoder::destroy() { + if (_surface) { + _surface->free(); + delete _surface; _surface = 0; + } + + delete[] _palette; _palette = 0; +} + +bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) { + destroy(); + + if (stream.readByte() != 'B') + return false; + + if (stream.readByte() != 'M') + return false; + + /* uint32 fileSize = */ stream.readUint32LE(); + /* uint16 res1 = */ stream.readUint16LE(); + /* uint16 res2 = */ stream.readUint16LE(); + uint32 imageOffset = stream.readUint32LE(); + + uint32 infoSize = stream.readUint32LE(); + if (infoSize != 40) { + warning("Only Windows v3 bitmaps are supported"); + return false; + } + + uint32 width = stream.readUint32LE(); + int32 height = stream.readSint32LE(); + + if (width == 0 || height == 0) + return false; + + if (height < 0) { + warning("Right-side up bitmaps not supported"); + return false; + } + + /* uint16 planes = */ stream.readUint16LE(); + uint16 bitsPerPixel = stream.readUint16LE(); + + if (bitsPerPixel != 8 && bitsPerPixel != 24) { + warning("%dbpp bitmaps not supported", bitsPerPixel); + return false; + } + + uint32 compression = stream.readUint32LE(); + + if (compression != 0) { + warning("Compressed bitmaps not supported"); + return false; + } + + /* uint32 imageSize = */ stream.readUint32LE(); + /* uint32 pixelsPerMeterX = */ stream.readUint32LE(); + /* uint32 pixelsPerMeterY = */ stream.readUint32LE(); + uint32 colorsUsed = stream.readUint32LE(); + /* uint32 colorsImportant = */ stream.readUint32LE(); + + if (colorsUsed == 0) + colorsUsed = 256; + + if (bitsPerPixel == 8) { + // Read the palette + _palette = new byte[colorsUsed * 3]; + for (uint16 i = 0; i < colorsUsed; i++) { + _palette[i * 3 + 2] = stream.readByte(); + _palette[i * 3 + 1] = stream.readByte(); + _palette[i * 3 + 0] = stream.readByte(); + stream.readByte(); + } + } + + // Start us at the beginning of the image + stream.seek(imageOffset); + + Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8(); + + // BGRA for 24bpp + if (bitsPerPixel == 24) + format = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0); + + _surface = new Graphics::Surface(); + _surface->create(width, height, format); + + int srcPitch = width * (bitsPerPixel >> 3); + const int extraDataLength = (srcPitch % 4) ? 4 - (srcPitch % 4) : 0; + + if (bitsPerPixel == 8) { + byte *dst = (byte *)_surface->pixels; + + for (int32 i = 0; i < height; i++) { + stream.read(dst + (height - i - 1) * width, width); + stream.skip(extraDataLength); + } + } else { + byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch; + + for (int32 i = 0; i < height; i++) { + for (uint32 j = 0; j < width; j++) { + byte b = stream.readByte(); + byte g = stream.readByte(); + byte r = stream.readByte(); + uint32 color = format.RGBToColor(r, g, b); + + *((uint32 *)dst) = color; + dst += format.bytesPerPixel; + } + + stream.skip(extraDataLength); + dst -= _surface->pitch * 2; + } + } + + return true; +} + +} // End of namespace Graphics diff --git a/graphics/imagedec.h b/graphics/decoders/bmp.h similarity index 53% rename from graphics/imagedec.h rename to graphics/decoders/bmp.h index e839d097b2c..e11b12fad69 100644 --- a/graphics/imagedec.h +++ b/graphics/decoders/bmp.h @@ -19,11 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef GRAPHICS_IMAGEDEC_H -#define GRAPHICS_IMAGEDEC_H +#ifndef GRAPHICS_DECODERS_BMP_H +#define GRAPHICS_DECODERS_BMP_H #include "common/scummsys.h" #include "common/str.h" +#include "graphics/decoders/image_decoder.h" namespace Common{ class SeekableReadStream; @@ -34,33 +35,22 @@ namespace Graphics { struct PixelFormat; struct Surface; -class ImageDecoder { +class BitmapDecoder : public ImageDecoder { public: - ImageDecoder() {} - virtual ~ImageDecoder() {} + BitmapDecoder(); + virtual ~BitmapDecoder(); - static Surface *loadFile(const Common::String &name, const PixelFormat &format); - static Surface *loadFile(Common::SeekableReadStream &stream, const PixelFormat &format); + // ImageDecoder API + void destroy(); + virtual bool loadStream(Common::SeekableReadStream &stream); + virtual const Surface *getSurface() const { return _surface; } + virtual const byte *getPalette() { return _palette; } - /** - * checks if the data can be decoded by this decoder - * - * @param stream memory read stream - * @return true if it can be decoded, otherwise false - */ - virtual bool decodeable(Common::SeekableReadStream &stream) = 0; - - /** - * decodes the data and returns an pointer to the resulting surface. - * Surface::free() must be called by the user also it must be deleted - * with delete; - * - * @param stream the memory stream which should be decoded - * @param format the pixel format used to generate the surface - * @return returns a new surface if the image could be decoded, otherwise 0 - */ - virtual Surface *decodeImage(Common::SeekableReadStream &stream, const PixelFormat &format) = 0; +private: + Surface *_surface; + byte *_palette; }; + } // End of namespace Graphics #endif diff --git a/graphics/decoders/image_decoder.h b/graphics/decoders/image_decoder.h new file mode 100644 index 00000000000..e768f7f9a20 --- /dev/null +++ b/graphics/decoders/image_decoder.h @@ -0,0 +1,85 @@ +/* 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. + */ + +#ifndef GRAPHICS_DECODERS_IMAGEDECODER_H +#define GRAPHICS_DECODERS_IMAGEDECODER_H + +#include "common/scummsys.h" +#include "common/str.h" + +namespace Common{ +class SeekableReadStream; +} + +namespace Graphics { + +struct PixelFormat; +struct Surface; + +/** + * A representation of an image decoder that maintains ownership of the surface + * and palette it decodes to. + */ +class ImageDecoder { +public: + virtual ~ImageDecoder() {} + + /** + * Load an image from the specified stream + * + * @param stream the input stream + * @return whether loading the file succeeded + * @see getSurface + * @see getPalette + */ + virtual bool loadStream(Common::SeekableReadStream &stream) = 0; + + /** + * Destroy this decoder's surface and palette + */ + virtual void destroy() = 0; + + /** + * Get the decoded surface + * + * This surface is owned by this ImageDecoder and will remain valid + * until destroy() or loadStream() is called, or until this ImageDecoder's + * destructor is called. + * + * @return the decoded surface, or 0 if no surface is present + */ + virtual const Surface *getSurface() const = 0; + + /** + * Get the decoded palette + * + * This palette is owned by this ImageDecoder and will remain valid + * until destroy() or loadStream() is called, or until this ImageDecoder's + * destructor is called. + * + * @return the decoded palette, or 0 if no palette is present + */ + virtual const byte *getPalette() const { return 0; } +}; + +} // End of namespace Graphics + +#endif diff --git a/graphics/jpeg.cpp b/graphics/decoders/jpeg.cpp similarity index 88% rename from graphics/jpeg.cpp rename to graphics/decoders/jpeg.cpp index 53e693a0454..a871377ca19 100644 --- a/graphics/jpeg.cpp +++ b/graphics/decoders/jpeg.cpp @@ -20,9 +20,9 @@ * */ -#include "graphics/conversion.h" -#include "graphics/jpeg.h" #include "graphics/pixelformat.h" +#include "graphics/yuv_to_rgb.h" +#include "graphics/decoders/jpeg.h" #include "common/debug.h" #include "common/endian.h" @@ -43,9 +43,9 @@ static const uint8 _zigZagOrder[64] = { 53, 60, 61, 54, 47, 55, 62, 63 }; -JPEG::JPEG() : +JPEGDecoder::JPEGDecoder() : ImageDecoder(), _stream(NULL), _w(0), _h(0), _numComp(0), _components(NULL), _numScanComp(0), - _scanComp(NULL), _currentComp(NULL) { + _scanComp(NULL), _currentComp(NULL), _rgbSurface(0) { // Initialize the quantization tables for (int i = 0; i < JPEG_MAX_QUANT_TABLES; i++) @@ -60,42 +60,33 @@ JPEG::JPEG() : } } -JPEG::~JPEG() { - reset(); +JPEGDecoder::~JPEGDecoder() { + destroy(); } -Surface *JPEG::getSurface(const PixelFormat &format) { +const Surface *JPEGDecoder::getSurface() const { // Make sure we have loaded data if (!isLoaded()) return 0; - // Only accept >8bpp surfaces - if (format.bytesPerPixel == 1) - return 0; + if (_rgbSurface) + return _rgbSurface; + + // Create an RGBA8888 surface + _rgbSurface = new Graphics::Surface(); + _rgbSurface->create(_w, _h, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); // Get our component surfaces - Graphics::Surface *yComponent = getComponent(1); - Graphics::Surface *uComponent = getComponent(2); - Graphics::Surface *vComponent = getComponent(3); + const Graphics::Surface *yComponent = getComponent(1); + const Graphics::Surface *uComponent = getComponent(2); + const Graphics::Surface *vComponent = getComponent(3); - Graphics::Surface *output = new Graphics::Surface(); - output->create(yComponent->w, yComponent->h, format); + convertYUV444ToRGB(_rgbSurface, (byte *)yComponent->pixels, (byte *)uComponent->pixels, (byte *)vComponent->pixels, yComponent->w, yComponent->h, yComponent->pitch, uComponent->pitch); - for (uint16 i = 0; i < output->h; i++) { - for (uint16 j = 0; j < output->w; j++) { - byte r = 0, g = 0, b = 0; - YUV2RGB(*((byte *)yComponent->getBasePtr(j, i)), *((byte *)uComponent->getBasePtr(j, i)), *((byte *)vComponent->getBasePtr(j, i)), r, g, b); - if (format.bytesPerPixel == 2) - *((uint16 *)output->getBasePtr(j, i)) = format.RGBToColor(r, g, b); - else - *((uint32 *)output->getBasePtr(j, i)) = format.RGBToColor(r, g, b); - } - } - - return output; + return _rgbSurface; } -void JPEG::reset() { +void JPEGDecoder::destroy() { // Reset member variables _stream = NULL; _w = _h = 0; @@ -125,14 +116,19 @@ void JPEG::reset() { delete[] _huff[i].sizes; _huff[i].sizes = NULL; delete[] _huff[i].codes; _huff[i].codes = NULL; } + + if (_rgbSurface) { + _rgbSurface->free(); + delete _rgbSurface; + } } -bool JPEG::read(Common::SeekableReadStream *stream) { +bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) { // Reset member variables and tables from previous reads - reset(); + destroy(); // Save the input stream - _stream = stream; + _stream = &stream; bool ok = true; bool done = false; @@ -211,41 +207,41 @@ bool JPEG::read(Common::SeekableReadStream *stream) { } } } + + _stream = 0; return ok; } -bool JPEG::readJFIF() { +bool JPEGDecoder::readJFIF() { uint16 length = _stream->readUint16BE(); uint32 tag = _stream->readUint32BE(); if (tag != MKTAG('J', 'F', 'I', 'F')) { - warning("JPEG::readJFIF() tag mismatch"); + warning("JPEGDecoder::readJFIF() tag mismatch"); return false; } if (_stream->readByte() != 0) { // NULL - warning("JPEG::readJFIF() NULL mismatch"); + warning("JPEGDecoder::readJFIF() NULL mismatch"); return false; } byte majorVersion = _stream->readByte(); byte minorVersion = _stream->readByte(); - - if (majorVersion != 1 || (minorVersion != 1 && minorVersion != 2)) - warning("JPEG::readJFIF() Non-v1.1/1.2 JPEGs may not be handled correctly"); - - /* byte densityUnits = */ _stream->readByte(); - /* uint16 xDensity = */ _stream->readUint16BE(); - /* uint16 yDensity = */ _stream->readUint16BE(); + if (majorVersion != 1 || minorVersion != 1) + warning("JPEGDecoder::readJFIF() Non-v1.1 JPEGs may not be handled correctly"); + /* byte densityUnits = */_stream->readByte(); + /* uint16 xDensity = */_stream->readUint16BE(); + /* uint16 yDensity = */_stream->readUint16BE(); byte thumbW = _stream->readByte(); byte thumbH = _stream->readByte(); _stream->seek(thumbW * thumbH * 3, SEEK_CUR); // Ignore thumbnail if (length != (thumbW * thumbH * 3) + 16) { - warning("JPEG::readJFIF() length mismatch"); + warning("JPEGDecoder::readJFIF() length mismatch"); return false; } return true; } // Marker 0xC0 (Start Of Frame, Baseline DCT) -bool JPEG::readSOF0() { +bool JPEGDecoder::readSOF0() { debug(5, "JPEG: readSOF0"); uint16 size = _stream->readUint16BE(); @@ -284,7 +280,7 @@ bool JPEG::readSOF0() { } // Marker 0xC4 (Define Huffman Tables) -bool JPEG::readDHT() { +bool JPEGDecoder::readDHT() { debug(5, "JPEG: readDHT"); uint16 size = _stream->readUint16BE() - 2; uint32 pos = _stream->pos(); @@ -346,7 +342,7 @@ bool JPEG::readDHT() { } // Marker 0xDA (Start Of Scan) -bool JPEG::readSOS() { +bool JPEGDecoder::readSOS() { debug(5, "JPEG: readSOS"); uint16 size = _stream->readUint16BE(); @@ -473,7 +469,7 @@ bool JPEG::readSOS() { } // Marker 0xDB (Define Quantization Tables) -bool JPEG::readDQT() { +bool JPEGDecoder::readDQT() { debug(5, "JPEG: readDQT"); uint16 size = _stream->readUint16BE() - 2; uint32 pos = _stream->pos(); @@ -503,7 +499,7 @@ bool JPEG::readDQT() { } // Marker 0xDD (Define Restart Interval) -bool JPEG::readDRI() { +bool JPEGDecoder::readDRI() { debug(5, "JPEG: readDRI"); uint16 size = _stream->readUint16BE() - 2; @@ -517,7 +513,7 @@ bool JPEG::readDRI() { return true; } -bool JPEG::readMCU(uint16 xMCU, uint16 yMCU) { +bool JPEGDecoder::readMCU(uint16 xMCU, uint16 yMCU) { bool ok = true; for (int c = 0; ok && (c < _numComp); c++) { // Set the current component @@ -549,7 +545,7 @@ bool JPEG::readMCU(uint16 xMCU, uint16 yMCU) { xb = (n - (k2 + k1) * p) >> sh; // IDCT based on public domain code from http://halicery.com/jpeg/idct.html -void JPEG::idct1D8x8(int32 src[8], int32 dest[64], int32 ps, int32 half) { +void JPEGDecoder::idct1D8x8(int32 src[8], int32 dest[64], int32 ps, int32 half) { int p, n; src[0] <<= 9; @@ -578,7 +574,7 @@ void JPEG::idct1D8x8(int32 src[8], int32 dest[64], int32 ps, int32 half) { dest[7 * 8] = (src[0] - src[1]) >> ps; } -void JPEG::idct2D8x8(int32 block[64]) { +void JPEGDecoder::idct2D8x8(int32 block[64]) { int32 tmp[64]; // Apply 1D IDCT to rows @@ -590,7 +586,7 @@ void JPEG::idct2D8x8(int32 block[64]) { idct1D8x8(&tmp[i * 8], &block[i], 12, 1 << 11); } -bool JPEG::readDataUnit(uint16 x, uint16 y) { +bool JPEGDecoder::readDataUnit(uint16 x, uint16 y) { // Prepare an empty data array int16 readData[64]; for (int i = 1; i < 64; i++) @@ -654,7 +650,7 @@ bool JPEG::readDataUnit(uint16 x, uint16 y) { return true; } -int16 JPEG::readDC() { +int16 JPEGDecoder::readDC() { // DC is type 0 uint8 tableNum = _currentComp->DCentropyTableSelector << 1; @@ -665,7 +661,7 @@ int16 JPEG::readDC() { return readSignedBits(numBits); } -void JPEG::readAC(int16 *out) { +void JPEGDecoder::readAC(int16 *out) { // AC is type 1 uint8 tableNum = (_currentComp->ACentropyTableSelector << 1) + 1; @@ -695,7 +691,7 @@ void JPEG::readAC(int16 *out) { } } -int16 JPEG::readSignedBits(uint8 numBits) { +int16 JPEGDecoder::readSignedBits(uint8 numBits) { uint16 ret = 0; if (numBits > 16) error("requested %d bits", numBits); //XXX @@ -713,7 +709,7 @@ int16 JPEG::readSignedBits(uint8 numBits) { } // TODO: optimize? -uint8 JPEG::readHuff(uint8 table) { +uint8 JPEGDecoder::readHuff(uint8 table) { bool foundCode = false; uint8 val = 0; @@ -743,7 +739,7 @@ uint8 JPEG::readHuff(uint8 table) { return val; } -uint8 JPEG::readBit() { +uint8 JPEGDecoder::readBit() { // Read a whole byte if necessary if (_bitsNumber == 0) { _bitsData = _stream->readByte(); @@ -773,12 +769,12 @@ uint8 JPEG::readBit() { return (_bitsData & (1 << _bitsNumber)) ? 1 : 0; } -Surface *JPEG::getComponent(uint c) { +const Surface *JPEGDecoder::getComponent(uint c) const { for (int i = 0; i < _numComp; i++) if (_components[i].id == c) // We found the desired component return &_components[i].surface; - error("JPEG::getComponent: No component %d present", c); + error("JPEGDecoder::getComponent: No component %d present", c); return NULL; } diff --git a/graphics/jpeg.h b/graphics/decoders/jpeg.h similarity index 85% rename from graphics/jpeg.h rename to graphics/decoders/jpeg.h index b87791470f7..c566d5ad210 100644 --- a/graphics/jpeg.h +++ b/graphics/decoders/jpeg.h @@ -24,6 +24,7 @@ #define GRAPHICS_JPEG_H #include "graphics/surface.h" +#include "graphics/decoders/image_decoder.h" namespace Common { class SeekableReadStream; @@ -36,26 +37,31 @@ struct PixelFormat; #define JPEG_MAX_QUANT_TABLES 4 #define JPEG_MAX_HUFF_TABLES 2 -class JPEG { +class JPEGDecoder : public ImageDecoder { public: - JPEG(); - ~JPEG(); + JPEGDecoder(); + ~JPEGDecoder(); + + // ImageDecoder API + void destroy(); + bool loadStream(Common::SeekableReadStream &str); + const Surface *getSurface() const; - bool read(Common::SeekableReadStream *str); bool isLoaded() const { return _numComp && _w && _h; } uint16 getWidth() const { return _w; } uint16 getHeight() const { return _h; } - - Surface *getComponent(uint c); - Surface *getSurface(const PixelFormat &format); + const Surface *getComponent(uint c) const; private: - void reset(); - Common::SeekableReadStream *_stream; uint16 _w, _h; uint16 _restartInterval; + // mutable so that we can convert to RGB only during + // a getSurface() call while still upholding the + // const requirement in other ImageDecoders + mutable Graphics::Surface *_rgbSurface; + // Image components uint8 _numComp; struct Component { diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp index 06231799ce3..7505f7913e4 100644 --- a/graphics/fonts/ttf.cpp +++ b/graphics/fonts/ttf.cpp @@ -338,7 +338,7 @@ void TTFFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const return; if (y < 0) { - srcPos += y * glyph.image.pitch; + srcPos -= y * glyph.image.pitch; h += y; y = 0; } @@ -395,11 +395,11 @@ bool TTFFont::cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr) { FT_Glyph_Metrics &metrics = _face->glyph->metrics; - glyph.xOffset = ftFloor26_6(metrics.horiBearingX); + glyph.xOffset = _face->glyph->bitmap_left; int xMax = glyph.xOffset + ftCeil26_6(metrics.width); - glyph.yOffset = _ascent - ftFloor26_6(metrics.horiBearingY); + glyph.yOffset = _ascent - _face->glyph->bitmap_top; - glyph.advance = ftCeil26_6(metrics.horiAdvance); + glyph.advance = ftCeil26_6(_face->glyph->advance.x); // In case we got a negative xMin we adjust that, this might make some // characters make a bit odd, but it's the only way we can assure no diff --git a/graphics/imagedec.cpp b/graphics/imagedec.cpp deleted file mode 100644 index 226378cb270..00000000000 --- a/graphics/imagedec.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* 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. - */ - -#include "graphics/imagedec.h" -#include "graphics/pixelformat.h" -#include "graphics/surface.h" - -#include "common/file.h" - -namespace Graphics { -// -// BMP Decoder -// -class BMPDecoder : public ImageDecoder { -public: - BMPDecoder() {} - virtual ~BMPDecoder() {} - - bool decodeable(Common::SeekableReadStream &stream); - Surface *decodeImage(Common::SeekableReadStream &stream, const PixelFormat &format); - - struct BitmapHeader { - uint16 type; - uint32 size; - uint16 res1; - uint16 res2; - uint32 imageOffset; - }; - - struct InfoHeader { - uint32 size; - uint32 width; - uint32 height; - uint16 planes; - uint16 bitsPerPixel; - uint32 compression; - uint32 imageSize; - uint32 pixelsPerMeterX; - uint32 pixelsPerMeterY; - uint32 colorsUsed; - uint32 colorsImportant; - }; -}; - -bool BMPDecoder::decodeable(Common::SeekableReadStream &stream) { - BitmapHeader header; - stream.seek(0); - header.type = stream.readUint16BE(); - header.size = stream.readUint32LE(); - - // TODO: maybe improve this detection - if (header.size == 0 || header.type != 'BM') - return false; - - return true; -} - -Surface *BMPDecoder::decodeImage(Common::SeekableReadStream &stream, const PixelFormat &format) { - if (!decodeable(stream)) { - return 0; - } - - BitmapHeader header; - InfoHeader info; - - stream.seek(0); - header.type = stream.readUint16BE(); - header.size = stream.readUint32LE(); - header.res1 = stream.readUint16LE(); - header.res2 = stream.readUint16LE(); - header.imageOffset = stream.readUint32LE(); - - if (header.size == 0 || header.type != 'BM') { - stream.seek(0); - return 0; - } - - info.size = stream.readUint32LE(); - info.width = stream.readUint32LE(); - info.height = stream.readUint32LE(); - info.planes = stream.readUint16LE(); - info.bitsPerPixel = stream.readUint16LE(); - info.compression = stream.readUint32LE(); - info.imageSize = stream.readUint32LE(); - info.pixelsPerMeterX = stream.readUint32LE(); - info.pixelsPerMeterY = stream.readUint32LE(); - info.colorsUsed = stream.readUint32LE(); - info.colorsImportant = stream.readUint32LE(); - - stream.seek(header.imageOffset); - - if (info.bitsPerPixel != 24) { - stream.seek(0); - return 0; - } - - uint8 r = 0, g = 0, b = 0; - Surface *newSurf = new Surface; - assert(newSurf); - newSurf->create(info.width, info.height, format); - assert(newSurf->pixels); - byte *curPixel = (byte *)newSurf->pixels + (newSurf->h - 1) * newSurf->pitch; - int pitchAdd = info.width % 4; - for (int i = 0; i < newSurf->h; ++i) { - for (int i2 = 0; i2 < newSurf->w; ++i2) { - b = stream.readByte(); - g = stream.readByte(); - r = stream.readByte(); - - if (format.bytesPerPixel == 2) - *((uint16 *)curPixel) = format.RGBToColor(r, g, b); - else - *((uint32 *)curPixel) = format.RGBToColor(r, g, b); - - curPixel += format.bytesPerPixel; - } - stream.seek(pitchAdd, SEEK_CUR); - curPixel -= newSurf->pitch * 2; - } - - stream.seek(0); - return newSurf; -} - -#pragma mark - - -Surface *ImageDecoder::loadFile(const Common::String &name, const PixelFormat &format) { - Surface *newSurf = 0; - - Common::File imageFile; - if (imageFile.open(name)) { - newSurf = loadFile(imageFile, format); - } - - return newSurf; -} - -Surface *ImageDecoder::loadFile(Common::SeekableReadStream &stream, const PixelFormat &format) { - // TODO: implement support for bzipped memory - - // FIXME: this is not a very nice solution but it should work - // for the moment, we should use a different way to get all - // decoders - static BMPDecoder bmpDecoder; - static ImageDecoder *decoderList[] = { - &bmpDecoder, // for uncompressed .BMP files - 0 - }; - - ImageDecoder *decoder = 0; - for (int i = 0; decoderList[i] != 0; ++i) { - if (decoderList[i]->decodeable(stream)) { - decoder = decoderList[i]; - break; - } - } - - if (!decoder) - return 0; - - return decoder->decodeImage(stream, format); -} -} // End of namespace Graphics diff --git a/graphics/module.mk b/graphics/module.mk index 2240b4b12d6..c359ba10913 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -18,6 +18,8 @@ MODULE_OBJS := \ VectorRendererSpec.o \ yuv_to_rgb.o \ yuva_to_rgba.o \ + decoders/bmp.o \ + decoders/jpeg.o \ pixelbuffer.o \ tinygl/api.o \ tinygl/arrays.o \ diff --git a/graphics/surface.cpp b/graphics/surface.cpp index 79a7821feb1..fcd702241ab 100644 --- a/graphics/surface.cpp +++ b/graphics/surface.cpp @@ -20,6 +20,7 @@ */ #include "common/algorithm.h" +#include "common/endian.h" #include "common/util.h" #include "common/rect.h" #include "common/textconsole.h" @@ -270,4 +271,82 @@ void Surface::move(int dx, int dy, int height) { } } +Graphics::Surface *Surface::convertTo(const PixelFormat &dstFormat, const byte *palette) const { + assert(pixels); + + Graphics::Surface *surface = new Graphics::Surface(); + + // If the target format is the same, just copy + if (format == dstFormat) { + surface->copyFrom(*this); + return surface; + } + + if (format.bytesPerPixel == 0 || format.bytesPerPixel > 4) + error("Surface::convertTo(): Can only convert from 1Bpp, 2Bpp, 3Bpp, and 4Bpp"); + + if (dstFormat.bytesPerPixel != 2 && dstFormat.bytesPerPixel != 4) + error("Surface::convertTo(): Can only convert to 2Bpp and 4Bpp"); + + surface->create(w, h, dstFormat); + + if (format.bytesPerPixel == 1) { + // Converting from paletted to high color + assert(palette); + + for (int y = 0; y < h; y++) { + const byte *srcRow = (byte *)getBasePtr(0, y); + byte *dstRow = (byte *)surface->getBasePtr(0, y); + + for (int x = 0; x < w; x++) { + byte index = *srcRow++; + byte r = palette[index * 3]; + byte g = palette[index * 3 + 1]; + byte b = palette[index * 3 + 2]; + + uint32 color = dstFormat.RGBToColor(r, g, b); + + if (dstFormat.bytesPerPixel == 2) + *((uint16 *)dstRow) = color; + else + *((uint32 *)dstRow) = color; + + dstRow += dstFormat.bytesPerPixel; + } + } + } else { + // Converting from high color to high color + for (int y = 0; y < h; y++) { + const byte *srcRow = (byte *)getBasePtr(0, y); + byte *dstRow = (byte *)surface->getBasePtr(0, y); + + for (int x = 0; x < w; x++) { + uint32 srcColor; + if (format.bytesPerPixel == 2) + srcColor = READ_UINT16(srcRow); + else if (format.bytesPerPixel == 3) + srcColor = READ_UINT24(srcRow); + else + srcColor = READ_UINT32(srcRow); + + srcRow += format.bytesPerPixel; + + // Convert that color to the new format + byte r, g, b, a; + format.colorToARGB(srcColor, a, r, g, b); + uint32 color = dstFormat.ARGBToColor(a, r, g, b); + + if (dstFormat.bytesPerPixel == 2) + *((uint16 *)dstRow) = color; + else + *((uint32 *)dstRow) = color; + + dstRow += dstFormat.bytesPerPixel; + } + } + } + + return surface; +} + } // End of namespace Graphics diff --git a/graphics/surface.h b/graphics/surface.h index 018a283aad8..eb8d1ac42eb 100644 --- a/graphics/surface.h +++ b/graphics/surface.h @@ -134,6 +134,17 @@ struct Surface { */ void copyFrom(const Surface &surf); + /** + * Convert the data to another pixel format. + * + * The calling code must call free on the returned surface and then delete + * it. + * + * @param dstFormat The desired format + * @param palette The palette (in RGB888), if the source format has a Bpp of 1 + */ + Graphics::Surface *convertTo(const PixelFormat &dstFormat, const byte *palette = 0) const; + /** * Draw a line. * diff --git a/graphics/yuv_to_rgb.cpp b/graphics/yuv_to_rgb.cpp index feda48bf6da..ac7f217feea 100644 --- a/graphics/yuv_to_rgb.cpp +++ b/graphics/yuv_to_rgb.cpp @@ -198,6 +198,52 @@ namespace Graphics { L = &rgbToPix[(s)]; \ *((PixelInt *)(d)) = (L[cr_r] | L[crb_g] | L[cb_b]) +template +void convertYUV444ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { + // Keep the tables in pointers here to avoid a dereference on each pixel + const int16 *Cr_r_tab = lookup->_colorTab; + const int16 *Cr_g_tab = Cr_r_tab + 256; + const int16 *Cb_g_tab = Cr_g_tab + 256; + const int16 *Cb_b_tab = Cb_g_tab + 256; + const uint32 *rgbToPix = lookup->_rgbToPix; + + for (int h = 0; h < yHeight; h++) { + for (int w = 0; w < yWidth; w++) { + register const uint32 *L; + + int16 cr_r = Cr_r_tab[*vSrc]; + int16 crb_g = Cr_g_tab[*vSrc] + Cb_g_tab[*uSrc]; + int16 cb_b = Cb_b_tab[*uSrc]; + ++uSrc; + ++vSrc; + + PUT_PIXEL(*ySrc, dstPtr); + ySrc++; + dstPtr += sizeof(PixelInt); + } + + dstPtr += dstPitch - yWidth * sizeof(PixelInt); + ySrc += yPitch - yWidth; + uSrc += uvPitch - yWidth; + vSrc += uvPitch - yWidth; + } +} + +void convertYUV444ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { + // Sanity checks + assert(dst && dst->pixels); + assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4); + assert(ySrc && uSrc && vSrc); + + const YUVToRGBLookup *lookup = YUVToRGBMan.getLookup(dst->format); + + // Use a templated function to avoid an if check on every pixel + if (dst->format.bytesPerPixel == 2) + convertYUV444ToRGB((byte *)dst->pixels, dst->pitch, lookup, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); + else + convertYUV444ToRGB((byte *)dst->pixels, dst->pitch, lookup, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); +} + template void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { int halfHeight = yHeight >> 1; diff --git a/graphics/yuv_to_rgb.h b/graphics/yuv_to_rgb.h index 259ba098105..8e025042dcf 100644 --- a/graphics/yuv_to_rgb.h +++ b/graphics/yuv_to_rgb.h @@ -23,6 +23,7 @@ /** * @file * YUV to RGB conversion used in engines: + * - mohawk * - scumm (he) * - sword25 */ @@ -35,6 +36,20 @@ namespace Graphics { +/** + * Convert a YUV444 image to an RGB surface + * + * @param dst the destination surface + * @param ySrc the source of the y component + * @param uSrc the source of the u component + * @param vSrc the source of the v component + * @param yWidth the width of the y surface + * @param yHeight the height of the y surface + * @param yPitch the pitch of the y surface + * @param uvPitch the pitch of the u and v surfaces + */ +void convertYUV444ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch); + /** * Convert a YUV420 image to an RGB surface * diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index ba77629b295..4261e230e5a 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -30,11 +30,11 @@ #include "graphics/cursorman.h" #include "graphics/fontman.h" -#include "graphics/imagedec.h" #include "graphics/surface.h" #include "graphics/VectorRenderer.h" #include "graphics/fonts/bdf.h" #include "graphics/fonts/ttf.h" +#include "graphics/decoders/bmp.h" #include "gui/widget.h" #include "gui/ThemeEngine.h" @@ -620,20 +620,25 @@ bool ThemeEngine::addBitmap(const Common::String &filename) { if (surf) return true; - // If not, try to load the bitmap via the ImageDecoder class. + // If not, try to load the bitmap via the BitmapDecoder class. + Graphics::BitmapDecoder bitmapDecoder; + const Graphics::Surface *srcSurface = 0; Common::ArchiveMemberList members; _themeFiles.listMatchingMembers(members, filename); for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) { Common::SeekableReadStream *stream = (*i)->createReadStream(); if (stream) { - surf = Graphics::ImageDecoder::loadFile(*stream, _overlayFormat); + bitmapDecoder.loadStream(*stream); + srcSurface = bitmapDecoder.getSurface(); delete stream; - - if (surf) + if (srcSurface) break; } } + if (srcSurface && srcSurface->format.bytesPerPixel != 1) + surf = srcSurface->convertTo(_overlayFormat); + // Store the surface into our hashmap (attention, may store NULL entries!) _bitmaps[filename] = surf; diff --git a/gui/debugger.cpp b/gui/debugger.cpp index 26e62dc1d9a..972163df6fd 100644 --- a/gui/debugger.cpp +++ b/gui/debugger.cpp @@ -200,9 +200,8 @@ void Debugger::enter() { bool Debugger::handleCommand(int argc, const char **argv, bool &result) { if (_cmds.contains(argv[0])) { - Debuglet *debuglet = _cmds[argv[0]].get(); - assert(debuglet); - result = (*debuglet)(argc, argv); + assert(_cmds[argv[0]]); + result = (*_cmds[argv[0]])(argc, argv); return true; } diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 0522b40b46b..2201e83ca54 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -21,6 +21,10 @@ #include "common/rect.h" +#ifdef ENABLE_KEYMAPPER +#include "common/events.h" +#endif + #include "gui/gui-manager.h" #include "gui/dialog.h" #include "gui/widget.h" @@ -314,6 +318,9 @@ void Dialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { } } +#ifdef ENABLE_KEYMAPPER +void Dialog::handleOtherEvent(Common::Event evt) { } +#endif /* * Determine the widget at location (x,y) if any. Assumes the coordinates are * in the local coordinate system, i.e. relative to the top left of the dialog. @@ -334,25 +341,7 @@ void Dialog::removeWidget(Widget *del) { if (del == _dragWidget) _dragWidget = NULL; - Widget *w = _firstWidget; - - if (del == _firstWidget) { - Widget *del_next = del->_next; - del->_next = 0; - _firstWidget = del_next; - return; - } - - w = _firstWidget; - while (w) { - if (w->_next == del) { - Widget *del_next = del->_next; - del->_next = 0; - w->_next = del_next; - return; - } - w = w->_next; - } + GuiObject::removeWidget(del); } } // End of namespace GUI diff --git a/gui/dialog.h b/gui/dialog.h index a324450996a..f5a5f94a68b 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -29,6 +29,12 @@ #include "gui/object.h" #include "gui/ThemeEngine.h" +#ifdef ENABLE_KEYMAPPER +namespace Common { +struct Event; +} +#endif + namespace GUI { class Widget; @@ -82,6 +88,9 @@ protected: virtual void handleKeyUp(Common::KeyState state); virtual void handleMouseMoved(int x, int y, int button); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); +#ifdef ENABLE_KEYMAPPER + virtual void handleOtherEvent(Common::Event evt); +#endif Widget *findWidget(int x, int y); // Find the widget at pos x,y if any Widget *findWidget(const char *name); diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index 4b8b9d0bf1f..15ff0c84741 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -188,7 +188,7 @@ bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx, } // refresh all dialogs - for (int i = 0; i < _dialogStack.size(); ++i) + for (DialogStack::size_type i = 0; i < _dialogStack.size(); ++i) _dialogStack[i]->reflowLayout(); // We need to redraw immediately. Otherwise @@ -202,7 +202,6 @@ bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx, } void GuiManager::redraw() { - int i; ThemeEngine::ShadingStyle shading; if (_redrawStatus == kRedrawDisabled || _dialogStack.empty()) @@ -223,7 +222,7 @@ void GuiManager::redraw() { _theme->clearAll(); _theme->openDialog(true, ThemeEngine::kShadingNone); - for (i = 0; i < _dialogStack.size() - 1; i++) + for (DialogStack::size_type i = 0; i < _dialogStack.size() - 1; i++) _dialogStack[i]->drawDialog(); _theme->finishBuffering(); @@ -367,6 +366,9 @@ void GuiManager::runLoop() { screenChange(); break; default: +#ifdef ENABLE_KEYMAPPER + activeDialog->handleOtherEvent(event); +#endif break; } @@ -515,7 +517,7 @@ void GuiManager::screenChange() { _theme->refresh(); // refresh all dialogs - for (int i = 0; i < _dialogStack.size(); ++i) { + for (DialogStack::size_type i = 0; i < _dialogStack.size(); ++i) { _dialogStack[i]->reflowLayout(); } // We need to redraw immediately. Otherwise diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 542b7662d2e..f2184b072a4 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -24,6 +24,7 @@ #include "common/config-manager.h" #include "common/events.h" #include "common/fs.h" +#include "common/gui_options.h" #include "common/util.h" #include "common/system.h" #include "common/translation.h" diff --git a/gui/object.cpp b/gui/object.cpp index 2ec42df9d72..73c4f74d6c2 100644 --- a/gui/object.cpp +++ b/gui/object.cpp @@ -59,4 +59,24 @@ void GuiObject::reflowLayout() { } } +void GuiObject::removeWidget(Widget *del) { + if (del == _firstWidget) { + Widget *del_next = del->next(); + del->setNext(0); + _firstWidget = del_next; + return; + } + + Widget *w = _firstWidget; + while (w) { + if (w->next() == del) { + Widget *del_next = del->next(); + del->setNext(0); + w->setNext(del_next); + return; + } + w = w->next(); + } +} + } // End of namespace GUI diff --git a/gui/object.h b/gui/object.h index 34ff0d47f22..bce3cd7846b 100644 --- a/gui/object.h +++ b/gui/object.h @@ -83,6 +83,8 @@ public: virtual void reflowLayout(); + virtual void removeWidget(Widget *widget); + protected: virtual void releaseFocus() = 0; }; diff --git a/gui/options.cpp b/gui/options.cpp index b8276d0a372..34deb1e92dd 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -30,6 +30,8 @@ #include "common/fs.h" #include "common/config-manager.h" +#include "common/gui_options.h" +#include "common/rendermode.h" #include "common/system.h" #include "common/textconsole.h" #include "common/translation.h" @@ -79,7 +81,7 @@ static const char *outputRateLabels[] = { _s(""), _s("8 kHz"), _s("11kH static const int outputRateValues[] = { 0, 8000, 11025, 22050, 44100, 48000, -1 }; OptionsDialog::OptionsDialog(const Common::String &domain, int x, int y, int w, int h) - : Dialog(x, y, w, h), _domain(domain), _graphicsTabId(-1), _tabWidget(0) { + : Dialog(x, y, w, h), _domain(domain), _graphicsTabId(-1), _midiTabId(-1), _pathsTabId(-1), _tabWidget(0) { init(); } @@ -901,7 +903,7 @@ bool OptionsDialog::loadMusicDeviceSetting(PopUpWidget *popup, Common::String se for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { if (setting.empty() ? (preferredType == d->getMusicType()) : (drv == d->getCompleteId())) { popup->setSelectedTag(d->getHandle()); - return popup->getSelected() == -1 ? false : true; + return popup->getSelected() != -1; } } } @@ -931,30 +933,6 @@ void OptionsDialog::saveMusicDeviceSetting(PopUpWidget *popup, Common::String se ConfMan.removeKey(setting, _domain); } -Common::String OptionsDialog::renderType2GUIO(uint32 renderType) { - static const struct { - Common::RenderMode type; - const char *guio; - } renderGUIOMapping[] = { - { Common::kRenderHercG, GUIO_RENDERHERCGREEN }, - { Common::kRenderHercA, GUIO_RENDERHERCAMBER }, - { Common::kRenderCGA, GUIO_RENDERCGA }, - { Common::kRenderEGA, GUIO_RENDEREGA }, - { Common::kRenderVGA, GUIO_RENDERVGA }, - { Common::kRenderAmiga, GUIO_RENDERAMIGA }, - { Common::kRenderFMTowns, GUIO_RENDERFMTOWNS }, - { Common::kRenderPC98, GUIO_RENDERPC98 } - }; - Common::String res; - - for (int i = 0; i < ARRAYSIZE(renderGUIOMapping); i++) { - if (renderType == renderGUIOMapping[i].type || renderType == (uint32)-1) - res += renderGUIOMapping[i].guio; - } - - return res; -} - int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) { if (_guioptions.contains(GUIO_NOSUBTITLES)) return kSubtitlesSpeech; // Speech only @@ -1012,7 +990,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() // // 3) The MIDI tab // - tab->addTab(_("MIDI")); + _midiTabId = tab->addTab(_("MIDI")); addMIDIControls(tab, "GlobalOptions_MIDI."); // @@ -1025,9 +1003,9 @@ GlobalOptionsDialog::GlobalOptionsDialog() // 5) The Paths tab // if (g_system->getOverlayWidth() > 320) - tab->addTab(_("Paths")); + _pathsTabId = tab->addTab(_("Paths")); else - tab->addTab(_c("Paths", "lowres")); + _pathsTabId = tab->addTab(_c("Paths", "lowres")); #if !( defined(__DC__) || defined(__GP32__) ) // These two buttons have to be extra wide, or the text will be @@ -1386,4 +1364,39 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 } } +void GlobalOptionsDialog::reflowLayout() { + int activeTab = _tabWidget->getActiveTab(); + + if (_midiTabId != -1) { + _tabWidget->setActiveTab(_midiTabId); + + _tabWidget->removeWidget(_soundFontClearButton); + _soundFontClearButton->setNext(0); + delete _soundFontClearButton; + _soundFontClearButton = addClearButton(_tabWidget, "GlobalOptions_MIDI.mcFontClearButton", kClearSoundFontCmd); + } + + if (_pathsTabId != -1) { + _tabWidget->setActiveTab(_pathsTabId); + + _tabWidget->removeWidget(_savePathClearButton); + _savePathClearButton->setNext(0); + delete _savePathClearButton; + _savePathClearButton = addClearButton(_tabWidget, "GlobalOptions_Paths.SavePathClearButton", kSavePathClearCmd); + + _tabWidget->removeWidget(_themePathClearButton); + _themePathClearButton->setNext(0); + delete _themePathClearButton; + _themePathClearButton = addClearButton(_tabWidget, "GlobalOptions_Paths.ThemePathClearButton", kThemePathClearCmd); + + _tabWidget->removeWidget(_extraPathClearButton); + _extraPathClearButton->setNext(0); + delete _extraPathClearButton; + _extraPathClearButton = addClearButton(_tabWidget, "GlobalOptions_Paths.ExtraPathClearButton", kExtraPathClearCmd); + } + + _tabWidget->setActiveTab(activeTab); + OptionsDialog::reflowLayout(); +} + } // End of namespace GUI diff --git a/gui/options.h b/gui/options.h index f8434b6f1a6..894c5a8e9f1 100644 --- a/gui/options.h +++ b/gui/options.h @@ -85,10 +85,10 @@ protected: bool loadMusicDeviceSetting(PopUpWidget *popup, Common::String setting, MusicType preferredType = MT_AUTO); void saveMusicDeviceSetting(PopUpWidget *popup, Common::String setting); - Common::String renderType2GUIO(uint32 renderType); - TabWidget *_tabWidget; int _graphicsTabId; + int _midiTabId; + int _pathsTabId; private: // @@ -193,6 +193,8 @@ public: void close(); void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); + virtual void reflowLayout(); + protected: #ifdef SMALL_SCREEN_DEVICE KeysDialog *_keysDialog; diff --git a/gui/themes/modern.zip b/gui/themes/modern.zip index 0c3e7b1064aed32af2098f17207ea6b03ffeeac1..5fab1527febbeb83d03c8e4c895e8a58c2fefe43 100644 GIT binary patch delta 28514 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 @@ -687,6 +687,7 @@ radius = '5' fg_color = 'paleyellow' shadow = '0' + stroke = '1' bevel = '1' bevel_color = 'shadowcolor' /> diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp index af8ab8aa5bd..4b266e81944 100644 --- a/gui/widgets/edittext.cpp +++ b/gui/widgets/edittext.cpp @@ -33,6 +33,7 @@ EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, cons _finishCmd = finishCmd; setEditString(text); + setFontStyle(ThemeEngine::kFontStyleNormal); } EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String &text, const char *tooltip, uint32 cmd, uint32 finishCmd) @@ -42,6 +43,7 @@ EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String _finishCmd = finishCmd; setEditString(text); + setFontStyle(ThemeEngine::kFontStyleNormal); } void EditTextWidget::setEditString(const String &str) { diff --git a/test/common/memoryreadstream.h b/test/common/memoryreadstream.h index a476f12a2fc..adef861a5e3 100644 --- a/test/common/memoryreadstream.h +++ b/test/common/memoryreadstream.h @@ -84,4 +84,20 @@ class MemoryReadStreamTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS(ms.pos(), 7); TS_ASSERT(!ms.eos()); } + + void test_eos() { + byte contents[] = { 1, 2, 3, 4, 5, 6, 7 }; + Common::MemoryReadStream ms(contents, sizeof(contents)); + + // Read after the end of the stream + for (int32 i = 0; i <= ms.size(); ++i) + ms.readByte(); + + // The eos flag should be set here + TS_ASSERT(ms.eos()); + + // Seeking should reset the eos flag + ms.seek(0, SEEK_SET); + TS_ASSERT(!ms.eos()); + } }; diff --git a/test/common/subreadstream.h b/test/common/subreadstream.h index 463f49e9295..32e6f938d2b 100644 --- a/test/common/subreadstream.h +++ b/test/common/subreadstream.h @@ -26,4 +26,22 @@ class SubReadStreamTestSuite : public CxxTest::TestSuite { b = srs.readByte(); TS_ASSERT(srs.eos()); } + + void test_safe_eos() { + byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + Common::MemoryReadStream ms(contents, sizeof(contents)); + + Common::SafeSeekableSubReadStream ssrs1(&ms, 0, sizeof(contents)); + Common::SafeSeekableSubReadStream ssrs2(&ms, 0, sizeof(contents)); + + // Read after the end of the stream of the first sub stream + for (int32 i = 0; i <= ssrs1.size(); ++i) + ssrs1.readByte(); + + // eos should be set for the first sub stream + TS_ASSERT(ssrs1.eos()); + + // eos should not be set for the second sub stream + TS_ASSERT(!ssrs2.eos()); + } };