mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-22 18:02:05 +00:00
Last part of patch #1163026 (Thumbnails for ScummEngine)
svn-id: r17982
This commit is contained in:
parent
20c8944189
commit
c33cc2ce85
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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 \
|
||||
|
@ -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)),
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
129
scumm/thumbnail.cpp
Normal file
129
scumm/thumbnail.cpp
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user