aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorMax Horn2005-05-09 00:09:01 +0000
committerMax Horn2005-05-09 00:09:01 +0000
commitc33cc2ce85dea20cd0eb749a06276d12ff31956c (patch)
tree1526599eb4dd8c0e6a4479b3e19f77a53a6af0ab /scumm
parent20c8944189941dbf0286afc28b361f7bb4e09e74 (diff)
downloadscummvm-rg350-c33cc2ce85dea20cd0eb749a06276d12ff31956c.tar.gz
scummvm-rg350-c33cc2ce85dea20cd0eb749a06276d12ff31956c.tar.bz2
scummvm-rg350-c33cc2ce85dea20cd0eb749a06276d12ff31956c.zip
Last part of patch #1163026 (Thumbnails for ScummEngine)
svn-id: r17982
Diffstat (limited to 'scumm')
-rw-r--r--scumm/dialogs.cpp124
-rw-r--r--scumm/dialogs.h17
-rw-r--r--scumm/module.mk3
-rw-r--r--scumm/saveload.cpp43
-rw-r--r--scumm/saveload.h2
-rw-r--r--scumm/scumm.h12
-rw-r--r--scumm/thumbnail.cpp129
7 files changed, 320 insertions, 10 deletions
diff --git a/scumm/dialogs.cpp b/scumm/dialogs.cpp
index e77142a073..6f92e75359 100644
--- a/scumm/dialogs.cpp
+++ b/scumm/dialogs.cpp
@@ -22,6 +22,7 @@
#include "common/config-manager.h"
#include "common/system.h"
+#include "common/scaler.h"
#include "gui/chooser.h"
#include "gui/newgui.h"
@@ -147,7 +148,6 @@ static ResString string_map_table_v5[] = {
#pragma mark -
-
const Common::String ScummDialog::queryResString(int stringno) {
byte buf[256];
byte *result;
@@ -199,7 +199,7 @@ enum {
kQuitCmd = 'QUIT'
};
-class SaveLoadChooser : public GUI::ChooserDialog {
+class SaveLoadChooser : public GUI::ChooserDialog, public BaseSaveLoadChooser {
typedef Common::String String;
typedef Common::StringList StringList;
protected:
@@ -210,6 +210,8 @@ public:
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
const String &getResultString() const;
+ void setList(const StringList& list) { GUI::ChooserDialog::setList(list); }
+ int runModal() { return GUI::ChooserDialog::runModal(); }
};
SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode)
@@ -250,6 +252,115 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da
}
}
+#pragma mark -
+
+enum {
+ kChooseCmd = 'Chos'
+};
+
+// only for use with >= 640x400 resolutions
+class SaveLoadChooserEx : public GUI::Dialog, public BaseSaveLoadChooser {
+ typedef Common::String String;
+ typedef Common::StringList StringList;
+protected:
+ bool _saveMode;
+ GUI::ListWidget *_list;
+ GUI::ButtonWidget *_chooseButton;
+ GUI::GraphicsWidget *_gfxWidget;
+ ScummEngine *_scumm;
+
+public:
+ SaveLoadChooserEx(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine);
+
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+ const String &getResultString() const;
+ void setList(const StringList& list);
+ int runModal();
+
+ bool wantsScaling() const { return false; }
+};
+
+SaveLoadChooserEx::SaveLoadChooserEx(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine)
+ : Dialog(8, 8, engine->_system->getOverlayWidth() - 2 * 8, engine->_system->getOverlayHeight() - 16), _saveMode(saveMode), _list(0), _chooseButton(0), _gfxWidget(0), _scumm(engine) {
+
+ new StaticTextWidget(this, 10, 6, _w - 2 * 10, kLineHeight, title, kTextAlignCenter);
+
+ // Add choice list
+ _list = new GUI::ListWidget(this, 10, 18, _w - 2 * 10 - 180, _h - 14 - 24 - 10);
+ _list->setEditable(saveMode);
+ _list->setNumberingMode(saveMode ? GUI::kListNumberingOne : GUI::kListNumberingZero);
+
+ // Add the thumbnail display
+ _gfxWidget = new GUI::GraphicsWidget(this,
+ _w - (kThumbnailWidth + 22),
+ 18,
+ kThumbnailWidth + 8,
+ ((_scumm->_system->getHeight() % 200 && _scumm->_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1) + 8);
+ _gfxWidget->setFlags(GUI::WIDGET_BORDER);
+
+ // Buttons
+ addButton(_w - 2 * (kButtonWidth + 10), _h - 24, "Cancel", kCloseCmd, 0);
+ _chooseButton = addButton(_w-(kButtonWidth + 10), _h - 24, buttonLabel, kChooseCmd, 0);
+ _chooseButton->setEnabled(false);
+}
+
+const Common::String &SaveLoadChooserEx::getResultString() const {
+ return _list->getSelectedString();
+}
+
+void SaveLoadChooserEx::setList(const StringList& list) {
+ _list->setList(list);
+}
+
+int SaveLoadChooserEx::runModal() {
+ _gfxWidget->setGfx(0);
+ int ret = GUI::Dialog::runModal();
+ return ret;
+}
+
+void SaveLoadChooserEx::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ int selItem = _list->getSelected();
+ switch (cmd) {
+ case GUI::kListItemActivatedCmd:
+ case GUI::kListItemDoubleClickedCmd:
+ if (selItem >= 0) {
+ if (_saveMode || !getResultString().isEmpty()) {
+ _list->endEditMode();
+ setResult(selItem);
+ close();
+ }
+ }
+ break;
+ case kChooseCmd:
+ _list->endEditMode();
+ setResult(selItem);
+ close();
+ break;
+ case GUI::kListSelectionChangedCmd: {
+ const Graphics::Surface *thumb;
+ thumb = _scumm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem);
+ _gfxWidget->setGfx(thumb);
+ delete thumb;
+ _gfxWidget->draw();
+
+ if (_saveMode) {
+ _list->startEditMode();
+ }
+ // Disable button if nothing is selected, or (in load mode) if an empty
+ // list item is selected. We allow choosing an empty item in save mode
+ // because we then just assign a default name.
+ _chooseButton->setEnabled(selItem >= 0 && (_saveMode || !getResultString().isEmpty()));
+ _chooseButton->draw();
+ } break;
+ case kCloseCmd:
+ setResult(-1);
+ default:
+ GUI::Dialog::handleCommand(sender, cmd, data);
+ }
+}
+
+#pragma mark -
+
Common::StringList generateSavegameList(ScummEngine *scumm, bool saveMode) {
// Get savegame names
Common::StringList l;
@@ -308,8 +419,13 @@ MainMenuDialog::MainMenuDialog(ScummEngine *scumm)
#ifndef DISABLE_HELP
_helpDialog = new HelpDialog(scumm);
#endif
- _saveDialog = new SaveLoadChooser("Save game:", "Save", true);
- _loadDialog = new SaveLoadChooser("Load game:", "Load", false);
+ if (scumm->_system->getOverlayWidth() <= 320) {
+ _saveDialog = new SaveLoadChooser("Save game:", "Save", true);
+ _loadDialog = new SaveLoadChooser("Load game:", "Load", false);
+ } else {
+ _saveDialog = new SaveLoadChooserEx("Save game:", "Save", true, scumm);
+ _loadDialog = new SaveLoadChooserEx("Load game:", "Load", false, scumm);
+ }
}
MainMenuDialog::~MainMenuDialog() {
diff --git a/scumm/dialogs.h b/scumm/dialogs.h
index 158e599fb7..5913686ae4 100644
--- a/scumm/dialogs.h
+++ b/scumm/dialogs.h
@@ -54,7 +54,18 @@ protected:
const String queryResString(int stringno);
};
-class SaveLoadChooser;
+// to have a base for all different Save/Load Choosers
+// currently only for SaveLoadChooser (320x200)
+// and for SaveLoadChooserEx (640x400/640x480)
+class BaseSaveLoadChooser
+{
+public:
+ virtual ~BaseSaveLoadChooser() {};
+
+ virtual const Common::String &getResultString() const = 0;
+ virtual void setList(const Common::StringList& list) = 0;
+ virtual int runModal() = 0;
+};
class MainMenuDialog : public ScummDialog {
public:
@@ -68,8 +79,8 @@ protected:
#ifndef DISABLE_HELP
GUI::Dialog *_helpDialog;
#endif
- SaveLoadChooser *_saveDialog;
- SaveLoadChooser *_loadDialog;
+ BaseSaveLoadChooser *_saveDialog;
+ BaseSaveLoadChooser *_loadDialog;
void save();
void load();
diff --git a/scumm/module.mk b/scumm/module.mk
index 16d28947fc..98fce55c52 100644
--- a/scumm/module.mk
+++ b/scumm/module.mk
@@ -79,7 +79,8 @@ MODULE_OBJS := \
scumm/smush/smush_player.o \
scumm/smush/saud_channel.o \
scumm/smush/smush_mixer.o \
- scumm/smush/smush_font.o
+ scumm/smush/smush_font.o \
+ scumm/thumbnail.o
MODULE_DIRS += \
scumm \
diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp
index 406db2f37a..8dc0039969 100644
--- a/scumm/saveload.cpp
+++ b/scumm/saveload.cpp
@@ -83,6 +83,7 @@ bool ScummEngine::saveState(int slot, bool compat) {
hdr.ver = TO_LE_32(CURRENT_VER);
out->write(&hdr, sizeof(hdr));
+ saveThumbnail(out);
Serializer ser(0, out, CURRENT_VER);
saveOrLoad(&ser, CURRENT_VER);
@@ -126,6 +127,18 @@ bool ScummEngine::loadState(int slot, bool compat) {
delete in;
return false;
}
+
+ // Sine version 52 a thumbnail is saved directly after the header
+ if (hdr.ver >= VER(52)) {
+ uint32 type = in->readUint32BE();
+ if (type != MKID('THMB')) {
+ warning("Can not load thumbnail");
+ delete in;
+ return false;
+ }
+ uint32 size = in->readUint32BE();
+ in->skip(size - 8);
+ }
// Due to a bug in scummvm up to and including 0.3.0, save games could be saved
// in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here
@@ -387,6 +400,36 @@ bool ScummEngine::getSavegameName(int slot, char *desc) {
return true;
}
+Graphics::Surface *ScummEngine::loadThumbnailFromSlot(int slot) {
+ char filename[256];
+ InSaveFile *in;
+ SaveGameHeader hdr;
+ int len;
+
+ makeSavegameName(filename, slot, false);
+ if (!(in = _saveFileMan->openForLoading(filename))) {
+ return 0;
+ }
+ len = in->read(&hdr, sizeof(hdr));
+
+ if (len != sizeof(hdr) || hdr.type != MKID('SCVM')) {
+ delete in;
+ return 0;
+ }
+
+ if (hdr.ver > CURRENT_VER)
+ hdr.ver = TO_LE_32(hdr.ver);
+ if (hdr.ver < VER(52)) {
+ delete in;
+ return 0;
+ }
+
+ Graphics::Surface *thumb = loadThumbnail(in);
+
+ delete in;
+ return thumb;
+}
+
void ScummEngine::saveOrLoad(Serializer *s, uint32 savegameVersion) {
const SaveLoadEntry objectEntries[] = {
MKLINE(ObjectData, OBIMoffset, sleUint32, VER(8)),
diff --git a/scumm/saveload.h b/scumm/saveload.h
index 046813867d..79cfb43cef 100644
--- a/scumm/saveload.h
+++ b/scumm/saveload.h
@@ -43,7 +43,7 @@ namespace Scumm {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
-#define CURRENT_VER 51
+#define CURRENT_VER 52
/**
* An auxillary macro, used to specify savegame versions. We use this instead
diff --git a/scumm/scumm.h b/scumm/scumm.h
index 7ff3d5fc12..91fc9b5901 100644
--- a/scumm/scumm.h
+++ b/scumm/scumm.h
@@ -27,6 +27,7 @@
#include "common/file.h"
#include "common/rect.h"
#include "common/str.h"
+#include "graphics/surface.h"
#include "scumm/gfx.h"
#include "scumm/script.h"
@@ -36,7 +37,8 @@ namespace GUI {
}
using GUI::Dialog;
class GameDetector;
-
+class InSaveFile;
+class OutSaveFile;
namespace Scumm {
@@ -579,6 +581,14 @@ public:
void requestSave(int slot, const char *name, bool temporary = false);
void requestLoad(int slot);
+// thumbnail stuff
+public:
+ Graphics::Surface *loadThumbnailFromSlot(int slot);
+
+protected:
+ Graphics::Surface *loadThumbnail(InSaveFile *file);
+ void saveThumbnail(OutSaveFile *file);
+
protected:
/* Script VM - should be in Script class */
uint32 _localScriptOffsets[1024];
diff --git a/scumm/thumbnail.cpp b/scumm/thumbnail.cpp
new file mode 100644
index 0000000000..dbe21698ed
--- /dev/null
+++ b/scumm/thumbnail.cpp
@@ -0,0 +1,129 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2005 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed file the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/savefile.h"
+#include "common/scaler.h"
+#include "scumm.h"
+
+namespace Scumm {
+
+#define THMB_VERSION 1
+
+#if !defined(__GNUC__)
+ #pragma START_PACK_STRUCTS
+#endif
+
+struct ThumbnailHeader {
+ uint32 type;
+ uint32 size;
+ byte version;
+ uint16 width, height;
+ byte bpp;
+} GCC_PACK;
+
+#if !defined(__GNUC__)
+ #pragma END_PACK_STRUCTS
+#endif
+
+
+inline void colorToRGB(uint16 color, uint8 &r, uint8 &g, uint8 &b) {
+ r = (((color >> 11) & 0x1F) << 3);
+ g = (((color >> 5) & 0x3F) << 2);
+ b = ((color&0x1F) << 3);
+}
+
+Graphics::Surface *ScummEngine::loadThumbnail(InSaveFile *file) {
+ ThumbnailHeader header;
+ header.type = file->readUint32BE();
+ if (header.type != MKID('THMB'))
+ return 0;
+
+ header.size = file->readUint32BE();
+ header.version = file->readByte();
+
+ if (header.version > THMB_VERSION) {
+ file->skip(header.size - 9);
+ warning("Loading a newer thumbnail version");
+ return 0;
+ }
+
+ header.width = file->readUint16BE();
+ header.height = file->readUint16BE();
+ header.bpp = file->readByte();
+
+ // TODO: support other bpp values than 2
+ if (header.bpp != 2) {
+ file->skip(header.size - 14);
+ return 0;
+ }
+
+ Graphics::Surface *thumb = new Graphics::Surface();
+ thumb->create(header.width, header.height, sizeof(uint16));
+
+ uint16* pixels = (uint16 *)thumb->pixels;
+
+ for (int y = 0; y < thumb->h; ++y) {
+ for (int x = 0; x < thumb->w; ++x) {
+ uint8 r, g, b;
+ colorToRGB(file->readUint16BE(), r, g, b);
+
+ // converting to current OSystem Color
+ *pixels++ = _system->RGBToColor(r, g, b);
+ }
+ }
+
+ return thumb;
+}
+
+void ScummEngine::saveThumbnail(OutSaveFile *file) {
+ Graphics::Surface thumb;
+
+ if (!createThumbnailFromScreen(&thumb))
+ thumb.create(kThumbnailWidth, kThumbnailHeight2, sizeof(uint16));
+
+ ThumbnailHeader header;
+ header.type = MKID('THMB');
+ header.size = sizeof(header) + thumb.w*thumb.h*thumb.bytesPerPixel;
+ header.version = THMB_VERSION;
+ header.width = thumb.w;
+ header.height = thumb.h;
+ header.bpp = thumb.bytesPerPixel;
+
+ file->writeUint32BE(header.type);
+ file->writeUint32BE(header.size);
+ file->writeByte(header.version);
+ file->writeUint16BE(header.width);
+ file->writeUint16BE(header.height);
+ file->writeByte(header.bpp);
+
+ // TODO: for later this shouldn't be casted to uint16...
+ uint16* pixels = (uint16 *)thumb.pixels;
+ for (uint16 p = 0; p < thumb.w*thumb.h; ++p, ++pixels)
+ file->writeUint16BE(*pixels);
+
+ thumb.free();
+}
+
+} // end of namespace Scumm