Initial commit
This commit is contained in:
2
engines/prince/POTFILES
Normal file
2
engines/prince/POTFILES
Normal file
@@ -0,0 +1,2 @@
|
||||
engines/prince/metaengine.cpp
|
||||
engines/prince/saveload.cpp
|
||||
177
engines/prince/animation.cpp
Normal file
177
engines/prince/animation.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/animation.h"
|
||||
#include "prince/decompress.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/endian.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
Animation::Animation() : _loopCount(0), _phaseCount(0), _frameCount(0), _baseX(0), _baseY(0)
|
||||
{
|
||||
}
|
||||
|
||||
Animation::~Animation() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void Animation::clear() {
|
||||
_phaseList.clear();
|
||||
for (int i = 0; i < _frameCount; i++) {
|
||||
_frameList[i]._surface->free();
|
||||
delete _frameList[i]._surface;
|
||||
_frameList[i]._surface = nullptr;
|
||||
if (_frameList[i]._compressedData != nullptr) {
|
||||
free(_frameList[i]._compressedData);
|
||||
_frameList[i]._compressedData = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Animation::loadStream(Common::SeekableReadStream &stream) {
|
||||
stream.skip(2); // skip not used x and y coord diff
|
||||
_loopCount = stream.readUint16LE();
|
||||
_phaseCount = stream.readUint16LE();
|
||||
stream.skip(2); // skip _frameCount here
|
||||
_baseX = stream.readUint16LE();
|
||||
_baseY = stream.readUint16LE();
|
||||
uint32 phaseTableOffset = stream.readUint32LE();
|
||||
uint32 tableOfFrameOffsets = stream.pos();
|
||||
|
||||
stream.seek(phaseTableOffset);
|
||||
Phase tempPhase;
|
||||
_frameCount = 0;
|
||||
for (int phase = 0; phase < _phaseCount; phase++) {
|
||||
tempPhase._phaseOffsetX = stream.readSint16LE();
|
||||
tempPhase._phaseOffsetY = stream.readSint16LE();
|
||||
tempPhase._phaseToFrameIndex = stream.readUint16LE();
|
||||
if (tempPhase._phaseToFrameIndex > _frameCount) {
|
||||
_frameCount = tempPhase._phaseToFrameIndex;
|
||||
}
|
||||
_phaseList.push_back(tempPhase);
|
||||
stream.skip(2);
|
||||
}
|
||||
if (_phaseCount) {
|
||||
_frameCount++;
|
||||
}
|
||||
|
||||
Frame tempFrame;
|
||||
for (int frame = 0; frame < _frameCount; frame++) {
|
||||
stream.seek(tableOfFrameOffsets + frame * 4);
|
||||
uint32 frameInfoOffset = stream.readUint32LE();
|
||||
stream.seek(frameInfoOffset);
|
||||
uint16 frameWidth = stream.readUint16LE();
|
||||
uint16 frameHeight = stream.readUint16LE();
|
||||
uint32 frameDataPos = stream.pos();
|
||||
uint32 frameDataOffset = stream.readUint32BE();
|
||||
|
||||
tempFrame._surface = new Graphics::Surface();
|
||||
tempFrame._surface->create(frameWidth, frameHeight, Graphics::PixelFormat::createFormatCLUT8());
|
||||
if (frameDataOffset == MKTAG('m', 'a', 's', 'm')) {
|
||||
tempFrame._isCompressed = true;
|
||||
tempFrame._dataSize = stream.readUint32LE();
|
||||
tempFrame._compressedData = (byte *)malloc(tempFrame._dataSize);
|
||||
stream.read(tempFrame._compressedData, tempFrame._dataSize);
|
||||
} else {
|
||||
tempFrame._isCompressed = false;
|
||||
tempFrame._dataSize = 0;
|
||||
tempFrame._compressedData = nullptr;
|
||||
stream.seek(frameDataPos);
|
||||
for (uint16 i = 0; i < frameHeight; i++) {
|
||||
stream.read(tempFrame._surface->getBasePtr(0, i), frameWidth);
|
||||
}
|
||||
}
|
||||
_frameList.push_back(tempFrame);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int16 Animation::getLoopCount() const {
|
||||
return _loopCount;
|
||||
}
|
||||
|
||||
int32 Animation::getPhaseCount() const {
|
||||
return _phaseCount;
|
||||
}
|
||||
|
||||
int32 Animation::getFrameCount() const {
|
||||
return _frameCount;
|
||||
}
|
||||
|
||||
int16 Animation::getBaseX() const {
|
||||
return _baseX;
|
||||
}
|
||||
|
||||
int16 Animation::getBaseY() const {
|
||||
return _baseY;
|
||||
}
|
||||
|
||||
int16 Animation::getPhaseOffsetX(int phaseIndex) const {
|
||||
if (phaseIndex < _phaseCount) {
|
||||
return _phaseList[phaseIndex]._phaseOffsetX;
|
||||
} else {
|
||||
error("getPhaseOffsetX() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
|
||||
}
|
||||
}
|
||||
|
||||
int16 Animation::getPhaseOffsetY(int phaseIndex) const {
|
||||
if (phaseIndex < _phaseCount) {
|
||||
return _phaseList[phaseIndex]._phaseOffsetY;
|
||||
} else {
|
||||
error("getPhaseOffsetY() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
|
||||
}
|
||||
}
|
||||
|
||||
int16 Animation::getPhaseFrameIndex(int phaseIndex) const {
|
||||
if (phaseIndex < _phaseCount) {
|
||||
return _phaseList[phaseIndex]._phaseToFrameIndex;
|
||||
} else {
|
||||
error("getPhaseFrameIndex() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Surface *Animation::getFrame(int frameIndex) {
|
||||
if (frameIndex < _frameCount) {
|
||||
if (_frameList[frameIndex]._isCompressed) {
|
||||
Decompressor dec;
|
||||
byte *ddata = (byte *)malloc(_frameList[frameIndex]._dataSize);
|
||||
dec.decompress(_frameList[frameIndex]._compressedData, ddata, _frameList[frameIndex]._dataSize);
|
||||
int frameHeight = _frameList[frameIndex]._surface->h;
|
||||
int frameWidth = _frameList[frameIndex]._surface->w;
|
||||
for (uint16 i = 0; i < frameHeight; i++) {
|
||||
memcpy(_frameList[frameIndex]._surface->getBasePtr(0, i), ddata + frameWidth * i, frameWidth);
|
||||
}
|
||||
free(ddata);
|
||||
free(_frameList[frameIndex]._compressedData);
|
||||
_frameList[frameIndex]._compressedData = nullptr;
|
||||
_frameList[frameIndex]._dataSize = 0;
|
||||
_frameList[frameIndex]._isCompressed = false;
|
||||
}
|
||||
return _frameList[frameIndex]._surface;
|
||||
} else {
|
||||
error("getFrame() frameIndex: %d, frameCount: %d", frameIndex, _frameCount);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
72
engines/prince/animation.h
Normal file
72
engines/prince/animation.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_ANIMATION_H
|
||||
#define PRINCE_ANIMATION_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Animation {
|
||||
public:
|
||||
Animation();
|
||||
~Animation();
|
||||
bool loadStream(Common::SeekableReadStream &stream);
|
||||
|
||||
int16 getLoopCount() const;
|
||||
int32 getPhaseCount() const;
|
||||
int32 getFrameCount() const;
|
||||
int16 getBaseX() const;
|
||||
int16 getBaseY() const;
|
||||
int16 getPhaseOffsetX(int phaseIndex) const;
|
||||
int16 getPhaseOffsetY(int phaseIndex) const;
|
||||
int16 getPhaseFrameIndex(int phaseIndex) const;
|
||||
Graphics::Surface *getFrame(int frameIndex);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
struct Phase {
|
||||
int16 _phaseOffsetX;
|
||||
int16 _phaseOffsetY;
|
||||
uint16 _phaseToFrameIndex;
|
||||
};
|
||||
struct Frame {
|
||||
bool _isCompressed;
|
||||
uint32 _dataSize;
|
||||
byte *_compressedData;
|
||||
Graphics::Surface *_surface;
|
||||
};
|
||||
Common::Array<Frame> _frameList;
|
||||
Common::Array<Phase> _phaseList;
|
||||
int16 _loopCount;
|
||||
int16 _phaseCount;
|
||||
int32 _frameCount;
|
||||
int16 _baseX;
|
||||
int16 _baseY;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
192
engines/prince/archive.cpp
Normal file
192
engines/prince/archive.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/archive.h"
|
||||
#include "prince/decompress.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
PtcArchive::PtcArchive() : _stream(nullptr) {
|
||||
}
|
||||
|
||||
PtcArchive::~PtcArchive() {
|
||||
close();
|
||||
}
|
||||
|
||||
static void decrypt(byte *buffer, uint32 size) {
|
||||
uint32 key = 0xDEADF00D;
|
||||
while (size--) {
|
||||
*buffer++ += key & 0xFF;
|
||||
key ^= 0x2E84299A;
|
||||
key += MKTAG('B', 'L', 'A', 'H');
|
||||
key = ((key & 1) << 31) | (key >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool PtcArchive::open(const Common::Path &filename) {
|
||||
_stream = SearchMan.createReadStreamForMember(filename);
|
||||
if (!_stream)
|
||||
return false;
|
||||
|
||||
_stream->readUint32LE(); // magic
|
||||
uint32 fileTableOffset = _stream->readUint32LE() ^ 0x4D4F4B2D; // MOK-
|
||||
uint32 fileTableSize = _stream->readUint32LE() ^ 0x534F4654; // SOFT
|
||||
|
||||
debug(8, "fileTableOffset : %08X", fileTableOffset);
|
||||
debug(8, "fileTableSize: %08X", fileTableSize);
|
||||
|
||||
_stream->seek(fileTableOffset);
|
||||
|
||||
byte *fileTable = (byte *)malloc(fileTableSize);
|
||||
byte *fileTableEnd = fileTable + fileTableSize;
|
||||
_stream->read(fileTable, fileTableSize);
|
||||
decrypt(fileTable, fileTableSize);
|
||||
|
||||
for (byte *fileItem = fileTable; fileItem < fileTableEnd; fileItem += 32) {
|
||||
FileEntry item;
|
||||
Common::String name = (const char*)fileItem;
|
||||
item._offset = READ_LE_UINT32(fileItem + 24);
|
||||
item._size = READ_LE_UINT32(fileItem + 28);
|
||||
debug(8, "%12s %8X %d", name.c_str(), item._offset, item._size);
|
||||
_items[name] = item;
|
||||
}
|
||||
|
||||
free(fileTable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PtcArchive::openTranslation(const Common::Path &filename) {
|
||||
_stream = SearchMan.createReadStreamForMember(filename);
|
||||
if (!_stream)
|
||||
return false;
|
||||
|
||||
Common::Array<Common::String> translationNames;
|
||||
Common::String translationFileName;
|
||||
const int kTranslationFiles = 5;
|
||||
for (int i = 0; i < kTranslationFiles; i++) {
|
||||
translationFileName = _stream->readLine();
|
||||
translationNames.push_back(translationFileName);
|
||||
}
|
||||
FileEntry item;
|
||||
for (int i = 0; i < kTranslationFiles; i++) {
|
||||
item._offset = _stream->readUint32LE();
|
||||
item._size = _stream->readUint32LE();
|
||||
_items[translationNames[i]] = item;
|
||||
}
|
||||
|
||||
if ((int32)_items[translationNames[0]]._offset == _stream->pos()) {
|
||||
warning("v0 translation file detected, update is needed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// We have latter versions of the file
|
||||
if (_stream->readByte() != '\n') {
|
||||
error("Malformed prince_translation.dat file");
|
||||
}
|
||||
|
||||
Common::String version = _stream->readLine();
|
||||
Common::String stamp = _stream->readLine();
|
||||
|
||||
warning("%s translation file detected, built on %s", version.c_str(), stamp.c_str());
|
||||
|
||||
if (version.equals("v1.0")) {
|
||||
// No more data, we all fine
|
||||
return true;
|
||||
}
|
||||
|
||||
// Here we have format extension data
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PtcArchive::close() {
|
||||
delete _stream;
|
||||
_stream = nullptr;
|
||||
_items.clear();
|
||||
}
|
||||
|
||||
bool PtcArchive::hasFile(const Common::Path &path) const {
|
||||
Common::String name = path.toString();
|
||||
// TODO: check if path matching should be added
|
||||
return _items.contains(name);
|
||||
}
|
||||
|
||||
int PtcArchive::listMembers(Common::ArchiveMemberList &list) const {
|
||||
int matches = 0;
|
||||
|
||||
for (const auto &item : _items) {
|
||||
list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(item._key, *this)));
|
||||
matches++;
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
const Common::ArchiveMemberPtr PtcArchive::getMember(const Common::Path &path) const {
|
||||
if (!hasFile(path)) {
|
||||
Common::ArchiveMemberPtr();
|
||||
}
|
||||
return Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(path, *this));
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *PtcArchive::createReadStreamForMember(const Common::Path &path) const {
|
||||
Common::String name = path.toString();
|
||||
if (!_items.contains(name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
debug(8, "PtcArchive::createReadStreamForMember(%s)", name.c_str());
|
||||
|
||||
const FileEntry &entryHeader = _items[name];
|
||||
|
||||
if (entryHeader._size < 4)
|
||||
return nullptr;
|
||||
|
||||
uint32 size = entryHeader._size;
|
||||
|
||||
_stream->seek(entryHeader._offset);
|
||||
|
||||
// This *HAS* to be malloc (not new[]) because MemoryReadStream uses free() to free the memory
|
||||
byte *buffer = (byte *)malloc(size);
|
||||
_stream->read(buffer, size);
|
||||
|
||||
if (READ_BE_UINT32(buffer) == MKTAG('M', 'A', 'S', 'M')) {
|
||||
Decompressor dec;
|
||||
uint32 decompLen = READ_BE_UINT32(buffer + 14);
|
||||
byte *decompData = (byte *)malloc(decompLen);
|
||||
dec.decompress(buffer + 18, decompData, decompLen);
|
||||
free(buffer);
|
||||
size = decompLen;
|
||||
buffer = decompData;
|
||||
|
||||
debug(8, "PtcArchive::createReadStreamForMember: decompressed %d to %d bytes", entryHeader._size, decompLen);
|
||||
}
|
||||
|
||||
return new Common::MemoryReadStream(buffer, size, DisposeAfterUse::YES);
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
61
engines/prince/archive.h
Normal file
61
engines/prince/archive.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_ARCHIVE_H
|
||||
#define PRINCE_ARCHIVE_H
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class PtcArchive : public Common::Archive {
|
||||
public:
|
||||
PtcArchive();
|
||||
~PtcArchive() override;
|
||||
|
||||
bool open(const Common::Path &filename);
|
||||
bool openTranslation(const Common::Path &filename);
|
||||
void close();
|
||||
bool isOpen() const { return _stream != 0; }
|
||||
|
||||
// Common::Archive API implementation
|
||||
bool hasFile(const Common::Path &path) const override;
|
||||
int listMembers(Common::ArchiveMemberList &list) const override;
|
||||
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
|
||||
Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
|
||||
|
||||
private:
|
||||
struct FileEntry {
|
||||
uint32 _offset;
|
||||
uint32 _size;
|
||||
};
|
||||
|
||||
Common::SeekableReadStream *_stream;
|
||||
|
||||
typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
|
||||
FileMap _items;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
44
engines/prince/common.h
Normal file
44
engines/prince/common.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_COMMON_H
|
||||
#define PRINCE_COMMON_H
|
||||
|
||||
namespace Prince {
|
||||
|
||||
enum Direction {
|
||||
kDirLD,
|
||||
kDirL,
|
||||
kDirLU,
|
||||
kDirRD,
|
||||
kDirR,
|
||||
kDirRU,
|
||||
kDirUL,
|
||||
kDirU,
|
||||
kDirUR,
|
||||
kDirDL,
|
||||
kDirD,
|
||||
kDirDR
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
3
engines/prince/configure.engine
Normal file
3
engines/prince/configure.engine
Normal file
@@ -0,0 +1,3 @@
|
||||
# This file is included from the main "configure" script
|
||||
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
|
||||
add_engine prince "The Prince and The Coward" yes "" "" "highres" "midi"
|
||||
5
engines/prince/credits.pl
Normal file
5
engines/prince/credits.pl
Normal file
@@ -0,0 +1,5 @@
|
||||
begin_section("Prince");
|
||||
add_person("Eugene Sandulenko", "sev", "");
|
||||
add_person("Łukasz Wątka", "lukaslw", "");
|
||||
add_person("Kamil Zbróg", "", "");
|
||||
end_section();
|
||||
153
engines/prince/cursor.cpp
Normal file
153
engines/prince/cursor.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "graphics/cursorman.h"
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "prince/cursor.h"
|
||||
#include "prince/debugger.h"
|
||||
#include "prince/script.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
Cursor::Cursor() : _surface(nullptr) {
|
||||
}
|
||||
|
||||
Cursor::~Cursor() {
|
||||
if (_surface != nullptr) {
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
_surface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Cursor::loadStream(Common::SeekableReadStream &stream) {
|
||||
stream.skip(4);
|
||||
uint16 width = stream.readUint16LE();
|
||||
uint16 height = stream.readUint16LE();
|
||||
|
||||
_surface = new Graphics::Surface();
|
||||
_surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
for (int h = 0; h < height; h++) {
|
||||
stream.read(_surface->getBasePtr(0, h), width);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrinceEngine::changeCursor(uint16 curId) {
|
||||
_debugger->_cursorNr = curId;
|
||||
_mouseFlag = curId;
|
||||
_flags->setFlagValue(Flags::MOUSEENABLED, curId);
|
||||
|
||||
const Graphics::Surface *curSurface = nullptr;
|
||||
|
||||
switch (curId) {
|
||||
default:
|
||||
error("Unknown cursor Id: %d", curId);
|
||||
case 0:
|
||||
CursorMan.showMouse(false);
|
||||
_optionsFlag = 0;
|
||||
_selectedMob = -1;
|
||||
_previousMob = -1;
|
||||
return;
|
||||
case 1:
|
||||
curSurface = _cursor1->getSurface();
|
||||
break;
|
||||
case 2:
|
||||
curSurface = _cursor2;
|
||||
break;
|
||||
case 3:
|
||||
curSurface = _cursor3->getSurface();
|
||||
Common::Point mousePos = _system->getEventManager()->getMousePos();
|
||||
mousePos.x = CLIP(mousePos.x, (int16) 315, (int16) 639);
|
||||
mousePos.y = CLIP(mousePos.y, (int16) 0, (int16) 170);
|
||||
_system->warpMouse(mousePos.x, mousePos.y);
|
||||
break;
|
||||
}
|
||||
|
||||
CursorMan.replaceCursorPalette(_roomBmp->getPalette().data(), 0, 255);
|
||||
CursorMan.replaceCursor(
|
||||
curSurface->getBasePtr(0, 0),
|
||||
curSurface->w, curSurface->h,
|
||||
0, 0,
|
||||
255, false,
|
||||
&curSurface->format
|
||||
);
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
void PrinceEngine::makeInvCursor(int itemNr) {
|
||||
const Graphics::Surface *cur1Surface = _cursor1->getSurface();
|
||||
int cur1W = cur1Surface->w;
|
||||
int cur1H = cur1Surface->h;
|
||||
const Common::Rect cur1Rect(0, 0, cur1W, cur1H);
|
||||
|
||||
const Graphics::Surface *itemSurface = _allInvList[itemNr].getSurface();
|
||||
int itemW = itemSurface->w;
|
||||
int itemH = itemSurface->h;
|
||||
|
||||
int cur2W = cur1W + itemW / 2;
|
||||
int cur2H = cur1H + itemH / 2;
|
||||
|
||||
if (_cursor2 != nullptr) {
|
||||
_cursor2->free();
|
||||
delete _cursor2;
|
||||
}
|
||||
_cursor2 = new Graphics::Surface();
|
||||
_cursor2->create(cur2W, cur2H, Graphics::PixelFormat::createFormatCLUT8());
|
||||
Common::Rect cur2Rect(0, 0, cur2W, cur2H);
|
||||
_cursor2->fillRect(cur2Rect, 255);
|
||||
_cursor2->copyRectToSurface(*cur1Surface, 0, 0, cur1Rect);
|
||||
|
||||
const byte *src1 = (const byte *)itemSurface->getBasePtr(0, 0);
|
||||
byte *dst1 = (byte *)_cursor2->getBasePtr(cur1W, cur1H);
|
||||
|
||||
if (itemH % 2) {
|
||||
itemH--;
|
||||
}
|
||||
if (itemW % 2) {
|
||||
itemW--;
|
||||
}
|
||||
|
||||
for (int y = 0; y < itemH; y++) {
|
||||
const byte *src2 = src1;
|
||||
byte *dst2 = dst1;
|
||||
if (y % 2 == 0) {
|
||||
for (int x = 0; x < itemW; x++, src2++) {
|
||||
if (x % 2 == 0) {
|
||||
if (*src2) {
|
||||
*dst2 = *src2;
|
||||
} else {
|
||||
*dst2 = 255;
|
||||
}
|
||||
dst2++;
|
||||
}
|
||||
}
|
||||
dst1 += _cursor2->pitch;
|
||||
}
|
||||
src1 += itemSurface->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
45
engines/prince/cursor.h
Normal file
45
engines/prince/cursor.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CURSOR_PRINCE_H
|
||||
#define CURSOR_PRINCE_H
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Cursor {
|
||||
public:
|
||||
Cursor();
|
||||
~Cursor();
|
||||
|
||||
bool loadStream(Common::SeekableReadStream &stream);
|
||||
const Graphics::Surface *getSurface() const { return _surface; }
|
||||
|
||||
private:
|
||||
Graphics::Surface *_surface;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
44
engines/prince/curve_values.h
Normal file
44
engines/prince/curve_values.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Prince {
|
||||
|
||||
const int curveValues[17][4] = {
|
||||
{ 32768, 0, 0, 0 },
|
||||
{ 25200, 7200, 480, -112 },
|
||||
{ 18816, 12544, 1792, -384 },
|
||||
{ 13520, 16224, 3744, -720 },
|
||||
{ 9216, 18432, 6144, -1024 },
|
||||
{ 5808, 19360, 8800, -1200 },
|
||||
{ 3200, 19200, 11520, -1152 },
|
||||
{ 1296, 18144, 14112, -784 },
|
||||
{ 0, 16384, 16384, 0 },
|
||||
{ -784, 14112, 18144, 1296 },
|
||||
{ -1152, 11520, 19200, 3200 },
|
||||
{ -1200, 8800, 19360, 5808 },
|
||||
{ -1024, 6144, 18432, 9216 },
|
||||
{ -720, 3744, 16224, 13520 },
|
||||
{ -384, 1792, 12544, 18816 },
|
||||
{ -112, 480, 7200, 25200 },
|
||||
{ 0, 0, 0, 32768 }
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
175
engines/prince/debugger.cpp
Normal file
175
engines/prince/debugger.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/debugger.h"
|
||||
#include "prince/prince.h"
|
||||
#include "prince/flags.h"
|
||||
#include "prince/script.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
Debugger::Debugger(PrinceEngine *vm, InterpreterFlags *flags) : GUI::Debugger(), _vm(vm), _locationNr(0), _flags(flags) {
|
||||
registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
|
||||
registerCmd("level", WRAP_METHOD(Debugger, Cmd_DebugLevel));
|
||||
registerCmd("setflag", WRAP_METHOD(Debugger, Cmd_SetFlag));
|
||||
registerCmd("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag));
|
||||
registerCmd("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag));
|
||||
registerCmd("viewflc", WRAP_METHOD(Debugger, Cmd_ViewFlc));
|
||||
registerCmd("initroom", WRAP_METHOD(Debugger, Cmd_InitRoom));
|
||||
registerCmd("changecursor", WRAP_METHOD(Debugger, Cmd_ChangeCursor));
|
||||
registerCmd("additem", WRAP_METHOD(Debugger, Cmd_AddItem));
|
||||
|
||||
_cursorNr = 0;
|
||||
}
|
||||
|
||||
static int strToInt(const char *s) {
|
||||
if (!*s)
|
||||
// No string at all
|
||||
return 0;
|
||||
else if (toupper(s[strlen(s) - 1]) != 'H')
|
||||
// Standard decimal string
|
||||
return atoi(s);
|
||||
|
||||
// Hexadecimal string
|
||||
uint tmp = 0;
|
||||
int read = sscanf(s, "%xh", &tmp);
|
||||
if (read < 1)
|
||||
error("strToInt failed on string \"%s\"", s);
|
||||
return (int)tmp;
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_DebugLevel(int argc, const char **argv) {
|
||||
if (argc == 1) {
|
||||
debugPrintf("Debugging is currently set at level %d\n", gDebugLevel);
|
||||
} else { // set level
|
||||
gDebugLevel = atoi(argv[1]);
|
||||
if (0 <= gDebugLevel && gDebugLevel < 11) {
|
||||
debugPrintf("Debug level set to level %d\n", gDebugLevel);
|
||||
} else if (gDebugLevel < 0) {
|
||||
debugPrintf("Debugging is now disabled\n");
|
||||
} else
|
||||
debugPrintf("Not a valid debug level (0 - 10)\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This command sets a flag
|
||||
*/
|
||||
bool Debugger::Cmd_SetFlag(int argc, const char **argv) {
|
||||
// Check for a flag to set
|
||||
if (argc != 3) {
|
||||
debugPrintf("Usage: %s <flag number> <value>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int flagNum = strToInt(argv[1]);
|
||||
uint16 value = strToInt(argv[2]);
|
||||
_flags->setFlagValue((Flags::Id)flagNum, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This command gets the value of a flag
|
||||
*/
|
||||
bool Debugger::Cmd_GetFlag(int argc, const char **argv) {
|
||||
// Check for a flag to display
|
||||
if (argc != 2) {
|
||||
debugPrintf("Usage: %s <flag number>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int flagNum = strToInt(argv[1]);
|
||||
debugPrintf("Value: %d\n", _flags->getFlagValue((Flags::Id)flagNum));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This command clears a flag
|
||||
*/
|
||||
bool Debugger::Cmd_ClearFlag(int argc, const char **argv) {
|
||||
// Check for a flag to clear
|
||||
if (argc != 2) {
|
||||
debugPrintf("Usage: %s <flag number>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int flagNum = strToInt(argv[1]);
|
||||
_flags->setFlagValue((Flags::Id)flagNum, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This command starts new flc anim
|
||||
*/
|
||||
bool Debugger::Cmd_ViewFlc(int argc, const char **argv) {
|
||||
// Check for a flag to clear
|
||||
if (argc != 2) {
|
||||
debugPrintf("Usage: %s <anim number>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int flagNum = strToInt(argv[1]);
|
||||
_vm->loadAnim(flagNum, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_InitRoom(int argc, const char **argv) {
|
||||
// Check for a flag to clear
|
||||
if (argc != 2) {
|
||||
debugPrintf("Usage: %s <anim number>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
_locationNr = strToInt(argv[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_ChangeCursor(int argc, const char **argv) {
|
||||
// Check for a flag to clear
|
||||
if (argc != 2) {
|
||||
debugPrintf("Usage: %s <curId>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
_cursorNr = strToInt(argv[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_AddItem(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("Usage: %s <itemId>\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(argv[1], "map")) {
|
||||
_vm->addInv(0, 29, true);
|
||||
_vm->_flags->setFlagValue(Flags::MapaUsable, 1);
|
||||
} else {
|
||||
int itemId = strToInt(argv[1]);
|
||||
_vm->addInv(0, itemId, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
56
engines/prince/debugger.h
Normal file
56
engines/prince/debugger.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_DEBUGGER_H
|
||||
#define PRINCE_DEBUGGER_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class PrinceEngine;
|
||||
class InterpreterFlags;
|
||||
|
||||
class Debugger : public GUI::Debugger {
|
||||
public:
|
||||
Debugger(PrinceEngine *vm, InterpreterFlags *flags);
|
||||
|
||||
uint8 _locationNr;
|
||||
uint8 _cursorNr;
|
||||
|
||||
private:
|
||||
bool Cmd_DebugLevel(int argc, const char **argv);
|
||||
bool Cmd_SetFlag(int argc, const char **argv);
|
||||
bool Cmd_GetFlag(int argc, const char **argv);
|
||||
bool Cmd_ClearFlag(int argc, const char **argv);
|
||||
bool Cmd_ViewFlc(int argc, const char **argv);
|
||||
bool Cmd_InitRoom(int argc, const char **argv);
|
||||
bool Cmd_ChangeCursor(int argc, const char **argv);
|
||||
bool Cmd_AddItem(int argc, const char **argv);
|
||||
|
||||
PrinceEngine *_vm;
|
||||
InterpreterFlags *_flags;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
172
engines/prince/decompress.cpp
Normal file
172
engines/prince/decompress.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// John_Doe's implementation
|
||||
|
||||
#include "prince/decompress.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
static const uint16 table1[] = {
|
||||
0x8000, 0x0002,
|
||||
0x4000, 0x0004,
|
||||
0x2000, 0x0008,
|
||||
0x1000, 0x0010,
|
||||
0x0800, 0x0020,
|
||||
0x0400, 0x0040,
|
||||
0x0200, 0x0080,
|
||||
0x0100, 0x0100,
|
||||
0x0080, 0x0200,
|
||||
0x0040, 0x0400
|
||||
};
|
||||
|
||||
static const uint32 table2[] = {
|
||||
0x0000F000,
|
||||
0x0020FC00,
|
||||
0x00A0FF00,
|
||||
0x02A0FF80,
|
||||
0x06A0FFC0,
|
||||
0x0EA0FFE0,
|
||||
0x1EA0FFF0,
|
||||
0x3EA0FFF8
|
||||
};
|
||||
|
||||
static const uint16 table3[] = {
|
||||
0x8000, 0x0000,
|
||||
0x4000, 0x0002,
|
||||
0x2000, 0x0006,
|
||||
0x1000, 0x000E,
|
||||
0x0800, 0x001E,
|
||||
0x0400, 0x003E,
|
||||
0x0200, 0x007E,
|
||||
0x0100, 0x00FE,
|
||||
0x0080, 0x01FE,
|
||||
0x0040, 0x03FE,
|
||||
0x0020, 0x07FE,
|
||||
0x0010, 0x0FFE,
|
||||
0x0008, 0x1FFE,
|
||||
0x0004, 0x3FFE,
|
||||
0x0002, 0x7FFE,
|
||||
0x0001, 0xFFFE
|
||||
};
|
||||
|
||||
void Decompressor::decompress(byte *source, byte *dest, uint32 destSize) {
|
||||
byte *destEnd = dest + destSize;
|
||||
int more;
|
||||
_src = source;
|
||||
_dst = dest;
|
||||
_bitBuffer = 0x80;
|
||||
while (_dst < destEnd) {
|
||||
uint32 ebp;
|
||||
uint16 offset, length;
|
||||
if (getBit()) {
|
||||
if (getBit()) {
|
||||
if (getBit()) {
|
||||
if (getBit()) {
|
||||
if (getBit()) {
|
||||
if (getBit()) {
|
||||
uint32 tableIndex = 0;
|
||||
while (getBit())
|
||||
tableIndex++;
|
||||
length = table3[tableIndex * 2 + 0];
|
||||
do {
|
||||
more = !(length & 0x8000);
|
||||
length = (length << 1) | getBit();
|
||||
} while (more);
|
||||
length += table3[tableIndex * 2 + 1];
|
||||
length++;
|
||||
memcpy(_dst, _src, length);
|
||||
_src += length;
|
||||
_dst += length;
|
||||
}
|
||||
*_dst++ = *_src++;
|
||||
}
|
||||
*_dst++ = *_src++;
|
||||
}
|
||||
*_dst++ = *_src++;
|
||||
}
|
||||
*_dst++ = *_src++;
|
||||
}
|
||||
*_dst++ = *_src++;
|
||||
}
|
||||
if (!getBit()) {
|
||||
if (getBit()) {
|
||||
uint32 tableIndex = getBit();
|
||||
tableIndex = (tableIndex << 1) | getBit();
|
||||
tableIndex = (tableIndex << 1) | getBit();
|
||||
ebp = table2[tableIndex];
|
||||
length = 1;
|
||||
} else {
|
||||
ebp = 0x0000FF00;
|
||||
length = 0;
|
||||
}
|
||||
} else {
|
||||
uint32 tableIndex = 0;
|
||||
while (getBit())
|
||||
tableIndex++;
|
||||
length = table1[tableIndex * 2 + 0];
|
||||
do {
|
||||
more = !(length & 0x8000);
|
||||
length = (length << 1) | getBit();
|
||||
} while (more);
|
||||
length += table1[tableIndex * 2 + 1];
|
||||
tableIndex = getBit();
|
||||
tableIndex = (tableIndex << 1) | getBit();
|
||||
tableIndex = (tableIndex << 1) | getBit();
|
||||
ebp = table2[tableIndex];
|
||||
}
|
||||
offset = ebp & 0xFFFF;
|
||||
do {
|
||||
if (_bitBuffer == 0x80) {
|
||||
if (offset >= 0xFF00) {
|
||||
offset = (offset << 8) | *_src++;
|
||||
}
|
||||
}
|
||||
more = offset & 0x8000;
|
||||
offset = (offset << 1) | getBit();
|
||||
} while (more);
|
||||
offset += (ebp >> 16);
|
||||
length += 2;
|
||||
while (length--) {
|
||||
if (_dst >= destEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_dst - offset >= dest)
|
||||
*_dst = *(_dst - offset);
|
||||
_dst++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Decompressor::getBit() {
|
||||
int bit = (_bitBuffer & 0x80) >> 7;
|
||||
_bitBuffer <<= 1;
|
||||
if (_bitBuffer == 0) {
|
||||
_bitBuffer = *_src++;
|
||||
bit = (_bitBuffer & 0x80) >> 7;
|
||||
_bitBuffer <<= 1;
|
||||
_bitBuffer |= 1;
|
||||
}
|
||||
return bit;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
43
engines/prince/decompress.h
Normal file
43
engines/prince/decompress.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// John_Doe's implementation
|
||||
|
||||
#ifndef PRINCE_DECOMPRESS_H
|
||||
#define PRINCE_DECOMPRESS_H
|
||||
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Decompressor {
|
||||
public:
|
||||
void decompress(byte *source, byte *dest, uint32 destSize);
|
||||
protected:
|
||||
byte *_src, *_dst;
|
||||
byte _bitBuffer;
|
||||
int _bitsLeft;
|
||||
int getBit();
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
188
engines/prince/detection.cpp
Normal file
188
engines/prince/detection.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "prince/detection.h"
|
||||
#include "prince/prince.h"
|
||||
|
||||
static const PlainGameDescriptor princeGames[] = {
|
||||
{"prince", "The Prince and the Coward"},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
static const DebugChannelDef debugFlagList[] = {
|
||||
{Prince::DebugChannel::kScript, "script", "Prince Script debug channel"},
|
||||
{Prince::DebugChannel::kEngine, "engine", "Prince Engine debug channel"},
|
||||
DEBUG_CHANNEL_END
|
||||
};
|
||||
|
||||
namespace Prince {
|
||||
static const PrinceGameDescription gameDescriptions[] = {
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"Galador: Der Fluch des Prinzen",
|
||||
AD_ENTRY1s("databank.ptc", "5fa03833177331214ec1354761b1d2ee", 3565031),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_USEEXTRAASTITLE | ADGF_DROPPLATFORM,
|
||||
GUIO2(GAMEOPTION_TTS_OBJECTS, GAMEOPTION_TTS_MISSING_VOICE)
|
||||
},
|
||||
kPrinceDataDE
|
||||
},
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"Ksiaze i Tchorz",
|
||||
AD_ENTRY1s("databank.ptc", "48ec9806bda9d152acbea8ce31c93c49", 3435298),
|
||||
Common::PL_POL,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_USEEXTRAASTITLE | ADGF_DROPPLATFORM,
|
||||
GUIO2(GAMEOPTION_TTS_OBJECTS, GAMEOPTION_TTS_MISSING_VOICE)
|
||||
},
|
||||
kPrinceDataPL
|
||||
},
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"",
|
||||
AD_ENTRY1s("talktxt.dat", "02bb2372f19aca3c65896ed81b2cefb3", 125702),
|
||||
Common::RU_RUS,
|
||||
Common::kPlatformWindows,
|
||||
GF_EXTRACTED | ADGF_DROPPLATFORM,
|
||||
GUIO2(GAMEOPTION_TTS_OBJECTS, GAMEOPTION_TTS_MISSING_VOICE)
|
||||
},
|
||||
kPrinceDataDE
|
||||
},
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"",
|
||||
AD_ENTRY1s("databank.ptc", "a67b55730f3d7064921bd2a59e1063a3", 3892982),
|
||||
Common::RU_RUS,
|
||||
Common::kPlatformWindows,
|
||||
GF_NOVOICES | ADGF_DROPPLATFORM,
|
||||
GUIO2(GAMEOPTION_TTS_OBJECTS, GAMEOPTION_TTS_SPEECH)
|
||||
},
|
||||
kPrinceDataDE
|
||||
},
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"",
|
||||
AD_ENTRY1s("databank.ptc", "eb702d16e88c8c41f963d449287c8023", 3730152),
|
||||
Common::RU_RUS,
|
||||
Common::kPlatformWindows,
|
||||
GF_RUSPROJEDITION | ADGF_USEEXTRAASTITLE | ADGF_DROPPLATFORM,
|
||||
GUIO2(GAMEOPTION_TTS_OBJECTS, GAMEOPTION_TTS_MISSING_VOICE)
|
||||
},
|
||||
kPrinceDataDE
|
||||
},
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"w/translation",
|
||||
AD_ENTRY2s("databank.ptc", "5fa03833177331214ec1354761b1d2ee", 3565031,
|
||||
"prince_translation.dat", nullptr, AD_NO_SIZE),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
GF_TRANSLATED | ADGF_DROPPLATFORM,
|
||||
GUIO2(GAMEOPTION_TTS_OBJECTS, GAMEOPTION_TTS_SPEECH)
|
||||
},
|
||||
kPrinceDataDE
|
||||
},
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"w/translation",
|
||||
AD_ENTRY2s("databank.ptc", "48ec9806bda9d152acbea8ce31c93c49", 3435298,
|
||||
"prince_translation.dat", nullptr, AD_NO_SIZE),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
GF_TRANSLATED | ADGF_DROPPLATFORM,
|
||||
GUIO2(GAMEOPTION_TTS_OBJECTS, GAMEOPTION_TTS_SPEECH)
|
||||
},
|
||||
kPrinceDataPL
|
||||
},
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"w/translation",
|
||||
AD_ENTRY3s("databank.ptc", "5fa03833177331214ec1354761b1d2ee", 3565031,
|
||||
"FONT1.RAW", "e80c50c8167d4d51c60d93e29bedb779", 27118,
|
||||
"prince_translation.dat", nullptr, AD_NO_SIZE),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformWindows,
|
||||
GF_TRANSLATED | ADGF_DROPPLATFORM,
|
||||
GUIO2(GAMEOPTION_TTS_OBJECTS, GAMEOPTION_TTS_SPEECH)
|
||||
},
|
||||
kPrinceDataDE
|
||||
},
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"w/translation",
|
||||
AD_ENTRY3s("databank.ptc", "48ec9806bda9d152acbea8ce31c93c49", 3435298,
|
||||
"FONT1.RAW", "e80c50c8167d4d51c60d93e29bedb779", 27118,
|
||||
"prince_translation.dat", nullptr, AD_NO_SIZE),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformWindows,
|
||||
GF_TRANSLATED | ADGF_DROPPLATFORM,
|
||||
GUIO2(GAMEOPTION_TTS_OBJECTS, GAMEOPTION_TTS_SPEECH)
|
||||
},
|
||||
kPrinceDataPL
|
||||
},
|
||||
{ AD_TABLE_END_MARKER, kPrinceDataUNK }
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
const static char *const directoryGlobs[] = {
|
||||
"all",
|
||||
nullptr
|
||||
};
|
||||
|
||||
class PrinceMetaEngineDetection : public AdvancedMetaEngineDetection<Prince::PrinceGameDescription> {
|
||||
public:
|
||||
PrinceMetaEngineDetection() : AdvancedMetaEngineDetection(Prince::gameDescriptions, princeGames) {
|
||||
_maxScanDepth = 2;
|
||||
_directoryGlobs = directoryGlobs;
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "prince";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "The Prince and the Coward";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "The Prince and the Coward (C) 1996-97 Metropolis";
|
||||
}
|
||||
|
||||
const DebugChannelDef *getDebugChannels() const override {
|
||||
return debugFlagList;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN_STATIC(PRINCE_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, PrinceMetaEngineDetection);
|
||||
55
engines/prince/detection.h
Normal file
55
engines/prince/detection.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_DETECTION_H
|
||||
#define PRINCE_DETECTION_H
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
enum PrinceGameType {
|
||||
kPrinceDataUNK,
|
||||
kPrinceDataDE,
|
||||
kPrinceDataPL
|
||||
};
|
||||
|
||||
enum {
|
||||
GF_TRANSLATED = 1 << 0,
|
||||
GF_EXTRACTED = 1 << 1,
|
||||
GF_NOVOICES = 1 << 2,
|
||||
GF_RUSPROJEDITION = 1 << 3
|
||||
};
|
||||
|
||||
struct PrinceGameDescription {
|
||||
AD_GAME_DESCRIPTION_HELPERS(desc);
|
||||
|
||||
ADGameDescription desc;
|
||||
PrinceGameType gameType;
|
||||
};
|
||||
|
||||
#define GAMEOPTION_TTS_OBJECTS GUIO_GAMEOPTIONS1
|
||||
#define GAMEOPTION_TTS_SPEECH GUIO_GAMEOPTIONS2
|
||||
#define GAMEOPTION_TTS_MISSING_VOICE GUIO_GAMEOPTIONS3
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif // PRINCE_DETECTION_H
|
||||
777
engines/prince/draw.cpp
Normal file
777
engines/prince/draw.cpp
Normal file
@@ -0,0 +1,777 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "graphics/paletteman.h"
|
||||
|
||||
#include "prince/prince.h"
|
||||
|
||||
#include "prince/animation.h"
|
||||
#include "prince/graphics.h"
|
||||
#include "prince/hero.h"
|
||||
#include "prince/script.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
bool PrinceEngine::spriteCheck(int sprWidth, int sprHeight, int destX, int destY) {
|
||||
destX -= _picWindowX;
|
||||
destY -= _picWindowY;
|
||||
|
||||
// if x1 is on visible part of screen
|
||||
if (destX < 0) {
|
||||
if (destX + sprWidth < 1) {
|
||||
//x2 is negative - out of window
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// if x1 is outside of screen on right side
|
||||
if (destX >= kNormalWidth) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (destY < 0) {
|
||||
if (destY + sprHeight < 1) {
|
||||
//y2 is negative - out of window
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (destY >= kNormalHeight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// CheckNak
|
||||
void PrinceEngine::checkMasks(int x1, int y1, int sprWidth, int sprHeight, int z) {
|
||||
int x2 = x1 + sprWidth - 1;
|
||||
int y2 = y1 + sprHeight - 1;
|
||||
if (x1 < 0) {
|
||||
x1 = 0;
|
||||
}
|
||||
for (uint i = 0; i < _maskList.size(); i++) {
|
||||
if (!_maskList[i]._state && !_maskList[i]._flags) {
|
||||
if (_maskList[i]._z > z) {
|
||||
if (_maskList[i]._x1 <= x2 && _maskList[i]._x2 >= x1) {
|
||||
if (_maskList[i]._y1 <= y2 && _maskList[i]._y2 >= y1) {
|
||||
_maskList[i]._state = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ClsNak
|
||||
void PrinceEngine::clsMasks() {
|
||||
for (uint i = 0; i < _maskList.size(); i++) {
|
||||
if (_maskList[i]._state) {
|
||||
_maskList[i]._state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// InsertNakladki
|
||||
void PrinceEngine::insertMasks(Graphics::Surface *originalRoomSurface) {
|
||||
for (uint i = 0; i < _maskList.size(); i++) {
|
||||
if (_maskList[i]._state) {
|
||||
if (_maskList[i]._data != nullptr) {
|
||||
showMask(i, originalRoomSurface);
|
||||
} else {
|
||||
error("insertMasks() - Wrong mask data- nr %d", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ShowNak
|
||||
void PrinceEngine::showMask(int maskNr, Graphics::Surface *originalRoomSurface) {
|
||||
if (!_maskList[maskNr]._flags) {
|
||||
if (spriteCheck(_maskList[maskNr]._width, _maskList[maskNr]._height, _maskList[maskNr]._x1, _maskList[maskNr]._y1)) {
|
||||
int destX = _maskList[maskNr]._x1 - _picWindowX;
|
||||
int destY = _maskList[maskNr]._y1 - _picWindowY;
|
||||
DrawNode newDrawNode;
|
||||
newDrawNode.posX = destX;
|
||||
newDrawNode.posY = destY;
|
||||
newDrawNode.posZ = _maskList[maskNr]._z;
|
||||
newDrawNode.width = _maskList[maskNr]._width;
|
||||
newDrawNode.height = _maskList[maskNr]._height;
|
||||
newDrawNode.s = nullptr;
|
||||
newDrawNode.originalRoomSurface = originalRoomSurface;
|
||||
newDrawNode.data = _maskList[maskNr].getMask();
|
||||
newDrawNode.drawFunction = &_graph->drawMaskDrawNode;
|
||||
_drawNodeList.push_back(newDrawNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ) {
|
||||
if (spriteCheck(spriteSurface->w, spriteSurface->h, destX, destY)) {
|
||||
destX -= _picWindowX;
|
||||
destY -= _picWindowY;
|
||||
DrawNode newDrawNode;
|
||||
newDrawNode.posX = destX;
|
||||
newDrawNode.posY = destY;
|
||||
newDrawNode.posZ = destZ;
|
||||
newDrawNode.width = 0;
|
||||
newDrawNode.height = 0;
|
||||
newDrawNode.s = spriteSurface;
|
||||
newDrawNode.originalRoomSurface = nullptr;
|
||||
newDrawNode.data = _transTable;
|
||||
newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
|
||||
_drawNodeList.push_back(newDrawNode);
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ) {
|
||||
if (spriteCheck(shadowSurface->w, shadowSurface->h, destX, destY)) {
|
||||
destX -= _picWindowX;
|
||||
destY -= _picWindowY;
|
||||
DrawNode newDrawNode;
|
||||
newDrawNode.posX = destX;
|
||||
newDrawNode.posY = destY;
|
||||
newDrawNode.posZ = destZ;
|
||||
newDrawNode.width = 0;
|
||||
newDrawNode.height = 0;
|
||||
newDrawNode.s = shadowSurface;
|
||||
newDrawNode.originalRoomSurface = nullptr;
|
||||
newDrawNode.data = _graph->_shadowTable70;
|
||||
newDrawNode.drawFunction = &_graph->drawAsShadowDrawNode;
|
||||
_drawNodeList.push_back(newDrawNode);
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::showAnim(Anim &anim) {
|
||||
//ShowFrameCode
|
||||
//ShowAnimFrame
|
||||
int phase = anim._showFrame;
|
||||
int phaseFrameIndex = anim._animData->getPhaseFrameIndex(phase);
|
||||
int x = anim._x + anim._animData->getPhaseOffsetX(phase);
|
||||
int y = anim._y + anim._animData->getPhaseOffsetY(phase);
|
||||
int animFlag = anim._flags;
|
||||
int checkMaskFlag = (animFlag & 1);
|
||||
int maxFrontFlag = (animFlag & 2);
|
||||
int specialZFlag = anim._nextAnim;
|
||||
int z = anim._nextAnim;
|
||||
Graphics::Surface *animSurface = anim._animData->getFrame(phaseFrameIndex);
|
||||
int frameWidth = animSurface->w;
|
||||
int frameHeight = animSurface->h;
|
||||
int shadowZ = 0;
|
||||
|
||||
if (checkMaskFlag) {
|
||||
if (!anim._nextAnim) {
|
||||
z = y + frameHeight - 1;
|
||||
}
|
||||
checkMasks(x, y, frameWidth, frameHeight, z);
|
||||
}
|
||||
|
||||
if (specialZFlag) {
|
||||
z = specialZFlag;
|
||||
} else if (maxFrontFlag) {
|
||||
z = kMaxPicHeight + 1;
|
||||
} else {
|
||||
z = y + frameHeight - 1;
|
||||
}
|
||||
shadowZ = z;
|
||||
|
||||
anim._currX = x;
|
||||
anim._currY = y;
|
||||
anim._currW = frameWidth;
|
||||
anim._currH = frameHeight;
|
||||
showSprite(animSurface, x, y, z);
|
||||
|
||||
// make_special_shadow
|
||||
if ((anim._flags & 0x80)) {
|
||||
DrawNode newDrawNode;
|
||||
newDrawNode.posX = x;
|
||||
newDrawNode.posY = y + animSurface->h - anim._shadowBack;
|
||||
newDrawNode.posZ = Hero::kHeroShadowZ;
|
||||
newDrawNode.width = 0;
|
||||
newDrawNode.height = 0;
|
||||
newDrawNode.scaleValue = _scaleValue;
|
||||
newDrawNode.originalRoomSurface = nullptr;
|
||||
newDrawNode.data = this;
|
||||
newDrawNode.drawFunction = &Hero::showHeroShadow;
|
||||
newDrawNode.s = animSurface;
|
||||
_drawNodeList.push_back(newDrawNode);
|
||||
}
|
||||
|
||||
//ShowFrameCodeShadow
|
||||
//ShowAnimFrameShadow
|
||||
if (anim._shadowData != nullptr) {
|
||||
int shadowPhaseFrameIndex = anim._shadowData->getPhaseFrameIndex(phase);
|
||||
int shadowX = anim._shadowData->getBaseX() + anim._shadowData->getPhaseOffsetX(phase);
|
||||
int shadowY = anim._shadowData->getBaseY() + anim._shadowData->getPhaseOffsetY(phase);
|
||||
Graphics::Surface *shadowSurface = anim._shadowData->getFrame(shadowPhaseFrameIndex);
|
||||
int shadowFrameWidth = shadowSurface->w;
|
||||
int shadowFrameHeight = shadowSurface->h;
|
||||
|
||||
if (checkMaskFlag) {
|
||||
checkMasks(shadowX, shadowY, shadowFrameWidth, shadowFrameHeight, shadowY + shadowFrameWidth - 1);
|
||||
}
|
||||
|
||||
if (!shadowZ) {
|
||||
if (maxFrontFlag) {
|
||||
shadowZ = kMaxPicHeight + 1;
|
||||
} else {
|
||||
shadowZ = shadowY + shadowFrameWidth - 1;
|
||||
}
|
||||
}
|
||||
showSpriteShadow(shadowSurface, shadowX, shadowY, shadowZ);
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::showNormAnims() {
|
||||
for (int i = 0; i < kMaxNormAnims; i++) {
|
||||
Anim &anim = _normAnimList[i];
|
||||
if (anim._animData != nullptr) {
|
||||
int phaseCount = anim._animData->getPhaseCount();
|
||||
if (!anim._state) {
|
||||
if (anim._frame == anim._lastFrame - 1) {
|
||||
if (anim._loopType) {
|
||||
if (anim._loopType == 1) {
|
||||
anim._frame = anim._loopFrame;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
anim._frame++;
|
||||
}
|
||||
anim._showFrame = anim._frame;
|
||||
if (anim._showFrame >= phaseCount) {
|
||||
anim._showFrame = phaseCount - 1;
|
||||
}
|
||||
showAnim(anim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::setBackAnim(Anim &backAnim) {
|
||||
int start = backAnim._basaData._start;
|
||||
if (start != -1) {
|
||||
backAnim._frame = start;
|
||||
backAnim._showFrame = start;
|
||||
backAnim._loopFrame = start;
|
||||
}
|
||||
int end = backAnim._basaData._end;
|
||||
if (end != -1) {
|
||||
backAnim._lastFrame = end;
|
||||
}
|
||||
backAnim._state = 0;
|
||||
}
|
||||
|
||||
void PrinceEngine::showBackAnims() {
|
||||
for (int i = 0; i < kMaxBackAnims; i++) {
|
||||
BAS &seq = _backAnimList[i]._seq;
|
||||
int activeSubAnim = seq._currRelative;
|
||||
if (!_backAnimList[i].backAnims.empty()) {
|
||||
if (_backAnimList[i].backAnims[activeSubAnim]._animData != nullptr) {
|
||||
if (!_backAnimList[i].backAnims[activeSubAnim]._state) {
|
||||
seq._counter++;
|
||||
if (seq._type == 2) {
|
||||
if (!seq._currRelative) {
|
||||
if (seq._counter >= seq._data) {
|
||||
if (seq._anims > 2) {
|
||||
seq._currRelative = _randomSource.getRandomNumber(seq._anims - 2) + 1;
|
||||
activeSubAnim = seq._currRelative;
|
||||
seq._current = _backAnimList[i].backAnims[activeSubAnim]._basaData._num;
|
||||
}
|
||||
setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
||||
seq._counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (seq._type == 3) {
|
||||
if (!seq._currRelative) {
|
||||
if (seq._counter < seq._data2) {
|
||||
continue;
|
||||
} else {
|
||||
setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_backAnimList[i].backAnims[activeSubAnim]._frame == _backAnimList[i].backAnims[activeSubAnim]._lastFrame - 1) {
|
||||
_backAnimList[i].backAnims[activeSubAnim]._frame = _backAnimList[i].backAnims[activeSubAnim]._loopFrame;
|
||||
switch (seq._type) {
|
||||
case 1:
|
||||
if (seq._anims > 1) {
|
||||
int rnd;
|
||||
do {
|
||||
rnd = _randomSource.getRandomNumber(seq._anims - 1);
|
||||
} while (rnd == seq._currRelative);
|
||||
seq._currRelative = rnd;
|
||||
seq._current = _backAnimList[i].backAnims[rnd]._basaData._num;
|
||||
activeSubAnim = rnd;
|
||||
setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
||||
seq._counter = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (seq._currRelative) {
|
||||
seq._currRelative = 0;
|
||||
seq._current = _backAnimList[i].backAnims[0]._basaData._num;
|
||||
activeSubAnim = 0;
|
||||
setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
||||
seq._counter = 0;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
seq._currRelative = 0;
|
||||
seq._current = _backAnimList[i].backAnims[0]._basaData._num;
|
||||
seq._counter = 0;
|
||||
seq._data2 = _randomSource.getRandomNumber(seq._data - 1);
|
||||
continue; // for bug in original game
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
_backAnimList[i].backAnims[activeSubAnim]._frame++;
|
||||
}
|
||||
_backAnimList[i].backAnims[activeSubAnim]._showFrame = _backAnimList[i].backAnims[activeSubAnim]._frame;
|
||||
showAnim(_backAnimList[i].backAnims[activeSubAnim]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::removeSingleBackAnim(int slot) {
|
||||
if (!_backAnimList[slot].backAnims.empty()) {
|
||||
for (uint j = 0; j < _backAnimList[slot].backAnims.size(); j++) {
|
||||
if (_backAnimList[slot].backAnims[j]._animData != nullptr) {
|
||||
delete _backAnimList[slot].backAnims[j]._animData;
|
||||
_backAnimList[slot].backAnims[j]._animData = nullptr;
|
||||
}
|
||||
if (_backAnimList[slot].backAnims[j]._shadowData != nullptr) {
|
||||
delete _backAnimList[slot].backAnims[j]._shadowData;
|
||||
_backAnimList[slot].backAnims[j]._shadowData = nullptr;
|
||||
}
|
||||
}
|
||||
_backAnimList[slot].backAnims.clear();
|
||||
_backAnimList[slot]._seq._currRelative = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::clearBackAnimList() {
|
||||
for (int i = 0; i < kMaxBackAnims; i++) {
|
||||
removeSingleBackAnim(i);
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::grabMap() {
|
||||
_graph->_frontScreen->copyFrom(*_roomBmp->getSurface());
|
||||
showObjects();
|
||||
runDrawNodes();
|
||||
_graph->_mapScreen->copyFrom(*_graph->_frontScreen);
|
||||
}
|
||||
|
||||
void PrinceEngine::initZoomIn(int slot) {
|
||||
freeZoomObject(slot);
|
||||
Object *object = _objList[slot];
|
||||
if (object != nullptr) {
|
||||
Graphics::Surface *zoomSource = object->getSurface();
|
||||
if (zoomSource != nullptr) {
|
||||
object->_flags |= 0x8000;
|
||||
object->_zoomSurface = new Graphics::Surface();
|
||||
object->_zoomSurface->create(zoomSource->w, zoomSource->h, Graphics::PixelFormat::createFormatCLUT8());
|
||||
object->_zoomSurface->fillRect(Common::Rect(zoomSource->w, zoomSource->h), 0xFF);
|
||||
object->_zoomTime = 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::initZoomOut(int slot) {
|
||||
freeZoomObject(slot);
|
||||
Object *object = _objList[slot];
|
||||
if (object != nullptr) {
|
||||
Graphics::Surface *zoomSource = object->getSurface();
|
||||
if (zoomSource != nullptr) {
|
||||
object->_flags |= 0x4000;
|
||||
object->_zoomSurface = new Graphics::Surface();
|
||||
object->_zoomSurface->copyFrom(*zoomSource);
|
||||
object->_zoomTime = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::doZoomIn(int slot) {
|
||||
Object *object = _objList[slot];
|
||||
if (object != nullptr) {
|
||||
Graphics::Surface *orgSurface = object->getSurface();
|
||||
if (orgSurface != nullptr) {
|
||||
byte *src1 = (byte *)orgSurface->getBasePtr(0, 0);
|
||||
byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
|
||||
int x = 0;
|
||||
int surfaceHeight = orgSurface->h;
|
||||
for (int y = 0; y < surfaceHeight; y++) {
|
||||
byte *src2 = src1;
|
||||
byte *dst2 = dst1;
|
||||
int w = orgSurface->w - x;
|
||||
src2 += x;
|
||||
dst2 += x;
|
||||
while (w > 0) {
|
||||
int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
|
||||
if (randVal < w) {
|
||||
*(dst2 + randVal) = *(src2 + randVal);
|
||||
src2 += zoomInStep;
|
||||
dst2 += zoomInStep;
|
||||
} else if (y + 1 != surfaceHeight) {
|
||||
*(dst1 + orgSurface->pitch + randVal - w) = *(src1 + orgSurface->pitch + randVal - w);
|
||||
}
|
||||
w -= zoomInStep;
|
||||
}
|
||||
x = -1 * w;
|
||||
src1 += orgSurface->pitch;
|
||||
dst1 += orgSurface->pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::doZoomOut(int slot) {
|
||||
Object *object = _objList[slot];
|
||||
if (object != nullptr) {
|
||||
Graphics::Surface *orgSurface = object->getSurface();
|
||||
if (orgSurface != nullptr) {
|
||||
byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
|
||||
int x = 0;
|
||||
int surfaceHeight = orgSurface->h;
|
||||
for (int y = 0; y < surfaceHeight; y++) {
|
||||
byte *dst2 = dst1;
|
||||
int w = orgSurface->w - x;
|
||||
dst2 += x;
|
||||
while (w > 0) {
|
||||
int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
|
||||
if (randVal < w) {
|
||||
*(dst2 + randVal) = 255;
|
||||
dst2 += zoomInStep;
|
||||
} else if (y + 1 != surfaceHeight) {
|
||||
*(dst1 + orgSurface->pitch + randVal - w) = 255;
|
||||
}
|
||||
w -= zoomInStep;
|
||||
}
|
||||
x = -1 * w;
|
||||
dst1 += orgSurface->pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::freeZoomObject(int slot) {
|
||||
Object *object = _objList[slot];
|
||||
if (object != nullptr) {
|
||||
if (object->_zoomSurface != nullptr) {
|
||||
object->_zoomSurface->free();
|
||||
delete object->_zoomSurface;
|
||||
object->_zoomSurface = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::showObjects() {
|
||||
for (int i = 0; i < kMaxObjects; i++) {
|
||||
int nr = _objSlot[i];
|
||||
if (nr != 0xFF) {
|
||||
Graphics::Surface *objSurface = nullptr;
|
||||
if ((_objList[nr]->_flags & 0x8000)) {
|
||||
_objList[nr]->_zoomTime--;
|
||||
if (!_objList[nr]->_zoomTime) {
|
||||
freeZoomObject(nr);
|
||||
_objList[nr]->_flags &= 0x7FFF;
|
||||
objSurface = _objList[nr]->getSurface();
|
||||
} else {
|
||||
doZoomIn(nr);
|
||||
objSurface = _objList[nr]->_zoomSurface;
|
||||
}
|
||||
} else if ((_objList[nr]->_flags & 0x4000)) {
|
||||
_objList[nr]->_zoomTime--;
|
||||
if (!_objList[nr]->_zoomTime) {
|
||||
freeZoomObject(nr);
|
||||
_objList[nr]->_flags &= 0xBFFF;
|
||||
objSurface = _objList[nr]->getSurface();
|
||||
} else {
|
||||
doZoomOut(nr);
|
||||
objSurface = _objList[nr]->_zoomSurface;
|
||||
}
|
||||
} else {
|
||||
objSurface = _objList[nr]->getSurface();
|
||||
}
|
||||
|
||||
if (objSurface != nullptr) {
|
||||
if (spriteCheck(objSurface->w, objSurface->h, _objList[nr]->_x, _objList[nr]->_y)) {
|
||||
int destX = _objList[nr]->_x - _picWindowX;
|
||||
int destY = _objList[nr]->_y - _picWindowY;
|
||||
DrawNode newDrawNode;
|
||||
newDrawNode.posX = destX;
|
||||
newDrawNode.posY = destY;
|
||||
newDrawNode.posZ = _objList[nr]->_z;
|
||||
newDrawNode.width = 0;
|
||||
newDrawNode.height = 0;
|
||||
newDrawNode.s = objSurface;
|
||||
newDrawNode.originalRoomSurface = nullptr;
|
||||
if ((_objList[nr]->_flags & 0x2000)) {
|
||||
newDrawNode.data = nullptr;
|
||||
newDrawNode.drawFunction = &_graph->drawBackSpriteDrawNode;
|
||||
} else {
|
||||
newDrawNode.data = _transTable;
|
||||
if (_flags->getFlagValue(Flags::NOANTIALIAS)) {
|
||||
newDrawNode.drawFunction = &_graph->drawTransparentDrawNode;
|
||||
} else {
|
||||
newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
|
||||
}
|
||||
}
|
||||
_drawNodeList.push_back(newDrawNode);
|
||||
}
|
||||
|
||||
if ((_objList[nr]->_flags & 1)) {
|
||||
checkMasks(_objList[nr]->_x, _objList[nr]->_y, objSurface->w, objSurface->h, _objList[nr]->_z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::showParallax() {
|
||||
if (!_pscrList.empty()) {
|
||||
for (uint i = 0; i < _pscrList.size(); i++) {
|
||||
Graphics::Surface *pscrSurface = _pscrList[i]->getSurface();
|
||||
if (pscrSurface != nullptr) {
|
||||
int x = _pscrList[i]->_x - (_pscrList[i]->_step * _picWindowX / 4);
|
||||
int y = _pscrList[i]->_y;
|
||||
int z = PScr::kPScrZ;
|
||||
if (spriteCheck(pscrSurface->w, pscrSurface->h, x, y)) {
|
||||
showSprite(pscrSurface, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PrinceEngine::compareDrawNodes(DrawNode d1, DrawNode d2) {
|
||||
if (d1.posZ < d2.posZ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PrinceEngine::runDrawNodes() {
|
||||
Common::sort(_drawNodeList.begin(), _drawNodeList.end(), compareDrawNodes);
|
||||
|
||||
for (uint i = 0; i < _drawNodeList.size(); i++) {
|
||||
(*_drawNodeList[i].drawFunction)(_graph->_frontScreen, &_drawNodeList[i]);
|
||||
}
|
||||
_graph->change();
|
||||
}
|
||||
|
||||
void PrinceEngine::drawScreen() {
|
||||
if (!_showInventoryFlag || _inventoryBackgroundRemember) {
|
||||
clsMasks();
|
||||
|
||||
_mainHero->showHero();
|
||||
_mainHero->scrollHero();
|
||||
_mainHero->drawHero();
|
||||
|
||||
_secondHero->showHero();
|
||||
_secondHero->_drawX -= _picWindowX;
|
||||
_secondHero->drawHero();
|
||||
|
||||
const Graphics::Surface *roomSurface;
|
||||
if (_locationNr != 50) {
|
||||
roomSurface = _roomBmp->getSurface();
|
||||
} else {
|
||||
roomSurface = _graph->_mapScreen;
|
||||
}
|
||||
Graphics::Surface visiblePart;
|
||||
if (roomSurface) {
|
||||
visiblePart = roomSurface->getSubArea(Common::Rect(_picWindowX, 0, roomSurface->w, roomSurface->h));
|
||||
_graph->draw(_graph->_frontScreen, &visiblePart);
|
||||
}
|
||||
|
||||
showBackAnims();
|
||||
|
||||
showNormAnims();
|
||||
|
||||
playNextFLCFrame();
|
||||
|
||||
showObjects();
|
||||
|
||||
if (roomSurface) {
|
||||
insertMasks(&visiblePart);
|
||||
}
|
||||
|
||||
showParallax();
|
||||
|
||||
runDrawNodes();
|
||||
|
||||
_drawNodeList.clear();
|
||||
|
||||
if (!_inventoryBackgroundRemember && !_dialogFlag) {
|
||||
if (!_optionsFlag) {
|
||||
_selectedMob = checkMob(_graph->_frontScreen, _mobList, true);
|
||||
}
|
||||
showTexts(_graph->_frontScreen);
|
||||
checkOptions();
|
||||
} else {
|
||||
_inventoryBackgroundRemember = false;
|
||||
}
|
||||
|
||||
showPower();
|
||||
|
||||
} else {
|
||||
displayInventory();
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::blackPalette() {
|
||||
byte *paletteBackup = (byte *)malloc(256 * 3);
|
||||
byte *blackPalette1 = (byte *)malloc(256 * 3);
|
||||
|
||||
int fadeStep = kFadeStep - 1;
|
||||
for (int i = 0; i < kFadeStep; i++) {
|
||||
_system->getPaletteManager()->grabPalette(paletteBackup, 0, 256);
|
||||
for (int j = 0; j < 256; j++) {
|
||||
blackPalette1[3 * j] = paletteBackup[3 * j] * fadeStep / 4;
|
||||
blackPalette1[3 * j + 1] = paletteBackup[3 * j + 1] * fadeStep / 4;
|
||||
blackPalette1[3 * j + 2] = paletteBackup[3 * j + 2] * fadeStep / 4;
|
||||
}
|
||||
fadeStep--;
|
||||
_graph->setPalette(blackPalette1);
|
||||
_system->updateScreen();
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _system->getEventManager();
|
||||
eventMan->pollEvent(event);
|
||||
if (shouldQuit()) {
|
||||
free(paletteBackup);
|
||||
free(blackPalette1);
|
||||
return;
|
||||
}
|
||||
pausePrinceEngine();
|
||||
}
|
||||
free(paletteBackup);
|
||||
free(blackPalette1);
|
||||
}
|
||||
|
||||
void PrinceEngine::setPalette(const byte *palette) {
|
||||
if (palette != nullptr) {
|
||||
byte *blackPalette_ = (byte *)malloc(256 * 3);
|
||||
int fadeStep = 0;
|
||||
for (int i = 0; i <= kFadeStep; i++) {
|
||||
for (int j = 0; j < 256; j++) {
|
||||
blackPalette_[3 * j] = palette[3 * j] * fadeStep / 4;
|
||||
blackPalette_[3 * j + 1] = palette[3 * j + 1] * fadeStep / 4;
|
||||
blackPalette_[3 * j + 2] = palette[3 * j + 2] * fadeStep / 4;
|
||||
}
|
||||
fadeStep++;
|
||||
_graph->setPalette(blackPalette_);
|
||||
_system->updateScreen();
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _system->getEventManager();
|
||||
eventMan->pollEvent(event);
|
||||
if (shouldQuit()) {
|
||||
_graph->setPalette(palette);
|
||||
free(blackPalette_);
|
||||
return;
|
||||
}
|
||||
pausePrinceEngine();
|
||||
}
|
||||
_graph->setPalette(palette);
|
||||
free(blackPalette_);
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::doTalkAnim(int animNumber, int slot, AnimType animType) {
|
||||
Text &text = _textSlots[slot];
|
||||
int lines = calcTextLines((const char *)_interpreter->getString());
|
||||
int time = lines * 30;
|
||||
if (animType == kNormalAnimation) {
|
||||
Anim &normAnim = _normAnimList[animNumber];
|
||||
if (normAnim._animData != nullptr) {
|
||||
if (!normAnim._state) {
|
||||
if (normAnim._currW && normAnim._currH) {
|
||||
text._color = _flags->getFlagValue(Flags::KOLOR);
|
||||
text._x = normAnim._currX + normAnim._currW / 2;
|
||||
text._y = normAnim._currY - 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (animType == kBackgroundAnimation) {
|
||||
if (!_backAnimList[animNumber].backAnims.empty()) {
|
||||
int currAnim = _backAnimList[animNumber]._seq._currRelative;
|
||||
Anim &backAnim = _backAnimList[animNumber].backAnims[currAnim];
|
||||
if (backAnim._animData != nullptr) {
|
||||
if (!backAnim._state) {
|
||||
if (backAnim._currW && backAnim._currH) {
|
||||
text._color = _flags->getFlagValue(Flags::KOLOR);
|
||||
text._x = backAnim._currX + backAnim._currW / 2;
|
||||
text._y = backAnim._currY - 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error("doTalkAnim() - wrong animType: %d", animType);
|
||||
}
|
||||
text._time = time;
|
||||
if (getLanguage() == Common::DE_DEU) {
|
||||
correctStringDEU((char *)_interpreter->getString());
|
||||
}
|
||||
text._str = (const char *)_interpreter->getString();
|
||||
|
||||
if (slot == 9) {
|
||||
// Location 4 has the gambling merchants, who speak frequently and can interrupt the player's
|
||||
// dialog with other characters, so don't voice their text unless the player isn't in dialog
|
||||
if ((!_dialogFlag && !_isConversing) || _locationNr != 4) {
|
||||
setTTSVoice(text._color);
|
||||
sayText(text._str, true, Common::TextToSpeechManager::QUEUE);
|
||||
}
|
||||
} else {
|
||||
setTTSVoice(text._color);
|
||||
sayText(text._str, true);
|
||||
}
|
||||
|
||||
_interpreter->increaseString();
|
||||
}
|
||||
|
||||
void PrinceEngine::freeNormAnim(int slot) {
|
||||
if (!_normAnimList.empty()) {
|
||||
_normAnimList[slot]._state = 1;
|
||||
if (_normAnimList[slot]._animData != nullptr) {
|
||||
delete _normAnimList[slot]._animData;
|
||||
_normAnimList[slot]._animData = nullptr;
|
||||
}
|
||||
if (_normAnimList[slot]._shadowData != nullptr) {
|
||||
delete _normAnimList[slot]._shadowData;
|
||||
_normAnimList[slot]._shadowData = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::freeAllNormAnims() {
|
||||
for (int i = 0; i < kMaxNormAnims; i++) {
|
||||
freeNormAnim(i);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
414
engines/prince/flags.cpp
Normal file
414
engines/prince/flags.cpp
Normal file
@@ -0,0 +1,414 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/flags.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
struct FlagDebug {
|
||||
uint id;
|
||||
char flagName[30];
|
||||
} static const flagNames[] = {
|
||||
{ Flags::FLAGA1, "FLAGA1" },
|
||||
{ Flags::FLAGA2, "FLAGA2" },
|
||||
{ Flags::FLAGA3, "FLAGA3" },
|
||||
{ Flags::DESTX, "DESTX" },
|
||||
{ Flags::DESTY, "DESTY" },
|
||||
{ Flags::DESTD, "DESTD" },
|
||||
{ Flags::DwarfDone, "DwarfDone" },
|
||||
{ Flags::GRABARZCOUNTER, "GRABARZCOUNTER" },
|
||||
{ Flags::KIERUNEK, "KIERUNEK" },
|
||||
{ Flags::BACKFLAG1, "BACKFLAG1" },
|
||||
{ Flags::BACKFLAG2, "BACKFLAG2" },
|
||||
{ Flags::BACKFLAG3, "BACKFLAG3" },
|
||||
{ Flags::BACKFLAG4, "BACKFLAG4" },
|
||||
{ Flags::MACROFLAG1, "MACROFLAG1" },
|
||||
{ Flags::MACROFLAG2, "MACROFLAG2" },
|
||||
{ Flags::MACROFLAG3, "MACROFLAG3" },
|
||||
{ Flags::HEROLDDONE, "HEROLDDONE" },
|
||||
{ Flags::BRIDGESET, "BRIDGESET" },
|
||||
{ Flags::U_BT_1, "U_BT_1" },
|
||||
{ Flags::U_BT_2, "U_BT_2" },
|
||||
{ Flags::U_BT_3, "U_BT_3" },
|
||||
{ Flags::U_BT_4, "U_BT_4" },
|
||||
{ Flags::U_BT_5, "U_BT_5" },
|
||||
{ Flags::U_BT_6, "U_BT_6" },
|
||||
{ Flags::U_BT_7, "U_BT_7" },
|
||||
{ Flags::U_BT_8, "U_BT_8" },
|
||||
{ Flags::U_BT_9, "U_BT_9" },
|
||||
{ Flags::U_BT_COUNTER, "U_BT_COUNTER" },
|
||||
{ Flags::ARIVALDALIVE, "ARIVALDALIVE" },
|
||||
{ Flags::TALKCHAR1, "TALKCHAR1" },
|
||||
{ Flags::TalkType1, "TalkType1" },
|
||||
{ Flags::TALKROUT1, "TALKROUT1" },
|
||||
{ Flags::TALKROUT2, "TALKROUT2" },
|
||||
{ Flags::TALKROUT3, "TALKROUT3" },
|
||||
{ Flags::TALKROUT4, "TALKROUT4" },
|
||||
{ Flags::TALKANIM1, "TALKANIM1" },
|
||||
{ Flags::TALKANIM2, "TALKANIM2" },
|
||||
{ Flags::TALKCOLOR1, "TALKCOLOR1" },
|
||||
{ Flags::TALKCOLOR2, "TALKCOLOR2" },
|
||||
{ Flags::KapciuchTaken, "KapciuchTaken" },
|
||||
{ Flags::CurrentBeggarA, "CurrentBeggarA" },
|
||||
{ Flags::TempKapc, "TempKapc" },
|
||||
{ Flags::HomTaken, "HomTaken" },
|
||||
{ Flags::WizardTalk, "WizardTalk" },
|
||||
{ Flags::SunlordTalk, "SunlordTalk" },
|
||||
{ Flags::HermitTalk, "HermitTalk" },
|
||||
{ Flags::RunyMode, "RunyMode" },
|
||||
{ Flags::FatMerchantTalk, "FatMerchantTalk" },
|
||||
{ Flags::HotDogTalk, "HotDogTalk" },
|
||||
{ Flags::ThiefTalk, "ThiefTalk" },
|
||||
{ Flags::BeggarTalk, "BeggarTalk" },
|
||||
{ Flags::MonkTalk, "MonkTalk" },
|
||||
{ Flags::BardTalk, "BardTalk" },
|
||||
{ Flags::BarmanTalk, "BarmanTalk" },
|
||||
{ Flags::LeftPlayerTalk, "LeftPlayerTalk" },
|
||||
{ Flags::OczySowy, "OczySowy" },
|
||||
{ Flags::CzachySpeed1, "CzachySpeed1" },
|
||||
{ Flags::CzachySpeed2, "CzachySpeed2" },
|
||||
{ Flags::CzachySpeed3, "CzachySpeed3" },
|
||||
{ Flags::CzachySlowDown1, "CzachySlowDown1" },
|
||||
{ Flags::CzachySlowDown2, "CzachySlowDown2" },
|
||||
{ Flags::CzachySlowDown3, "CzachySlowDown3" },
|
||||
{ Flags::FjordDane, "FjordDane" },
|
||||
{ Flags::GKopany1, "GKopany1" },
|
||||
{ Flags::GKopany2, "GKopany2" },
|
||||
{ Flags::GKopany3, "GKopany3" },
|
||||
{ Flags::GKopany4, "GKopany4" },
|
||||
{ Flags::KnowGodWord, "KnowGodWord" },
|
||||
{ Flags::TALKROUT21, "TALKROUT21" },
|
||||
{ Flags::TALKROUT22, "TALKROUT22" },
|
||||
{ Flags::TALKROUT23, "TALKROUT23" },
|
||||
{ Flags::TALKROUT24, "TALKROUT24" },
|
||||
{ Flags::TalkType2, "TalkType2" },
|
||||
{ Flags::GrabarzTalk, "GrabarzTalk" },
|
||||
{ Flags::LastTalker, "LastTalker" },
|
||||
{ Flags::MapaPustelniaEnabled, "MapaPustelniaEnabled" },
|
||||
{ Flags::MapaTempleEnabled, "MapaTempleEnabled" },
|
||||
{ Flags::MapaFjordEnabled, "MapaFjordEnabled" },
|
||||
{ Flags::MapaSilmanionaEnabled, "MapaSilmanionaEnabled" },
|
||||
{ Flags::MapaKurhanEnabled, "MapaKurhanEnabled" },
|
||||
{ Flags::MapaDragonEnabled, "MapaDragonEnabled" },
|
||||
{ Flags::MapaMillEnabled, "MapaMillEnabled" },
|
||||
{ Flags::DwarfRunning, "DwarfRunning" },
|
||||
{ Flags::DwarfTalk, "DwarfTalk" },
|
||||
{ Flags::CurseLift, "CurseLift" },
|
||||
{ Flags::KosciSwapped, "KosciSwapped" },
|
||||
{ Flags::BookStolen, "BookStolen" },
|
||||
{ Flags::MapaUsable, "MapaUsable" },
|
||||
{ Flags::FjordBoss, "FjordBoss" },
|
||||
{ Flags::FjordHotDog, "FjordHotDog" },
|
||||
{ Flags::FjordLewy, "FjordLewy" },
|
||||
{ Flags::FjordPrawy, "FjordPrawy" },
|
||||
{ Flags::TalkArivald, "TalkArivald" },
|
||||
{ Flags::ShootDone, "ShootDone" },
|
||||
{ Flags::ShootRunning, "ShootRunning" },
|
||||
{ Flags::ShootKnow, "ShootKnow" },
|
||||
{ Flags::MirrorKnow, "MirrorKnow" },
|
||||
{ Flags::Gar1stTime, "Gar1stTime" },
|
||||
{ Flags::KosciTaken, "KosciTaken" },
|
||||
{ Flags::ArivGotSpell, "ArivGotSpell" },
|
||||
{ Flags::BookGiven, "BookGiven" },
|
||||
{ Flags::Wywieszka, "Wywieszka" },
|
||||
{ Flags::TalkSheila, "TalkSheila" },
|
||||
{ Flags::TalkSheila2, "TalkSheila2" },
|
||||
{ Flags::BackHuman, "BackHuman" },
|
||||
{ Flags::SkarbiecOpen, "SkarbiecOpen" },
|
||||
{ Flags::LustroTaken, "LustroTaken" },
|
||||
{ Flags::GargoyleHom, "GargoyleHom" },
|
||||
{ Flags::GargoyleBroken, "GargoyleBroken" },
|
||||
{ Flags::FjordDzien, "FjordDzien" },
|
||||
{ Flags::GargoyleHom2, "GargoyleHom2" },
|
||||
{ Flags::RunMonstersRunning, "RunMonstersRunning" },
|
||||
{ Flags::FoundPaperInCoffin, "FoundPaperInCoffin" },
|
||||
{ Flags::KnowSunlord, "KnowSunlord" },
|
||||
{ Flags::KnowSunlordTalk, "KnowSunlordTalk" },
|
||||
{ Flags::ArivaldCzyta, "ArivaldCzyta" },
|
||||
{ Flags::TelepX, "TelepX" },
|
||||
{ Flags::TelepY, "TelepY" },
|
||||
{ Flags::TelepDir, "TelepDir" },
|
||||
{ Flags::TelepRoom, "TelepRoom" },
|
||||
{ Flags::ListStolen, "ListStolen" },
|
||||
{ Flags::WifeInDoor, "WifeInDoor" },
|
||||
{ Flags::TalkWifeFlag, "TalkWifeFlag" },
|
||||
{ Flags::LetterGiven, "LetterGiven" },
|
||||
{ Flags::LutniaTaken, "LutniaTaken" },
|
||||
{ Flags::BardHomeOpen, "BardHomeOpen" },
|
||||
{ Flags::FjordNoMonsters, "FjordNoMonsters" },
|
||||
{ Flags::ShandriaWallTalking, "ShandriaWallTalking" },
|
||||
{ Flags::ShandriaWallCounter, "ShandriaWallCounter" },
|
||||
{ Flags::ShandriaWallDone, "ShandriaWallDone" },
|
||||
{ Flags::FutureDone, "FutureDone" },
|
||||
{ Flags::TalkButch, "TalkButch" },
|
||||
{ Flags::GotSzalik, "GotSzalik" },
|
||||
{ Flags::GotCzosnek, "GotCzosnek" },
|
||||
{ Flags::BearDone, "BearDone" },
|
||||
{ Flags::NekrVisited, "NekrVisited" },
|
||||
{ Flags::SunRiddle, "SunRiddle" },
|
||||
{ Flags::PtaszekAway, "PtaszekAway" },
|
||||
{ Flags::KotGadanie, "KotGadanie" },
|
||||
{ Flags::SzlafmycaTaken, "SzlafmycaTaken" },
|
||||
{ Flags::BabkaTalk, "BabkaTalk" },
|
||||
{ Flags::SellerTalk, "SellerTalk" },
|
||||
{ Flags::CzosnekDone, "CzosnekDone" },
|
||||
{ Flags::PriestCounter, "PriestCounter" },
|
||||
{ Flags::PriestGest1, "PriestGest1" },
|
||||
{ Flags::PriestGest2, "PriestGest2" },
|
||||
{ Flags::PriestGest3, "PriestGest3" },
|
||||
{ Flags::PriestGest4, "PriestGest4" },
|
||||
{ Flags::PriestAnim, "PriestAnim" },
|
||||
{ Flags::HolyWaterTaken, "HolyWaterTaken" },
|
||||
{ Flags::AxeTaken, "AxeTaken" },
|
||||
{ Flags::BadylTaken1, "BadylTaken1" },
|
||||
{ Flags::BadylTaken2, "BadylTaken2" },
|
||||
{ Flags::BadylSharpened, "BadylSharpened" },
|
||||
{ Flags::PorwanieSmoka, "PorwanieSmoka" },
|
||||
{ Flags::ShopReOpen, "ShopReOpen" },
|
||||
{ Flags::LuskaShown, "LuskaShown" },
|
||||
{ Flags::CudKnow, "CudKnow" },
|
||||
{ Flags::VampireDead, "VampireDead" },
|
||||
{ Flags::MapaVisible1, "MapaVisible1" },
|
||||
{ Flags::MapaVisible2, "MapaVisible2" },
|
||||
{ Flags::MapaVisible3, "MapaVisible3" },
|
||||
{ Flags::MapaVisible4, "MapaVisible4" },
|
||||
{ Flags::MapaVisible5, "MapaVisible5" },
|
||||
{ Flags::MapaVisible6, "MapaVisible6" },
|
||||
{ Flags::MapaVisible7, "MapaVisible7" },
|
||||
{ Flags::MapaVisible8, "MapaVisible8" },
|
||||
{ Flags::MapaVisible9, "MapaVisible9" },
|
||||
{ Flags::MapaX, "MapaX" },
|
||||
{ Flags::MapaY, "MapaY" },
|
||||
{ Flags::MapaD, "MapaD" },
|
||||
{ Flags::OldMapaX, "OldMapaX" },
|
||||
{ Flags::OldMapaY, "OldMapaY" },
|
||||
{ Flags::OldMapaD, "OldMapaD" },
|
||||
{ Flags::MovingBack, "MovingBack" },
|
||||
{ Flags::MapaCount, "MapaCount" },
|
||||
{ Flags::Pustelnia1st, "Pustelnia1st" },
|
||||
{ Flags::CzarnePole1st, "CzarnePole1st" },
|
||||
{ Flags::TalkArivNum, "TalkArivNum" },
|
||||
{ Flags::Pfui, "Pfui" },
|
||||
{ Flags::MapaSunlordEnabled, "MapaSunlordEnabled" },
|
||||
{ Flags::WebDone, "WebDone" },
|
||||
{ Flags::DragonDone, "DragonDone" },
|
||||
{ Flags::KanPlay, "KanPlay" },
|
||||
{ Flags::OldKanPlay, "OldKanPlay" },
|
||||
{ Flags::LapkiWait, "LapkiWait" },
|
||||
{ Flags::WebNoCheck, "WebNoCheck" },
|
||||
{ Flags::Perfumeria, "Perfumeria" },
|
||||
{ Flags::SmokNoCheck, "SmokNoCheck" },
|
||||
{ Flags::IluzjaBroken, "IluzjaBroken" },
|
||||
{ Flags::IluzjaWorking, "IluzjaWorking" },
|
||||
{ Flags::IluzjaCounter, "IluzjaCounter" },
|
||||
{ Flags::KurhanOpen1, "KurhanOpen1" },
|
||||
{ Flags::KastetTaken, "KastetTaken" },
|
||||
{ Flags::KastetDown, "KastetDown" },
|
||||
{ Flags::KurhanDone, "KurhanDone" },
|
||||
{ Flags::SkelCounter, "SkelCounter" },
|
||||
{ Flags::SkelDial1, "SkelDial1" },
|
||||
{ Flags::SkelDial2, "SkelDial2" },
|
||||
{ Flags::SkelDial3, "SkelDial3" },
|
||||
{ Flags::SkelDial4, "SkelDial4" },
|
||||
{ Flags::SameTalker, "SameTalker" },
|
||||
{ Flags::RunMonstersText, "RunMonstersText" },
|
||||
{ Flags::PiwnicaChecked, "PiwnicaChecked" },
|
||||
{ Flags::DragonTalked, "DragonTalked" },
|
||||
{ Flags::ToldAboutBook, "ToldAboutBook" },
|
||||
{ Flags::SilmanionaDone, "SilmanionaDone" },
|
||||
{ Flags::ToldBookCount, "ToldBookCount" },
|
||||
{ Flags::SmrodNoCheck, "SmrodNoCheck" },
|
||||
{ Flags::RopeTaken, "RopeTaken" },
|
||||
{ Flags::RopeTime, "RopeTime" },
|
||||
{ Flags::LaskaFree, "LaskaFree" },
|
||||
{ Flags::ShanSmokTalked, "ShanSmokTalked" },
|
||||
{ Flags::SwordTaken, "SwordTaken" },
|
||||
{ Flags::Mill1st, "Mill1st" },
|
||||
{ Flags::SawRat, "SawRat" },
|
||||
{ Flags::KnowRat, "KnowRat" },
|
||||
{ Flags::DziuraTimer, "DziuraTimer" },
|
||||
{ Flags::LaskaInside, "LaskaInside" },
|
||||
{ Flags::HoleBig, "HoleBig" },
|
||||
{ Flags::EnableWiedzmin, "EnableWiedzmin" },
|
||||
{ Flags::EnableTrucizna, "EnableTrucizna" },
|
||||
{ Flags::KnowPoison, "KnowPoison" },
|
||||
{ Flags::KufelTaken, "KufelTaken" },
|
||||
{ Flags::BojkaEnabled, "BojkaEnabled" },
|
||||
{ Flags::BitwaNot1st, "BitwaNot1st" },
|
||||
{ Flags::BojkaTimer, "BojkaTimer" },
|
||||
{ Flags::BojkaGirl, "BojkaGirl" },
|
||||
{ Flags::Look1st, "Look1st" },
|
||||
{ Flags::RatTaken, "RatTaken" },
|
||||
{ Flags::LaskaTalkedGr, "LaskaTalkedGr" },
|
||||
{ Flags::RatusGivus, "RatusGivus" },
|
||||
{ Flags::MamObole, "MamObole" },
|
||||
{ Flags::Speed1st, "Speed1st" },
|
||||
{ Flags::SpeedTimer, "SpeedTimer" },
|
||||
{ Flags::ProveIt, "ProveIt" },
|
||||
{ Flags::Proven, "Proven" },
|
||||
{ Flags::ShowWoalka, "ShowWoalka" },
|
||||
{ Flags::PoisonTaken, "PoisonTaken" },
|
||||
{ Flags::HellOpened, "HellOpened" },
|
||||
{ Flags::HellNoCheck, "HellNoCheck" },
|
||||
{ Flags::TalAn1, "TalAn1" },
|
||||
{ Flags::TalAn2, "TalAn2" },
|
||||
{ Flags::TalAn3, "TalAn3" },
|
||||
{ Flags::TalkDevilGuard, "TalkDevilGuard" },
|
||||
{ Flags::Sword1st, "Sword1st" },
|
||||
{ Flags::IluzjaNoCheck, "IluzjaNoCheck" },
|
||||
{ Flags::RozdzielniaNumber, "RozdzielniaNumber" },
|
||||
{ Flags::JailChecked, "JailChecked" },
|
||||
{ Flags::JailTalked, "JailTalked" },
|
||||
{ Flags::TrickFailed, "TrickFailed" },
|
||||
{ Flags::WegielVisible, "WegielVisible" },
|
||||
{ Flags::WegielTimer1, "WegielTimer1" },
|
||||
{ Flags::RandomSample, "RandomSample" },
|
||||
{ Flags::RandomSampleTimer, "RandomSampleTimer" },
|
||||
{ Flags::SampleTimer, "SampleTimer" },
|
||||
{ Flags::ZonaSample, "ZonaSample" },
|
||||
{ Flags::HoleTryAgain, "HoleTryAgain" },
|
||||
{ Flags::TeleportTimer, "TeleportTimer" },
|
||||
{ Flags::RozLezy, "RozLezy" },
|
||||
{ Flags::UdkoTimer, "UdkoTimer" },
|
||||
{ Flags::ZaworZatkany, "ZaworZatkany" },
|
||||
{ Flags::ZaworOpened, "ZaworOpened" },
|
||||
{ Flags::DoorExploded, "DoorExploded" },
|
||||
{ Flags::SkoraTaken, "SkoraTaken" },
|
||||
{ Flags::CiezkieByl, "CiezkieByl" },
|
||||
{ Flags::MamWegiel, "MamWegiel" },
|
||||
{ Flags::SwiecaAway, "SwiecaAway" },
|
||||
{ Flags::ITSAVE, "ITSAVE" },
|
||||
{ Flags::RozpadlSie, "RozpadlSie" },
|
||||
{ Flags::WegielFullTimer, "WegielFullTimer" },
|
||||
{ Flags::WegielDown, "WegielDown" },
|
||||
{ Flags::WegielDownTimer, "WegielDownTimer" },
|
||||
{ Flags::PaliSie, "PaliSie" },
|
||||
{ Flags::DiabGuardTalked, "DiabGuardTalked" },
|
||||
{ Flags::GuardsNoCheck, "GuardsNoCheck" },
|
||||
{ Flags::TalkedPowloka, "TalkedPowloka" },
|
||||
{ Flags::JailOpen, "JailOpen" },
|
||||
{ Flags::PrzytulTimer, "PrzytulTimer" },
|
||||
{ Flags::JailDone, "JailDone" },
|
||||
{ Flags::MamMonety, "MamMonety" },
|
||||
{ Flags::LotTimer, "LotTimer" },
|
||||
{ Flags::LotObj, "LotObj" },
|
||||
{ Flags::PtakTimer, "PtakTimer" },
|
||||
{ Flags::BookTimer, "BookTimer" },
|
||||
{ Flags::BookGiba, "BookGiba" },
|
||||
{ Flags::PtakLata, "PtakLata" },
|
||||
{ Flags::Podej, "Podej" },
|
||||
{ Flags::GotHint, "GotHint" },
|
||||
{ Flags::LawaLeci, "LawaLeci" },
|
||||
{ Flags::PowerKlik, "PowerKlik" },
|
||||
{ Flags::LucekBad, "LucekBad" },
|
||||
{ Flags::LucekBad1st, "LucekBad1st" },
|
||||
{ Flags::IntroDial1, "IntroDial1" },
|
||||
{ Flags::IntroDial2, "IntroDial2" },
|
||||
{ Flags::ItsOutro, "ItsOutro" },
|
||||
{ Flags::KamienComment, "KamienComment" },
|
||||
{ Flags::KamienSkip, "KamienSkip" },
|
||||
{ Flags::TesterFlag, "TesterFlag" },
|
||||
{ Flags::RememberLine, "RememberLine" },
|
||||
{ Flags::OpisLapek, "OpisLapek" },
|
||||
{ Flags::TalWait, "TalWait" },
|
||||
{ Flags::OpisKamienia, "OpisKamienia" },
|
||||
{ Flags::JumpBox, "JumpBox" },
|
||||
{ Flags::JumpBox1, "JumpBox1" },
|
||||
{ Flags::JumpBox2, "JumpBox2" },
|
||||
{ Flags::JumpBox3, "JumpBox3" },
|
||||
{ Flags::SpecPiesek, "SpecPiesek" },
|
||||
{ Flags::SpecPiesekCount, "SpecPiesekCount" },
|
||||
{ Flags::SpecPiesekGadanie, "SpecPiesekGadanie" },
|
||||
{ Flags::ZnikaFlag, "ZnikaFlag" },
|
||||
{ Flags::ZnikaTimer, "ZnikaTimer" },
|
||||
{ Flags::SowaTimer, "SowaTimer" },
|
||||
{ Flags::MamrotanieOff, "MamrotanieOff" },
|
||||
{ Flags::CURRMOB, "CURRMOB" },
|
||||
{ Flags::KOLOR, "KOLOR" },
|
||||
{ Flags::MBFLAG, "MBFLAG" },
|
||||
{ Flags::MXFLAG, "MXFLAG" },
|
||||
{ Flags::MYFLAG, "MYFLAG" },
|
||||
{ Flags::SCROLLTYPE, "SCROLLTYPE" },
|
||||
{ Flags::SCROLLVALUE, "SCROLLVALUE" },
|
||||
{ Flags::SCROLLVALUE2, "SCROLLVALUE2" },
|
||||
{ Flags::TALKEXITCODE, "TALKEXITCODE" },
|
||||
{ Flags::SPECROUTFLAG1, "SPECROUTFLAG1" },
|
||||
{ Flags::SPECROUTFLAG2, "SPECROUTFLAG2" },
|
||||
{ Flags::SPECROUTFLAG3, "SPECROUTFLAG3" },
|
||||
{ Flags::TALKFLAGCODE, "TALKFLAGCODE" },
|
||||
{ Flags::CURRROOM, "CURRROOM" },
|
||||
{ Flags::Talker1Init, "Talker1Init" },
|
||||
{ Flags::Talker2Init, "Talker2Init" },
|
||||
{ Flags::RESTOREROOM, "RESTOREROOM" },
|
||||
{ Flags::INVALLOWED, "INVALLOWED" },
|
||||
{ Flags::BOXSEL, "BOXSEL" },
|
||||
{ Flags::CURSEBLINK, "CURSEBLINK" },
|
||||
{ Flags::EXACTMOVE, "EXACTMOVE" },
|
||||
{ Flags::MOVEDESTX, "MOVEDESTX" },
|
||||
{ Flags::MOVEDESTY, "MOVEDESTY" },
|
||||
{ Flags::NOANTIALIAS, "NOANTIALIAS" },
|
||||
{ Flags::ESCAPED, "ESCAPED" },
|
||||
{ Flags::ALLOW1OPTION, "ALLOW1OPTION" },
|
||||
{ Flags::VOICE_H_LINE, "VOICE_H_LINE" },
|
||||
{ Flags::VOICE_A_LINE, "VOICE_A_LINE" },
|
||||
{ Flags::VOICE_B_LINE, "VOICE_B_LINE" },
|
||||
{ Flags::VOICE_C_LINE, "VOICE_C_LINE" },
|
||||
{ Flags::NOHEROATALL, "NOHEROATALL" },
|
||||
{ Flags::MOUSEENABLED, "MOUSEENABLED" },
|
||||
{ Flags::DIALINES, "DIALINES" },
|
||||
{ Flags::SHANWALK, "SHANWALK" },
|
||||
{ Flags::SHANDOG, "SHANDOG" },
|
||||
{ Flags::GETACTIONBACK, "GETACTIONBACK" },
|
||||
{ Flags::GETACTIONDATA, "GETACTIONDATA" },
|
||||
{ Flags::GETACTION, "GETACTION" },
|
||||
{ Flags::HEROFAST, "HEROFAST" },
|
||||
{ Flags::SELITEM, "SELITEM" },
|
||||
{ Flags::LMOUSE, "LMOUSE" },
|
||||
{ Flags::MINMX, "MINMX" },
|
||||
{ Flags::MAXMX, "MAXMX" },
|
||||
{ Flags::MINMY, "MINMY" },
|
||||
{ Flags::MAXMY, "MAXMY" },
|
||||
{ Flags::TORX1, "TORX1" },
|
||||
{ Flags::TORY1, "TORY1" },
|
||||
{ Flags::TORX2, "TORX2" },
|
||||
{ Flags::TORY2, "TORY2" },
|
||||
{ Flags::POWER, "POWER" },
|
||||
{ Flags::POWERENABLED, "POWERENABLED" },
|
||||
{ Flags::FLCRESTORE, "FLCRESTORE" },
|
||||
{ Flags::NOCLSTEXT, "NOCLSTEXT" },
|
||||
{ Flags::ESCAPED2, "ESCAPED2" },
|
||||
};
|
||||
|
||||
|
||||
Flags::Flags() {
|
||||
for (uint i = 0; i < ARRAYSIZE(flagNames); i++) {
|
||||
_flagMap[flagNames[i].id] = flagNames[i].flagName;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Flags::getFlagName(uint16 flagId) {
|
||||
if (_flagMap.contains(flagId))
|
||||
return _flagMap[flagId];
|
||||
|
||||
return "unknown_flag";
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
416
engines/prince/flags.h
Normal file
416
engines/prince/flags.h
Normal file
@@ -0,0 +1,416 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_FLAGS_H
|
||||
#define PRINCE_FLAGS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/hashmap.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Flags {
|
||||
public:
|
||||
Flags();
|
||||
const char *getFlagName(uint16 flagId);
|
||||
|
||||
enum Id {
|
||||
FLAGA1 = 0x8000,
|
||||
FLAGA2 = 0x8002,
|
||||
FLAGA3 = 0x8004,
|
||||
DESTX = 0x8006,
|
||||
DESTY = 0x8008,
|
||||
DESTD = 0x800A,
|
||||
DwarfDone = 0x800C,
|
||||
GRABARZCOUNTER = 0x800E,
|
||||
KIERUNEK = 0x8010,
|
||||
BACKFLAG1 = 0x8012,
|
||||
BACKFLAG2 = 0x8014,
|
||||
BACKFLAG3 = 0x8016,
|
||||
BACKFLAG4 = 0x8018,
|
||||
MACROFLAG1 = 0x801A,
|
||||
MACROFLAG2 = 0x801C,
|
||||
MACROFLAG3 = 0x801E,
|
||||
HEROLDDONE = 0x8020,
|
||||
BRIDGESET = 0x8022,
|
||||
U_BT_1 = 0x8024,
|
||||
U_BT_2 = 0x8026,
|
||||
U_BT_3 = 0x8028,
|
||||
U_BT_4 = 0x802A,
|
||||
U_BT_5 = 0x802C,
|
||||
U_BT_6 = 0x802E,
|
||||
U_BT_7 = 0x8030,
|
||||
U_BT_8 = 0x8032,
|
||||
U_BT_9 = 0x8034,
|
||||
U_BT_COUNTER = 0x8036,
|
||||
ARIVALDALIVE = 0x8038,
|
||||
TALKCHAR1 = 0x803A,
|
||||
TalkType1 = 0x803C,
|
||||
TALKROUT1 = 0x803E,
|
||||
TALKROUT2 = 0x8042,
|
||||
TALKROUT3 = 0x8046,
|
||||
TALKROUT4 = 0x804A,
|
||||
TALKANIM1 = 0x804E,
|
||||
TALKANIM2 = 0x8050,
|
||||
TALKCOLOR1 = 0x8052,
|
||||
TALKCOLOR2 = 0x8054,
|
||||
KapciuchTaken = 0x8056,
|
||||
CurrentBeggarA = 0x8058,
|
||||
TempKapc = 0x805A,
|
||||
HomTaken = 0x805C,
|
||||
WizardTalk = 0x805E,
|
||||
SunlordTalk = 0x8060,
|
||||
HermitTalk = 0x8062,
|
||||
RunyMode = 0x8064,
|
||||
FatMerchantTalk = 0x8066,
|
||||
HotDogTalk = 0x8068,
|
||||
ThiefTalk = 0x806A,
|
||||
BeggarTalk = 0x806C,
|
||||
// DwarfTalk = 0x806E, // Redefinition
|
||||
MonkTalk = 0x8070,
|
||||
BardTalk = 0x8072,
|
||||
BarmanTalk = 0x8074,
|
||||
LeftPlayerTalk = 0x8076,
|
||||
OczySowy = 0x8078,
|
||||
CzachySpeed1 = 0x807A,
|
||||
CzachySpeed2 = 0x807C,
|
||||
CzachySpeed3 = 0x807E,
|
||||
CzachySlowDown1 = 0x8080,
|
||||
CzachySlowDown2 = 0x8082,
|
||||
CzachySlowDown3 = 0x8084,
|
||||
FjordDane = 0x8086,
|
||||
GKopany1 = 0x8088,
|
||||
GKopany2 = 0x808A,
|
||||
GKopany3 = 0x808C,
|
||||
GKopany4 = 0x808E,
|
||||
KnowGodWord = 0x8090,
|
||||
TALKROUT21 = 0x8092,
|
||||
TALKROUT22 = 0x8096,
|
||||
TALKROUT23 = 0x809A,
|
||||
TALKROUT24 = 0x809E,
|
||||
TalkType2 = 0x80A2,
|
||||
GrabarzTalk = 0x80A4,
|
||||
LastTalker = 0x80A6,
|
||||
MapaPustelniaEnabled = 0x80A8,
|
||||
MapaTempleEnabled = 0x80AA,
|
||||
MapaFjordEnabled = 0x80AC,
|
||||
MapaSilmanionaEnabled = 0x80AE,
|
||||
MapaKurhanEnabled = 0x80B0,
|
||||
MapaDragonEnabled = 0x80B2,
|
||||
MapaMillEnabled = 0x80B4,
|
||||
DwarfRunning = 0x80B6,
|
||||
DwarfTalk = 0x80B8,
|
||||
CurseLift = 0x80BA,
|
||||
KosciSwapped = 0x80BC,
|
||||
BookStolen = 0x80BE,
|
||||
MapaUsable = 0x80C0,
|
||||
FjordBoss = 0x80C2,
|
||||
FjordHotDog = 0x80C4,
|
||||
FjordLewy = 0x80C6,
|
||||
FjordPrawy = 0x80C8,
|
||||
TalkArivald = 0x80CA,
|
||||
ShootDone = 0x80CC,
|
||||
ShootRunning = 0x80CE,
|
||||
ShootKnow = 0x80D0,
|
||||
MirrorKnow = 0x80D2,
|
||||
Gar1stTime = 0x80D4,
|
||||
KosciTaken = 0x80D6,
|
||||
ArivGotSpell = 0x80D8,
|
||||
BookGiven = 0x80DA,
|
||||
Wywieszka = 0x80DC,
|
||||
TalkSheila = 0x80DE,
|
||||
TalkSheila2 = 0x80E0,
|
||||
BackHuman = 0x80E2,
|
||||
SkarbiecOpen = 0x80E4,
|
||||
LustroTaken = 0x80E6,
|
||||
GargoyleHom = 0x80E8,
|
||||
GargoyleBroken = 0x80EA,
|
||||
FjordDzien = 0x80EC,
|
||||
GargoyleHom2 = 0x80EE,
|
||||
RunMonstersRunning = 0x80F0,
|
||||
FoundPaperInCoffin = 0x80F2,
|
||||
KnowSunlord = 0x80F4,
|
||||
KnowSunlordTalk = 0x80F6,
|
||||
ArivaldCzyta = 0x80F8,
|
||||
TelepX = 0x80FA,
|
||||
TelepY = 0x80FC,
|
||||
TelepDir = 0x80FE,
|
||||
TelepRoom = 0x8100,
|
||||
ListStolen = 0x8102,
|
||||
WifeInDoor = 0x8104,
|
||||
TalkWifeFlag = 0x8106,
|
||||
LetterGiven = 0x8108,
|
||||
LutniaTaken = 0x810A,
|
||||
BardHomeOpen = 0x810C,
|
||||
FjordNoMonsters = 0x810E,
|
||||
ShandriaWallTalking = 0x8110,
|
||||
ShandriaWallCounter = 0x8112,
|
||||
ShandriaWallDone = 0x8114,
|
||||
FutureDone = 0x8116,
|
||||
TalkButch = 0x8118,
|
||||
GotSzalik = 0x811A,
|
||||
GotCzosnek = 0x811C,
|
||||
BearDone = 0x811E,
|
||||
NekrVisited = 0x8120,
|
||||
SunRiddle = 0x8122,
|
||||
PtaszekAway = 0x8124,
|
||||
KotGadanie = 0x8126,
|
||||
SzlafmycaTaken = 0x8128,
|
||||
BabkaTalk = 0x812A,
|
||||
SellerTalk = 0x812C,
|
||||
CzosnekDone = 0x812E,
|
||||
PriestCounter = 0x8130,
|
||||
PriestGest1 = 0x8132,
|
||||
PriestGest2 = 0x8134,
|
||||
PriestGest3 = 0x8136,
|
||||
PriestGest4 = 0x8138,
|
||||
PriestAnim = 0x813A,
|
||||
HolyWaterTaken = 0x813C,
|
||||
AxeTaken = 0x813E,
|
||||
BadylTaken1 = 0x8140,
|
||||
BadylTaken2 = 0x8142,
|
||||
BadylSharpened = 0x8144,
|
||||
PorwanieSmoka = 0x8146,
|
||||
ShopReOpen = 0x8148,
|
||||
LuskaShown = 0x814A,
|
||||
CudKnow = 0x814C,
|
||||
VampireDead = 0x814E,
|
||||
MapaVisible1 = 0x8150,
|
||||
MapaVisible2 = 0x8152,
|
||||
MapaVisible3 = 0x8154,
|
||||
MapaVisible4 = 0x8156,
|
||||
MapaVisible5 = 0x8158,
|
||||
MapaVisible6 = 0x815A,
|
||||
MapaVisible7 = 0x815C,
|
||||
MapaVisible8 = 0x815E,
|
||||
MapaVisible9 = 0x8160,
|
||||
MapaX = 0x8162,
|
||||
MapaY = 0x8164,
|
||||
MapaD = 0x8166,
|
||||
OldMapaX = 0x8168,
|
||||
OldMapaY = 0x816A,
|
||||
OldMapaD = 0x816C,
|
||||
MovingBack = 0x816E,
|
||||
MapaCount = 0x8170,
|
||||
Pustelnia1st = 0x8172,
|
||||
CzarnePole1st = 0x8174,
|
||||
TalkArivNum = 0x8176,
|
||||
Pfui = 0x8178,
|
||||
MapaSunlordEnabled = 0x817A,
|
||||
WebDone = 0x817C,
|
||||
DragonDone = 0x817E,
|
||||
KanPlay = 0x8180,
|
||||
OldKanPlay = 0x8182,
|
||||
LapkiWait = 0x8184,
|
||||
WebNoCheck = 0x8186,
|
||||
Perfumeria = 0x8188,
|
||||
SmokNoCheck = 0x818A,
|
||||
IluzjaBroken = 0x818C,
|
||||
IluzjaWorking = 0x818E,
|
||||
IluzjaCounter = 0x8190,
|
||||
KurhanOpen1 = 0x8192,
|
||||
KastetTaken = 0x8194,
|
||||
KastetDown = 0x8196,
|
||||
KurhanDone = 0x8198,
|
||||
SkelCounter = 0x819A,
|
||||
SkelDial1 = 0x819C,
|
||||
SkelDial2 = 0x819E,
|
||||
SkelDial3 = 0x81A0,
|
||||
SkelDial4 = 0x81A2,
|
||||
SameTalker = 0x81A4,
|
||||
RunMonstersText = 0x81A6,
|
||||
PiwnicaChecked = 0x81A8,
|
||||
DragonTalked = 0x81AA,
|
||||
ToldAboutBook = 0x81AC,
|
||||
SilmanionaDone = 0x81AE,
|
||||
ToldBookCount = 0x81B0,
|
||||
SmrodNoCheck = 0x81B2,
|
||||
RopeTaken = 0x81B4,
|
||||
RopeTime = 0x81B6,
|
||||
LaskaFree = 0x81B8,
|
||||
ShanSmokTalked = 0x81BA,
|
||||
SwordTaken = 0x81BC,
|
||||
Mill1st = 0x81BE,
|
||||
SawRat = 0x81C0,
|
||||
KnowRat = 0x81C2,
|
||||
DziuraTimer = 0x81C4,
|
||||
LaskaInside = 0x81C6,
|
||||
HoleBig = 0x81C8,
|
||||
EnableWiedzmin = 0x81CA,
|
||||
EnableTrucizna = 0x81CC,
|
||||
KnowPoison = 0x81CE,
|
||||
KufelTaken = 0x81D0,
|
||||
BojkaEnabled = 0x81D2,
|
||||
BitwaNot1st = 0x81D4,
|
||||
BojkaTimer = 0x81D6,
|
||||
BojkaGirl = 0x81D8,
|
||||
Look1st = 0x81DA,
|
||||
RatTaken = 0x81DC,
|
||||
LaskaTalkedGr = 0x81DE,
|
||||
RatusGivus = 0x81E0,
|
||||
MamObole = 0x81E2,
|
||||
Speed1st = 0x81E4,
|
||||
SpeedTimer = 0x81E6,
|
||||
ProveIt = 0x81E8,
|
||||
Proven = 0x81EA,
|
||||
ShowWoalka = 0x81EC,
|
||||
PoisonTaken = 0x81EE,
|
||||
HellOpened = 0x81F0,
|
||||
HellNoCheck = 0x81F2,
|
||||
TalAn1 = 0x81F4,
|
||||
TalAn2 = 0x81F6,
|
||||
TalAn3 = 0x81F8,
|
||||
TalkDevilGuard = 0x81fA,
|
||||
Sword1st = 0x81FC,
|
||||
IluzjaNoCheck = 0x81FE,
|
||||
RozdzielniaNumber = 0x8200,
|
||||
JailChecked = 0x8202,
|
||||
JailTalked = 0x8204,
|
||||
TrickFailed = 0x8206,
|
||||
WegielVisible = 0x8208,
|
||||
WegielTimer1 = 0x820A,
|
||||
RandomSample = 0x820C,
|
||||
RandomSampleTimer = 0x820E,
|
||||
SampleTimer = 0x8210,
|
||||
ZonaSample = 0x8212,
|
||||
HoleTryAgain = 0x8214,
|
||||
TeleportTimer = 0x8216,
|
||||
RozLezy = 0x8218,
|
||||
UdkoTimer = 0x821A,
|
||||
ZaworZatkany = 0x821C,
|
||||
ZaworOpened = 0x821E,
|
||||
DoorExploded = 0x8220,
|
||||
SkoraTaken = 0x8222,
|
||||
CiezkieByl = 0x8224,
|
||||
MamWegiel = 0x8226,
|
||||
SwiecaAway = 0x8228,
|
||||
ITSAVE = 0x822A,
|
||||
RozpadlSie = 0x822C,
|
||||
WegielFullTimer = 0x822E,
|
||||
WegielDown = 0x8230,
|
||||
WegielDownTimer = 0x8232,
|
||||
PaliSie = 0x8234,
|
||||
DiabGuardTalked = 0x8236,
|
||||
GuardsNoCheck = 0x8238,
|
||||
TalkedPowloka = 0x823A,
|
||||
JailOpen = 0x823C,
|
||||
PrzytulTimer = 0x823E,
|
||||
JailDone = 0x8240,
|
||||
MamMonety = 0x8242,
|
||||
LotTimer = 0x8244,
|
||||
LotObj = 0x8246,
|
||||
PtakTimer = 0x8248,
|
||||
BookTimer = 0x824A,
|
||||
BookGiba = 0x824C,
|
||||
PtakLata = 0x824E,
|
||||
Podej = 0x8250,
|
||||
GotHint = 0x8252,
|
||||
LawaLeci = 0x8254,
|
||||
PowerKlik = 0x8258,
|
||||
LucekBad = 0x825A,
|
||||
LucekBad1st = 0x825C,
|
||||
IntroDial1 = 0x825E,
|
||||
IntroDial2 = 0x8260,
|
||||
ItsOutro = 0x8262,
|
||||
KamienComment = 0x8264,
|
||||
KamienSkip = 0x8266,
|
||||
TesterFlag = 0x8268,
|
||||
RememberLine = 0x826A,
|
||||
OpisLapek = 0x826C,
|
||||
//OpisKamienia = 0x826E, // Redefinition
|
||||
TalWait = 0x8270,
|
||||
OpisKamienia = 0x8272,
|
||||
JumpBox = 0x8274,
|
||||
JumpBox1 = 0x8276,
|
||||
JumpBox2 = 0x8278,
|
||||
JumpBox3 = 0x827A,
|
||||
SpecPiesek = 0x827C,
|
||||
SpecPiesekCount = 0x827E,
|
||||
SpecPiesekGadanie = 0x8282,
|
||||
ZnikaFlag = 0x8284,
|
||||
ZnikaTimer = 0x8286,
|
||||
SowaTimer = 0x8288,
|
||||
MamrotanieOff = 0x828A,
|
||||
// System flags controlled by script
|
||||
CURRMOB = 0x8400,
|
||||
KOLOR = 0x8402,
|
||||
MBFLAG = 0x8404,
|
||||
MXFLAG = 0x8406,
|
||||
MYFLAG = 0x8408,
|
||||
SCROLLTYPE = 0x840A,
|
||||
SCROLLVALUE = 0x840C,
|
||||
SCROLLVALUE2 = 0x840E,
|
||||
TALKEXITCODE = 0x8410,
|
||||
SPECROUTFLAG1 = 0x8412,
|
||||
SPECROUTFLAG2 = 0x8414,
|
||||
SPECROUTFLAG3 = 0x8416,
|
||||
TALKFLAGCODE = 0x8418,
|
||||
CURRROOM = 0x841A,
|
||||
Talker1Init = 0x841C,
|
||||
Talker2Init = 0x841E,
|
||||
RESTOREROOM = 0x8420,
|
||||
INVALLOWED = 0x8422,
|
||||
BOXSEL = 0x8424,
|
||||
CURSEBLINK = 0x8426,
|
||||
EXACTMOVE = 0x8428,
|
||||
MOVEDESTX = 0x842A,
|
||||
MOVEDESTY = 0x842C,
|
||||
NOANTIALIAS = 0x842E,
|
||||
ESCAPED = 0x8430,
|
||||
ALLOW1OPTION = 0x8432,
|
||||
VOICE_H_LINE = 0x8434,
|
||||
VOICE_A_LINE = 0x8436,
|
||||
VOICE_B_LINE = 0x8438,
|
||||
VOICE_C_LINE = 0x843A,
|
||||
NOHEROATALL = 0x843C,
|
||||
MOUSEENABLED = 0x843E,
|
||||
DIALINES = 0x8440,
|
||||
//SELITEM = 0x8442, // Redefinition
|
||||
SHANWALK = 0x8444,
|
||||
SHANDOG = 0x8446,
|
||||
GETACTIONBACK = 0x8448,
|
||||
GETACTIONDATA = 0x844C,
|
||||
GETACTION = 0x8450,
|
||||
HEROFAST = 0x8452,
|
||||
SELITEM = 0x8454,
|
||||
LMOUSE = 0x8456,
|
||||
MINMX = 0x8458,
|
||||
MAXMX = 0x845A,
|
||||
MINMY = 0x845C,
|
||||
MAXMY = 0x845E,
|
||||
TORX1 = 0x8460,
|
||||
TORY1 = 0x8462,
|
||||
TORX2 = 0x8464,
|
||||
TORY2 = 0x8466,
|
||||
POWER = 0x8468,
|
||||
POWERENABLED = 0x846A,
|
||||
FLCRESTORE = 0x846C,
|
||||
NOCLSTEXT = 0x846E,
|
||||
ESCAPED2 = 0x8470
|
||||
};
|
||||
|
||||
private:
|
||||
Common::HashMap<uint, const char *> _flagMap;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
93
engines/prince/font.cpp
Normal file
93
engines/prince/font.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "prince/font.h"
|
||||
#include "prince/prince.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
Font::Font() : _fontData(nullptr) {
|
||||
}
|
||||
|
||||
Font::~Font() {
|
||||
if (_fontData != nullptr) {
|
||||
free(_fontData);
|
||||
_fontData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Font::loadStream(Common::SeekableReadStream &stream) {
|
||||
stream.seek(0);
|
||||
uint32 dataSize = stream.size();
|
||||
_fontData = (byte *)malloc(dataSize);
|
||||
stream.read(_fontData, stream.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
int Font::getFontHeight() const {
|
||||
return _fontData[5];
|
||||
}
|
||||
|
||||
int Font::getMaxCharWidth() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Font::ChrData Font::getChrData(byte chr) const {
|
||||
chr -= 32;
|
||||
uint16 chrOffset = 4 * chr + 6;
|
||||
|
||||
ChrData chrData;
|
||||
chrData._width = _fontData[chrOffset + 2];
|
||||
chrData._height = _fontData[chrOffset + 3];
|
||||
chrData._pixels = _fontData + READ_LE_UINT16(_fontData + chrOffset);
|
||||
|
||||
return chrData;
|
||||
}
|
||||
|
||||
int Font::getCharWidth(uint32 chr) const {
|
||||
return getChrData(chr)._width;
|
||||
}
|
||||
|
||||
void Font::drawChar(Graphics::Surface *dst, uint32 chr, int posX, int posY, uint32 color) const {
|
||||
const ChrData chrData = getChrData(chr);
|
||||
Common::Rect screenRect(0, 0, PrinceEngine::kNormalWidth, PrinceEngine::kNormalHeight);
|
||||
|
||||
for (int y = 0; y < chrData._height; y++) {
|
||||
for (int x = 0; x < chrData._width; x++) {
|
||||
byte d = chrData._pixels[x + (chrData._width * y)];
|
||||
if (d == 0) d = 255;
|
||||
else if (d == 1) d = 0;
|
||||
else if (d == 2) d = color;
|
||||
else if (d == 3) d = 0;
|
||||
if (d != 255) {
|
||||
if (screenRect.contains(posX + x, posY + y)) {
|
||||
*(byte *)dst->getBasePtr(posX + x, posY + y) = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
63
engines/prince/font.h
Normal file
63
engines/prince/font.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_FONT_H
|
||||
#define PRINCE_FONT_H
|
||||
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Font : public Graphics::Font {
|
||||
public:
|
||||
Font();
|
||||
~Font() override;
|
||||
|
||||
bool loadStream(Common::SeekableReadStream &stream);
|
||||
|
||||
int getFontHeight() const override;
|
||||
|
||||
int getMaxCharWidth() const override;
|
||||
|
||||
int getCharWidth(uint32 chr) const override;
|
||||
|
||||
void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
|
||||
|
||||
int getKerningOffset(uint32 left, uint32 right) const override { return -2; }
|
||||
|
||||
private:
|
||||
struct ChrData {
|
||||
byte *_pixels;
|
||||
byte _width;
|
||||
byte _height;
|
||||
};
|
||||
|
||||
ChrData getChrData(byte chr) const;
|
||||
|
||||
byte *_fontData;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
475
engines/prince/graphics.cpp
Normal file
475
engines/prince/graphics.cpp
Normal file
@@ -0,0 +1,475 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/graphics.h"
|
||||
#include "prince/prince.h"
|
||||
#include "prince/mhwanh.h"
|
||||
|
||||
#include "graphics/paletteman.h"
|
||||
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
GraphicsMan::GraphicsMan(PrinceEngine *vm) : _vm(vm), _changed(false) {
|
||||
initGraphics(640, 480);
|
||||
|
||||
_frontScreen = new Graphics::Surface();
|
||||
_frontScreen->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
_screenForInventory = new Graphics::Surface();
|
||||
_screenForInventory->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
_mapScreen = new Graphics::Surface();
|
||||
_mapScreen->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
_shadowTable70 = (byte *)malloc(256);
|
||||
_shadowTable50 = (byte *)malloc(256);
|
||||
|
||||
_roomBackground = nullptr;
|
||||
}
|
||||
|
||||
GraphicsMan::~GraphicsMan() {
|
||||
_frontScreen->free();
|
||||
delete _frontScreen;
|
||||
|
||||
_screenForInventory->free();
|
||||
delete _screenForInventory;
|
||||
|
||||
_mapScreen->free();
|
||||
delete _mapScreen;
|
||||
|
||||
free(_shadowTable70);
|
||||
free(_shadowTable50);
|
||||
}
|
||||
|
||||
void GraphicsMan::update(Graphics::Surface *screen) {
|
||||
if (_changed) {
|
||||
_vm->_system->copyRectToScreen((byte *)screen->getBasePtr(0, 0), 640, 0, 0, 640, 480);
|
||||
|
||||
_vm->_system->updateScreen();
|
||||
_changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsMan::setPalette(const byte *palette) {
|
||||
_vm->_system->getPaletteManager()->setPalette(palette, 0, 256);
|
||||
}
|
||||
|
||||
void GraphicsMan::change() {
|
||||
_changed = true;
|
||||
}
|
||||
|
||||
void GraphicsMan::draw(Graphics::Surface *screen, const Graphics::Surface *s) {
|
||||
uint16 w = MIN(screen->w, s->w);
|
||||
const byte *src = (const byte *)s->getBasePtr(0, 0);
|
||||
byte *dst = (byte *)screen->getBasePtr(0, 0);
|
||||
for (int y = 0; y < s->h; y++) {
|
||||
if (y < screen->h) {
|
||||
memcpy(dst, src, w);
|
||||
}
|
||||
src += s->pitch;
|
||||
dst += screen->pitch;
|
||||
}
|
||||
change();
|
||||
}
|
||||
|
||||
// Black (value = 0) as a primary transparent color, fix for FLC animations
|
||||
void GraphicsMan::drawTransparentSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s, int secondTransColor) {
|
||||
const byte *src1 = (const byte *)s->getBasePtr(0, 0);
|
||||
byte *dst1 = (byte *)screen->getBasePtr(posX, posY);
|
||||
for (int y = 0; y < s->h; y++) {
|
||||
if (y + posY < screen->h && y + posY >= 0) {
|
||||
const byte *src2 = src1;
|
||||
byte *dst2 = dst1;
|
||||
for (int x = 0; x < s->w; x++, src2++, dst2++) {
|
||||
if (*src2 && *src2 != secondTransColor) {
|
||||
if (x + posX < screen->w && x + posX >= 0) {
|
||||
*dst2 = *src2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
src1 += s->pitch;
|
||||
dst1 += screen->pitch;
|
||||
}
|
||||
change();
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to drawTransparentSurface but with use of shadowTable for color recalculation
|
||||
* and kShadowColor (191) as a transparent color.
|
||||
*/
|
||||
void GraphicsMan::drawAsShadowSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s, byte *shadowTable) {
|
||||
const byte *src1 = (const byte *)s->getBasePtr(0, 0);
|
||||
byte *dst1 = (byte *)screen->getBasePtr(posX, posY);
|
||||
for (int y = 0; y < s->h; y++) {
|
||||
if (y + posY < screen->h && y + posY >= 0) {
|
||||
const byte *src2 = src1;
|
||||
byte *dst2 = dst1;
|
||||
for (int x = 0; x < s->w; x++, src2++, dst2++) {
|
||||
if (*src2 == kShadowColor) {
|
||||
if (x + posX < screen->w && x + posX >= 0) {
|
||||
*dst2 = *(shadowTable + *dst2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
src1 += s->pitch;
|
||||
dst1 += screen->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in glowing animation for inventory items. Creates special blendTable array of colors,
|
||||
* use black (0) as a transparent color.
|
||||
*/
|
||||
void GraphicsMan::drawTransparentWithBlendSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s) {
|
||||
const byte *src1 = (const byte *)s->getBasePtr(0, 0);
|
||||
byte *dst1 = (byte *)screen->getBasePtr(posX, posY);
|
||||
byte *blendTable = (byte *)malloc(256);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
blendTable[i] = 255;
|
||||
}
|
||||
for (int y = 0; y < s->h; y++) {
|
||||
if (y + posY < screen->h && y + posY >= 0) {
|
||||
const byte *src2 = src1;
|
||||
byte *dst2 = dst1;
|
||||
for (int x = 0; x < s->w; x++, src2++, dst2++) {
|
||||
if (*src2) {
|
||||
if (x + posX < screen->w && x + posX >= 0) {
|
||||
*dst2 = getBlendTableColor(*src2, *dst2, blendTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
src1 += s->pitch;
|
||||
dst1 += screen->pitch;
|
||||
}
|
||||
free(blendTable);
|
||||
change();
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to drawTransparentSurface but with with use of DrawNode as argument for Z axis sorting
|
||||
* and white (255) as transparent color.
|
||||
*/
|
||||
void GraphicsMan::drawTransparentDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
|
||||
byte *src1 = (byte *)drawNode->s->getBasePtr(0, 0);
|
||||
byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
|
||||
for (int y = 0; y < drawNode->s->h; y++) {
|
||||
if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
|
||||
byte *src2 = src1;
|
||||
byte *dst2 = dst1;
|
||||
for (int x = 0; x < drawNode->s->w; x++, src2++, dst2++) {
|
||||
if (*src2 != 255) {
|
||||
if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
|
||||
*dst2 = *src2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
src1 += drawNode->s->pitch;
|
||||
dst1 += screen->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to drawTransparentDrawNode but with additional anti-aliasing code for sprite drawing.
|
||||
* Edge smoothing is based on 256 x 256 table of colors transition.
|
||||
* Algorithm is checking if currently drawing pixel is located next to the edge of sprite and if it makes jagged line.
|
||||
* If it does then this pixel is set with color from transition table calculated of original background pixel color
|
||||
* and sprite's edge pixel color.
|
||||
*/
|
||||
void GraphicsMan::drawTransparentWithTransDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
|
||||
// pos of first pixel for each row of source sprite
|
||||
byte *src1 = (byte *)drawNode->s->getBasePtr(0, 0);
|
||||
// pos of drawing first pixel for each row on screen surface
|
||||
byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
|
||||
// trasition table for calculating new color value
|
||||
byte *transTableData = (byte *)drawNode->data;
|
||||
for (int y = 0; y < drawNode->s->h; y++) {
|
||||
if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
|
||||
// current pixel in row of source sprite
|
||||
byte *src2 = src1;
|
||||
// current pixel in row of screen surface
|
||||
byte *dst2 = dst1;
|
||||
for (int x = 0; x < drawNode->s->w; x++, src2++, dst2++) {
|
||||
if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
|
||||
if (*src2 != 255) {
|
||||
// if source sprite pixel is not mask color than draw it normally
|
||||
*dst2 = *src2;
|
||||
} else {
|
||||
// check for making jagged line
|
||||
if (x) {
|
||||
// not first pixel in row
|
||||
if (*(src2 - 1) == 255) {
|
||||
// if it has mask color to the left - check right
|
||||
if (x != drawNode->s->w - 1) {
|
||||
// not last pixel in row
|
||||
if (*(src2 + 1) == 255) {
|
||||
// pixel to the right with mask color - no anti-alias
|
||||
continue;
|
||||
}
|
||||
// it's not mask color to the right - we continue checking
|
||||
} else {
|
||||
// last pixel in row, no right check - no anti-alias
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// it's not mask color to the left - we continue checking
|
||||
} else if (x != drawNode->s->w - 1) {
|
||||
// first pixel in row but not last - just right pixel checking
|
||||
if (*(src2 + 1) == 255) {
|
||||
// pixel to the right with mask color - no anti-alias
|
||||
continue;
|
||||
}
|
||||
// it's not mask color to the right - we continue checking
|
||||
} else {
|
||||
// it's first and last pixel in row at the same time (width = 1) - no anti-alias
|
||||
continue;
|
||||
}
|
||||
byte value = 0;
|
||||
if (y != drawNode->s->h - 1) {
|
||||
// not last row
|
||||
// check pixel below of current src2 pixel
|
||||
value = *(src2 + drawNode->s->pitch);
|
||||
if (value == 255) {
|
||||
// pixel below with mask color - check above
|
||||
if (y) {
|
||||
// not first row
|
||||
value = *(src2 - drawNode->s->pitch);
|
||||
if (value == 255) {
|
||||
// pixel above with mask color - no anti-alias
|
||||
continue;
|
||||
}
|
||||
// it's not mask color above - we draw as transition color
|
||||
} else {
|
||||
// first row - no anti-alias
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// it's not mask color below - we draw as transition color
|
||||
} else if (y) {
|
||||
// last row - just check above
|
||||
value = *(src2 - drawNode->s->pitch);
|
||||
if (value == 255) {
|
||||
// pixel above with mask color - no anti-alias
|
||||
continue;
|
||||
}
|
||||
// it's not mask color above - we draw as transition color
|
||||
} else {
|
||||
// first and last row at the same time (height = 1) - no anti-alias
|
||||
continue;
|
||||
}
|
||||
// new color value based on original screen surface color and sprite's edge pixel color
|
||||
*dst2 = transTableData[*dst2 * 256 + value];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// adding pitch to jump to next row of pixels
|
||||
src1 += drawNode->s->pitch;
|
||||
dst1 += screen->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsMan::drawMaskDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
|
||||
byte *maskData = (byte *)drawNode->data;
|
||||
byte *src1 = (byte *)drawNode->originalRoomSurface->getBasePtr(drawNode->posX, drawNode->posY);
|
||||
byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
|
||||
int maskWidth = drawNode->width >> 3;
|
||||
int maskPostion = 0;
|
||||
int maskCounter = 128;
|
||||
for (int y = 0; y < drawNode->height; y++) {
|
||||
if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
|
||||
byte *src2 = src1;
|
||||
byte *dst2 = dst1;
|
||||
int tempMaskPostion = maskPostion;
|
||||
for (int x = 0; x < drawNode->width; x++, src2++, dst2++) {
|
||||
if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
|
||||
if ((maskData[tempMaskPostion] & maskCounter) != 0) {
|
||||
*dst2 = *src2;
|
||||
}
|
||||
}
|
||||
maskCounter >>= 1;
|
||||
if (maskCounter == 0) {
|
||||
maskCounter = 128;
|
||||
tempMaskPostion++;
|
||||
}
|
||||
}
|
||||
}
|
||||
src1 += drawNode->originalRoomSurface->pitch;
|
||||
dst1 += screen->pitch;
|
||||
maskPostion += maskWidth;
|
||||
maskCounter = 128;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsMan::drawAsShadowDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
|
||||
byte *shadowData = (byte *)drawNode->data;
|
||||
byte *src1 = (byte *)drawNode->s->getBasePtr(0, 0);
|
||||
byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
|
||||
for (int y = 0; y < drawNode->s->h; y++) {
|
||||
if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
|
||||
byte *src2 = src1;
|
||||
byte *dst2 = dst1;
|
||||
for (int x = 0; x < drawNode->s->w; x++, src2++, dst2++) {
|
||||
if (*src2 == kShadowColor) {
|
||||
if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
|
||||
*dst2 = *(shadowData + *dst2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
src1 += drawNode->s->pitch;
|
||||
dst1 += screen->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsMan::drawBackSpriteDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
|
||||
byte *src1 = (byte *)drawNode->s->getBasePtr(0, 0);
|
||||
byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
|
||||
for (int y = 0; y < drawNode->s->h; y++) {
|
||||
if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
|
||||
byte *src2 = src1;
|
||||
byte *dst2 = dst1;
|
||||
for (int x = 0; x < drawNode->s->w; x++, src2++, dst2++) {
|
||||
if (*src2 != 255) {
|
||||
if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
|
||||
if (*dst2 == 255) {
|
||||
*dst2 = *src2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
src1 += drawNode->s->pitch;
|
||||
dst1 += screen->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
byte GraphicsMan::getBlendTableColor(byte pixelColor, byte backgroundPixelColor, byte *blendTable) {
|
||||
int currColor = 0;
|
||||
|
||||
if (blendTable[pixelColor] != 255) {
|
||||
currColor = blendTable[pixelColor];
|
||||
} else {
|
||||
const byte *originalPalette = _vm->_roomBmp->getPalette().data();
|
||||
|
||||
int redFirstOrg = originalPalette[pixelColor * 3] * _vm->_mst_shadow / 256;
|
||||
redFirstOrg = CLIP(redFirstOrg, 0, 255);
|
||||
if (_vm->_mst_shadow <= 256) {
|
||||
int redFirstBack = originalPalette[backgroundPixelColor * 3] * (256 - _vm->_mst_shadow) / 256;
|
||||
redFirstBack = CLIP(redFirstBack, 0, 255);
|
||||
redFirstOrg += redFirstBack;
|
||||
redFirstOrg = CLIP(redFirstOrg, 0, 255);
|
||||
}
|
||||
|
||||
int greenFirstOrg = originalPalette[pixelColor * 3 + 1] * _vm->_mst_shadow / 256;
|
||||
greenFirstOrg = CLIP(greenFirstOrg, 0, 255);
|
||||
if (_vm->_mst_shadow <= 256) {
|
||||
int greenFirstBack = originalPalette[backgroundPixelColor * 3 + 1] * (256 - _vm->_mst_shadow) / 256;
|
||||
greenFirstBack = CLIP(greenFirstBack, 0, 255);
|
||||
greenFirstOrg += greenFirstBack;
|
||||
greenFirstOrg = CLIP(greenFirstOrg, 0, 255);
|
||||
}
|
||||
|
||||
int blueFirstOrg = originalPalette[pixelColor * 3 + 2] * _vm->_mst_shadow / 256;
|
||||
blueFirstOrg = CLIP(blueFirstOrg, 0, 255);
|
||||
if (_vm->_mst_shadow <= 256) {
|
||||
int blueFirstBack = originalPalette[backgroundPixelColor * 3 + 2] * (256 - _vm->_mst_shadow) / 256;
|
||||
blueFirstBack = CLIP(blueFirstBack, 0, 255);
|
||||
blueFirstOrg += blueFirstBack;
|
||||
blueFirstOrg = CLIP(blueFirstOrg, 0, 255);
|
||||
}
|
||||
|
||||
int bigValue = PrinceEngine::kIntMax; // infinity
|
||||
for (int j = 0; j < 256; j++) {
|
||||
int redSecondOrg = originalPalette[3 * j];
|
||||
int redNew = redFirstOrg - redSecondOrg;
|
||||
redNew = redNew * redNew;
|
||||
|
||||
int greenSecondOrg = originalPalette[3 * j + 1];
|
||||
int greenNew = greenFirstOrg - greenSecondOrg;
|
||||
greenNew = greenNew * greenNew;
|
||||
|
||||
int blueSecondOrg = originalPalette[3 * j + 2];
|
||||
int blueNew = blueFirstOrg - blueSecondOrg;
|
||||
blueNew = blueNew * blueNew;
|
||||
|
||||
int sumOfColorValues = redNew + greenNew + blueNew;
|
||||
|
||||
if (sumOfColorValues < bigValue) {
|
||||
bigValue = sumOfColorValues;
|
||||
currColor = j;
|
||||
}
|
||||
|
||||
if (sumOfColorValues == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
blendTable[pixelColor] = currColor;
|
||||
}
|
||||
return currColor;
|
||||
}
|
||||
|
||||
void GraphicsMan::makeShadowTable(int brightness, byte *shadowPalette) {
|
||||
int shadow = brightness * 256 / 100;
|
||||
const byte *originalPalette = _vm->_roomBmp->getPalette().data();
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
int redFirstOrg = originalPalette[3 * i] * shadow / 256;
|
||||
int greenFirstOrg = originalPalette[3 * i + 1] * shadow / 256;
|
||||
int blueFirstOrg = originalPalette[3 * i + 2] * shadow / 256;
|
||||
|
||||
int currColor = 0;
|
||||
int bigValue = 999999999; // infinity
|
||||
|
||||
for (int j = 0; j < 256; j++) {
|
||||
int redSecondOrg = originalPalette[3 * j];
|
||||
int redNew = redFirstOrg - redSecondOrg;
|
||||
redNew = redNew * redNew;
|
||||
|
||||
int greenSecondOrg = originalPalette[3 * j + 1];
|
||||
int greenNew = greenFirstOrg - greenSecondOrg;
|
||||
greenNew = greenNew * greenNew;
|
||||
|
||||
int blueSecondOrg = originalPalette[3 * j + 2];
|
||||
int blueNew = blueFirstOrg - blueSecondOrg;
|
||||
blueNew = blueNew * blueNew;
|
||||
|
||||
int sumOfColorValues = redNew + greenNew + blueNew;
|
||||
|
||||
if (sumOfColorValues < bigValue) {
|
||||
bigValue = sumOfColorValues;
|
||||
currColor = j;
|
||||
}
|
||||
|
||||
if (sumOfColorValues == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
shadowPalette[i] = currColor;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
75
engines/prince/graphics.h
Normal file
75
engines/prince/graphics.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_GRAPHICS_H
|
||||
#define PRINCE_GRAPHICS_H
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class PrinceEngine;
|
||||
class MhwanhDecoder;
|
||||
struct DrawNode;
|
||||
|
||||
class GraphicsMan {
|
||||
public:
|
||||
GraphicsMan(PrinceEngine *vm);
|
||||
~GraphicsMan();
|
||||
|
||||
void update(Graphics::Surface *screen);
|
||||
|
||||
void change();
|
||||
|
||||
void setPalette(const byte *palette);
|
||||
void makeShadowTable(int brightness, byte *shadowTable);
|
||||
|
||||
void draw(Graphics::Surface *screen, const Graphics::Surface *s);
|
||||
void drawTransparentSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s, int secondTransColor = 0);
|
||||
void drawAsShadowSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s, byte *shadowTable);
|
||||
void drawTransparentWithBlendSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s);
|
||||
|
||||
static void drawTransparentDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
|
||||
static void drawTransparentWithTransDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
|
||||
static void drawAsShadowDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
|
||||
static void drawMaskDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
|
||||
static void drawBackSpriteDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
|
||||
|
||||
byte getBlendTableColor(byte pixelColor, byte backgroundPixelColor, byte *blendTable);
|
||||
|
||||
Graphics::Surface *_frontScreen;
|
||||
Graphics::Surface *_screenForInventory;
|
||||
Graphics::Surface *_mapScreen;
|
||||
const Graphics::Surface *_roomBackground;
|
||||
|
||||
byte *_shadowTable70;
|
||||
byte *_shadowTable50;
|
||||
|
||||
static const byte kShadowColor = 191;
|
||||
|
||||
private:
|
||||
PrinceEngine *_vm;
|
||||
bool _changed;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
1027
engines/prince/hero.cpp
Normal file
1027
engines/prince/hero.cpp
Normal file
File diff suppressed because it is too large
Load Diff
183
engines/prince/hero.h
Normal file
183
engines/prince/hero.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_HERO_H
|
||||
#define PRINCE_HERO_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/primitives.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Animation;
|
||||
class PrinceEngine;
|
||||
class GraphicsMan;
|
||||
struct InventoryItem;
|
||||
struct DrawNode;
|
||||
|
||||
class Hero {
|
||||
public:
|
||||
static const uint32 kMoveSetSize = 26;
|
||||
static const int16 kStepLeftRight = 8;
|
||||
static const int16 kStepUpDown = 4;
|
||||
static const int16 kHeroShadowZ = 2;
|
||||
|
||||
enum State {
|
||||
kHeroStateStay,
|
||||
kHeroStateTurn,
|
||||
kHeroStateMove,
|
||||
kHeroStateBore,
|
||||
kHeroStateSpec,
|
||||
kHeroStateTalk,
|
||||
kHeroStateMvan,
|
||||
kHeroStateTran,
|
||||
kHeroStateRun,
|
||||
kHeroStateDelayMove
|
||||
};
|
||||
|
||||
enum Direction {
|
||||
kHeroDirLeft = 1,
|
||||
kHeroDirRight = 2,
|
||||
kHeroDirUp = 3,
|
||||
kHeroDirDown = 4
|
||||
};
|
||||
|
||||
enum MoveSet {
|
||||
kMove_SL,
|
||||
kMove_SR,
|
||||
kMove_SU,
|
||||
kMove_SD,
|
||||
kMove_ML,
|
||||
kMove_MR,
|
||||
kMove_MU,
|
||||
kMove_MD,
|
||||
kMove_TL,
|
||||
kMove_TR,
|
||||
kMove_TU,
|
||||
kMove_TD,
|
||||
kMove_MLU,
|
||||
kMove_MLD,
|
||||
kMove_MLR,
|
||||
kMove_MRU,
|
||||
kMove_MRD,
|
||||
kMove_MRL,
|
||||
kMove_MUL,
|
||||
kMove_MUR,
|
||||
kMove_MUD,
|
||||
kMove_MDL,
|
||||
kMove_MDR,
|
||||
kMove_MDU,
|
||||
kMove_BORED1,
|
||||
kMove_BORED2
|
||||
};
|
||||
|
||||
// Used instead of offset in getData
|
||||
enum AttrId {
|
||||
kHeroLastDir = 26,
|
||||
kHeroAnimSet = 120
|
||||
};
|
||||
|
||||
uint16 getData(AttrId dataId);
|
||||
|
||||
Hero(PrinceEngine *vm, GraphicsMan *graph);
|
||||
~Hero();
|
||||
bool loadAnimSet(uint32 heroAnimNumber);
|
||||
|
||||
Graphics::Surface *getSurface();
|
||||
|
||||
void setPos(int16 x, int16 y) { _middleX = x; _middleY = y; }
|
||||
void setVisible(bool flag) { _visible = flag; }
|
||||
|
||||
void showHero();
|
||||
void drawHero();
|
||||
void freeZoomedSurface();
|
||||
void heroStanding();
|
||||
void heroMoveGotIt(int x, int y, int dir);
|
||||
int rotateHero(int oldDirection, int newDirection);
|
||||
void scrollHero();
|
||||
void setScale(int8 zoomBitmapValue);
|
||||
int getScaledValue(int size);
|
||||
void selectZoom();
|
||||
void countDrawPosition();
|
||||
Graphics::Surface *zoomSprite(Graphics::Surface *heroFrame);
|
||||
void line(int x1, int y1, int x2, int y2);
|
||||
void plotPoint(int x, int y);
|
||||
static void showHeroShadow(Graphics::Surface *screen, DrawNode *drawNode);
|
||||
void drawHeroShadow(Graphics::Surface *heroFrame);
|
||||
void freeOldMove();
|
||||
void freeHeroAnim();
|
||||
|
||||
uint16 _number;
|
||||
uint16 _visible;
|
||||
int16 _state;
|
||||
int16 _middleX; // middle of X
|
||||
int16 _middleY; // lower part of hero
|
||||
int16 _moveSetType;
|
||||
|
||||
int16 _frameXSize;
|
||||
int16 _frameYSize;
|
||||
int16 _scaledFrameXSize;
|
||||
int16 _scaledFrameYSize;
|
||||
int16 _drawX;
|
||||
int16 _drawY;
|
||||
int16 _drawZ;
|
||||
|
||||
byte *_coords; // array of coordinates
|
||||
byte *_dirTab; // array of directions
|
||||
byte *_currCoords; // current coordinations
|
||||
byte *_currDirTab; // current direction
|
||||
int16 _lastDirection; // previous move direction
|
||||
int16 _destDirection;
|
||||
int16 _leftRightMainDir; // left or right - dominant direction
|
||||
int16 _upDownMainDir; // up or down - dominant direction
|
||||
int32 _phase; // Phase animation phase
|
||||
int16 _step; // Step x/y step size depends on direction
|
||||
int16 _maxBoredom; // stand still timeout
|
||||
int16 _boredomTime; // Boredom current boredom time in frames
|
||||
uint16 _boreNum; // Bore anim frame
|
||||
int16 _talkTime; // TalkTime time of talk anim
|
||||
Animation *_specAnim; // additional anim
|
||||
Graphics::Surface *_zoomedHeroSurface;
|
||||
|
||||
uint16 _currHeight; // height of current anim phase
|
||||
|
||||
Common::Array<byte> _inventory; // Inventory array of items
|
||||
Common::Array<byte> _inventory2; // Inventory2 array of items
|
||||
// Font subtitiles font
|
||||
int _color; // subtitles color
|
||||
uint32 _animSetNr; // number of animation set
|
||||
Common::Array<Animation *> _moveSet; // MoveAnims MoveSet
|
||||
|
||||
uint32 _moveDelay;
|
||||
uint32 _shadMinus;
|
||||
|
||||
private:
|
||||
PrinceEngine *_vm;
|
||||
GraphicsMan *_graph;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
243
engines/prince/hero_set.h
Normal file
243
engines/prince/hero_set.h
Normal file
@@ -0,0 +1,243 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
const int heroSetBack[7] = { 0, 0, 10, 0, 6, 0, 0 };
|
||||
|
||||
typedef const char *HeroSetAnimNames[26];
|
||||
|
||||
static HeroSetAnimNames heroSet5 = {
|
||||
"SL_DIAB.ANI",
|
||||
"SR_DIAB.ANI",
|
||||
"SU_DIAB.ANI",
|
||||
"SD_DIAB.ANI",
|
||||
nullptr,
|
||||
nullptr,
|
||||
"MU_DIAB.ANI",
|
||||
"MD_DIAB.ANI",
|
||||
"TL_DIAB.ANI",
|
||||
"TR_DIAB.ANI",
|
||||
"TU_DIAB.ANI",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr
|
||||
};
|
||||
|
||||
static HeroSetAnimNames heroSet1 = {
|
||||
"SL_HERO1.ANI",
|
||||
"SR_HERO1.ANI",
|
||||
"SU_HERO1.ANI",
|
||||
"SD_HERO1.ANI",
|
||||
"ML_HERO1.ANI",
|
||||
"MR_HERO1.ANI",
|
||||
"MU_HERO1.ANI",
|
||||
"MD_HERO1.ANI",
|
||||
"TL_HERO1.ANI",
|
||||
"TR_HERO1.ANI",
|
||||
"TU_HERO1.ANI",
|
||||
"TD_HERO1.ANI",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
"KSI_KURZ.ANI",
|
||||
"KS_WLOSY.ANI"
|
||||
};
|
||||
|
||||
static HeroSetAnimNames heroSet2 = {
|
||||
"SL_HERO2.ANI",
|
||||
"SR_HERO2.ANI",
|
||||
"SU_HERO2.ANI",
|
||||
"SD_HERO2.ANI",
|
||||
"ML_HERO2.ANI",
|
||||
"MR_HERO2.ANI",
|
||||
"MU_HERO2.ANI",
|
||||
"MD_HERO2.ANI",
|
||||
"TL_HERO2.ANI",
|
||||
"TR_HERO2.ANI",
|
||||
"TU_HERO2.ANI",
|
||||
"TD_HERO2.ANI",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
"KSI_KU_S.ANI",
|
||||
"KS_WLO_S.ANI"
|
||||
};
|
||||
|
||||
static HeroSetAnimNames heroSet3 = {
|
||||
"SL_BEAR.ANI",
|
||||
"SR_BEAR.ANI",
|
||||
"SU_BEAR.ANI",
|
||||
"SD_BEAR.ANI",
|
||||
"NIED-LEW.ANI",
|
||||
"NIED-PRW.ANI",
|
||||
"NIED-TYL.ANI",
|
||||
"NIED-PRZ.ANI",
|
||||
"SL_BEAR.ANI",
|
||||
"SR_BEAR.ANI",
|
||||
"SU_BEAR.ANI",
|
||||
"SD_BEAR.ANI",
|
||||
"N_LW-TYL.ANI",
|
||||
"N_LW-PRZ.ANI",
|
||||
"N_LW-PR.ANI",
|
||||
"N_PR-TYL.ANI",
|
||||
"N_PR-PRZ.ANI",
|
||||
"N_PR-LW.ANI",
|
||||
"N_TYL-LW.ANI",
|
||||
"N_TYL-PR.ANI",
|
||||
"N_TL-PRZ.ANI",
|
||||
"N_PRZ-LW.ANI",
|
||||
"N_PRZ-PR.ANI",
|
||||
"N_PRZ-TL.ANI",
|
||||
nullptr,
|
||||
nullptr,
|
||||
};
|
||||
|
||||
static HeroSetAnimNames shanSet1 = {
|
||||
"SL_SHAN.ANI",
|
||||
"SR_SHAN.ANI",
|
||||
"SU_SHAN.ANI",
|
||||
"SD_SHAN.ANI",
|
||||
"ML_SHAN.ANI",
|
||||
"MR_SHAN.ANI",
|
||||
"MU_SHAN.ANI",
|
||||
"MD_SHAN.ANI",
|
||||
"TL_SHAN.ANI",
|
||||
"TR_SHAN.ANI",
|
||||
"TU_SHAN.ANI",
|
||||
"TD_SHAN.ANI",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
"B1_SHAN.ANI",
|
||||
"B2_SHAN.ANI",
|
||||
};
|
||||
|
||||
static HeroSetAnimNames shanSet2 = {
|
||||
"SL_SHAN2.ANI",
|
||||
"SR_SHAN2.ANI",
|
||||
"SU_SHAN.ANI",
|
||||
"SD_SHAN2.ANI",
|
||||
"ML_SHAN2.ANI",
|
||||
"MR_SHAN2.ANI",
|
||||
"MU_SHAN.ANI",
|
||||
"MD_SHAN2.ANI",
|
||||
"TL_SHAN2.ANI",
|
||||
"TR_SHAN2.ANI",
|
||||
"TU_SHAN.ANI",
|
||||
"TD_SHAN2.ANI",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
"B1_SHAN2.ANI",
|
||||
"B2_SHAN2.ANI"
|
||||
};
|
||||
|
||||
static HeroSetAnimNames arivSet1 = {
|
||||
"SL_ARIV.ANI",
|
||||
"SR_ARIV.ANI",
|
||||
"SU_ARIV.ANI",
|
||||
"SD_ARIV.ANI",
|
||||
"ML_ARIV.ANI",
|
||||
"MR_ARIV.ANI",
|
||||
"MU_ARIV.ANI",
|
||||
"MD_ARIV.ANI",
|
||||
"TL_ARIV.ANI",
|
||||
"TR_ARIV.ANI",
|
||||
"TU_ARIV.ANI",
|
||||
"TD_ARIV.ANI",
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr
|
||||
};
|
||||
|
||||
const HeroSetAnimNames *heroSetTable[7] = {
|
||||
&heroSet1,
|
||||
&heroSet2,
|
||||
&heroSet3,
|
||||
&shanSet1,
|
||||
&arivSet1,
|
||||
&heroSet5,
|
||||
&shanSet2,
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
736
engines/prince/inventory.cpp
Normal file
736
engines/prince/inventory.cpp
Normal file
@@ -0,0 +1,736 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/prince.h"
|
||||
|
||||
#include "prince/graphics.h"
|
||||
#include "prince/hero.h"
|
||||
#include "prince/script.h"
|
||||
#include "prince/mhwanh.h"
|
||||
#include "prince/variatxt.h"
|
||||
#include "prince/option_text.h"
|
||||
#include "prince/font.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
void PrinceEngine::addInv(int heroId, int item, bool addItemQuiet) {
|
||||
Hero *hero = nullptr;
|
||||
if (!heroId) {
|
||||
hero = _mainHero;
|
||||
} else if (heroId == 1) {
|
||||
hero = _secondHero;
|
||||
}
|
||||
if (hero != nullptr) {
|
||||
if (hero->_inventory.size() < kMaxItems) {
|
||||
if (item != 0x7FFF) {
|
||||
hero->_inventory.push_back(item);
|
||||
}
|
||||
if (!addItemQuiet) {
|
||||
addInvObj();
|
||||
}
|
||||
_interpreter->setResult(0);
|
||||
} else {
|
||||
_interpreter->setResult(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::remInv(int heroId, int item) {
|
||||
Hero *hero = nullptr;
|
||||
if (!heroId) {
|
||||
hero = _mainHero;
|
||||
} else if (heroId == 1) {
|
||||
hero = _secondHero;
|
||||
}
|
||||
if (hero != nullptr) {
|
||||
for (uint i = 0; i < hero->_inventory.size(); i++) {
|
||||
if (hero->_inventory[i] == item) {
|
||||
hero->_inventory.remove_at(i);
|
||||
_interpreter->setResult(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_interpreter->setResult(1);
|
||||
}
|
||||
|
||||
void PrinceEngine::clearInv(int heroId) {
|
||||
switch (heroId) {
|
||||
case 0:
|
||||
_mainHero->_inventory.clear();
|
||||
break;
|
||||
case 1:
|
||||
_secondHero->_inventory.clear();
|
||||
break;
|
||||
default:
|
||||
error("clearInv() - wrong hero slot");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::swapInv(int heroId) {
|
||||
Common::Array<int> tempInv;
|
||||
Hero *hero = nullptr;
|
||||
if (!heroId) {
|
||||
hero = _mainHero;
|
||||
} else if (heroId == 1) {
|
||||
hero = _secondHero;
|
||||
}
|
||||
if (hero != nullptr) {
|
||||
for (uint i = 0; i < hero->_inventory.size(); i++) {
|
||||
tempInv.push_back(hero->_inventory[i]);
|
||||
}
|
||||
hero->_inventory.clear();
|
||||
for (uint i = 0; i < hero->_inventory2.size(); i++) {
|
||||
hero->_inventory.push_back(hero->_inventory2[i]);
|
||||
}
|
||||
hero->_inventory2.clear();
|
||||
for (uint i = 0; i < tempInv.size(); i++) {
|
||||
hero->_inventory2.push_back(tempInv[i]);
|
||||
}
|
||||
tempInv.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::addInvObj() {
|
||||
changeCursor(0);
|
||||
prepareInventoryToView();
|
||||
|
||||
_inventoryBackgroundRemember = true;
|
||||
drawScreen();
|
||||
|
||||
Graphics::Surface *suitcase = _suitcaseBmp->getSurface();
|
||||
|
||||
if (!_flags->getFlagValue(Flags::CURSEBLINK)) {
|
||||
|
||||
loadSample(27, "PRZEDMIO.WAV");
|
||||
playSample(27, 0);
|
||||
|
||||
_mst_shadow2 = 1;
|
||||
|
||||
while (_mst_shadow2 < 512) {
|
||||
rememberScreenInv();
|
||||
_graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
|
||||
drawInvItems();
|
||||
_graph->update(_graph->_screenForInventory);
|
||||
_mst_shadow2 += 50;
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _system->getEventManager();
|
||||
eventMan->pollEvent(event);
|
||||
if (shouldQuit()) {
|
||||
return;
|
||||
}
|
||||
pausePrinceEngine();
|
||||
}
|
||||
while (_mst_shadow2 > 256) {
|
||||
rememberScreenInv();
|
||||
_graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
|
||||
drawInvItems();
|
||||
_graph->update(_graph->_screenForInventory);
|
||||
_mst_shadow2 -= 42;
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _system->getEventManager();
|
||||
eventMan->pollEvent(event);
|
||||
if (shouldQuit()) {
|
||||
return;
|
||||
}
|
||||
pausePrinceEngine();
|
||||
}
|
||||
} else {
|
||||
//CURSEBLINK:
|
||||
for (int i = 0; i < 3; i++) {
|
||||
_mst_shadow2 = 256;
|
||||
while (_mst_shadow2 < 512) {
|
||||
rememberScreenInv();
|
||||
_graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
|
||||
drawInvItems();
|
||||
_graph->update(_graph->_screenForInventory);
|
||||
_mst_shadow2 += 50;
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _system->getEventManager();
|
||||
eventMan->pollEvent(event);
|
||||
if (shouldQuit()) {
|
||||
return;
|
||||
}
|
||||
pausePrinceEngine();
|
||||
}
|
||||
while (_mst_shadow2 > 256) {
|
||||
rememberScreenInv();
|
||||
_graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
|
||||
drawInvItems();
|
||||
_graph->update(_graph->_screenForInventory);
|
||||
_mst_shadow2 -= 50;
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _system->getEventManager();
|
||||
eventMan->pollEvent(event);
|
||||
if (shouldQuit()) {
|
||||
return;
|
||||
}
|
||||
pausePrinceEngine();
|
||||
}
|
||||
}
|
||||
}
|
||||
_mst_shadow2 = 0;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
rememberScreenInv();
|
||||
_graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
|
||||
drawInvItems();
|
||||
_graph->update(_graph->_screenForInventory);
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _system->getEventManager();
|
||||
eventMan->pollEvent(event);
|
||||
if (shouldQuit()) {
|
||||
return;
|
||||
}
|
||||
pausePrinceEngine();
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::rememberScreenInv() {
|
||||
_graph->_screenForInventory->copyFrom(*_graph->_frontScreen);
|
||||
}
|
||||
|
||||
void PrinceEngine::inventoryFlagChange(bool inventoryState) {
|
||||
if (inventoryState) {
|
||||
_showInventoryFlag = true;
|
||||
_inventoryBackgroundRemember = true;
|
||||
} else {
|
||||
_showInventoryFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::prepareInventoryToView() {
|
||||
_invMobList.clear();
|
||||
int invItem = _mainHero->_inventory.size();
|
||||
_invLine = invItem / 3;
|
||||
if (invItem % 3) {
|
||||
_invLine++;
|
||||
}
|
||||
if (_invLine < 4) {
|
||||
_invLine = 4;
|
||||
}
|
||||
_maxInvW = (374 - 2 * _invLine) / _invLine;
|
||||
_invLineW = _maxInvW - 2;
|
||||
|
||||
int currInvX = _invLineX;
|
||||
int currInvY = _invLineY;
|
||||
|
||||
Common::MemoryReadStream stream(_invTxt, _invTxtSize);
|
||||
byte c;
|
||||
|
||||
uint item = 0;
|
||||
for (int i = 0; i < _invLines; i++) {
|
||||
for (int j = 0; j < _invLine; j++) {
|
||||
Mob tempMobItem;
|
||||
if (item < _mainHero->_inventory.size()) {
|
||||
int itemNr = _mainHero->_inventory[item];
|
||||
tempMobItem._visible = 0;
|
||||
tempMobItem._mask = itemNr;
|
||||
tempMobItem._rect = Common::Rect(currInvX + _picWindowX, currInvY, currInvX + _picWindowX + _invLineW - 1, currInvY + _invLineH - 1);
|
||||
tempMobItem._type = 0; // to work with checkMob()
|
||||
|
||||
tempMobItem._name = "";
|
||||
tempMobItem._examText = "";
|
||||
int txtOffset = READ_LE_UINT32(&_invTxt[itemNr * 8]);
|
||||
int examTxtOffset = READ_LE_UINT32(&_invTxt[itemNr * 8 + 4]);
|
||||
|
||||
stream.seek(txtOffset);
|
||||
while ((c = stream.readByte())) {
|
||||
tempMobItem._name += c;
|
||||
}
|
||||
|
||||
stream.seek(examTxtOffset);
|
||||
while ((c = stream.readByte())) {
|
||||
tempMobItem._examText += c;
|
||||
}
|
||||
_invMobList.push_back(tempMobItem);
|
||||
}
|
||||
currInvX += _invLineW + _invLineSkipX;
|
||||
item++;
|
||||
}
|
||||
currInvX = _invLineX;
|
||||
currInvY += _invLineSkipY + _invLineH;
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::drawInvItems() {
|
||||
int currInvX = _invLineX;
|
||||
int currInvY = _invLineY;
|
||||
uint item = 0;
|
||||
for (int i = 0; i < _invLines; i++) {
|
||||
for (int j = 0; j < _invLine; j++) {
|
||||
if (item < _mainHero->_inventory.size()) {
|
||||
int itemNr = _mainHero->_inventory[item];
|
||||
_mst_shadow = 0;
|
||||
if (_mst_shadow2) {
|
||||
if (!_flags->getFlagValue(Flags::CURSEBLINK)) {
|
||||
if (item + 1 == _mainHero->_inventory.size()) { // last item in inventory
|
||||
_mst_shadow = 1;
|
||||
}
|
||||
} else if (itemNr == 1 || itemNr == 3 || itemNr == 4 || itemNr == 7) {
|
||||
_mst_shadow = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int drawX = currInvX;
|
||||
int drawY = currInvY;
|
||||
Graphics::Surface *itemSurface = nullptr;
|
||||
if (itemNr != 68) {
|
||||
itemSurface = _allInvList[itemNr].getSurface();
|
||||
if (itemSurface->h < _maxInvH) {
|
||||
drawY += (_maxInvH - itemSurface->h) / 2;
|
||||
}
|
||||
} else {
|
||||
// candle item:
|
||||
if (_candleCounter == 8) {
|
||||
_candleCounter = 0;
|
||||
}
|
||||
itemNr = _candleCounter;
|
||||
_candleCounter++;
|
||||
itemNr &= 7;
|
||||
itemNr += 71;
|
||||
itemSurface = _allInvList[itemNr].getSurface();
|
||||
drawY += _allInvList[itemNr]._y + (_maxInvH - 76) / 2 - 200;
|
||||
}
|
||||
if (itemSurface->w < _maxInvW) {
|
||||
drawX += (_maxInvW - itemSurface->w) / 2;
|
||||
}
|
||||
if (!_mst_shadow) {
|
||||
_graph->drawTransparentSurface(_graph->_screenForInventory, drawX, drawY, itemSurface);
|
||||
} else {
|
||||
_mst_shadow = _mst_shadow2;
|
||||
_graph->drawTransparentWithBlendSurface(_graph->_screenForInventory, drawX, drawY, itemSurface);
|
||||
}
|
||||
}
|
||||
currInvX += _invLineW + _invLineSkipX;
|
||||
item++;
|
||||
}
|
||||
currInvX = _invLineX;
|
||||
currInvY += _invLineSkipY + _invLineH;
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::inventoryLeftMouseButton() {
|
||||
if (!_mouseFlag) {
|
||||
_textSlots[0]._time = 0;
|
||||
_textSlots[0]._str = nullptr;
|
||||
stopTextToSpeech();
|
||||
stopSample(28);
|
||||
}
|
||||
|
||||
if (_optionsFlag == 1) {
|
||||
if (_selectedMob != -1) {
|
||||
if (_optionEnabled < _invOptionsNumber) {
|
||||
_optionsFlag = 0;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
error("PrinceEngine::inventoryLeftMouseButton() - optionsFlag = 1, selectedMob = 0");
|
||||
if (_currentPointerNumber == 2) {
|
||||
changeCursor(1);
|
||||
_currentPointerNumber = 1;
|
||||
_selectedMob = -1;
|
||||
_optionsMob = -1;
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_selectedMob != -1) {
|
||||
if (_currentPointerNumber != 2) {
|
||||
if (_invMobList[_selectedMob]._mask != 29) {
|
||||
_optionEnabled = 0;
|
||||
} else {
|
||||
// map item
|
||||
_optionEnabled = 1;
|
||||
}
|
||||
} else {
|
||||
//use_item_on_item
|
||||
int invObjUU = _script->scanMobEventsWithItem(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUU, _selectedItem);
|
||||
if (invObjUU == -1) {
|
||||
int textNr = 80011; // "I can't do it."
|
||||
if (_selectedItem == 31 || _invMobList[_selectedMob]._mask == 31) {
|
||||
textNr = 80020; // "Nothing is happening."
|
||||
}
|
||||
_interpreter->setCurrentString(textNr);
|
||||
printAt(0, 216, (char *)_variaTxt->getString(textNr - 80000), kNormalWidth / 2, 100);
|
||||
setVoice(0, 28, 1);
|
||||
playSample(28, 0);
|
||||
_selectedMob = -1;
|
||||
_optionsMob = -1;
|
||||
return;
|
||||
} else {
|
||||
_interpreter->storeNewPC(invObjUU);
|
||||
_flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
|
||||
_showInventoryFlag = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
//do_option
|
||||
if (_optionEnabled == 0) {
|
||||
int invObjExamEvent = _script->scanMobEvents(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjExam);
|
||||
if (invObjExamEvent == -1) {
|
||||
static char buf[256];
|
||||
strncpy(buf, _invMobList[_selectedMob]._examText.c_str(), 256);
|
||||
printAt(0, 216, buf, kNormalWidth / 2, _invExamY);
|
||||
_interpreter->setCurrentString(_invMobList[_selectedMob]._mask + 70000);
|
||||
setVoice(0, 28, 1);
|
||||
playSample(28, 0);
|
||||
// disableuseuse
|
||||
changeCursor(0);
|
||||
_currentPointerNumber = 1;
|
||||
} else {
|
||||
_interpreter->storeNewPC(invObjExamEvent);
|
||||
_flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
|
||||
_showInventoryFlag = false;
|
||||
}
|
||||
} else if (_optionEnabled == 1) {
|
||||
// not_examine
|
||||
int invObjUse = _script->scanMobEvents(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUse);
|
||||
if (invObjUse == -1) {
|
||||
// do_standard_use
|
||||
_selectedMode = 0;
|
||||
_selectedItem = _invMobList[_selectedMob]._mask;
|
||||
makeInvCursor(_invMobList[_selectedMob]._mask);
|
||||
_currentPointerNumber = 2;
|
||||
changeCursor(2);
|
||||
} else {
|
||||
_interpreter->storeNewPC(invObjUse);
|
||||
_flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
|
||||
_showInventoryFlag = false;
|
||||
}
|
||||
} else if (_optionEnabled == 4) {
|
||||
// do_standard_give
|
||||
_selectedMode = 1;
|
||||
_selectedItem = _invMobList[_selectedMob]._mask;
|
||||
makeInvCursor(_invMobList[_selectedMob]._mask);
|
||||
_currentPointerNumber = 2;
|
||||
changeCursor(2);
|
||||
} else {
|
||||
// use_item_on_item
|
||||
int invObjUU = _script->scanMobEventsWithItem(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUU, _selectedItem);
|
||||
if (invObjUU == -1) {
|
||||
int textNr = 80011; // "I can't do it."
|
||||
if (_selectedItem == 31 || _invMobList[_selectedMob]._mask == 31) {
|
||||
textNr = 80020; // "Nothing is happening."
|
||||
}
|
||||
_interpreter->setCurrentString(textNr);
|
||||
printAt(0, 216, (char *)_variaTxt->getString(textNr - 80000), kNormalWidth / 2, 100);
|
||||
setVoice(0, 28, 1);
|
||||
playSample(28, 0);
|
||||
} else {
|
||||
_interpreter->storeNewPC(invObjUU);
|
||||
_flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
|
||||
_showInventoryFlag = false;
|
||||
}
|
||||
}
|
||||
_selectedMob = -1;
|
||||
_optionsMob = -1;
|
||||
}
|
||||
|
||||
void PrinceEngine::inventoryRightMouseButton() {
|
||||
if (_textSlots[0]._str == nullptr) {
|
||||
enableOptions(false);
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::enableOptions(bool checkType) {
|
||||
if (_optionsFlag != 1) {
|
||||
changeCursor(1);
|
||||
_currentPointerNumber = 1;
|
||||
if (_selectedMob != -1) {
|
||||
if (checkType) {
|
||||
if (_mobList[_selectedMob]._type & 0x100) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Common::Point mousePos = _system->getEventManager()->getMousePos();
|
||||
int x1 = mousePos.x - _optionsWidth / 2;
|
||||
int x2 = mousePos.x + _optionsWidth / 2;
|
||||
if (x1 < 0) {
|
||||
x1 = 0;
|
||||
x2 = _optionsWidth;
|
||||
} else if (x2 >= kNormalWidth) {
|
||||
x1 = kNormalWidth - _optionsWidth;
|
||||
x2 = kNormalWidth;
|
||||
}
|
||||
int y1 = mousePos.y - 10;
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
}
|
||||
if (y1 + _optionsHeight >= kNormalHeight) {
|
||||
y1 = kNormalHeight - _optionsHeight;
|
||||
}
|
||||
_optionsMob = _selectedMob;
|
||||
_optionsX = x1;
|
||||
_optionsY = y1;
|
||||
_optionsFlag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::checkOptions() {
|
||||
if (_optionsFlag) {
|
||||
Common::Rect optionsRect(_optionsX, _optionsY, _optionsX + _optionsWidth, _optionsY + _optionsHeight);
|
||||
Common::Point mousePos = _system->getEventManager()->getMousePos();
|
||||
if (!optionsRect.contains(mousePos)) {
|
||||
_optionsFlag = 0;
|
||||
_selectedMob = -1;
|
||||
return;
|
||||
}
|
||||
_graph->drawAsShadowSurface(_graph->_frontScreen, _optionsX, _optionsY, _optionsPic, _graph->_shadowTable50);
|
||||
|
||||
int previousOption = _optionEnabled;
|
||||
_optionEnabled = -1;
|
||||
int optionsYCord = mousePos.y - (_optionsY + 16);
|
||||
if (optionsYCord >= 0) {
|
||||
int selectedOptionNr = optionsYCord / _optionsStep;
|
||||
if (selectedOptionNr < _optionsNumber) {
|
||||
_optionEnabled = selectedOptionNr;
|
||||
}
|
||||
}
|
||||
int optionsColor;
|
||||
int textY = _optionsY + 16;
|
||||
for (int i = 0; i < _optionsNumber; i++) {
|
||||
Common::String optText;
|
||||
switch(getLanguage()) {
|
||||
case Common::PL_POL:
|
||||
optText = optionsTextPL[i];
|
||||
break;
|
||||
case Common::DE_DEU:
|
||||
optText = optionsTextDE[i];
|
||||
break;
|
||||
case Common::EN_ANY:
|
||||
optText = optionsTextEN[i];
|
||||
break;
|
||||
case Common::ES_ESP:
|
||||
optText = optionsTextES[i];
|
||||
break;
|
||||
case Common::RU_RUS:
|
||||
if (getFeatures() & GF_RUSPROJEDITION) {
|
||||
optText = optionsTextRU2[i];
|
||||
} else {
|
||||
optText = optionsTextRU[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if (i != _optionEnabled) {
|
||||
optionsColor = _optionsColor1;
|
||||
} else {
|
||||
optionsColor = _optionsColor2;
|
||||
|
||||
if (_optionEnabled != previousOption) {
|
||||
setTTSVoice(kHeroTextColor);
|
||||
sayText(optText, false);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 textW = getTextWidth(optText.c_str());
|
||||
uint16 textX = _optionsX + _optionsWidth / 2 - textW / 2;
|
||||
_font->drawString(_graph->_frontScreen, optText, textX, textY, textW, optionsColor);
|
||||
textY += _optionsStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::checkInvOptions() {
|
||||
if (_optionsFlag) {
|
||||
Common::Rect optionsRect(_optionsX, _optionsY, _optionsX + _invOptionsWidth, _optionsY + _invOptionsHeight);
|
||||
Common::Point mousePos = _system->getEventManager()->getMousePos();
|
||||
if (!optionsRect.contains(mousePos)) {
|
||||
_optionsFlag = 0;
|
||||
_selectedMob = -1;
|
||||
return;
|
||||
}
|
||||
_graph->drawAsShadowSurface(_graph->_screenForInventory, _optionsX, _optionsY, _optionsPicInInventory, _graph->_shadowTable50);
|
||||
|
||||
int previousOption = _optionEnabled;
|
||||
_optionEnabled = -1;
|
||||
int optionsYCord = mousePos.y - (_optionsY + 16);
|
||||
if (optionsYCord >= 0) {
|
||||
int selectedOptionNr = optionsYCord / _invOptionsStep;
|
||||
if (selectedOptionNr < _invOptionsNumber) {
|
||||
_optionEnabled = selectedOptionNr;
|
||||
}
|
||||
}
|
||||
int optionsColor;
|
||||
int textY = _optionsY + 16;
|
||||
for (int i = 0; i < _invOptionsNumber; i++) {
|
||||
Common::String invText;
|
||||
switch(getLanguage()) {
|
||||
case Common::PL_POL:
|
||||
invText = invOptionsTextPL[i];
|
||||
break;
|
||||
case Common::DE_DEU:
|
||||
invText = invOptionsTextDE[i];
|
||||
break;
|
||||
case Common::EN_ANY:
|
||||
invText = invOptionsTextEN[i];
|
||||
break;
|
||||
case Common::ES_ESP:
|
||||
invText = invOptionsTextES[i];
|
||||
break;
|
||||
case Common::RU_RUS:
|
||||
if (getFeatures() & GF_RUSPROJEDITION) {
|
||||
invText = invOptionsTextRU2[i];
|
||||
} else {
|
||||
invText = invOptionsTextRU[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error("Unknown game language %d", getLanguage());
|
||||
break;
|
||||
};
|
||||
|
||||
if (i != _optionEnabled) {
|
||||
optionsColor = _optionsColor1;
|
||||
} else {
|
||||
optionsColor = _optionsColor2;
|
||||
|
||||
if (_optionEnabled != previousOption) {
|
||||
setTTSVoice(kHeroTextColor);
|
||||
sayText(invText, false);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 textW = getTextWidth(invText.c_str());
|
||||
uint16 textX = _optionsX + _invOptionsWidth / 2 - textW / 2;
|
||||
_font->drawString(_graph->_screenForInventory, invText, textX, textY, _graph->_screenForInventory->w, optionsColor);
|
||||
textY += _invOptionsStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::displayInventory() {
|
||||
|
||||
_mainHero->freeOldMove();
|
||||
_secondHero->freeOldMove();
|
||||
|
||||
_interpreter->setFgOpcodePC(0);
|
||||
|
||||
stopAllSamples();
|
||||
|
||||
prepareInventoryToView();
|
||||
|
||||
while (!shouldQuit()) {
|
||||
|
||||
if (_textSlots[0]._str != nullptr) {
|
||||
changeCursor(0);
|
||||
} else {
|
||||
changeCursor(_currentPointerNumber);
|
||||
|
||||
Common::Rect inventoryRect(_invX1, _invY1, _invX1 + _invWidth, _invY1 + _invHeight);
|
||||
Common::Point mousePos = _system->getEventManager()->getMousePos();
|
||||
|
||||
if (!_invCurInside && inventoryRect.contains(mousePos)) {
|
||||
_invCurInside = true;
|
||||
}
|
||||
|
||||
if (_invCurInside && !inventoryRect.contains(mousePos)) {
|
||||
inventoryFlagChange(false);
|
||||
_invCurInside = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rememberScreenInv();
|
||||
|
||||
Graphics::Surface *suitcase = _suitcaseBmp->getSurface();
|
||||
_graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
|
||||
|
||||
drawInvItems();
|
||||
|
||||
showTexts(_graph->_screenForInventory);
|
||||
|
||||
if (!_optionsFlag && _textSlots[0]._str == nullptr) {
|
||||
_selectedMob = checkMob(_graph->_screenForInventory, _invMobList, false);
|
||||
}
|
||||
|
||||
checkInvOptions();
|
||||
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _system->getEventManager();
|
||||
while (eventMan->pollEvent(event)) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
|
||||
keyHandler(event);
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
inventoryLeftMouseButton();
|
||||
break;
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
inventoryRightMouseButton();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_showInventoryFlag) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (shouldQuit())
|
||||
return;
|
||||
|
||||
_graph->update(_graph->_screenForInventory);
|
||||
pausePrinceEngine();
|
||||
}
|
||||
|
||||
if (_currentPointerNumber == 2) {
|
||||
_flags->setFlagValue(Flags::SELITEM, _selectedItem);
|
||||
} else {
|
||||
_flags->setFlagValue(Flags::SELITEM, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::openInventoryCheck() {
|
||||
if (!_optionsFlag) {
|
||||
if (_mouseFlag == 1 || _mouseFlag == 2) {
|
||||
if (_mainHero->_visible) {
|
||||
if (!_flags->getFlagValue(Flags::INVALLOWED)) {
|
||||
// 29 - Basement, 50 - Map
|
||||
if (_locationNr != 29 && _locationNr != 50) {
|
||||
Common::Point mousePos = _system->getEventManager()->getMousePos();
|
||||
if (mousePos.y < 4 && !_showInventoryFlag) {
|
||||
_invCounter++;
|
||||
} else {
|
||||
_invCounter = 0;
|
||||
}
|
||||
if (_invCounter >= _invMaxCount) {
|
||||
inventoryFlagChange(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
282
engines/prince/metaengine.cpp
Normal file
282
engines/prince/metaengine.cpp
Normal file
@@ -0,0 +1,282 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "prince/prince.h"
|
||||
#include "prince/detection.h"
|
||||
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
#include "backends/keymapper/standard-actions.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const ADExtraGuiOptionsMap optionsList[] = {
|
||||
{
|
||||
GAMEOPTION_TTS_OBJECTS,
|
||||
{
|
||||
_s("Enable Text to Speech for Objects and Options"),
|
||||
_s("Use TTS to read the descriptions (if TTS is available)"),
|
||||
"tts_enabled_objects",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
GAMEOPTION_TTS_SPEECH,
|
||||
{
|
||||
_s("Enable Text to Speech for Subtitles"),
|
||||
_s("Use TTS to read the subtitles (if TTS is available)"),
|
||||
"tts_enabled_speech",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
GAMEOPTION_TTS_MISSING_VOICE,
|
||||
{
|
||||
_s("Enable Text to Speech for Missing Voiceovers"),
|
||||
_s("Use TTS to read the subtitles of missing voiceovers (if TTS is available)"),
|
||||
"tts_enabled_missing_voice",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
|
||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int PrinceEngine::getGameType() const {
|
||||
return _gameDescription->gameType;
|
||||
}
|
||||
|
||||
const char *PrinceEngine::getGameId() const {
|
||||
return _gameDescription->desc.gameId;
|
||||
}
|
||||
|
||||
uint32 PrinceEngine::getFeatures() const {
|
||||
return _gameDescription->desc.flags;
|
||||
}
|
||||
|
||||
Common::Language PrinceEngine::getLanguage() const {
|
||||
return _gameDescription->desc.language;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
class PrinceMetaEngine : public AdvancedMetaEngine<Prince::PrinceGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "prince";
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
|
||||
return Prince::optionsList;
|
||||
}
|
||||
#endif
|
||||
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const Prince::PrinceGameDescription *desc) const override;
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
|
||||
int getMaximumSaveSlot() const override { return 99; }
|
||||
SaveStateList listSaves(const char *target) const override;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
|
||||
bool removeSaveState(const char *target, int slot) const override;
|
||||
Common::KeymapArray initKeymaps(const char *target) const override;
|
||||
};
|
||||
|
||||
bool PrinceMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsDeleteSave) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail) ||
|
||||
(f == kSavesSupportCreationDate) ||
|
||||
(f == kSavesSupportPlayTime) ||
|
||||
(f == kSupportsListSaves) ||
|
||||
(f == kSupportsLoadingDuringStartup) ||
|
||||
(f == kSimpleSavesNames);
|
||||
}
|
||||
|
||||
bool Prince::PrinceEngine::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime) ||
|
||||
(f == kSupportsReturnToLauncher);
|
||||
}
|
||||
|
||||
SaveStateList PrinceMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Common::StringArray filenames;
|
||||
Common::String pattern = target;
|
||||
pattern += ".###";
|
||||
|
||||
filenames = saveFileMan->listSavefiles(pattern);
|
||||
|
||||
SaveStateList saveList;
|
||||
for (const auto &filename : filenames) {
|
||||
// Obtain the last 3 digits of the filename, since they correspond to the save slot
|
||||
int slotNum = atoi(filename.c_str() + filename.size() - 3);
|
||||
|
||||
if (slotNum >= 0 && slotNum <= 99) {
|
||||
|
||||
Common::InSaveFile *file = saveFileMan->openForLoading(filename);
|
||||
if (file) {
|
||||
Prince::SavegameHeader header;
|
||||
|
||||
// Check to see if it's a ScummVM savegame or not
|
||||
char buffer[kSavegameStrSize + 1];
|
||||
file->read(buffer, kSavegameStrSize + 1);
|
||||
|
||||
if (!strncmp(buffer, kSavegameStr, kSavegameStrSize + 1)) {
|
||||
// Valid savegame
|
||||
if (Prince::PrinceEngine::readSavegameHeader(file, header)) {
|
||||
saveList.push_back(SaveStateDescriptor(this, slotNum, header.saveName));
|
||||
}
|
||||
} else {
|
||||
// Must be an original format savegame
|
||||
saveList.push_back(SaveStateDescriptor(this, slotNum, "Unknown"));
|
||||
}
|
||||
|
||||
delete file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
|
||||
return saveList;
|
||||
}
|
||||
|
||||
SaveStateDescriptor PrinceMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
Common::String fileName = Common::String::format("%s.%03d", target, slot);
|
||||
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName);
|
||||
|
||||
if (f) {
|
||||
Prince::SavegameHeader header;
|
||||
|
||||
// Check to see if it's a ScummVM savegame or not
|
||||
char buffer[kSavegameStrSize + 1];
|
||||
f->read(buffer, kSavegameStrSize + 1);
|
||||
|
||||
bool hasHeader = !strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) &&
|
||||
Prince::PrinceEngine::readSavegameHeader(f, header, false);
|
||||
delete f;
|
||||
|
||||
if (!hasHeader) {
|
||||
// Original savegame perhaps?
|
||||
SaveStateDescriptor desc(this, slot, "Unknown");
|
||||
return desc;
|
||||
} else {
|
||||
// Create the return descriptor
|
||||
SaveStateDescriptor desc(this, slot, header.saveName);
|
||||
desc.setThumbnail(header.thumbnail);
|
||||
desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
|
||||
desc.setSaveTime(header.saveHour, header.saveMinutes);
|
||||
desc.setPlayTime(header.playTime * 1000);
|
||||
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
bool PrinceMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
Common::String fileName = Common::String::format("%s.%03d", target, slot);
|
||||
return g_system->getSavefileManager()->removeSavefile(fileName);
|
||||
}
|
||||
|
||||
Common::Error PrinceMetaEngine::createInstance(OSystem *syst, Engine **engine, const Prince::PrinceGameDescription *desc) const {
|
||||
*engine = new Prince::PrinceEngine(syst,desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::KeymapArray PrinceMetaEngine::initKeymaps(const char *target) const {
|
||||
using namespace Common;
|
||||
using namespace Prince;
|
||||
|
||||
Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "prince-default", _("Default keymappings"));
|
||||
|
||||
Common::Action *act;
|
||||
|
||||
act = new Common::Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Common::Action(kStandardActionRightClick, _("Open interaction menu"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Common::Action("SAVE", _("Save game"));
|
||||
act->setCustomEngineActionEvent(kActionSave);
|
||||
act->addDefaultInputMapping("F1");
|
||||
act->addDefaultInputMapping("JOY_X");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOAD", _("Load game"));
|
||||
act->setCustomEngineActionEvent(kActionLoad);
|
||||
act->addDefaultInputMapping("F2");
|
||||
act->addDefaultInputMapping("JOY_Y");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
// I18N: This refers to the Z key on a keyboard.
|
||||
act = new Action("Z", _("Z key")); // TODO: Rename this action to better reflect its use in the prison cell minigame near the end of the game.
|
||||
act->setCustomEngineActionEvent(kActionZ);
|
||||
act->addDefaultInputMapping("z");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
// I18N: This refers to the X key on a keyboard.
|
||||
act = new Action("X", _("X key")); // TODO: Rename this action to better reflect its use in the prison cell minigame near the end of the game.
|
||||
act->setCustomEngineActionEvent(kActionX);
|
||||
act->addDefaultInputMapping("x");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SKIP", _("Skip"));
|
||||
act->setCustomEngineActionEvent(kActionSkip);
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_UP");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
return Keymap::arrayOf(engineKeyMap);
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(PRINCE)
|
||||
REGISTER_PLUGIN_DYNAMIC(PRINCE, PLUGIN_TYPE_ENGINE, PrinceMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(PRINCE, PLUGIN_TYPE_ENGINE, PrinceMetaEngine);
|
||||
#endif
|
||||
68
engines/prince/mhwanh.cpp
Normal file
68
engines/prince/mhwanh.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "prince/mhwanh.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
MhwanhDecoder::MhwanhDecoder() : _surface(nullptr), _palette(0) {
|
||||
}
|
||||
|
||||
MhwanhDecoder::~MhwanhDecoder() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void MhwanhDecoder::destroy() {
|
||||
if (_surface != nullptr) {
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
_surface = nullptr;
|
||||
}
|
||||
_palette.clear();
|
||||
}
|
||||
|
||||
bool MhwanhDecoder::loadStream(Common::SeekableReadStream &stream) {
|
||||
destroy();
|
||||
stream.seek(0);
|
||||
stream.skip(0x20);
|
||||
// Read the palette
|
||||
_palette.resize(kPaletteColorCount, false);
|
||||
for (uint16 i = 0; i < kPaletteColorCount; i++) {
|
||||
byte r = stream.readByte();
|
||||
byte g = stream.readByte();
|
||||
byte b = stream.readByte();
|
||||
_palette.set(i, r, g, b);
|
||||
}
|
||||
|
||||
_surface = new Graphics::Surface();
|
||||
_surface->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
|
||||
for (int h = 0; h < 480; h++) {
|
||||
stream.read(_surface->getBasePtr(0, h), 640);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
54
engines/prince/mhwanh.h
Normal file
54
engines/prince/mhwanh.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_MHWANH_H
|
||||
#define PRINCE_MHWANH_H
|
||||
|
||||
#include "image/image_decoder.h"
|
||||
#include "image/bmp.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class MhwanhDecoder : public Image::ImageDecoder {
|
||||
public:
|
||||
MhwanhDecoder();
|
||||
~MhwanhDecoder() override;
|
||||
|
||||
// ImageDecoder API
|
||||
void destroy() override;
|
||||
bool loadStream(Common::SeekableReadStream &stream) override;
|
||||
Graphics::Surface *getSurface() const override { return _surface; }
|
||||
const Graphics::Palette &getPalette() const override { return _palette; }
|
||||
uint16 getPaletteCount() const { return kPaletteColorCount; }
|
||||
static const uint16 kPaletteColorCount = 256;
|
||||
|
||||
private:
|
||||
Graphics::Surface *_surface;
|
||||
Graphics::Palette _palette;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
276
engines/prince/mob.cpp
Normal file
276
engines/prince/mob.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/prince.h"
|
||||
|
||||
#include "prince/mob.h"
|
||||
#include "prince/animation.h"
|
||||
#include "prince/font.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
bool Mob::loadFromStream(Common::SeekableReadStream &stream) {
|
||||
int32 pos = stream.pos();
|
||||
|
||||
uint16 visible = stream.readUint16LE();
|
||||
|
||||
if (visible == 0xFFFF)
|
||||
return false;
|
||||
|
||||
_visible = visible;
|
||||
_type = stream.readUint16LE();
|
||||
_rect.left = stream.readUint16LE();
|
||||
_rect.top = stream.readUint16LE();
|
||||
_rect.right = stream.readUint16LE();
|
||||
_rect.bottom = stream.readUint16LE();
|
||||
|
||||
_mask = stream.readUint16LE();
|
||||
|
||||
_examPosition.x = stream.readUint16LE();
|
||||
_examPosition.y = stream.readUint16LE();
|
||||
_examDirection = (Direction)stream.readUint16LE();
|
||||
|
||||
_usePosition.x = stream.readByte();
|
||||
_usePosition.y = stream.readByte();
|
||||
_useDirection = (Direction)stream.readUint16LE();
|
||||
|
||||
uint32 nameOffset = stream.readUint32LE();
|
||||
uint32 examTextOffset = stream.readUint32LE();
|
||||
|
||||
byte c;
|
||||
stream.seek(nameOffset);
|
||||
_name.clear();
|
||||
while ((c = stream.readByte()))
|
||||
_name += c;
|
||||
|
||||
stream.seek(examTextOffset);
|
||||
_examText.clear();
|
||||
c = stream.readByte();
|
||||
if (c) {
|
||||
_examText += c;
|
||||
do {
|
||||
c = stream.readByte();
|
||||
_examText += c;
|
||||
} while (c != 255);
|
||||
}
|
||||
stream.seek(pos + 32);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mob::setData(AttrId dataId, uint16 value) {
|
||||
switch (dataId) {
|
||||
case kMobExamDir:
|
||||
_examDirection = (Direction)value;
|
||||
break;
|
||||
case kMobExamX:
|
||||
_examPosition.x = value;
|
||||
break;
|
||||
case kMobExamY:
|
||||
_examPosition.y = value;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Mob::getData(AttrId dataId) {
|
||||
switch (dataId) {
|
||||
case kMobVisible:
|
||||
return _visible;
|
||||
case kMobExamDir:
|
||||
return _examDirection;
|
||||
case kMobExamX:
|
||||
return _examPosition.x;
|
||||
case kMobExamY:
|
||||
return _examPosition.y;
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int PrinceEngine::getMob(Common::Array<Mob> &mobList, bool usePriorityList, int posX, int posY) {
|
||||
|
||||
Common::Point pointPos(posX, posY);
|
||||
|
||||
int mobListSize;
|
||||
if (usePriorityList) {
|
||||
mobListSize = _mobPriorityList.size();
|
||||
} else {
|
||||
mobListSize = mobList.size();
|
||||
}
|
||||
|
||||
for (int mobNumber = 0; mobNumber < mobListSize; mobNumber++) {
|
||||
Mob *mob = nullptr;
|
||||
if (usePriorityList) {
|
||||
mob = &mobList[_mobPriorityList[mobNumber]];
|
||||
} else {
|
||||
mob = &mobList[mobNumber];
|
||||
}
|
||||
|
||||
if (mob->_visible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int type = mob->_type & 7;
|
||||
switch (type) {
|
||||
case 0:
|
||||
case 1:
|
||||
//normal_mob
|
||||
if (!mob->_rect.contains(pointPos)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
//mob_obj
|
||||
if (mob->_mask < kMaxObjects) {
|
||||
int nr = _objSlot[mob->_mask];
|
||||
if (nr != 0xFF) {
|
||||
Object &obj = *_objList[nr];
|
||||
Common::Rect objectRect(obj._x, obj._y, obj._x + obj._width, obj._y + obj._height);
|
||||
if (objectRect.contains(pointPos)) {
|
||||
Graphics::Surface *objSurface = obj.getSurface();
|
||||
byte *pixel = (byte *)objSurface->getBasePtr(posX - obj._x, posY - obj._y);
|
||||
if (*pixel != 255) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
case 2:
|
||||
case 5:
|
||||
//check_ba_mob
|
||||
if (!_backAnimList[mob->_mask].backAnims.empty()) {
|
||||
int currentAnim = _backAnimList[mob->_mask]._seq._currRelative;
|
||||
Anim &backAnim = _backAnimList[mob->_mask].backAnims[currentAnim];
|
||||
if (backAnim._animData != nullptr) {
|
||||
if (!backAnim._state) {
|
||||
Common::Rect backAnimRect(backAnim._currX, backAnim._currY, backAnim._currX + backAnim._currW, backAnim._currY + backAnim._currH);
|
||||
if (backAnimRect.contains(pointPos)) {
|
||||
int phase = backAnim._showFrame;
|
||||
int phaseFrameIndex = backAnim._animData->getPhaseFrameIndex(phase);
|
||||
Graphics::Surface *backAnimSurface = backAnim._animData->getFrame(phaseFrameIndex);
|
||||
byte pixel = *(byte *)backAnimSurface->getBasePtr(posX - backAnim._currX, posY - backAnim._currY);
|
||||
if (pixel != 255) {
|
||||
if (type == 5) {
|
||||
if (mob->_rect.contains(pointPos)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
//not_part_ba
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (usePriorityList) {
|
||||
return _mobPriorityList[mobNumber];
|
||||
} else {
|
||||
return mobNumber;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int PrinceEngine::checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobList, bool usePriorityList) {
|
||||
if (_mouseFlag == 0 || _mouseFlag == 3) {
|
||||
return -1;
|
||||
}
|
||||
Common::Point mousePos = _system->getEventManager()->getMousePos();
|
||||
int mobNumber = getMob(mobList, usePriorityList, mousePos.x + _picWindowX, mousePos.y);
|
||||
|
||||
if (mobNumber != -1) {
|
||||
Common::String mobName = mobList[mobNumber]._name;
|
||||
|
||||
if (getLanguage() == Common::DE_DEU) {
|
||||
for (uint i = 0; i < mobName.size(); i++) {
|
||||
switch (mobName[i]) {
|
||||
case '\xc4':
|
||||
mobName.setChar('\x83', i);
|
||||
break;
|
||||
case '\xd6':
|
||||
mobName.setChar('\x84', i);
|
||||
break;
|
||||
case '\xdc':
|
||||
mobName.setChar('\x85', i);
|
||||
break;
|
||||
case '\xdf':
|
||||
mobName.setChar('\x7f', i);
|
||||
break;
|
||||
case '\xe4':
|
||||
mobName.setChar('\x80', i);
|
||||
break;
|
||||
case '\xf6':
|
||||
mobName.setChar('\x81', i);
|
||||
break;
|
||||
case '\xfc':
|
||||
mobName.setChar('\x82', i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _selectedMob can't be used here, as it gets reset when the player clicks, causing the mob
|
||||
// name to be voiced again
|
||||
if (mobNumber != _previousMob) {
|
||||
setTTSVoice(kHeroTextColor);
|
||||
sayText(mobName, false);
|
||||
}
|
||||
|
||||
uint16 textW = getTextWidth(mobName.c_str());
|
||||
|
||||
uint16 x = mousePos.x - textW / 2;
|
||||
if (x > screen->w) {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (x + textW > screen->w) {
|
||||
x = screen->w - textW;
|
||||
}
|
||||
|
||||
uint16 y = mousePos.y - _font->getFontHeight();
|
||||
if (y > screen->h) {
|
||||
y = _font->getFontHeight() - 2;
|
||||
}
|
||||
|
||||
_font->drawString(screen, mobName, x, y, screen->w, 216);
|
||||
}
|
||||
|
||||
_previousMob = mobNumber;
|
||||
|
||||
return mobNumber;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
69
engines/prince/mob.h
Normal file
69
engines/prince/mob.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_MOB_H
|
||||
#define PRINCE_MOB_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "prince/common.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Mob {
|
||||
public:
|
||||
|
||||
Mob() : _name(""), _examText(""), _visible(false), _type(0), _mask(0), _examDirection(kDirL), _useDirection(kDirL) {}
|
||||
|
||||
bool loadFromStream(Common::SeekableReadStream &stream);
|
||||
|
||||
// Used instead of offset in setData and getData
|
||||
enum AttrId {
|
||||
kMobVisible = 0,
|
||||
kMobExamX = 14,
|
||||
kMobExamY = 16,
|
||||
kMobExamDir = 18
|
||||
};
|
||||
|
||||
void setData(AttrId dataId, uint16 value);
|
||||
uint16 getData(AttrId dataId);
|
||||
|
||||
bool _visible;
|
||||
uint16 _type;
|
||||
uint16 _mask;
|
||||
Common::Rect _rect;
|
||||
|
||||
Common::Point _examPosition;
|
||||
Direction _examDirection;
|
||||
|
||||
Common::Point _usePosition;
|
||||
Direction _useDirection;
|
||||
|
||||
Common::String _name;
|
||||
Common::String _examText;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
39
engines/prince/module.mk
Normal file
39
engines/prince/module.mk
Normal file
@@ -0,0 +1,39 @@
|
||||
MODULE := engines/prince
|
||||
|
||||
MODULE_OBJS = \
|
||||
animation.o \
|
||||
archive.o \
|
||||
cursor.o \
|
||||
debugger.o \
|
||||
decompress.o \
|
||||
draw.o \
|
||||
flags.o \
|
||||
font.o \
|
||||
graphics.o \
|
||||
hero.o \
|
||||
inventory.o \
|
||||
metaengine.o \
|
||||
mhwanh.o \
|
||||
music.o \
|
||||
mob.o \
|
||||
object.o \
|
||||
prince.o \
|
||||
pscr.o \
|
||||
resource.o \
|
||||
saveload.o \
|
||||
script.o \
|
||||
sound.o \
|
||||
variatxt.o \
|
||||
videoplayer.o \
|
||||
walk.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_PRINCE), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
86
engines/prince/musNum.h
Normal file
86
engines/prince/musNum.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Prince {
|
||||
|
||||
enum RoomMus {
|
||||
ROOM01MUS = 3,
|
||||
ROOM02MUS = 9,
|
||||
ROOM03MUS = 9,
|
||||
ROOM04MUS = 9,
|
||||
ROOM05MUS = 13,
|
||||
ROOM06MUS = 9,
|
||||
ROOM07MUS = 9,
|
||||
ROOM08MUS = 9,
|
||||
ROOM09MUS = 14,
|
||||
ROOM10MUS = 9,
|
||||
ROOM11MUS = 9,
|
||||
ROOM12MUS = 9,
|
||||
ROOM13MUS = 9,
|
||||
ROOM14MUS = 9,
|
||||
ROOM15MUS = 5,
|
||||
ROOM16MUS = 5,
|
||||
ROOM17MUS = 5,
|
||||
ROOM18MUS = 5,
|
||||
ROOM19MUS = 5,
|
||||
ROOM20MUS = 12,
|
||||
ROOM21MUS = 9,
|
||||
ROOM22MUS = 9,
|
||||
ROOM23MUS = 1,
|
||||
ROOM24MUS = 1,
|
||||
ROOM25MUS = 2,
|
||||
ROOM26MUS = 10,
|
||||
ROOM27MUS = 7,
|
||||
ROOM28MUS = 10,
|
||||
ROOM29MUS = 10,
|
||||
ROOM30MUS = 11,
|
||||
ROOM31MUS = 14,
|
||||
ROOM32MUS = 11,
|
||||
ROOM33MUS = 7,
|
||||
ROOM34MUS = 7,
|
||||
ROOM35MUS = 7,
|
||||
ROOM36MUS = 7,
|
||||
ROOM37MUS = 7,
|
||||
ROOM38MUS = 7,
|
||||
ROOM39MUS = 7,
|
||||
ROOM40MUS = 7,
|
||||
ROOM41MUS = 7,
|
||||
ROOM42MUS = 7,
|
||||
ROOM43MUS = 15,
|
||||
ROOM46MUS = 100,
|
||||
ROOM47MUS = 100,
|
||||
ROOM48MUS = 100,
|
||||
ROOM49MUS = 100,
|
||||
ROOM50MUS = 100,
|
||||
ROOM51MUS = 12,
|
||||
ROOM52MUS = 9,
|
||||
ROOM53MUS = 5,
|
||||
ROOM54MUS = 11,
|
||||
ROOM55MUS = 11,
|
||||
ROOM56MUS = 11,
|
||||
ROOM57MUS = 7,
|
||||
ROOM58MUS = 13,
|
||||
ROOM59MUS = 16,
|
||||
ROOM60MUS = 4,
|
||||
ROOM61MUS = 0
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
235
engines/prince/music.cpp
Normal file
235
engines/prince/music.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "prince/music.h"
|
||||
#include "prince/musNum.h"
|
||||
#include "prince/resource.h"
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/debug.h"
|
||||
#include "audio/mididrv.h"
|
||||
#include "audio/midiparser.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
const char *MusicPlayer::_musTable[] = {
|
||||
"",
|
||||
"Battlfld.mid",
|
||||
"Cave.mid",
|
||||
"Cemetery.mid",
|
||||
"Credits.mid",
|
||||
"Fjord.mid",
|
||||
"Guitar.mid",
|
||||
"Hell.mid",
|
||||
"Jingle.mid",
|
||||
"Main.mid",
|
||||
"Night.mid",
|
||||
"Reality.mid",
|
||||
"Sunlord.mid",
|
||||
"Tavern.mid",
|
||||
"Temple.mid",
|
||||
"Boruta.mid",
|
||||
"Intro.mid"
|
||||
};
|
||||
|
||||
const uint8 MusicPlayer::_musRoomTable[] = {
|
||||
0,
|
||||
ROOM01MUS,
|
||||
ROOM02MUS,
|
||||
ROOM03MUS,
|
||||
ROOM04MUS,
|
||||
ROOM05MUS,
|
||||
ROOM06MUS,
|
||||
ROOM07MUS,
|
||||
ROOM08MUS,
|
||||
ROOM09MUS,
|
||||
ROOM10MUS,
|
||||
ROOM11MUS,
|
||||
ROOM12MUS,
|
||||
ROOM13MUS,
|
||||
ROOM14MUS,
|
||||
ROOM15MUS,
|
||||
ROOM16MUS,
|
||||
ROOM17MUS,
|
||||
ROOM18MUS,
|
||||
ROOM19MUS,
|
||||
ROOM20MUS,
|
||||
ROOM21MUS,
|
||||
ROOM22MUS,
|
||||
ROOM23MUS,
|
||||
ROOM24MUS,
|
||||
ROOM25MUS,
|
||||
ROOM26MUS,
|
||||
ROOM27MUS,
|
||||
ROOM28MUS,
|
||||
ROOM29MUS,
|
||||
ROOM30MUS,
|
||||
ROOM31MUS,
|
||||
ROOM32MUS,
|
||||
ROOM33MUS,
|
||||
ROOM34MUS,
|
||||
ROOM35MUS,
|
||||
ROOM36MUS,
|
||||
ROOM37MUS,
|
||||
ROOM38MUS,
|
||||
ROOM39MUS,
|
||||
ROOM40MUS,
|
||||
ROOM41MUS,
|
||||
ROOM42MUS,
|
||||
ROOM43MUS,
|
||||
0,
|
||||
0,
|
||||
ROOM46MUS,
|
||||
ROOM47MUS,
|
||||
ROOM48MUS,
|
||||
ROOM49MUS,
|
||||
ROOM50MUS,
|
||||
ROOM51MUS,
|
||||
ROOM52MUS,
|
||||
ROOM53MUS,
|
||||
ROOM54MUS,
|
||||
ROOM55MUS,
|
||||
ROOM56MUS,
|
||||
ROOM57MUS,
|
||||
ROOM58MUS,
|
||||
ROOM59MUS,
|
||||
ROOM60MUS,
|
||||
ROOM61MUS
|
||||
};
|
||||
|
||||
|
||||
MusicPlayer::MusicPlayer(PrinceEngine *vm) : _vm(vm) {
|
||||
_data = nullptr;
|
||||
_dataSize = 0;
|
||||
_isGM = false;
|
||||
|
||||
MidiPlayer::createDriver();
|
||||
|
||||
int ret = _driver->open();
|
||||
if (ret == 0) {
|
||||
if (_nativeMT32)
|
||||
_driver->sendMT32Reset();
|
||||
else
|
||||
_driver->sendGMReset();
|
||||
|
||||
_driver->setTimerCallback(this, &timerCallback);
|
||||
}
|
||||
}
|
||||
|
||||
MusicPlayer::~MusicPlayer() {
|
||||
killMidi();
|
||||
}
|
||||
|
||||
void MusicPlayer::killMidi() {
|
||||
Audio::MidiPlayer::stop();
|
||||
|
||||
free(_data);
|
||||
_data = nullptr;
|
||||
}
|
||||
|
||||
void MusicPlayer::loadMidi(const char *name) {
|
||||
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
|
||||
if (!stream) {
|
||||
warning("Can't load midi stream %s", name);
|
||||
return;
|
||||
}
|
||||
|
||||
stream = Resource::getDecompressedStream(stream);
|
||||
|
||||
// Stop any currently playing MIDI file
|
||||
killMidi();
|
||||
|
||||
// Read in the data for the file
|
||||
_dataSize = stream->size();
|
||||
_data = (byte *)malloc(_dataSize);
|
||||
stream->read(_data, _dataSize);
|
||||
|
||||
delete stream;
|
||||
|
||||
// Start playing the music
|
||||
sndMidiStart();
|
||||
}
|
||||
|
||||
void MusicPlayer::sndMidiStart() {
|
||||
_isGM = true;
|
||||
|
||||
MidiParser *parser = MidiParser::createParser_SMF();
|
||||
if (parser->loadMusic(_data, _dataSize)) {
|
||||
parser->setTrack(0);
|
||||
parser->setMidiDriver(this);
|
||||
parser->setTimerRate(_driver->getBaseTempo());
|
||||
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
|
||||
|
||||
_parser = parser;
|
||||
|
||||
syncVolume();
|
||||
|
||||
// Al the tracks are supposed to loop
|
||||
_isLooping = true;
|
||||
_isPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MusicPlayer::send(uint32 b) {
|
||||
if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
|
||||
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
|
||||
}
|
||||
|
||||
Audio::MidiPlayer::send(b);
|
||||
}
|
||||
|
||||
void MusicPlayer::sendToChannel(byte channel, uint32 b) {
|
||||
if (!_channelsTable[channel]) {
|
||||
_channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
|
||||
// If a new channel is allocated during the playback, make sure
|
||||
// its volume is correctly initialized.
|
||||
if (_channelsTable[channel])
|
||||
_channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
|
||||
}
|
||||
|
||||
if (_channelsTable[channel])
|
||||
_channelsTable[channel]->send(b);
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadMusic(int musNumber) {
|
||||
uint8 midiNumber = MusicPlayer::_musRoomTable[musNumber];
|
||||
if (midiNumber) {
|
||||
if (midiNumber != 100) {
|
||||
if (_currentMidi != midiNumber) {
|
||||
_currentMidi = midiNumber;
|
||||
const char *musName = MusicPlayer::_musTable[_currentMidi];
|
||||
_midiPlayer->loadMidi(musName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stopMusic();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrinceEngine::stopMusic() {
|
||||
if (_midiPlayer->isPlaying()) {
|
||||
_midiPlayer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
60
engines/prince/music.h
Normal file
60
engines/prince/music.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_MUSIC_H
|
||||
#define PRINCE_MUSIC_H
|
||||
|
||||
#include "audio/midiplayer.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class PrinceEngine;
|
||||
|
||||
class MusicPlayer: public Audio::MidiPlayer {
|
||||
private:
|
||||
PrinceEngine *_vm;
|
||||
byte *_data;
|
||||
int _dataSize;
|
||||
bool _isGM;
|
||||
|
||||
// Start MIDI File
|
||||
void sndMidiStart();
|
||||
|
||||
// Stop MIDI File
|
||||
void sndMidiStop();
|
||||
public:
|
||||
MusicPlayer(PrinceEngine *vm);
|
||||
~MusicPlayer() override;
|
||||
|
||||
void loadMidi(const char *);
|
||||
void killMidi();
|
||||
|
||||
void send(uint32 b) override;
|
||||
void sendToChannel(byte channel, uint32 b) override;
|
||||
|
||||
static const char *_musTable[];
|
||||
static const uint8 _musRoomTable[];
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
115
engines/prince/object.cpp
Normal file
115
engines/prince/object.cpp
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "prince/object.h"
|
||||
#include "prince/resource.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
Object::Object() : _surface(nullptr), _x(0), _y(0), _z(0), _flags(0), _width(0),
|
||||
_height(0), _zoomTime(0), _zoomSurface(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Object::~Object() {
|
||||
if (_surface != nullptr) {
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
_surface = nullptr;
|
||||
}
|
||||
if (_zoomSurface != nullptr) {
|
||||
_zoomSurface->free();
|
||||
delete _zoomSurface;
|
||||
_zoomSurface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Object::loadSurface(Common::SeekableReadStream &stream) {
|
||||
stream.skip(4);
|
||||
_width = stream.readUint16LE();
|
||||
_height = stream.readUint16LE();
|
||||
_surface = new Graphics::Surface();
|
||||
_surface->create(_width, _height, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
for (int h = 0; h < _surface->h; h++) {
|
||||
stream.read(_surface->getBasePtr(0, h), _surface->w);
|
||||
}
|
||||
}
|
||||
|
||||
bool Object::loadFromStream(Common::SeekableReadStream &stream) {
|
||||
int32 pos = stream.pos();
|
||||
uint16 x = stream.readUint16LE();
|
||||
if (x == 0xFFFF) {
|
||||
return false;
|
||||
}
|
||||
_x = x;
|
||||
_y = stream.readSint16LE(); // skull mini-game has some signed y coords
|
||||
|
||||
const Common::Path obStreamName(Common::String::format("OB%02d", stream.readUint16LE()));
|
||||
Common::SeekableReadStream *obStream = SearchMan.createReadStreamForMember(obStreamName);
|
||||
if (obStream) {
|
||||
obStream = Resource::getDecompressedStream(obStream);
|
||||
|
||||
loadSurface(*obStream);
|
||||
}
|
||||
delete obStream;
|
||||
|
||||
_flags = stream.readUint16LE();
|
||||
_z = stream.readUint16LE();
|
||||
|
||||
stream.seek(pos + 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Object::setData(AttrId dataId, int32 value) {
|
||||
switch (dataId) {
|
||||
case kObjectX:
|
||||
_x = value;
|
||||
break;
|
||||
case kObjectY:
|
||||
_y = value;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
int32 Object::getData(AttrId dataId) {
|
||||
switch (dataId) {
|
||||
case kObjectX:
|
||||
return _x;
|
||||
case kObjectY:
|
||||
return _y;
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
69
engines/prince/object.h
Normal file
69
engines/prince/object.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_OBJECT_H
|
||||
#define PRINCE_OBJECT_H
|
||||
|
||||
#include "image/image_decoder.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class Object {
|
||||
public:
|
||||
Object();
|
||||
~Object();
|
||||
|
||||
int32 _x;
|
||||
int32 _y;
|
||||
int32 _z;
|
||||
uint16 _width;
|
||||
uint16 _height;
|
||||
int32 _flags;
|
||||
int32 _zoomTime;
|
||||
Graphics::Surface *_zoomSurface;
|
||||
|
||||
// Used instead of offset in setData and getData
|
||||
enum AttrId {
|
||||
kObjectAddr = 0,
|
||||
kObjectX = 4,
|
||||
kObjectY = 6,
|
||||
kObjectZ = 8,
|
||||
kObjectFlags = 10,
|
||||
kObjectZoomInSource = 12,
|
||||
kObjectZoomInLen = 16,
|
||||
kObjectZoomInAddr = 20,
|
||||
kObjectZoomInTime = 24
|
||||
};
|
||||
|
||||
bool loadFromStream(Common::SeekableReadStream &stream);
|
||||
Graphics::Surface *getSurface() const { return _surface; }
|
||||
int32 getData(AttrId dataId);
|
||||
void setData(AttrId dataId, int32 value);
|
||||
|
||||
private:
|
||||
void loadSurface(Common::SeekableReadStream &stream);
|
||||
Graphics::Surface *_surface;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
141
engines/prince/option_text.h
Normal file
141
engines/prince/option_text.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Prince {
|
||||
|
||||
// PL - Mazovia coding
|
||||
const char invOptionsTextPL[5][18] = {
|
||||
"Obejrzyj",
|
||||
"U\xa7""yj",
|
||||
"Otw\xa2""rz/Pchnij",
|
||||
"Zamknij/Poci\x86""gnij",
|
||||
"Daj"
|
||||
};
|
||||
|
||||
const char optionsTextPL[7][18] = {
|
||||
"Podejd\xa6",
|
||||
"Obejrzyj",
|
||||
"Zabierz",
|
||||
"U\xa7""yj",
|
||||
"Otw\xa2""rz/Pchnij",
|
||||
"Zamknij/Poci\x86""gnij",
|
||||
"Porozmawiaj"
|
||||
};
|
||||
|
||||
// DE - Other font then for PL + ISO 8859-2 or Windows-1250
|
||||
// + special letter values changing
|
||||
// Normal value: 196, 214, 220, 223, 228, 246, 252
|
||||
// Prince change: 131, 132, 133, 127, 128, 129, 130
|
||||
char invOptionsTextDE[5][17] = {
|
||||
"Anschauen",
|
||||
"Benutzen",
|
||||
"\x84""ffnen/Sto\x7f""en",
|
||||
("Schlie\x7f""en/Ziehen"),
|
||||
"Geben"
|
||||
};
|
||||
|
||||
const char optionsTextDE[7][17] = {
|
||||
"Hingehen",
|
||||
"Anschauen",
|
||||
"Wegnehmen",
|
||||
"Benutzen",
|
||||
"\x84""ffnen/Sto\x7f""en",
|
||||
("Schlie\x7f""en/Ziehen"),
|
||||
"Ansprechen"
|
||||
};
|
||||
|
||||
// EN
|
||||
const char *invOptionsTextEN[] = {
|
||||
"Examine",
|
||||
"Use",
|
||||
"Open/Push",
|
||||
"Close/Pull",
|
||||
"Give"
|
||||
};
|
||||
|
||||
const char *optionsTextEN[] = {
|
||||
"Walk to",
|
||||
"Examine",
|
||||
"Pick up",
|
||||
"Use",
|
||||
"Open/Push",
|
||||
"Close/Pull",
|
||||
"Talk to"
|
||||
};
|
||||
|
||||
// ES
|
||||
const char *invOptionsTextES[] = {
|
||||
"Examinar",
|
||||
"Usar",
|
||||
"Abrir/Empujar",
|
||||
"Cerrar/Tirar de",
|
||||
"Dar"
|
||||
};
|
||||
|
||||
const char *optionsTextES[] = {
|
||||
"Ir hacia",
|
||||
"Examinar",
|
||||
"Coger",
|
||||
"Usar",
|
||||
"Abrir/Empujar",
|
||||
"Cerrar/Tirar de",
|
||||
"Hablar a"
|
||||
};
|
||||
|
||||
// RU
|
||||
const char *invOptionsTextRU[] = {
|
||||
"Cvjnhtnm",
|
||||
"Bcgjkmp.",
|
||||
"Jnrhsnm/""\x83""bnm ",
|
||||
"Pfrhsnm/Nzyenm ",
|
||||
"Lfnm "
|
||||
};
|
||||
|
||||
const char *optionsTextRU[] = {
|
||||
"Gjljqnb",
|
||||
"Jcvjnhtnm",
|
||||
"Dpznm ",
|
||||
"Bcgjkmp.",
|
||||
"Jnrhsnm/""\x83""bnm ",
|
||||
"Pfrhsnm/Nzyenm ",
|
||||
"Ujdjhbnm "
|
||||
};
|
||||
|
||||
// RU localization from "Russian Project"
|
||||
const char *invOptionsTextRU2[] = {
|
||||
"n""\x91""\x8c""\x8e""\x92""\x90""\x85""\x92""\x9c",
|
||||
"h""\x91""\x8f""\x8e""\x8b""\x9c""\x87"".",
|
||||
"n""\x92""\x8a""\x90""\x9b""\x92""\x9c""/r""\x8e""\x8b""\x8a""\x80""\x92""\x9c",
|
||||
"g""\x80""\x8a""\x90""\x9b""\x92""\x9c""/r""\x9f""\x8d""\x93""\x92""\x9c",
|
||||
"d""\x80""\x92""\x9c"
|
||||
};
|
||||
|
||||
const char *optionsTextRU2[] = {
|
||||
"o""\x8e""\x84""\x8e""\x89""\x92""\x88",
|
||||
"n""\x91""\x8c""\x8e""\x92""\x90""\x85""\x92""\x9c",
|
||||
"b""\x87""\x9f""\x92""\x9c",
|
||||
"h""\x91""\x8f""\x8e""\x8b""\x9c""\x87"".",
|
||||
"n""\x92""\x8a""\x90""\x9b""\x92""\x9c""/r""\x8e""\x8b""\x8a""\x80""\x92""\x9c",
|
||||
"g""\x80""\x8a""\x90""\x9b""\x92""\x9c""/r""\x9f""\x8d""\x93""\x92""\x9c",
|
||||
"c""\x8e""\x82""\x8e""\x90""\x88""\x92""\x9c"
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
1526
engines/prince/prince.cpp
Normal file
1526
engines/prince/prince.cpp
Normal file
File diff suppressed because it is too large
Load Diff
724
engines/prince/prince.h
Normal file
724
engines/prince/prince.h
Normal file
@@ -0,0 +1,724 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_PRINCE_H
|
||||
#define PRINCE_PRINCE_H
|
||||
|
||||
#include "common/random.h"
|
||||
#include "common/system.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "common/text-to-speech.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/events.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
#include "image/bmp.h"
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
#include "engines/util.h"
|
||||
|
||||
#include "audio/mixer.h"
|
||||
|
||||
#include "video/flic_decoder.h"
|
||||
|
||||
#include "prince/mob.h"
|
||||
#include "prince/object.h"
|
||||
#include "prince/pscr.h"
|
||||
#include "prince/detection.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
enum PRINCEActions {
|
||||
kActionNone,
|
||||
kActionSave,
|
||||
kActionLoad,
|
||||
kActionZ,
|
||||
kActionX,
|
||||
kActionSkip,
|
||||
};
|
||||
|
||||
struct SavegameHeader;
|
||||
|
||||
class PrinceEngine;
|
||||
class GraphicsMan;
|
||||
class Script;
|
||||
class Interpreter;
|
||||
class InterpreterFlags;
|
||||
class Debugger;
|
||||
class MusicPlayer;
|
||||
class VariaTxt;
|
||||
class Cursor;
|
||||
class MhwanhDecoder;
|
||||
class Font;
|
||||
class Hero;
|
||||
class Animation;
|
||||
class Room;
|
||||
class Pscr;
|
||||
|
||||
struct SavegameHeader {
|
||||
uint8 version;
|
||||
Common::String saveName;
|
||||
Graphics::Surface *thumbnail;
|
||||
int16 saveYear, saveMonth, saveDay;
|
||||
int16 saveHour, saveMinutes;
|
||||
uint32 playTime;
|
||||
};
|
||||
|
||||
#define kSavegameStrSize 14
|
||||
#define kSavegameStr "SCUMMVM_PRINCE"
|
||||
|
||||
struct Text {
|
||||
const char *_str;
|
||||
uint16 _x, _y;
|
||||
uint16 _time;
|
||||
uint32 _color;
|
||||
|
||||
Text() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_str = nullptr;
|
||||
_x = 0;
|
||||
_y = 0;
|
||||
_time = 0;
|
||||
_color = 255;
|
||||
}
|
||||
};
|
||||
|
||||
struct AnimListItem {
|
||||
uint16 _type; // type of animation - for background anims RND of frame
|
||||
uint16 _fileNumber;
|
||||
uint16 _startPhase; // first phase number
|
||||
uint16 _endPhase;
|
||||
uint16 _loopPhase;
|
||||
int16 _x;
|
||||
int16 _y;
|
||||
uint16 _loopType;
|
||||
uint16 _nextAnim; // number of animation to do for loop = 3
|
||||
uint16 _flags; // byte 0 - draw masks, byte 1 - draw in front of mask, byte 2 - load but turn off drawing
|
||||
bool loadFromStream(Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct BAS {
|
||||
int32 _type; // type of sequence
|
||||
int32 _data; // additional data
|
||||
int32 _anims; // number of animations
|
||||
int32 _current; // actual number of animation
|
||||
int32 _counter; // time counter for animation
|
||||
int32 _currRelative; //actual relative number for animation
|
||||
int32 _data2; // additional data for measurements
|
||||
};
|
||||
|
||||
const int kStructSizeBAS = 28;
|
||||
|
||||
struct BASA {
|
||||
int16 _num; // animation number
|
||||
int16 _start; // initial frame
|
||||
int16 _end; // final frame
|
||||
//int16 _pad; // fulfilment to 8 bytes
|
||||
};
|
||||
|
||||
const int kStructSizeBASA = 8;
|
||||
|
||||
// background and normal animation
|
||||
struct Anim {
|
||||
BASA _basaData;
|
||||
int32 _addr; // animation address
|
||||
int16 _usage;
|
||||
int16 _state; // state of animation: 0 - turning on, 1 - turning off
|
||||
int16 _flags;
|
||||
int16 _frame; // number of phase to show
|
||||
int16 _lastFrame; // last phase
|
||||
int16 _loopFrame; // first frame of loop
|
||||
int16 _showFrame; // actual visible frame of animation
|
||||
int16 _loopType; // type of loop (0 - last frame; 1 - normal loop (begin from _loopFrame); 2 - no loop; 3 - load new animation)
|
||||
int16 _nextAnim; // number of next animation to load after actual
|
||||
int16 _x;
|
||||
int16 _y;
|
||||
int32 _currFrame;
|
||||
int16 _currX;
|
||||
int16 _currY;
|
||||
int16 _currW;
|
||||
int16 _currH;
|
||||
int16 _packFlag;
|
||||
int32 _currShadowFrame;
|
||||
int16 _packShadowFlag;
|
||||
int32 _shadowBack;
|
||||
int16 _relX;
|
||||
int16 _relY;
|
||||
Animation *_animData;
|
||||
Animation *_shadowData;
|
||||
|
||||
enum AnimOffsets {
|
||||
kAnimState = 10,
|
||||
kAnimFrame = 14,
|
||||
kAnimLastFrame = 16,
|
||||
kAnimX = 26
|
||||
};
|
||||
|
||||
int16 getAnimData(Anim::AnimOffsets offset) {
|
||||
switch (offset) {
|
||||
case kAnimState:
|
||||
return _state;
|
||||
case kAnimFrame:
|
||||
return _frame + 1; // fix for location 30 - man with a dog animation
|
||||
case kAnimX:
|
||||
return _x;
|
||||
default:
|
||||
error("getAnimData() - Wrong offset type: %d", (int)offset);
|
||||
}
|
||||
}
|
||||
|
||||
void setAnimData(Anim::AnimOffsets offset, int16 value) {
|
||||
if (offset == kAnimX) {
|
||||
_x = value;
|
||||
} else {
|
||||
error("setAnimData() - Wrong offset: %d, value: %d", (int)offset, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BackgroundAnim {
|
||||
BAS _seq;
|
||||
Common::Array<Anim> backAnims;
|
||||
};
|
||||
|
||||
enum AnimType {
|
||||
kBackgroundAnimation,
|
||||
kNormalAnimation
|
||||
};
|
||||
|
||||
// Nak (PL - Nakladka)
|
||||
struct Mask {
|
||||
uint16 _state; // visible / invisible
|
||||
int16 _flags; // turning on / turning off of a mask
|
||||
int16 _x1;
|
||||
int16 _y1;
|
||||
int16 _x2;
|
||||
int16 _y2;
|
||||
int16 _z;
|
||||
int16 _number; // number of mask for background recreating
|
||||
int16 _width;
|
||||
int16 _height;
|
||||
byte *_data;
|
||||
|
||||
int16 getX() const {
|
||||
return READ_LE_UINT16(_data);
|
||||
}
|
||||
|
||||
int16 getY() const {
|
||||
return READ_LE_UINT16(_data + 2);
|
||||
}
|
||||
|
||||
int16 getWidth() const {
|
||||
return READ_LE_UINT16(_data + 4);
|
||||
}
|
||||
|
||||
int16 getHeight() const {
|
||||
return READ_LE_UINT16(_data + 6);
|
||||
}
|
||||
|
||||
byte *getMask() const {
|
||||
return (byte *)(_data + 8);
|
||||
}
|
||||
};
|
||||
|
||||
struct InvItem {
|
||||
int _x;
|
||||
int _y;
|
||||
Graphics::Surface *_surface;
|
||||
Graphics::Surface *getSurface() const { return _surface; }
|
||||
};
|
||||
|
||||
struct DrawNode {
|
||||
int posX;
|
||||
int posY;
|
||||
int posZ;
|
||||
int32 width;
|
||||
int32 height;
|
||||
int32 scaleValue;
|
||||
Graphics::Surface *s;
|
||||
Graphics::Surface *originalRoomSurface;
|
||||
void *data;
|
||||
void (*drawFunction)(Graphics::Surface *, DrawNode *);
|
||||
};
|
||||
|
||||
struct DebugChannel {
|
||||
|
||||
enum Type {
|
||||
kScript = 1 << 0,
|
||||
kEngine = 1 << 1
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
static const uint8 kHeroTextColor = 220;
|
||||
|
||||
class PrinceEngine : public Engine {
|
||||
protected:
|
||||
Common::Error run() override;
|
||||
|
||||
public:
|
||||
PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc);
|
||||
~PrinceEngine() override;
|
||||
|
||||
bool scummVMSaveLoadDialog(bool isSave);
|
||||
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
void pauseEngineIntern(bool pause) override;
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
|
||||
Common::Error loadGameState(int slot) override;
|
||||
|
||||
void playVideo(const Common::Path &videoFilename);
|
||||
|
||||
WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail = true);
|
||||
void writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header);
|
||||
void syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream);
|
||||
bool loadGame(int slotNumber);
|
||||
void resetGame();
|
||||
|
||||
int32 _creditsDataSize;
|
||||
byte *_creditsData;
|
||||
void scrollCredits();
|
||||
|
||||
int getGameType() const;
|
||||
const char *getGameId() const;
|
||||
uint32 getFeatures() const;
|
||||
Common::Language getLanguage() const;
|
||||
|
||||
const PrinceGameDescription *_gameDescription;
|
||||
Video::FlicDecoder _flicPlayer;
|
||||
const Graphics::Surface *_flcFrameSurface;
|
||||
VariaTxt *_variaTxt;
|
||||
|
||||
uint32 _talkTxtSize;
|
||||
byte *_talkTxt;
|
||||
|
||||
uint32 _mobTranslationSize;
|
||||
byte *_mobTranslationData;
|
||||
|
||||
bool _missingVoice;
|
||||
|
||||
bool loadLocation(uint16 locationNr);
|
||||
bool loadAnim(uint16 animNr, bool loop);
|
||||
bool loadVoice(uint32 textSlot, uint32 sampleSlot, const Common::String &name);
|
||||
bool loadSample(uint32 sampleSlot, const Common::String &name);
|
||||
bool loadZoom(byte *zoomBitmap, uint32 dataSize, const char *resourceName);
|
||||
bool loadShadow(byte *shadowBitmap, uint32 dataSize, const char *resourceName1, const char *resourceName2);
|
||||
bool loadTrans(byte *transTable, const char *resourceName);
|
||||
bool loadMobPriority(const char *resourceName);
|
||||
|
||||
void loadMobTranslationTexts();
|
||||
void setMobTranslationTexts();
|
||||
|
||||
bool loadMusic(int musNumber);
|
||||
void stopMusic();
|
||||
|
||||
void playSample(uint16 sampleId, uint16 loopType);
|
||||
void stopSample(uint16 sampleId);
|
||||
void stopAllSamples();
|
||||
void freeSample(uint16 sampleId);
|
||||
void freeAllSamples();
|
||||
|
||||
void setVoice(uint16 slot, uint32 sampleSlot, uint16 flag);
|
||||
|
||||
void changeCursor(uint16 curId);
|
||||
void printAt(uint32 slot, uint8 color, char *s, uint16 x, uint16 y);
|
||||
int calcTextLines(const char *s);
|
||||
int calcTextTime(int numberOfLines);
|
||||
void correctStringDEU(char *s);
|
||||
|
||||
void sayText(const Common::String &text, bool isSpeech, Common::TextToSpeechManager::Action action = Common::TextToSpeechManager::INTERRUPT);
|
||||
#ifdef USE_TTS
|
||||
Common::U32String convertText(const Common::String &text) const;
|
||||
bool checkConversionTable(const byte *character, int &index, byte *convertedBytes, const uint16 *table) const;
|
||||
#endif
|
||||
void setTTSVoice(uint8 textColor) const;
|
||||
void stopTextToSpeech() const;
|
||||
|
||||
static const uint8 kMaxTexts = 32;
|
||||
Text _textSlots[kMaxTexts];
|
||||
|
||||
Hero *_mainHero;
|
||||
Hero *_secondHero;
|
||||
|
||||
enum HeroId {
|
||||
kMainHero,
|
||||
kSecondHero
|
||||
};
|
||||
|
||||
int _mouseFlag;
|
||||
uint32 _currentTime;
|
||||
uint16 _locationNr;
|
||||
uint16 _sceneWidth;
|
||||
int32 _picWindowX;
|
||||
int32 _picWindowY;
|
||||
|
||||
bool _printMapNotification;
|
||||
bool _intro;
|
||||
bool _credits;
|
||||
|
||||
Image::BitmapDecoder *_roomBmp;
|
||||
MhwanhDecoder *_suitcaseBmp;
|
||||
Room *_room;
|
||||
Script *_script;
|
||||
InterpreterFlags *_flags;
|
||||
Interpreter *_interpreter;
|
||||
GraphicsMan *_graph;
|
||||
uint8 _currentMidi;
|
||||
byte *_zoomBitmap;
|
||||
byte *_shadowBitmap;
|
||||
byte *_transTable;
|
||||
|
||||
int16 _scaleValue; // scale for hero or special shadow animation
|
||||
int16 _lightX; // for hero shadow
|
||||
int16 _lightY;
|
||||
int32 _shadScaleValue;
|
||||
int32 _shadLineLen;
|
||||
byte *_shadowLine;
|
||||
void setShadowScale(int32 shadowScale);
|
||||
|
||||
static const int16 kFPS = 15;
|
||||
static const int32 kIntMax = 2147483647;
|
||||
|
||||
static const int16 kMaxPicWidth = 1280;
|
||||
static const int16 kMaxPicHeight = 480;
|
||||
static const int16 kZoomStep = 4;
|
||||
static const int32 kZoomBitmapLen = kMaxPicHeight / kZoomStep * kMaxPicWidth / kZoomStep;
|
||||
static const int32 kShadowBitmapSize = kMaxPicWidth * kMaxPicHeight / 8;
|
||||
static const int16 kShadowLineArraySize = 2 * 1280 * 4;
|
||||
static const int16 kZoomBitmapWidth = kMaxPicWidth / kZoomStep;
|
||||
static const int16 kZoomBitmapHeight = kMaxPicHeight / kZoomStep;
|
||||
static const int16 kNormalWidth = 640;
|
||||
static const int16 kNormalHeight = 480;
|
||||
static const uint32 kTransTableSize = 256 * 256;
|
||||
|
||||
static const int kMaxNormAnims = 64;
|
||||
static const int kMaxBackAnims = 64;
|
||||
static const int kMaxObjects = 64;
|
||||
static const int kMaxMobs = 64;
|
||||
|
||||
Common::Array<DrawNode> _drawNodeList;
|
||||
Common::Array<AnimListItem> _animList;
|
||||
Common::Array<BackgroundAnim> _backAnimList;
|
||||
Common::Array<Anim> _normAnimList;
|
||||
Common::Array<Mob> _mobList;
|
||||
Common::Array<uint32> _mobPriorityList;
|
||||
Common::Array<Mask> _maskList;
|
||||
Common::Array<Object *> _objList;
|
||||
uint16 *_objSlot;
|
||||
|
||||
void freeNormAnim(int slot);
|
||||
void freeAllNormAnims();
|
||||
void removeSingleBackAnim(int slot);
|
||||
|
||||
Common::RandomSource _randomSource;
|
||||
|
||||
void checkMasks(int x1, int y1, int sprWidth, int sprHeight, int z);
|
||||
void insertMasks(Graphics::Surface *originalRoomSurface);
|
||||
void showMask(int maskNr, Graphics::Surface *originalRoomSurface);
|
||||
void clsMasks();
|
||||
|
||||
void grabMap();
|
||||
|
||||
int _selectedMob; // number of selected Mob / inventory item
|
||||
int _previousMob;
|
||||
int _dialogMob;
|
||||
int _selectedItem; // number of item on mouse cursor
|
||||
int _selectedMode;
|
||||
int _currentPointerNumber;
|
||||
|
||||
static const int16 kMaxInv = 90; // max amount of inventory items in whole game
|
||||
static const uint16 kMaxItems = 30; // size of inventory
|
||||
|
||||
uint32 _invTxtSize;
|
||||
byte *_invTxt;
|
||||
|
||||
Graphics::Surface *_optionsPic;
|
||||
Graphics::Surface *_optionsPicInInventory;
|
||||
|
||||
bool _optionsFlag;
|
||||
int _optionEnabled;
|
||||
int _optionsMob;
|
||||
int _optionsX;
|
||||
int _optionsY;
|
||||
int _optionsWidth;
|
||||
int _optionsHeight;
|
||||
int _invOptionsWidth;
|
||||
int _invOptionsHeight;
|
||||
int _optionsStep;
|
||||
int _invOptionsStep;
|
||||
int _optionsNumber;
|
||||
int _invOptionsNumber;
|
||||
int _optionsColor1; // color for non-selected options
|
||||
int _optionsColor2; // color for selected option
|
||||
|
||||
bool _showInventoryFlag;
|
||||
int _invExamY;
|
||||
bool _inventoryBackgroundRemember;
|
||||
int _invLineX;
|
||||
int _invLineY;
|
||||
int _invLine; // number of items in one line
|
||||
int _invLines; // number of lines with inventory items
|
||||
int _invLineW;
|
||||
int _invLineH;
|
||||
int _maxInvW;
|
||||
int _maxInvH;
|
||||
int _invLineSkipX;
|
||||
int _invLineSkipY;
|
||||
int _invX1;
|
||||
int _invY1;
|
||||
int _invWidth;
|
||||
int _invHeight;
|
||||
bool _invCurInside;
|
||||
int _mst_shadow;
|
||||
int _mst_shadow2; // blinking after adding new item
|
||||
int _candleCounter; // special counter for candle inventory item
|
||||
int _invMaxCount; // time to turn inventory on
|
||||
int _invCounter; // turning on counter
|
||||
|
||||
void inventoryFlagChange(bool inventoryState);
|
||||
bool loadAllInv();
|
||||
void rememberScreenInv();
|
||||
void prepareInventoryToView();
|
||||
void drawInvItems();
|
||||
void displayInventory();
|
||||
void addInv(int heroId, int item, bool addItemQuiet);
|
||||
void remInv(int heroId, int item);
|
||||
void clearInv(int heroId);
|
||||
void swapInv(int heroId);
|
||||
void addInvObj();
|
||||
void makeInvCursor(int itemNr);
|
||||
void enableOptions(bool checkType);
|
||||
void checkOptions();
|
||||
void checkInvOptions();
|
||||
void openInventoryCheck();
|
||||
|
||||
void leftMouseButton();
|
||||
void rightMouseButton();
|
||||
void inventoryLeftMouseButton();
|
||||
void inventoryRightMouseButton();
|
||||
void dialogLeftMouseButton(byte *string, int dialogSelected);
|
||||
|
||||
uint32 _dialogDatSize;
|
||||
byte *_dialogDat;
|
||||
byte *_dialogData; // on, off flags for lines of dialog text
|
||||
|
||||
byte *_dialogBoxAddr[32]; // adresses of dialog windows
|
||||
byte *_dialogOptAddr[32]; // adresses of dialog options
|
||||
int _dialogOptLines[4 * 32]; // numbers of initial dialog lines
|
||||
|
||||
byte *_dialogText;
|
||||
int _dialogLines;
|
||||
bool _dialogFlag;
|
||||
int _dialogWidth;
|
||||
int _dialogHeight;
|
||||
int _dialogLineSpace;
|
||||
int _dialogColor1; // color for non-selected options
|
||||
int _dialogColor2; // color for selected option
|
||||
int _previousSelectedDialog;
|
||||
bool _isConversing;
|
||||
Graphics::Surface *_dialogImage;
|
||||
|
||||
void createDialogBox(int dialogBoxNr);
|
||||
void dialogRun();
|
||||
void talkHero(int slot);
|
||||
void doTalkAnim(int animNumber, int slot, AnimType animType);
|
||||
|
||||
static const uint8 zoomInStep = 8;
|
||||
void initZoomIn(int slot);
|
||||
void initZoomOut(int slot);
|
||||
void doZoomIn(int slot);
|
||||
void doZoomOut(int slot);
|
||||
void freeZoomObject(int slot);
|
||||
|
||||
static const uint8 kFadeStep = 4;
|
||||
void blackPalette();
|
||||
void setPalette(const byte *palette);
|
||||
|
||||
int getMob(Common::Array<Mob> &mobList, bool usePriorityList, int posX, int posY);
|
||||
|
||||
// 'Throw a rock' mini-game:
|
||||
static const int16 kCurveLen = 17;
|
||||
static const int kCelStep = 4;
|
||||
int16 *_curveData;
|
||||
int _curvPos;
|
||||
void makeCurve();
|
||||
void getCurve();
|
||||
void mouseWeirdo();
|
||||
|
||||
static const uint16 kPowerBarPosX = 288;
|
||||
static const uint16 kPowerBarPosY = 430;
|
||||
static const uint8 kPowerBarWidth = 64;
|
||||
static const uint8 kPowerBarHeight = 16;
|
||||
static const uint8 kPowerBarBackgroundColor = 0;
|
||||
static const uint16 kPowerBarGreenPosY = 434;
|
||||
static const uint8 kPowerBarGreenColor1 = 202;
|
||||
static const uint8 kPowerBarGreenColor2 = 235;
|
||||
static const uint8 kPowerBarGreenHeight = 8;
|
||||
void showPower();
|
||||
|
||||
// Pathfinding
|
||||
static const int16 kPathGridStep = 2;
|
||||
static const uint32 kPathBitmapLen = (kMaxPicHeight / kPathGridStep * kMaxPicWidth / kPathGridStep) / 8;
|
||||
static const int32 kTracePts = 8000;
|
||||
static const int32 kPBW = kMaxPicWidth / 16; // PathBitmapWidth
|
||||
static const int kMinDistance = 2500;
|
||||
|
||||
byte *_roomPathBitmap; // PL - Sala
|
||||
byte *_roomPathBitmapTemp; // PL - SSala
|
||||
byte *_coordsBufEnd;
|
||||
byte *_coordsBuf; // optimal path
|
||||
byte *_coords; // last path point address from coordsBuf
|
||||
byte *_coordsBuf2;
|
||||
byte *_coords2;
|
||||
byte *_coordsBuf3;
|
||||
byte *_coords3;
|
||||
int _traceLineLen;
|
||||
bool _traceLineFirstPointFlag; // if plotTraceLine after first point
|
||||
bool _tracePointFirstPointFlag; // if plotTracePoint after first point
|
||||
byte *_directionTable;
|
||||
int _shanLen;
|
||||
|
||||
byte *_checkBitmapTemp;
|
||||
byte *_checkBitmap;
|
||||
int _checkMask;
|
||||
int _checkX;
|
||||
int _checkY;
|
||||
|
||||
byte *_rembBitmapTemp;
|
||||
byte *_rembBitmap;
|
||||
int _rembMask;
|
||||
int _rembX;
|
||||
int _rembY;
|
||||
|
||||
int _fpX;
|
||||
int _fpY;
|
||||
|
||||
int drawLine(int x0, int y0, int x1, int y1, int (*plotProc)(int, int, void *), void *data);
|
||||
bool loadPath(const char *resourceName);
|
||||
byte *makePath(int heroId, int currX, int currY, int destX, int destY);
|
||||
void findPoint(int x, int y);
|
||||
int getPixelAddr(byte *pathBitmap, int x, int y);
|
||||
static int plotTraceLine(int x, int y, void *data);
|
||||
void specialPlotInside(int x, int y);
|
||||
bool tracePath(int x1, int y1, int x2, int y2);
|
||||
Direction makeDirection(int x1, int y1, int x2, int y2);
|
||||
void specialPlot(int x, int y);
|
||||
void specialPlot2(int x, int y);
|
||||
void allocCoords2();
|
||||
void freeCoords2();
|
||||
void freeCoords3();
|
||||
static int plotTracePoint(int x, int y, void *data);
|
||||
void specialPlotInside2(int x, int y);
|
||||
void approxPath();
|
||||
void freeDirectionTable();
|
||||
void scanDirections();
|
||||
int scanDirectionsFindNext(byte *coords, int xDiff, int yDiff);
|
||||
void moveShandria();
|
||||
void walkTo();
|
||||
void moveRunHero(int heroId, int x, int y, int dir, bool runHeroFlag);
|
||||
|
||||
int leftDownDir();
|
||||
int leftDir();
|
||||
int leftUpDir();
|
||||
int rightDownDir();
|
||||
int rightDir();
|
||||
int rightUpDir();
|
||||
int upLeftDir();
|
||||
int upDir();
|
||||
int upRightDir();
|
||||
int downLeftDir();
|
||||
int downDir();
|
||||
int downRightDir();
|
||||
|
||||
int cpe();
|
||||
int checkLeftDownDir();
|
||||
int checkLeftDir();
|
||||
int checkDownDir();
|
||||
int checkUpDir();
|
||||
int checkRightDir();
|
||||
int checkLeftUpDir();
|
||||
int checkRightDownDir();
|
||||
int checkRightUpDir();
|
||||
|
||||
private:
|
||||
bool playNextFLCFrame();
|
||||
void keyHandler(Common::Event event);
|
||||
int checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobList, bool usePriorityList);
|
||||
void drawScreen();
|
||||
void showTexts(Graphics::Surface *screen);
|
||||
void init();
|
||||
void showLogo();
|
||||
void showAnim(Anim &anim);
|
||||
void showNormAnims();
|
||||
void setBackAnim(Anim &backAnim);
|
||||
void showBackAnims();
|
||||
void clearBackAnimList();
|
||||
bool spriteCheck(int sprWidth, int sprHeight, int destX, int destY);
|
||||
void showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ);
|
||||
void showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ);
|
||||
void showObjects();
|
||||
void showParallax();
|
||||
static bool compareDrawNodes(DrawNode d1, DrawNode d2);
|
||||
void runDrawNodes();
|
||||
void makeShadowTable(int brightness);
|
||||
void pausePrinceEngine(int fps = kFPS);
|
||||
|
||||
uint32 getTextWidth(const char *s);
|
||||
void debugEngine(const char *s, ...);
|
||||
|
||||
uint8 _cursorNr;
|
||||
|
||||
Common::RandomSource *_rnd;
|
||||
Cursor *_cursor1;
|
||||
Graphics::Surface *_cursor2;
|
||||
Cursor *_cursor3;
|
||||
Debugger *_debugger;
|
||||
Font *_font;
|
||||
MusicPlayer *_midiPlayer;
|
||||
|
||||
static const int kMaxSamples = 60;
|
||||
Audio::RewindableAudioStream *_audioStream[kMaxSamples];
|
||||
Audio::SoundHandle _soundHandle[kMaxSamples];
|
||||
|
||||
Common::Array<PScr *> _pscrList;
|
||||
Common::Array<InvItem> _allInvList;
|
||||
Common::Array<Mob> _invMobList;
|
||||
|
||||
bool _flicLooped;
|
||||
|
||||
void mainLoop();
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
77
engines/prince/pscr.cpp
Normal file
77
engines/prince/pscr.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "prince/pscr.h"
|
||||
#include "prince/resource.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
PScr::PScr() : _x(0), _y(0), _step(0), _surface(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
PScr::~PScr() {
|
||||
if (_surface != nullptr) {
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
_surface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PScr::loadSurface(Common::SeekableReadStream &stream) {
|
||||
stream.skip(4);
|
||||
int width = stream.readUint16LE();
|
||||
int height = stream.readUint16LE();
|
||||
_surface = new Graphics::Surface();
|
||||
_surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
for (int h = 0; h < _surface->h; h++) {
|
||||
stream.read(_surface->getBasePtr(0, h), _surface->w);
|
||||
}
|
||||
}
|
||||
|
||||
bool PScr::loadFromStream(Common::SeekableReadStream &stream) {
|
||||
int32 pos = stream.pos();
|
||||
uint16 file = stream.readUint16LE();
|
||||
if (file == 0xFFFF) {
|
||||
return false;
|
||||
}
|
||||
_x = stream.readUint16LE();
|
||||
_y = stream.readUint16LE();
|
||||
_step = stream.readUint16LE();
|
||||
|
||||
const Common::Path pscrStreamName(Common::String::format("PS%02d", file));
|
||||
Common::SeekableReadStream *pscrStream = SearchMan.createReadStreamForMember(pscrStreamName);
|
||||
if (pscrStream != nullptr) {
|
||||
pscrStream = Resource::getDecompressedStream(pscrStream);
|
||||
|
||||
loadSurface(*pscrStream);
|
||||
}
|
||||
delete pscrStream;
|
||||
stream.seek(pos + 12); // size of PScrList struct
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
47
engines/prince/pscr.h
Normal file
47
engines/prince/pscr.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_PSCR_H
|
||||
#define PRINCE_PSCR_H
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class PScr {
|
||||
public:
|
||||
PScr();
|
||||
~PScr();
|
||||
int16 _x;
|
||||
int16 _y;
|
||||
int16 _step;
|
||||
static const int16 kPScrZ = 1000;
|
||||
|
||||
bool loadFromStream(Common::SeekableReadStream &stream);
|
||||
Graphics::Surface *getSurface() const { return _surface; }
|
||||
private:
|
||||
void loadSurface(Common::SeekableReadStream &stream);
|
||||
Graphics::Surface *_surface;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
366
engines/prince/resource.cpp
Normal file
366
engines/prince/resource.cpp
Normal file
@@ -0,0 +1,366 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/fs.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "prince/graphics.h"
|
||||
#include "prince/debugger.h"
|
||||
#include "prince/script.h"
|
||||
#include "prince/hero.h"
|
||||
#include "prince/resource.h"
|
||||
#include "prince/archive.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
Common::SeekableReadStream *Resource::getDecompressedStream(Common::SeekableReadStream *stream) {
|
||||
if (!(((PrinceEngine *)g_engine)->getFeatures() & GF_EXTRACTED))
|
||||
return stream;
|
||||
|
||||
byte header[4];
|
||||
|
||||
stream->read(header, 4);
|
||||
stream->seek(0);
|
||||
|
||||
if (READ_BE_UINT32(header) == MKTAG('M', 'A', 'S', 'M')) {
|
||||
byte *buffer = (byte *)malloc(stream->size());
|
||||
stream->read(buffer, stream->size());
|
||||
|
||||
Decompressor dec;
|
||||
uint32 decompLen = READ_BE_UINT32(buffer + 14);
|
||||
byte *decompData = (byte *)malloc(decompLen);
|
||||
dec.decompress(buffer + 18, decompData, decompLen);
|
||||
free(buffer);
|
||||
|
||||
debug(8, "Resource::getDecompressedStream: decompressed %d to %d bytes", (int)stream->size(), decompLen);
|
||||
|
||||
return new Common::MemoryReadStream(decompData, decompLen, DisposeAfterUse::YES);
|
||||
} else {
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
bool AnimListItem::loadFromStream(Common::SeekableReadStream &stream) {
|
||||
int32 pos = stream.pos();
|
||||
|
||||
uint16 type = stream.readUint16LE();
|
||||
if (type == 0xFFFF) {
|
||||
return false;
|
||||
}
|
||||
_type = type;
|
||||
_fileNumber = stream.readUint16LE();
|
||||
_startPhase = stream.readUint16LE();
|
||||
_endPhase = stream.readUint16LE();
|
||||
_loopPhase = stream.readUint16LE();
|
||||
_x = stream.readSint16LE();
|
||||
_y = stream.readSint16LE();
|
||||
_loopType = stream.readUint16LE();
|
||||
_nextAnim = stream.readUint16LE();
|
||||
_flags = stream.readUint16LE();
|
||||
|
||||
debug(7, "AnimListItem type %d, fileNumber %d, x %d, y %d, flags %d", _type, _fileNumber, _x, _y, _flags);
|
||||
debug(7, "startPhase %d, endPhase %d, loopPhase %d", _startPhase, _endPhase, _loopPhase);
|
||||
|
||||
// 32 byte aligment
|
||||
stream.seek(pos + 32);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadLocation(uint16 locationNr) {
|
||||
|
||||
blackPalette();
|
||||
|
||||
_flicPlayer.close();
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE(_textSlots); i++) {
|
||||
_textSlots[i].clear();
|
||||
_textSlots[i]._color = 0; // FIXME: Can be left at default of 255?
|
||||
}
|
||||
freeAllSamples();
|
||||
|
||||
debugEngine("PrinceEngine::loadLocation %d", locationNr);
|
||||
const Common::FSNode gameDataDir(ConfMan.getPath("path"));
|
||||
SearchMan.remove(Common::String::format("%02d", _locationNr));
|
||||
|
||||
_locationNr = locationNr;
|
||||
_debugger->_locationNr = locationNr;
|
||||
|
||||
_flags->setFlagValue(Flags::CURRROOM, _locationNr);
|
||||
_interpreter->stopBg();
|
||||
|
||||
changeCursor(0);
|
||||
|
||||
const Common::String locationNrStr = Common::String::format("%02d", _locationNr);
|
||||
debugEngine("loadLocation %s", locationNrStr.c_str());
|
||||
|
||||
if (!(getFeatures() & GF_EXTRACTED)) {
|
||||
PtcArchive *locationArchive = new PtcArchive();
|
||||
if (!locationArchive->open(Common::Path(locationNrStr).appendComponent("databank.ptc")))
|
||||
error("Can't open location %s", locationNrStr.c_str());
|
||||
|
||||
SearchMan.add(locationNrStr, locationArchive);
|
||||
} else {
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, locationNrStr);
|
||||
}
|
||||
|
||||
loadMusic(_locationNr);
|
||||
|
||||
// load location background, replace old one
|
||||
Resource::loadResource(_roomBmp, "room", true);
|
||||
if (_roomBmp->getSurface()) {
|
||||
_sceneWidth = _roomBmp->getSurface()->w;
|
||||
}
|
||||
|
||||
loadZoom(_zoomBitmap, kZoomBitmapLen, "zoom");
|
||||
loadShadow(_shadowBitmap, kShadowBitmapSize, "shadow", "shadow2");
|
||||
loadTrans(_transTable, "trans");
|
||||
loadPath("path");
|
||||
|
||||
for (uint32 i = 0; i < _pscrList.size(); i++) {
|
||||
delete _pscrList[i];
|
||||
}
|
||||
_pscrList.clear();
|
||||
Resource::loadResource(_pscrList, "pscr.lst", false);
|
||||
|
||||
loadMobPriority("mobpri");
|
||||
|
||||
_mobList.clear();
|
||||
if (getGameType() == kPrinceDataDE) {
|
||||
const Common::String mobLstName = Common::String::format("mob%02d.lst", _locationNr);
|
||||
debug(3, "moblist name: %s", mobLstName.c_str());
|
||||
Resource::loadResource(_mobList, mobLstName.c_str(), false);
|
||||
} else if (getGameType() == kPrinceDataPL) {
|
||||
Resource::loadResource(_mobList, "mob.lst", false);
|
||||
}
|
||||
if (getFeatures() & GF_TRANSLATED) {
|
||||
// update Mob texts for translated version
|
||||
setMobTranslationTexts();
|
||||
}
|
||||
|
||||
_animList.clear();
|
||||
Resource::loadResource(_animList, "anim.lst", false);
|
||||
|
||||
for (uint32 i = 0; i < _objList.size(); i++) {
|
||||
delete _objList[i];
|
||||
}
|
||||
_objList.clear();
|
||||
Resource::loadResource(_objList, "obj.lst", false);
|
||||
|
||||
_room->loadRoom(_script->getRoomOffset(_locationNr));
|
||||
|
||||
for (uint i = 0; i < _maskList.size(); i++) {
|
||||
free(_maskList[i]._data);
|
||||
}
|
||||
_maskList.clear();
|
||||
_script->loadAllMasks(_maskList, _room->_nak);
|
||||
|
||||
_picWindowX = 0;
|
||||
|
||||
_lightX = _script->getLightX(_locationNr);
|
||||
_lightY = _script->getLightY(_locationNr);
|
||||
setShadowScale(_script->getShadowScale(_locationNr));
|
||||
|
||||
for (uint i = 0; i < _mobList.size(); i++) {
|
||||
_mobList[i]._visible = _script->getMobVisible(_room->_mobs, i);
|
||||
}
|
||||
|
||||
_script->installObjects(_room->_obj);
|
||||
|
||||
freeAllNormAnims();
|
||||
|
||||
clearBackAnimList();
|
||||
_script->installBackAnims(_backAnimList, _room->_backAnim);
|
||||
|
||||
_graph->makeShadowTable(70, _graph->_shadowTable70);
|
||||
_graph->makeShadowTable(50, _graph->_shadowTable50);
|
||||
|
||||
_mainHero->freeOldMove();
|
||||
_secondHero->freeOldMove();
|
||||
|
||||
_mainHero->scrollHero();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadAnim(uint16 animNr, bool loop) {
|
||||
Common::Path streamName(Common::String::format("AN%02d", animNr));
|
||||
Common::SeekableReadStream *flicStream = SearchMan.createReadStreamForMember(streamName);
|
||||
|
||||
if (!flicStream) {
|
||||
error("Can't open %s", streamName.toString().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
flicStream = Resource::getDecompressedStream(flicStream);
|
||||
|
||||
if (!_flicPlayer.loadStream(flicStream)) {
|
||||
error("Can't load flic stream %s", streamName.toString().c_str());
|
||||
}
|
||||
|
||||
debugEngine("%s loaded", streamName.toString().c_str());
|
||||
_flicLooped = loop;
|
||||
_flicPlayer.start();
|
||||
playNextFLCFrame();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadZoom(byte *zoomBitmap, uint32 dataSize, const char *resourceName) {
|
||||
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
|
||||
if (!stream) {
|
||||
return false;
|
||||
}
|
||||
stream = Resource::getDecompressedStream(stream);
|
||||
|
||||
if (stream->read(zoomBitmap, dataSize) != dataSize) {
|
||||
free(zoomBitmap);
|
||||
delete stream;
|
||||
return false;
|
||||
}
|
||||
delete stream;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadShadow(byte *shadowBitmap, uint32 dataSize, const char *resourceName1, const char *resourceName2) {
|
||||
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName1);
|
||||
if (!stream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
stream = Resource::getDecompressedStream(stream);
|
||||
|
||||
if (stream->read(shadowBitmap, dataSize) != dataSize) {
|
||||
free(shadowBitmap);
|
||||
delete stream;
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *stream2 = SearchMan.createReadStreamForMember(resourceName2);
|
||||
if (!stream2) {
|
||||
delete stream;
|
||||
return false;
|
||||
}
|
||||
|
||||
stream2 = Resource::getDecompressedStream(stream2);
|
||||
|
||||
byte *shadowBitmap2 = shadowBitmap + dataSize;
|
||||
if (stream2->read(shadowBitmap2, dataSize) != dataSize) {
|
||||
free(shadowBitmap);
|
||||
delete stream;
|
||||
delete stream2;
|
||||
return false;
|
||||
}
|
||||
|
||||
delete stream;
|
||||
delete stream2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadTrans(byte *transTable, const char *resourceName) {
|
||||
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
|
||||
if (!stream) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
for (int j = 0; j < 256; j++) {
|
||||
transTable[i * 256 + j] = j;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
stream = Resource::getDecompressedStream(stream);
|
||||
|
||||
if (stream->read(transTable, kTransTableSize) != kTransTableSize) {
|
||||
delete stream;
|
||||
return false;
|
||||
}
|
||||
delete stream;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadPath(const char *resourceName) {
|
||||
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
|
||||
if (!stream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
stream = Resource::getDecompressedStream(stream);
|
||||
|
||||
if (stream->read(_roomPathBitmap, kPathBitmapLen) != kPathBitmapLen) {
|
||||
delete stream;
|
||||
return false;
|
||||
}
|
||||
delete stream;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadAllInv() {
|
||||
for (int i = 0; i < kMaxInv; i++) {
|
||||
InvItem tempInvItem;
|
||||
|
||||
const Common::Path invStreamName(Common::String::format("INV%02d", i));
|
||||
Common::SeekableReadStream *invStream = SearchMan.createReadStreamForMember(invStreamName);
|
||||
if (!invStream) {
|
||||
return true;
|
||||
}
|
||||
|
||||
invStream = Resource::getDecompressedStream(invStream);
|
||||
|
||||
tempInvItem._x = invStream->readUint16LE();
|
||||
tempInvItem._y = invStream->readUint16LE();
|
||||
int width = invStream->readUint16LE();
|
||||
int height = invStream->readUint16LE();
|
||||
tempInvItem._surface = new Graphics::Surface();
|
||||
tempInvItem._surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
for (int h = 0; h < tempInvItem._surface->h; h++) {
|
||||
invStream->read(tempInvItem._surface->getBasePtr(0, h), tempInvItem._surface->w);
|
||||
}
|
||||
|
||||
_allInvList.push_back(tempInvItem);
|
||||
delete invStream;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadMobPriority(const char *resourceName) {
|
||||
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
|
||||
if (!stream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
stream = Resource::getDecompressedStream(stream);
|
||||
|
||||
_mobPriorityList.clear();
|
||||
uint mobId;
|
||||
while (1) {
|
||||
mobId = stream->readUint32LE();
|
||||
if (mobId == 0xFFFFFFFF) {
|
||||
break;
|
||||
}
|
||||
_mobPriorityList.push_back(mobId);
|
||||
}
|
||||
delete stream;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
110
engines/prince/resource.h
Normal file
110
engines/prince/resource.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_RESOURCE_H
|
||||
#define PRINCE_RESOURCE_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/archive.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/ptr.h"
|
||||
|
||||
#include "prince/decompress.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
namespace Resource {
|
||||
|
||||
Common::SeekableReadStream *getDecompressedStream(Common::SeekableReadStream *stream);
|
||||
|
||||
template <typename T>
|
||||
bool loadFromStream(T &resource, Common::SeekableReadStream &stream) {
|
||||
return resource.loadStream(stream);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool loadResource(T *resource, const char *resourceName, bool required) {
|
||||
Common::SeekableReadStream *stream_(SearchMan.createReadStreamForMember(resourceName));
|
||||
if (!stream_) {
|
||||
if (required)
|
||||
error("Can't load %s", resourceName);
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::ScopedPtr<Common::SeekableReadStream> stream(getDecompressedStream(stream_));
|
||||
|
||||
return loadFromStream(*resource, *stream);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool loadResource(Common::Array<T> &array, Common::SeekableReadStream &stream, bool required = true) {
|
||||
T t;
|
||||
while (t.loadFromStream(stream))
|
||||
array.push_back(t);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
bool loadResource(Common::Array<T> &array, const char *resourceName, bool required = true) {
|
||||
Common::SeekableReadStream *stream_(SearchMan.createReadStreamForMember(resourceName));
|
||||
if (!stream_) {
|
||||
if (required)
|
||||
error("Can't load %s", resourceName);
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::ScopedPtr<Common::SeekableReadStream> stream(getDecompressedStream(stream_));
|
||||
|
||||
return loadResource(array, *stream, required);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool loadResource(Common::Array<T *> &array, const char *resourceName, bool required = true) {
|
||||
|
||||
Common::SeekableReadStream *stream_(SearchMan.createReadStreamForMember(resourceName));
|
||||
if (!stream_) {
|
||||
if (required)
|
||||
error("Can't load %s", resourceName);
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::ScopedPtr<Common::SeekableReadStream> stream(getDecompressedStream(stream_));
|
||||
|
||||
// FIXME: This is stupid. Maybe loadFromStream should be helper method that returns initialized object
|
||||
while (true) {
|
||||
T* t = new T();
|
||||
if (!t->loadFromStream(*stream)) {
|
||||
delete t;
|
||||
break;
|
||||
}
|
||||
array.push_back(t);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
471
engines/prince/saveload.cpp
Normal file
471
engines/prince/saveload.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "prince/graphics.h"
|
||||
#include "prince/flags.h"
|
||||
#include "prince/script.h"
|
||||
#include "prince/hero.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "graphics/thumbnail.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/paletteman.h"
|
||||
#include "graphics/scaler.h"
|
||||
|
||||
#include "gui/saveload.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
#define kSavegameVersion 1
|
||||
|
||||
class InterpreterFlags;
|
||||
class Interpreter;
|
||||
|
||||
bool PrinceEngine::scummVMSaveLoadDialog(bool isSave) {
|
||||
GUI::SaveLoadChooser *dialog;
|
||||
Common::String desc;
|
||||
int slot;
|
||||
|
||||
if (isSave) {
|
||||
dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
|
||||
|
||||
slot = dialog->runModalWithCurrentTarget();
|
||||
desc = dialog->getResultString();
|
||||
|
||||
if (desc.empty()) {
|
||||
desc = dialog->createDefaultSaveDescription(slot);
|
||||
}
|
||||
} else {
|
||||
dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
|
||||
slot = dialog->runModalWithCurrentTarget();
|
||||
}
|
||||
|
||||
delete dialog;
|
||||
|
||||
if (slot < 0)
|
||||
return false;
|
||||
|
||||
if (isSave) {
|
||||
return saveGameState(slot, desc).getCode() == Common::kNoError;
|
||||
} else {
|
||||
return loadGameState(slot).getCode() == Common::kNoError;
|
||||
}
|
||||
}
|
||||
|
||||
WARN_UNUSED_RESULT bool PrinceEngine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail) {
|
||||
header.version = 0;
|
||||
header.saveName.clear();
|
||||
header.thumbnail = nullptr;
|
||||
header.saveYear = 0;
|
||||
header.saveMonth = 0;
|
||||
header.saveDay = 0;
|
||||
header.saveHour = 0;
|
||||
header.saveMinutes = 0;
|
||||
header.playTime = 0;
|
||||
|
||||
// Get the savegame version
|
||||
header.version = in->readByte();
|
||||
if (header.version > kSavegameVersion)
|
||||
return false;
|
||||
|
||||
// Read in the string
|
||||
char ch;
|
||||
while ((ch = (char)in->readByte()) != '\0')
|
||||
header.saveName += ch;
|
||||
|
||||
// Get the thumbnail
|
||||
if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read in save date/time
|
||||
header.saveYear = in->readSint16LE();
|
||||
header.saveMonth = in->readSint16LE();
|
||||
header.saveDay = in->readSint16LE();
|
||||
header.saveHour = in->readSint16LE();
|
||||
header.saveMinutes = in->readSint16LE();
|
||||
header.playTime = in->readUint32LE();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::canSaveGameStateCurrently(Common::U32String *msg) {
|
||||
if (_mouseFlag && _mouseFlag != 3) {
|
||||
if (_mainHero->_visible) {
|
||||
// 29 - Basement
|
||||
if (_locationNr != 29) {
|
||||
// No dialog box and not in inventory
|
||||
if (!_dialogFlag && !_showInventoryFlag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PrinceEngine::canLoadGameStateCurrently(Common::U32String *msg) {
|
||||
if (_mouseFlag && _mouseFlag != 3) {
|
||||
if (_mainHero->_visible) {
|
||||
// 29 - Basement
|
||||
if (_locationNr != 29) {
|
||||
// No dialog box and not in inventory
|
||||
if (!_dialogFlag && !_showInventoryFlag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::Error PrinceEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
||||
// Set up the serializer
|
||||
Common::String slotName = getSaveStateName(slot);
|
||||
Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(slotName);
|
||||
|
||||
// Write out the ScummVM savegame header
|
||||
SavegameHeader header;
|
||||
header.saveName = desc;
|
||||
header.version = kSavegameVersion;
|
||||
writeSavegameHeader(saveFile, header);
|
||||
|
||||
// Write out the data of the savegame
|
||||
syncGame(nullptr, saveFile);
|
||||
|
||||
// Finish writing out game data
|
||||
saveFile->finalize();
|
||||
delete saveFile;
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
void PrinceEngine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header) {
|
||||
// Write out a savegame header
|
||||
out->write(kSavegameStr, kSavegameStrSize + 1);
|
||||
|
||||
out->writeByte(kSavegameVersion);
|
||||
|
||||
// Write savegame name
|
||||
out->write(header.saveName.c_str(), header.saveName.size() + 1);
|
||||
|
||||
// Get the active palette
|
||||
uint8 thumbPalette[256 * 3];
|
||||
_system->getPaletteManager()->grabPalette(thumbPalette, 0, 256);
|
||||
|
||||
// Create a thumbnail and save it
|
||||
Graphics::Surface *thumb = new Graphics::Surface();
|
||||
Graphics::Surface *s = _graph->_frontScreen; // check inventory / map etc..
|
||||
::createThumbnail(thumb, (const byte *)s->getPixels(), s->w, s->h, thumbPalette);
|
||||
Graphics::saveThumbnail(*out, *thumb);
|
||||
thumb->free();
|
||||
delete thumb;
|
||||
|
||||
// Write out the save date/time
|
||||
TimeDate td;
|
||||
g_system->getTimeAndDate(td);
|
||||
out->writeSint16LE(td.tm_year + 1900);
|
||||
out->writeSint16LE(td.tm_mon + 1);
|
||||
out->writeSint16LE(td.tm_mday);
|
||||
out->writeSint16LE(td.tm_hour);
|
||||
out->writeSint16LE(td.tm_min);
|
||||
|
||||
out->writeUint32LE(g_engine->getTotalPlayTime() / 1000);
|
||||
}
|
||||
|
||||
void PrinceEngine::syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream) {
|
||||
int emptyRoom = 0x00;
|
||||
int normRoom = 0xFF;
|
||||
byte endInv = 0xFF;
|
||||
|
||||
Common::Serializer s(readStream, writeStream);
|
||||
|
||||
if (s.isSaving()) {
|
||||
// Flag values
|
||||
for (int i = 0; i < _flags->kMaxFlags; i++) {
|
||||
uint32 value = _flags->getFlagValue((Flags::Id)(_flags->kFlagMask + i));
|
||||
s.syncAsUint32LE(value);
|
||||
}
|
||||
|
||||
// Dialog data
|
||||
for (uint32 i = 0; i < _dialogDatSize; i++) {
|
||||
byte value = _dialogDat[i];
|
||||
s.syncAsByte(value);
|
||||
}
|
||||
|
||||
// Location number
|
||||
s.syncAsUint16LE(_locationNr);
|
||||
|
||||
// Rooms
|
||||
for (int roomId = 0; roomId < _script->kMaxRooms; roomId++) {
|
||||
Room *room = new Room();
|
||||
room->loadRoom(_script->getRoomOffset(roomId));
|
||||
|
||||
if (room->_mobs) {
|
||||
s.syncAsByte(normRoom);
|
||||
} else {
|
||||
s.syncAsByte(emptyRoom);
|
||||
delete room;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mobs
|
||||
for (int mobId = 0; mobId < kMaxMobs; mobId++) {
|
||||
byte value = _script->getMobVisible(room->_mobs, mobId);
|
||||
s.syncAsByte(value);
|
||||
}
|
||||
|
||||
// Background animations
|
||||
for (int backAnimSlot = 0; backAnimSlot < kMaxBackAnims; backAnimSlot++) {
|
||||
uint32 value = _script->getBackAnimId(room->_backAnim, backAnimSlot);
|
||||
s.syncAsUint32LE(value);
|
||||
}
|
||||
|
||||
// Objects
|
||||
for (int objectSlot = 0; objectSlot < kMaxObjects; objectSlot++) {
|
||||
byte value = _script->getObjId(room->_obj, objectSlot);
|
||||
s.syncAsByte(value);
|
||||
}
|
||||
|
||||
delete room;
|
||||
}
|
||||
|
||||
// Main hero
|
||||
s.syncAsUint16LE(_mainHero->_visible);
|
||||
s.syncAsUint16LE(_mainHero->_middleX);
|
||||
s.syncAsUint16LE(_mainHero->_middleY);
|
||||
s.syncAsUint16LE(_mainHero->_lastDirection);
|
||||
s.syncAsUint32LE(_mainHero->_color);
|
||||
s.syncAsUint16LE(_mainHero->_maxBoredom);
|
||||
s.syncAsUint32LE(_mainHero->_animSetNr);
|
||||
|
||||
for (uint inv1Slot = 0; inv1Slot < _mainHero->_inventory.size(); inv1Slot++) {
|
||||
s.syncAsByte(_mainHero->_inventory[inv1Slot]);
|
||||
}
|
||||
s.syncAsByte(endInv);
|
||||
|
||||
for (uint inv2Slot = 0; inv2Slot < _mainHero->_inventory2.size(); inv2Slot++) {
|
||||
s.syncAsByte(_mainHero->_inventory2[inv2Slot]);
|
||||
}
|
||||
s.syncAsByte(endInv);
|
||||
|
||||
// Second hero
|
||||
s.syncAsUint16LE(_secondHero->_visible);
|
||||
s.syncAsUint16LE(_secondHero->_middleX);
|
||||
s.syncAsUint16LE(_secondHero->_middleY);
|
||||
s.syncAsUint16LE(_secondHero->_lastDirection);
|
||||
s.syncAsUint32LE(_secondHero->_color);
|
||||
s.syncAsUint16LE(_secondHero->_maxBoredom);
|
||||
s.syncAsUint32LE(_secondHero->_animSetNr);
|
||||
|
||||
for (uint inv1Slot = 0; inv1Slot < _secondHero->_inventory.size(); inv1Slot++) {
|
||||
s.syncAsByte(_secondHero->_inventory[inv1Slot]);
|
||||
}
|
||||
s.syncAsByte(endInv);
|
||||
|
||||
for (uint inv2Slot = 0; inv2Slot < _secondHero->_inventory2.size(); inv2Slot++) {
|
||||
s.syncAsByte(_secondHero->_inventory2[inv2Slot]);
|
||||
}
|
||||
s.syncAsByte(endInv);
|
||||
|
||||
} else {
|
||||
// Cursor reset
|
||||
changeCursor(1);
|
||||
_currentPointerNumber = 1;
|
||||
|
||||
// Flag values
|
||||
for (int i = 0; i < _flags->kMaxFlags; i++) {
|
||||
uint32 value = 0;
|
||||
s.syncAsUint32LE(value);
|
||||
_flags->setFlagValue((Flags::Id)(_flags->kFlagMask + i), value);
|
||||
}
|
||||
|
||||
// Dialog data
|
||||
for (uint32 i = 0; i < _dialogDatSize; i++) {
|
||||
byte value = 0;
|
||||
s.syncAsByte(value);
|
||||
_dialogDat[i] = value;
|
||||
}
|
||||
|
||||
// Location number
|
||||
int restoreRoom = 0;
|
||||
s.syncAsUint16LE(restoreRoom);
|
||||
_flags->setFlagValue(Flags::RESTOREROOM, restoreRoom);
|
||||
|
||||
// Rooms
|
||||
for (int roomId = 0; roomId < _script->kMaxRooms; roomId++) {
|
||||
Room *room = new Room();
|
||||
room->loadRoom(_script->getRoomOffset(roomId));
|
||||
|
||||
byte roomType = emptyRoom;
|
||||
s.syncAsByte(roomType);
|
||||
if (roomType == emptyRoom) {
|
||||
delete room;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mobs
|
||||
for (int mobId = 0; mobId < kMaxMobs; mobId++) {
|
||||
byte value = 0;
|
||||
s.syncAsByte(value);
|
||||
_script->setMobVisible(room->_mobs, mobId, value);
|
||||
}
|
||||
|
||||
// Background animations
|
||||
for (int backAnimSlot = 0; backAnimSlot < kMaxBackAnims; backAnimSlot++) {
|
||||
uint32 value = 0;
|
||||
s.syncAsUint32LE(value);
|
||||
_script->setBackAnimId(room->_backAnim, backAnimSlot, value);
|
||||
}
|
||||
|
||||
// Objects
|
||||
for (int objectSlot = 0; objectSlot < kMaxObjects; objectSlot++) {
|
||||
byte value = 0;
|
||||
s.syncAsByte(value);
|
||||
_script->setObjId(room->_obj, objectSlot, value);
|
||||
}
|
||||
|
||||
delete room;
|
||||
}
|
||||
|
||||
// Main hero
|
||||
s.syncAsUint16LE(_mainHero->_visible);
|
||||
s.syncAsUint16LE(_mainHero->_middleX);
|
||||
s.syncAsUint16LE(_mainHero->_middleY);
|
||||
s.syncAsUint16LE(_mainHero->_lastDirection);
|
||||
s.syncAsUint32LE(_mainHero->_color);
|
||||
s.syncAsUint16LE(_mainHero->_maxBoredom);
|
||||
s.syncAsUint32LE(_mainHero->_animSetNr);
|
||||
_mainHero->loadAnimSet(_mainHero->_animSetNr);
|
||||
|
||||
_mainHero->_inventory.clear();
|
||||
byte invId = endInv;
|
||||
while (1) {
|
||||
s.syncAsByte(invId);
|
||||
if (invId == endInv) {
|
||||
break;
|
||||
}
|
||||
_mainHero->_inventory.push_back(invId);
|
||||
}
|
||||
|
||||
_mainHero->_inventory2.clear();
|
||||
invId = endInv;
|
||||
while (1) {
|
||||
s.syncAsByte(invId);
|
||||
if (invId == endInv) {
|
||||
break;
|
||||
}
|
||||
_mainHero->_inventory2.push_back(invId);
|
||||
}
|
||||
|
||||
// Second hero
|
||||
s.syncAsUint16LE(_secondHero->_visible);
|
||||
s.syncAsUint16LE(_secondHero->_middleX);
|
||||
s.syncAsUint16LE(_secondHero->_middleY);
|
||||
s.syncAsUint16LE(_secondHero->_lastDirection);
|
||||
s.syncAsUint32LE(_secondHero->_color);
|
||||
s.syncAsUint16LE(_secondHero->_maxBoredom);
|
||||
s.syncAsUint32LE(_secondHero->_animSetNr);
|
||||
_secondHero->loadAnimSet(_secondHero->_animSetNr);
|
||||
|
||||
_secondHero->_inventory.clear();
|
||||
invId = endInv;
|
||||
while (1) {
|
||||
s.syncAsByte(invId);
|
||||
if (invId == endInv) {
|
||||
break;
|
||||
}
|
||||
_secondHero->_inventory.push_back(invId);
|
||||
}
|
||||
|
||||
_secondHero->_inventory2.clear();
|
||||
invId = endInv;
|
||||
while (1) {
|
||||
s.syncAsByte(invId);
|
||||
if (invId == endInv) {
|
||||
break;
|
||||
}
|
||||
_secondHero->_inventory2.push_back(invId);
|
||||
}
|
||||
|
||||
// Script
|
||||
_interpreter->setBgOpcodePC(0);
|
||||
_interpreter->setFgOpcodePC(_script->_scriptInfo.restoreGame);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Common::Error PrinceEngine::loadGameState(int slot) {
|
||||
if (!loadGame(slot)) {
|
||||
return Common::kReadingFailed;
|
||||
}
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadGame(int slotNumber) {
|
||||
Common::MemoryReadStream *readStream;
|
||||
|
||||
// Open up the savegame file
|
||||
Common::String slotName = getSaveStateName(slotNumber);
|
||||
Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(slotName);
|
||||
|
||||
if (!saveFile)
|
||||
return false;
|
||||
|
||||
// Read the data into a data buffer
|
||||
int size = saveFile->size();
|
||||
byte *dataBuffer = (byte *)malloc(size);
|
||||
saveFile->read(dataBuffer, size);
|
||||
readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES);
|
||||
delete saveFile;
|
||||
|
||||
// Check to see if it's a ScummVM savegame or not
|
||||
char buffer[kSavegameStrSize + 1];
|
||||
readStream->read(buffer, kSavegameStrSize + 1);
|
||||
|
||||
if (strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) != 0) {
|
||||
delete readStream;
|
||||
return false;
|
||||
} else {
|
||||
SavegameHeader saveHeader;
|
||||
|
||||
if (!readSavegameHeader(readStream, saveHeader)) {
|
||||
delete readStream;
|
||||
return false;
|
||||
}
|
||||
|
||||
g_engine->setTotalPlayTime(saveHeader.playTime * 1000);
|
||||
}
|
||||
|
||||
// Get in the savegame
|
||||
syncGame(readStream, nullptr);
|
||||
delete readStream;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
2113
engines/prince/script.cpp
Normal file
2113
engines/prince/script.cpp
Normal file
File diff suppressed because it is too large
Load Diff
400
engines/prince/script.h
Normal file
400
engines/prince/script.h
Normal file
@@ -0,0 +1,400 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_SCRIPT_H
|
||||
#define PRINCE_SCRIPT_H
|
||||
|
||||
#include "common/random.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/array.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "prince/flags.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class PrinceEngine;
|
||||
class Animation;
|
||||
class Object;
|
||||
struct Anim;
|
||||
struct BackgroundAnim;
|
||||
struct Mask;
|
||||
|
||||
class Room {
|
||||
public:
|
||||
Room();
|
||||
int _mobs; // mob flag offset
|
||||
int _backAnim; // offset to array of animation numbers
|
||||
int _obj; // offset to array of object numbers
|
||||
int _nak; // offset to array of masks
|
||||
int _itemUse;
|
||||
int _itemGive;
|
||||
int _walkTo; // offset to array of WALKTO events or 0
|
||||
int _examine; // offset to array of EXAMINE events or 0
|
||||
int _pickup;
|
||||
int _use;
|
||||
int _pushOpen;
|
||||
int _pullClose;
|
||||
int _talk;
|
||||
int _give;
|
||||
|
||||
bool loadStream(Common::SeekableReadStream &stream);
|
||||
bool loadRoom(byte *roomData);
|
||||
int getOptionOffset(int option);
|
||||
|
||||
private:
|
||||
|
||||
typedef void (Room::*LoadingStep)(Common::SeekableReadStream &stream);
|
||||
|
||||
void nextLoadStep(Common::SeekableReadStream &stream, LoadingStep step);
|
||||
|
||||
void loadMobs(Common::SeekableReadStream &stream);
|
||||
void loadBackAnim(Common::SeekableReadStream &stream);
|
||||
void loadObj(Common::SeekableReadStream &stream);
|
||||
void loadNak(Common::SeekableReadStream &stream);
|
||||
void loadItemUse(Common::SeekableReadStream &stream);
|
||||
void loadItemGive(Common::SeekableReadStream &stream);
|
||||
void loadWalkTo(Common::SeekableReadStream &stream);
|
||||
void loadExamine(Common::SeekableReadStream &stream);
|
||||
void loadPickup(Common::SeekableReadStream &stream);
|
||||
void loadUse(Common::SeekableReadStream &stream);
|
||||
void loadPushOpen(Common::SeekableReadStream &stream);
|
||||
void loadPullClose(Common::SeekableReadStream &stream);
|
||||
void loadTalk(Common::SeekableReadStream &stream);
|
||||
void loadGive(Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
|
||||
class Script {
|
||||
public:
|
||||
static const int16 kMaxRooms = 60;
|
||||
|
||||
Script(PrinceEngine *vm);
|
||||
~Script();
|
||||
|
||||
struct ScriptInfo {
|
||||
int rooms;
|
||||
int startGame;
|
||||
int restoreGame;
|
||||
int stdExamine;
|
||||
int stdPickup;
|
||||
int stdUse;
|
||||
int stdOpen;
|
||||
int stdClose;
|
||||
int stdTalk;
|
||||
int stdGive;
|
||||
int usdCode;
|
||||
int invObjExam;
|
||||
int invObjUse;
|
||||
int invObjUU;
|
||||
int stdUseItem;
|
||||
int lightSources;
|
||||
int specRout;
|
||||
int invObjGive;
|
||||
int stdGiveItem;
|
||||
int goTester;
|
||||
};
|
||||
|
||||
ScriptInfo _scriptInfo;
|
||||
|
||||
bool loadStream(Common::SeekableReadStream &stream);
|
||||
|
||||
uint16 readScript16(uint32 address);
|
||||
uint32 readScript32(uint32 address);
|
||||
|
||||
uint32 getStartGameOffset();
|
||||
uint32 getLocationInitScript(int initRoomTableOffset, int roomNr);
|
||||
int16 getLightX(int locationNr);
|
||||
int16 getLightY(int locationNr);
|
||||
int32 getShadowScale(int locationNr);
|
||||
uint8 *getRoomOffset(int locationNr);
|
||||
int32 getOptionStandardOffset(int option);
|
||||
uint8 *getHeroAnimName(int offset);
|
||||
|
||||
void installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int roomBackAnimOffset);
|
||||
void installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int roomBackAnimOffset);
|
||||
void installObjects(int offset);
|
||||
bool loadAllMasks(Common::Array<Mask> &maskList, int offset);
|
||||
|
||||
int scanMobEvents(int mobMask, int dataEventOffset);
|
||||
int scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask);
|
||||
|
||||
byte getMobVisible(int roomMobOffset, uint16 mob);
|
||||
void setMobVisible(int roomMobOffset, uint16 mob, byte value);
|
||||
|
||||
uint32 getBackAnimId(int roomBackAnimOffset, int slot);
|
||||
void setBackAnimId(int roomBackAnimOffset, int slot, int animId);
|
||||
|
||||
byte getObjId(int roomObjOffset, int slot);
|
||||
void setObjId(int roomObjOffset, int slot, byte objectId);
|
||||
|
||||
const char *getString(uint32 offset) {
|
||||
return (const char *)(&_data[offset]);
|
||||
}
|
||||
|
||||
private:
|
||||
PrinceEngine *_vm;
|
||||
uint8 *_data;
|
||||
uint32 _dataSize;
|
||||
Common::Array<Room> _roomList;
|
||||
};
|
||||
|
||||
class InterpreterFlags {
|
||||
public:
|
||||
InterpreterFlags();
|
||||
|
||||
void setFlagValue(Flags::Id flag, int32 value);
|
||||
int32 getFlagValue(Flags::Id flag);
|
||||
|
||||
void resetAllFlags();
|
||||
|
||||
static const uint16 kFlagMask = 0x8000;
|
||||
static const uint16 kMaxFlags = 2000;
|
||||
private:
|
||||
int32 _flags[kMaxFlags];
|
||||
};
|
||||
|
||||
class Interpreter {
|
||||
public:
|
||||
Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags);
|
||||
|
||||
void stopBg() { _bgOpcodePC = 0; }
|
||||
|
||||
void stepBg();
|
||||
void stepFg();
|
||||
void storeNewPC(int opcodePC);
|
||||
int getLastOPCode();
|
||||
int getFgOpcodePC();
|
||||
|
||||
void setBgOpcodePC(uint32 value);
|
||||
void setFgOpcodePC(uint32 value);
|
||||
|
||||
uint32 getCurrentString();
|
||||
void setCurrentString(uint32 value);
|
||||
|
||||
byte *getString();
|
||||
void setString(byte *newString);
|
||||
void increaseString();
|
||||
|
||||
void setResult(byte value);
|
||||
|
||||
private:
|
||||
PrinceEngine *_vm;
|
||||
Script *_script;
|
||||
InterpreterFlags *_flags;
|
||||
|
||||
uint32 _currentInstruction;
|
||||
|
||||
uint32 _bgOpcodePC;
|
||||
uint32 _fgOpcodePC;
|
||||
|
||||
uint16 _lastOpcode;
|
||||
uint32 _lastInstruction;
|
||||
byte _result;
|
||||
|
||||
bool _opcodeNF; // break interpreter loop
|
||||
bool _opcodeEnd; // end of a game flag
|
||||
|
||||
static const uint32 _STACK_SIZE = 500;
|
||||
uint32 _stack[_STACK_SIZE];
|
||||
struct stringStack {
|
||||
byte *string;
|
||||
byte *dialogData;
|
||||
uint32 currentString;
|
||||
} _stringStack;
|
||||
uint8 _stacktop;
|
||||
uint32 _waitFlag;
|
||||
|
||||
byte *_string;
|
||||
byte _stringBuf[1024];
|
||||
uint32 _currentString;
|
||||
const char *_mode;
|
||||
|
||||
Flags _flagMap;
|
||||
|
||||
// Helper functions
|
||||
uint32 step(uint32 opcodePC);
|
||||
uint16 readScript16();
|
||||
uint32 readScript32();
|
||||
int32 readScriptFlagValue();
|
||||
Flags::Id readScriptFlagId();
|
||||
int checkSeq(byte *string);
|
||||
|
||||
void debugInterpreter(const char *s, ...);
|
||||
|
||||
typedef void (Interpreter::*OpcodeFunc)();
|
||||
static OpcodeFunc _opcodes[];
|
||||
|
||||
static const uint kGiveLetterScriptFix = 79002;
|
||||
static const uint kSecondBirdAnimationScriptFix = 45658;
|
||||
|
||||
// Keep opcode handlers names as they are in original code
|
||||
// making it easier to switch back and forth
|
||||
void O_WAITFOREVER();
|
||||
void O_BLACKPALETTE();
|
||||
void O_SETUPPALETTE();
|
||||
void O_INITROOM();
|
||||
void O_SETSAMPLE();
|
||||
void O_FREESAMPLE();
|
||||
void O_PLAYSAMPLE();
|
||||
void O_PUTOBJECT();
|
||||
void O_REMOBJECT();
|
||||
void O_SHOWANIM();
|
||||
void O_CHECKANIMEND();
|
||||
void O_FREEANIM();
|
||||
void O_CHECKANIMFRAME();
|
||||
void O_PUTBACKANIM();
|
||||
void O_REMBACKANIM();
|
||||
void O_CHECKBACKANIMFRAME();
|
||||
void O_FREEALLSAMPLES();
|
||||
void O_SETMUSIC();
|
||||
void O_STOPMUSIC();
|
||||
void O__WAIT();
|
||||
void O_UPDATEOFF();
|
||||
void O_UPDATEON();
|
||||
void O_UPDATE ();
|
||||
void O_CLS();
|
||||
void O__CALL();
|
||||
void O_RETURN();
|
||||
void O_GO();
|
||||
void O_BACKANIMUPDATEOFF();
|
||||
void O_BACKANIMUPDATEON();
|
||||
void O_CHANGECURSOR();
|
||||
void O_CHANGEANIMTYPE();
|
||||
void O__SETFLAG();
|
||||
void O_COMPARE();
|
||||
void O_JUMPZ();
|
||||
void O_JUMPNZ();
|
||||
void O_EXIT();
|
||||
void O_ADDFLAG();
|
||||
void O_TALKANIM();
|
||||
void O_SUBFLAG();
|
||||
void O_SETSTRING();
|
||||
void O_ANDFLAG();
|
||||
void O_GETMOBDATA();
|
||||
void O_ORFLAG();
|
||||
void O_SETMOBDATA();
|
||||
void O_XORFLAG();
|
||||
void O_GETMOBTEXT();
|
||||
void O_MOVEHERO();
|
||||
void O_WALKHERO();
|
||||
void O_SETHERO();
|
||||
void O_HEROOFF();
|
||||
void O_HEROON();
|
||||
void O_CLSTEXT();
|
||||
void O_CALLTABLE();
|
||||
void O_CHANGEMOB();
|
||||
void O_ADDINV();
|
||||
void O_REMINV();
|
||||
void O_REPINV();
|
||||
void O_OBSOLETE_GETACTION();
|
||||
void O_ADDWALKAREA();
|
||||
void O_REMWALKAREA();
|
||||
void O_RESTOREWALKAREA();
|
||||
void O_WAITFRAME();
|
||||
void O_SETFRAME();
|
||||
void O_RUNACTION();
|
||||
void O_COMPAREHI();
|
||||
void O_COMPARELO();
|
||||
void O_PRELOADSET();
|
||||
void O_FREEPRELOAD();
|
||||
void O_CHECKINV();
|
||||
void O_TALKHERO();
|
||||
void O_WAITTEXT();
|
||||
void O_SETHEROANIM();
|
||||
void O_WAITHEROANIM();
|
||||
void O_GETHERODATA();
|
||||
void O_GETMOUSEBUTTON();
|
||||
void O_CHANGEFRAMES();
|
||||
void O_CHANGEBACKFRAMES();
|
||||
void O_GETBACKANIMDATA();
|
||||
void O_GETANIMDATA();
|
||||
void O_SETBGCODE();
|
||||
void O_SETBACKFRAME();
|
||||
void O_GETRND();
|
||||
void O_TALKBACKANIM();
|
||||
void O_LOADPATH();
|
||||
void O_GETCHAR();
|
||||
void O_SETDFLAG();
|
||||
void O_CALLDFLAG();
|
||||
void O_PRINTAT();
|
||||
void O_ZOOMIN();
|
||||
void O_ZOOMOUT();
|
||||
void O_SETSTRINGOFFSET();
|
||||
void O_GETOBJDATA();
|
||||
void O_SETOBJDATA();
|
||||
void O_SWAPOBJECTS();
|
||||
void O_CHANGEHEROSET();
|
||||
void O_ADDSTRING();
|
||||
void O_SUBSTRING();
|
||||
void O_INITDIALOG();
|
||||
void O_ENABLEDIALOGOPT();
|
||||
void O_DISABLEDIALOGOPT();
|
||||
void O_SHOWDIALOGBOX();
|
||||
void O_STOPSAMPLE();
|
||||
void O_BACKANIMRANGE();
|
||||
void O_CLEARPATH();
|
||||
void O_SETPATH();
|
||||
void O_GETHEROX();
|
||||
void O_GETHEROY();
|
||||
void O_GETHEROD();
|
||||
void O_PUSHSTRING();
|
||||
void O_POPSTRING();
|
||||
void O_SETFGCODE();
|
||||
void O_STOPHERO();
|
||||
void O_ANIMUPDATEOFF();
|
||||
void O_ANIMUPDATEON();
|
||||
void O_FREECURSOR();
|
||||
void O_ADDINVQUIET();
|
||||
void O_RUNHERO();
|
||||
void O_SETBACKANIMDATA();
|
||||
void O_VIEWFLC();
|
||||
void O_CHECKFLCFRAME();
|
||||
void O_CHECKFLCEND();
|
||||
void O_FREEFLC();
|
||||
void O_TALKHEROSTOP();
|
||||
void O_HEROCOLOR();
|
||||
void O_GRABMAPA();
|
||||
void O_ENABLENAK();
|
||||
void O_DISABLENAK();
|
||||
void O_GETMOBNAME();
|
||||
void O_SWAPINVENTORY();
|
||||
void O_CLEARINVENTORY();
|
||||
void O_SKIPTEXT();
|
||||
void O_SETVOICEH();
|
||||
void O_SETVOICEA();
|
||||
void O_SETVOICEB();
|
||||
void O_SETVOICEC();
|
||||
void O_VIEWFLCLOOP();
|
||||
void O_FLCSPEED();
|
||||
void O_OPENINVENTORY();
|
||||
void O_KRZYWA();
|
||||
void O_GETKRZYWA();
|
||||
void O_GETMOB();
|
||||
void O_INPUTLINE();
|
||||
void O_SETVOICED();
|
||||
void O_BREAK_POINT();
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
||||
180
engines/prince/sound.cpp
Normal file
180
engines/prince/sound.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "audio/decoders/wave.h"
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "prince/hero.h"
|
||||
#include "prince/script.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
|
||||
if (_audioStream[sampleId]) {
|
||||
if (_mixer->isSoundIDActive(sampleId)) {
|
||||
return;
|
||||
}
|
||||
_audioStream[sampleId]->rewind();
|
||||
if (sampleId < 28) {
|
||||
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
|
||||
} else {
|
||||
_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::stopSample(uint16 sampleId) {
|
||||
_mixer->stopID(sampleId);
|
||||
}
|
||||
|
||||
void PrinceEngine::stopAllSamples() {
|
||||
_mixer->stopAll();
|
||||
}
|
||||
|
||||
void PrinceEngine::freeSample(uint16 sampleId) {
|
||||
stopSample(sampleId);
|
||||
if (_audioStream[sampleId] != nullptr) {
|
||||
delete _audioStream[sampleId];
|
||||
_audioStream[sampleId] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PrinceEngine::freeAllSamples() {
|
||||
for (int sampleId = 0; sampleId < kMaxSamples; sampleId++) {
|
||||
freeSample(sampleId);
|
||||
}
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) {
|
||||
// FIXME: This is just a workaround streamName is a path
|
||||
// SOUND\\SCIERKA1.WAV for now only last path component is used
|
||||
Common::String normalizedPath = lastPathComponent(streamName, '\\');
|
||||
|
||||
// WALKAROUND: Wrong name in script, not existing sound in data files
|
||||
if (!normalizedPath.compareTo("9997BEKA.WAV")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str());
|
||||
|
||||
freeSample(sampleSlot);
|
||||
Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(Common::Path(normalizedPath));
|
||||
if (sampleStream == nullptr) {
|
||||
error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot);
|
||||
}
|
||||
_audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream->readStream(sampleStream->size()), DisposeAfterUse::YES);
|
||||
delete sampleStream;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
|
||||
if (getFeatures() & GF_NOVOICES)
|
||||
return false;
|
||||
|
||||
_missingVoice = false;
|
||||
|
||||
debugEngine("Loading wav %s slot %d", streamName.c_str(), slot);
|
||||
|
||||
if (slot >= kMaxTexts) {
|
||||
error("Text slot bigger than MAXTEXTS %d", kMaxTexts - 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
freeSample(sampleSlot);
|
||||
Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(Common::Path(streamName));
|
||||
if (sampleStream == nullptr) {
|
||||
warning("loadVoice: Can't open %s", streamName.c_str());
|
||||
_missingVoice = true; // Insert END tag if needed
|
||||
_textSlots[slot]._time = 1; // Set phrase time to none
|
||||
_mainHero->_talkTime = 1;
|
||||
|
||||
// Speak missing voice clips like objects
|
||||
if (_textSlots[slot]._str && (ConfMan.getBool("tts_enabled_missing_voice") || ConfMan.getBool("tts_enabled_speech"))) {
|
||||
sayText(_textSlots[slot]._str, false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 id = sampleStream->readUint32LE();
|
||||
if (id != MKTAG('F', 'F', 'I', 'R')) {
|
||||
error("It's not RIFF file %s", streamName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
sampleStream->skip(0x20);
|
||||
id = sampleStream->readUint32LE();
|
||||
if (id != MKTAG('a', 't', 'a', 'd')) {
|
||||
error("No data section in %s id %04x", streamName.c_str(), id);
|
||||
return false;
|
||||
}
|
||||
|
||||
id = sampleStream->readUint32LE();
|
||||
debugEngine("SetVoice slot %d time %04x", slot, id);
|
||||
id <<= 3;
|
||||
id /= 22050;
|
||||
id += 2;
|
||||
|
||||
_textSlots[slot]._time = id;
|
||||
if (!slot) {
|
||||
_mainHero->_talkTime = id;
|
||||
} else if (slot == 1) {
|
||||
_secondHero->_talkTime = id;
|
||||
}
|
||||
|
||||
debugEngine("SetVoice slot %d time %04x", slot, id);
|
||||
sampleStream->seek(SEEK_SET);
|
||||
_audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream->readStream(sampleStream->size()), DisposeAfterUse::YES);
|
||||
delete sampleStream;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrinceEngine::setVoice(uint16 slot, uint32 sampleSlot, uint16 flag) {
|
||||
Common::String sampleName;
|
||||
uint32 currentString = _interpreter->getCurrentString();
|
||||
|
||||
if (currentString >= 80000) {
|
||||
uint32 nr = currentString - 80000;
|
||||
sampleName = Common::String::format("%02d0%02d-%02d.WAV", nr / 100, nr % 100, flag);
|
||||
} else if (currentString >= 70000) {
|
||||
sampleName = Common::String::format("inv%02d-01.WAV", currentString - 70000);
|
||||
} else if (currentString >= 60000) {
|
||||
sampleName = Common::String::format("M%04d-%02d.WAV", currentString - 60000, flag);
|
||||
// String 316.
|
||||
// Fixes PRINCE: conversation with the priest bug #11771
|
||||
// When Galador starts conversation with the priest with any gesture,
|
||||
// the priest sits down to his place and conversation cannot be continued.
|
||||
} else if (currentString == 316 || currentString >= 2000) {
|
||||
return;
|
||||
} else if (flag >= 100) {
|
||||
sampleName = Common::String::format("%03d-%03d.WAV", currentString, flag);
|
||||
} else {
|
||||
sampleName = Common::String::format("%03d-%02d.WAV", currentString, flag);
|
||||
}
|
||||
|
||||
loadVoice(slot, sampleSlot, sampleName);
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
54
engines/prince/variatxt.cpp
Normal file
54
engines/prince/variatxt.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/variatxt.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
VariaTxt::VariaTxt() : _dataSize(0), _data(nullptr) {
|
||||
}
|
||||
|
||||
VariaTxt::~VariaTxt() {
|
||||
_dataSize = 0;
|
||||
if (_data != nullptr) {
|
||||
free(_data);
|
||||
_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool VariaTxt::loadStream(Common::SeekableReadStream &stream) {
|
||||
_dataSize = stream.size();
|
||||
_data = (byte *)malloc(_dataSize);
|
||||
stream.read(_data, _dataSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
byte *VariaTxt::getString(uint32 stringId) {
|
||||
uint32 stringOffset = READ_LE_UINT32(_data + stringId * 4);
|
||||
if (stringOffset > _dataSize) {
|
||||
assert(false);
|
||||
}
|
||||
return _data + stringOffset;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
39
engines/prince/variatxt.h
Normal file
39
engines/prince/variatxt.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
class VariaTxt {
|
||||
public:
|
||||
VariaTxt();
|
||||
~VariaTxt();
|
||||
|
||||
bool loadStream(Common::SeekableReadStream &stream);
|
||||
byte *getString(uint32 stringId);
|
||||
|
||||
private:
|
||||
uint32 _dataSize;
|
||||
byte *_data;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
82
engines/prince/videoplayer.cpp
Normal file
82
engines/prince/videoplayer.cpp
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "engines/util.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "video/avi_decoder.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
void PrinceEngine::playVideo(const Common::Path &videoFilename) {
|
||||
// Set the correct video mode
|
||||
initGraphics(640, 480, nullptr);
|
||||
if (_system->getScreenFormat().bytesPerPixel == 1) {
|
||||
warning("Couldn't switch to a RGB color video mode to play a video.");
|
||||
return;
|
||||
}
|
||||
|
||||
debug(2, "Screen format: %s", _system->getScreenFormat().toString().c_str());
|
||||
|
||||
Video::VideoDecoder *videoDecoder = new Video::AVIDecoder();
|
||||
if (!videoDecoder->loadFile(videoFilename)) {
|
||||
delete videoDecoder;
|
||||
warning("Unable to open video %s", videoFilename.toString().c_str());
|
||||
initGraphics(640, 480);
|
||||
return;
|
||||
}
|
||||
|
||||
videoDecoder->start();
|
||||
|
||||
bool skipVideo = false;
|
||||
|
||||
while (!shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
|
||||
if (videoDecoder->needsUpdate()) {
|
||||
const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
|
||||
if (frame) {
|
||||
if (frame->format.bytesPerPixel > 1) {
|
||||
Graphics::Surface *frame1 = frame->convertTo(_system->getScreenFormat());
|
||||
_system->copyRectToScreen(frame1->getPixels(), frame1->pitch, 0, 0, frame1->w, frame1->h);
|
||||
frame1->free();
|
||||
delete frame1;
|
||||
} else {
|
||||
_system->copyRectToScreen(frame->getPixels(), frame->pitch, 0, 0, frame->w, frame->h);
|
||||
}
|
||||
_system->updateScreen();
|
||||
}
|
||||
}
|
||||
|
||||
Common::Event event;
|
||||
while (_system->getEventManager()->pollEvent(event)) {
|
||||
if ((event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START && event.customType == kActionSkip) ||
|
||||
event.type == Common::EVENT_LBUTTONUP)
|
||||
skipVideo = true;
|
||||
}
|
||||
|
||||
_system->delayMillis(10);
|
||||
}
|
||||
|
||||
delete videoDecoder;
|
||||
|
||||
initGraphics(640, 480);
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
1609
engines/prince/walk.cpp
Normal file
1609
engines/prince/walk.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user