Initial commit
This commit is contained in:
3
engines/cine/POTFILES
Normal file
3
engines/cine/POTFILES
Normal file
@@ -0,0 +1,3 @@
|
||||
engines/cine/metaengine.cpp
|
||||
engines/cine/saveload.cpp
|
||||
engines/cine/various.cpp
|
||||
921
engines/cine/anim.cpp
Normal file
921
engines/cine/anim.cpp
Normal file
@@ -0,0 +1,921 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* @todo Make resource manager class and make load* functions its members
|
||||
*/
|
||||
|
||||
#include "common/endian.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "audio/mididrv.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/anim.h"
|
||||
#include "cine/gfx.h"
|
||||
#include "cine/pal.h"
|
||||
#include "cine/part.h"
|
||||
#include "cine/various.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
struct AnimHeader2Struct {
|
||||
uint32 field_0;
|
||||
int16 width;
|
||||
int16 height;
|
||||
int16 type;
|
||||
uint16 field_A;
|
||||
uint16 field_C;
|
||||
uint16 field_E;
|
||||
};
|
||||
|
||||
static const AnimDataMapping resNameMapping[] = {
|
||||
{"PLONGEON", "PLONG110"},
|
||||
{"PNEUMATI", "PNEUMA05"},
|
||||
{"RELAITRE", "RIDEAU__"},
|
||||
{"TIRROIR_", "PORTE___"},
|
||||
{"VERREDO_", "EAU_____"},
|
||||
{"ZODIAC__", "TAXIGO__"}
|
||||
};
|
||||
|
||||
static const AnimDataEntry transparencyData[] = {
|
||||
{"ALPHA", 0xF},
|
||||
{"TITRE2", 0xF},
|
||||
{"ET", 0xC},
|
||||
{"L311", 0x3},
|
||||
{"L405", 0x1},
|
||||
{"L515", 0xC},
|
||||
{"L009", 0xE},
|
||||
{"L010", 0xE},
|
||||
{"FUTUR", 0x6},
|
||||
{"PAYSAN3", 0xB},
|
||||
{"L801", 0xC},
|
||||
{"L802", 0xC},
|
||||
{"L803", 0xC},
|
||||
{"L901", 0xD},
|
||||
{"L902", 0x8},
|
||||
{"L903", 0xD},
|
||||
{"L904", 0xD},
|
||||
{"L905", 0xD},
|
||||
{"L906", 0xD},
|
||||
{"L907", 0xD},
|
||||
{"LA03", 0x4},
|
||||
{"MOINE", 0xB},
|
||||
{"L908", 0x8},
|
||||
{"L909", 0x8},
|
||||
{"L807", 0xC},
|
||||
{"L808", 0xC},
|
||||
{"LA01", 0xB},
|
||||
{"L1201", 0xC},
|
||||
{"L1202", 0xC},
|
||||
{"L1203", 0xC},
|
||||
{"L1210", 0x5},
|
||||
{"L1211", 0xC},
|
||||
{"L1214", 0xC},
|
||||
{"L1215", 0xC},
|
||||
{"L1216", 0xC},
|
||||
{"L1217", 0xC},
|
||||
{"L1218", 0xC},
|
||||
{"L1219", 0xC},
|
||||
{"L1220", 0xC},
|
||||
{"SEIGNEUR", 0x6},
|
||||
{"PERE0", 0xD},
|
||||
{"L1302", 0x4},
|
||||
{"L1303", 0x4},
|
||||
{"L1304", 0x4},
|
||||
{"L1401", 0xF},
|
||||
{"L1402", 0xF},
|
||||
{"L1501", 0x8},
|
||||
{"L1503", 0x8},
|
||||
{"L1504", 0x4},
|
||||
{"L1505", 0x8},
|
||||
{"L1506", 0x8},
|
||||
{"L1601", 0xB},
|
||||
{"L1602", 0xB},
|
||||
{"L1603", 0xB},
|
||||
{"L1604", 0x4},
|
||||
{"L1605", 0x4},
|
||||
{"L1701", 0x4},
|
||||
{"L1702", 0x4},
|
||||
{"L1801", 0x6},
|
||||
{"L1904", 0x8},
|
||||
{"L2002", 0x8},
|
||||
{"L2003", 0x8},
|
||||
{"L2101", 0x4},
|
||||
{"L2102", 0x4},
|
||||
{"L2201", 0x7},
|
||||
{"L2202", 0x7},
|
||||
{"L2203", 0xE},
|
||||
{"L2305", 0x9},
|
||||
{"L2306", 0x9},
|
||||
{"GARDE1", 0x7},
|
||||
{"L2402", 0x7},
|
||||
{"L2407", 0x7},
|
||||
{"L2408", 0x7},
|
||||
{"GARDE2", 0x6},
|
||||
{"L2601", 0x6},
|
||||
{"L2602", 0x6},
|
||||
{"L2603", 0x6},
|
||||
{"L2604", 0x6},
|
||||
{"L2605", 0x8},
|
||||
{"L2606", 0x8},
|
||||
{"L2607", 0x8},
|
||||
{"L2610", 0x6},
|
||||
{"L2611", 0x6},
|
||||
{"L2612", 0x6},
|
||||
{"L2613", 0x8},
|
||||
{"L2614", 0x6},
|
||||
{"VOYAGEUR", 0x6},
|
||||
{"L2701", 0xD},
|
||||
{"L2702", 0xD},
|
||||
{"L2703", 0x6},
|
||||
{"L2801", 0xD},
|
||||
{"L2802", 0xD},
|
||||
{"L2803", 0xD},
|
||||
{"L2804", 0xD},
|
||||
{"L2807", 0xD},
|
||||
{"L2902", 0x8},
|
||||
{"L2903", 0x8},
|
||||
{"L3101", 0xA},
|
||||
{"L3102", 0xA},
|
||||
{"L3103", 0xA},
|
||||
{"L3203", 0xF},
|
||||
{"L3204", 0xF},
|
||||
{"L3001", 0x7},
|
||||
{"L3002", 0x7},
|
||||
{"L3416", 0xC},
|
||||
{"L3601", 0x5},
|
||||
{"L3602", 0x5},
|
||||
{"L3603", 0x5},
|
||||
{"L3607", 0x5},
|
||||
{"L3701", 0x8},
|
||||
{"L3702", 0x8},
|
||||
{"L3703", 0x8},
|
||||
{"L4001", 0xD},
|
||||
{"L4002", 0xD},
|
||||
{"L4103", 0xF},
|
||||
{"L4106", 0xF},
|
||||
{"CRUGHON1", 0xC},
|
||||
{"L4203", 0xC},
|
||||
{"L4301", 0xC},
|
||||
{"L4302", 0xC},
|
||||
{"L4303", 0xC},
|
||||
{"FUTUR2", 0x6},
|
||||
{"L4601", 0xE},
|
||||
{"L4603", 0x1},
|
||||
{"L4106", 0xF},
|
||||
{"L4801", 0xD},
|
||||
{"L4802", 0xD},
|
||||
{"FIN01", 0xB},
|
||||
{"FIN02", 0xB},
|
||||
{"FIN03", 0xB},
|
||||
{"FIN", 0x9},
|
||||
};
|
||||
|
||||
void convertMask(byte *dest, const byte *source, int16 width, int16 height);
|
||||
void convert8BBP(byte *dest, const byte *source, int16 width, int16 height);
|
||||
void convert8BBP2(byte *dest, byte *source, int16 width, int16 height);
|
||||
int loadSet(const char *resourceName, int16 idx, int16 frameIndex = -1);
|
||||
|
||||
void checkAnimDataTableBounds(int entry) {
|
||||
if (entry < 0) {
|
||||
error("Out of free animation space");
|
||||
} else if (entry >= (int)g_cine->_animDataTable.size()) {
|
||||
error("Animation entry (%d) out of bounds", entry);
|
||||
}
|
||||
}
|
||||
|
||||
int16 fixAnimDataTableEndFrame(int entry, int16 startFrame, int16 endFrame) {
|
||||
checkAnimDataTableBounds(entry);
|
||||
|
||||
// Ensure that a non-empty range [entry, entry + endFrame - startFrame) stays in bounds
|
||||
if (endFrame > startFrame &&
|
||||
entry + (endFrame - startFrame - 1) >= (int)g_cine->_animDataTable.size()) {
|
||||
warning("Restricting out of bounds animation data table write to in bounds");
|
||||
return (int16)(g_cine->_animDataTable.size() - entry + startFrame);
|
||||
} else {
|
||||
return endFrame;
|
||||
}
|
||||
}
|
||||
|
||||
AnimData::AnimData() : _width(0), _height(0), _bpp(0), _var1(0), _data(nullptr),
|
||||
_mask(nullptr), _fileIdx(-1), _frameIdx(-1), _realWidth(0), _size(0) {
|
||||
|
||||
memset(_name, 0, sizeof(_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
AnimData::AnimData(const AnimData &src) : _width(src._width),
|
||||
_height(src._height), _bpp(src._bpp), _var1(src._var1),
|
||||
_data(nullptr), _mask(nullptr), _fileIdx(src._fileIdx),
|
||||
_frameIdx(src._frameIdx), _realWidth(src._realWidth), _size(src._size) {
|
||||
|
||||
if (src._data) {
|
||||
_data = new byte[_size];
|
||||
assert(_data);
|
||||
memcpy(_data, src._data, _size * sizeof(byte));
|
||||
}
|
||||
|
||||
if (src._mask) {
|
||||
_mask = new byte[_size];
|
||||
assert(_mask);
|
||||
memcpy(_mask, src._mask, _size * sizeof(byte));
|
||||
}
|
||||
|
||||
memset(_name, 0, sizeof(_name));
|
||||
Common::strcpy_s(_name, src._name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
AnimData::~AnimData() {
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assingment operator
|
||||
*/
|
||||
AnimData &AnimData::operator=(const AnimData &src) {
|
||||
AnimData tmp = src;
|
||||
byte *ptr;
|
||||
|
||||
_width = tmp._width;
|
||||
_height = tmp._height;
|
||||
_bpp = tmp._bpp;
|
||||
_var1 = tmp._var1;
|
||||
|
||||
ptr = _data;
|
||||
_data = tmp._data;
|
||||
tmp._data = ptr;
|
||||
|
||||
ptr = _mask;
|
||||
_mask = tmp._mask;
|
||||
tmp._mask = ptr;
|
||||
|
||||
_fileIdx = tmp._fileIdx;
|
||||
_frameIdx = tmp._frameIdx;
|
||||
memset(_name, 0, sizeof(_name));
|
||||
Common::strcpy_s(_name, tmp._name);
|
||||
_realWidth = tmp._realWidth;
|
||||
_size = tmp._size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
byte AnimData::getColor(int x, int y) {
|
||||
assert(_data);
|
||||
assert(x >= 0 && x < _realWidth && y >= 0 && y <= _height);
|
||||
assert(x + y * _realWidth < _size);
|
||||
|
||||
return _data[x + y * _realWidth];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and decode image frame
|
||||
* @param d Encoded image data
|
||||
* @param type Encoding type
|
||||
* @param w Image width
|
||||
* @param h Image height
|
||||
* @param file Data file index in bundle
|
||||
* @param frame Image frame index
|
||||
* @param n Part name
|
||||
* @param transparent Transparent color (for ANIM_MASKSPRITE)
|
||||
*/
|
||||
void AnimData::load(byte *d, int type, uint16 w, uint16 h, int16 file,
|
||||
int16 frame, const char *n, byte transparent) {
|
||||
assert(d);
|
||||
|
||||
if (_data) {
|
||||
clear();
|
||||
}
|
||||
|
||||
_width = w * 2;
|
||||
_height = h;
|
||||
_var1 = _width >> 3;
|
||||
_data = nullptr;
|
||||
_mask = nullptr;
|
||||
_fileIdx = file;
|
||||
_frameIdx = frame;
|
||||
memset(_name, 0, sizeof(_name));
|
||||
Common::strlcpy(_name, n, sizeof(_name));
|
||||
_realWidth = w;
|
||||
|
||||
switch (type) {
|
||||
case ANIM_RAW:
|
||||
_width = w;
|
||||
_var1 = w >> 3;
|
||||
_bpp = 4;
|
||||
_size = w * h;
|
||||
_data = new byte[_size];
|
||||
assert(_data);
|
||||
memcpy(_data, d, _size * sizeof(byte));
|
||||
break;
|
||||
|
||||
case ANIM_MASK:
|
||||
_bpp = 1;
|
||||
_size = w * h * 8;
|
||||
_data = new byte[_size];
|
||||
_realWidth = w * 8;
|
||||
assert(_data);
|
||||
convertMask(_data, d, w, h);
|
||||
break;
|
||||
|
||||
case ANIM_SPRITE:
|
||||
_bpp = 4;
|
||||
_size = w * h * 2;
|
||||
_data = new byte[_size];
|
||||
_realWidth = w * 2;
|
||||
assert(_data);
|
||||
gfxConvertSpriteToRaw(_data, d, w, h);
|
||||
break;
|
||||
|
||||
case ANIM_MASKSPRITE:
|
||||
_bpp = 4;
|
||||
_size = w * h * 2;
|
||||
_data = new byte[_size];
|
||||
_mask = new byte[_size];
|
||||
_realWidth = w * 2;
|
||||
assert(_data && _mask);
|
||||
gfxConvertSpriteToRaw(_data, d, w, h);
|
||||
generateMask(_data, _mask, _size, transparent);
|
||||
break;
|
||||
|
||||
case ANIM_PALSPRITE:
|
||||
_bpp = 5;
|
||||
_size = w * h * 2;
|
||||
_data = new byte[_size];
|
||||
_realWidth = w * 2;
|
||||
assert(_data);
|
||||
convert8BBP(_data, d, w, h);
|
||||
break;
|
||||
|
||||
case ANIM_FULLSPRITE:
|
||||
_bpp = 8;
|
||||
_var1 = _width >> 4;
|
||||
_size = w * h;
|
||||
_data = new byte[_size];
|
||||
assert(_data);
|
||||
convert8BBP2(_data, d, w, h);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("AnimData::load: unknown image type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset image
|
||||
*/
|
||||
void AnimData::clear() {
|
||||
delete[] _data;
|
||||
delete[] _mask;
|
||||
|
||||
_width = 0;
|
||||
_height = 0;
|
||||
_bpp = 0;
|
||||
_var1 = 0;
|
||||
_data = nullptr;
|
||||
_mask = nullptr;
|
||||
_fileIdx = -1;
|
||||
_frameIdx = -1;
|
||||
memset(_name, 0, sizeof(_name));
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write image identifiers to savefile
|
||||
* @param fHandle Savefile open for writing
|
||||
*/
|
||||
void AnimData::save(Common::OutSaveFile &fHandle) const {
|
||||
fHandle.writeUint16BE(_width);
|
||||
fHandle.writeUint16BE(_var1);
|
||||
fHandle.writeUint16BE(_bpp);
|
||||
fHandle.writeUint16BE(_height);
|
||||
fHandle.writeUint32BE(_data != nullptr); // _data
|
||||
fHandle.writeUint32BE(_mask != nullptr); // _mask
|
||||
fHandle.writeUint16BE(_fileIdx);
|
||||
fHandle.writeUint16BE(_frameIdx);
|
||||
fHandle.write(_name, sizeof(_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear part of animDataTable
|
||||
* @param startIdx First image frame to be cleared
|
||||
* @param numIdx Number of image frames to be cleared
|
||||
*/
|
||||
void freeAnimDataRange(byte startIdx, byte numIdx) {
|
||||
if (numIdx > 0) {
|
||||
// Make sure starting index is in bounds
|
||||
if (startIdx >= g_cine->_animDataTable.size()) {
|
||||
startIdx = (byte)(MAX<int>(0, g_cine->_animDataTable.size() - 1));
|
||||
}
|
||||
|
||||
// Make sure last accessed index is in bounds
|
||||
if (static_cast<uint>(startIdx + numIdx) > g_cine->_animDataTable.size()) {
|
||||
numIdx = (byte)(g_cine->_animDataTable.size() - startIdx);
|
||||
}
|
||||
assert(startIdx < g_cine->_animDataTable.size());
|
||||
assert(static_cast<uint>(startIdx + numIdx) <= g_cine->_animDataTable.size());
|
||||
}
|
||||
|
||||
for (byte i = 0; i < numIdx; i++) {
|
||||
g_cine->_animDataTable[startIdx + i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear whole animDataTable
|
||||
*/
|
||||
void freeAnimDataTable() {
|
||||
freeAnimDataRange(0, NUM_MAX_ANIMDATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find transparent color index for image
|
||||
* @param animName Image file name
|
||||
*/
|
||||
static byte getAnimTransparentColor(const char *animName) {
|
||||
char name[15];
|
||||
|
||||
removeExtension(name, animName, sizeof(name));
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(transparencyData); i++) {
|
||||
if (!strcmp(name, transparencyData[i].name)) {
|
||||
return transparencyData[i].color;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate mask for image
|
||||
* @param[in] sprite Image data
|
||||
* @param[out] mask Image mask
|
||||
* @param size Image data length
|
||||
* @param transparency Transparent color index
|
||||
*/
|
||||
void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency) {
|
||||
for (uint16 i = 0; i < size; i++) {
|
||||
if (*(sprite++) != transparency) {
|
||||
*(mask++) = 0;
|
||||
} else {
|
||||
*(mask++) = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode 1bpp mask
|
||||
* @param[out] dest Decoded mask
|
||||
* @param[in] source Encoded mask
|
||||
* @param width Mask width
|
||||
* @param height Mask height
|
||||
*/
|
||||
void convertMask(byte *dest, const byte *source, int16 width, int16 height) {
|
||||
int16 i, j;
|
||||
byte maskEntry;
|
||||
|
||||
for (i = 0; i < width * height; i++) {
|
||||
maskEntry = *(source++);
|
||||
for (j = 0; j < 8; j++) {
|
||||
*(dest++) = (maskEntry & 0x80) ? 0 : 1;
|
||||
maskEntry <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode 4bpp sprite
|
||||
* @param[out] dest Decoded image
|
||||
* @param[in] source Encoded image
|
||||
* @param width Image width
|
||||
* @param height Image height
|
||||
*/
|
||||
void convert4BBP(byte *dest, const byte *source, int16 width, int16 height) {
|
||||
byte maskEntry;
|
||||
|
||||
for (int16 i = 0; i < width * height; i++) {
|
||||
maskEntry = *(source++);
|
||||
*(dest++) = (maskEntry & 0xF0) >> 4;
|
||||
*(dest++) = (maskEntry & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read image header
|
||||
* @param[out] animHeader Image header reference
|
||||
* @param readS Input stream open for reading
|
||||
*/
|
||||
void loadAnimHeader(AnimHeaderStruct &animHeader, Common::SeekableReadStream &readS) {
|
||||
readS.read(animHeader.idString, sizeof(animHeader.idString));
|
||||
animHeader.idString[sizeof(animHeader.idString) - 1] = 0;
|
||||
animHeader.frameWidth = readS.readSint16BE();
|
||||
animHeader.frameHeight = readS.readSint16BE();
|
||||
animHeader.field_8 = readS.readByte();
|
||||
animHeader.field_9 = readS.readByte();
|
||||
animHeader.field_A = readS.readByte();
|
||||
animHeader.field_B = readS.readByte();
|
||||
animHeader.field_C = readS.readByte();
|
||||
animHeader.field_D = readS.readByte();
|
||||
animHeader.numFrames = readS.readSint16BE();
|
||||
animHeader.field_10 = readS.readByte();
|
||||
animHeader.field_11 = readS.readByte();
|
||||
animHeader.field_12 = readS.readByte();
|
||||
animHeader.field_13 = readS.readByte();
|
||||
animHeader.field_14 = readS.readUint16BE();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find next empty space animDataTable
|
||||
* @param start First index to check
|
||||
*/
|
||||
int emptyAnimSpace(int start = 0) {
|
||||
for (; start < NUM_MAX_ANIMDATA; start++) {
|
||||
if (!g_cine->_animDataTable[start].data()) {
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load SPL data into animDataTable
|
||||
* @param resourceName SPL filename
|
||||
* @param idx Target index in animDataTable (-1 if any empty space will do)
|
||||
* @return The number of the animDataTable entry after the loaded SPL data (-1 if error)
|
||||
*/
|
||||
int loadSpl(const char *resourceName, int16 idx) {
|
||||
int16 foundFileIdx = findFileInBundle(resourceName);
|
||||
int entry;
|
||||
|
||||
if (foundFileIdx < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
byte *dataPtr = readBundleFile(foundFileIdx);
|
||||
|
||||
entry = idx < 0 ? emptyAnimSpace() : idx;
|
||||
checkAnimDataTableBounds(entry);
|
||||
g_cine->_animDataTable[entry].load(dataPtr, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize, 1, foundFileIdx, 0, currentPartName);
|
||||
|
||||
free(dataPtr);
|
||||
return entry + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load 1bpp mask
|
||||
* @param resourceName Mask filename
|
||||
* @param idx Target index in animDataTable (-1 if any empty space will do)
|
||||
* @param frameIndex frame of animation to load (-1 for all frames)
|
||||
* @return The number of the animDataTable entry after the loaded mask (-1 if error)
|
||||
*/
|
||||
int loadMsk(const char *resourceName, int16 idx, int16 frameIndex) {
|
||||
int16 foundFileIdx = findFileInBundle(resourceName);
|
||||
if (foundFileIdx < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int entry = 0;
|
||||
byte *dataPtr = readBundleFile(foundFileIdx);
|
||||
byte *ptr;
|
||||
AnimHeaderStruct animHeader;
|
||||
|
||||
Common::MemoryReadStream readS(dataPtr, ANIM_HEADER_SIZE);
|
||||
loadAnimHeader(animHeader, readS);
|
||||
ptr = dataPtr + ANIM_HEADER_SIZE;
|
||||
|
||||
int16 startFrame = 0;
|
||||
int16 endFrame = animHeader.numFrames;
|
||||
|
||||
if (frameIndex >= 0) {
|
||||
startFrame = frameIndex;
|
||||
endFrame = frameIndex + 1;
|
||||
ptr += frameIndex * animHeader.frameWidth * animHeader.frameHeight;
|
||||
}
|
||||
|
||||
entry = idx < 0 ? emptyAnimSpace() : idx;
|
||||
endFrame = fixAnimDataTableEndFrame(entry, startFrame, endFrame);
|
||||
for (int16 i = startFrame; i < endFrame; i++, entry++) {
|
||||
g_cine->_animDataTable[entry].load(ptr, ANIM_MASK, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName);
|
||||
ptr += animHeader.frameWidth * animHeader.frameHeight;
|
||||
}
|
||||
|
||||
free(dataPtr);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load animation
|
||||
* @param resourceName Animation filename
|
||||
* @param idx Target index in animDataTable (-1 if any empty space will do)
|
||||
* @param frameIndex frame of animation to load (-1 for all frames)
|
||||
* @return The number of the animDataTable entry after the loaded animation (-1 if error)
|
||||
*/
|
||||
int loadAni(const char *resourceName, int16 idx, int16 frameIndex) {
|
||||
int16 foundFileIdx = findFileInBundle(resourceName);
|
||||
if (foundFileIdx < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int entry = 0;
|
||||
byte *dataPtr = readBundleFile(foundFileIdx);
|
||||
byte *ptr;
|
||||
byte transparentColor;
|
||||
AnimHeaderStruct animHeader;
|
||||
|
||||
Common::MemoryReadStream readS(dataPtr, ANIM_HEADER_SIZE);
|
||||
loadAnimHeader(animHeader, readS);
|
||||
ptr = dataPtr + ANIM_HEADER_SIZE;
|
||||
|
||||
// HACK: If the underlying resource is really a ".SET" then use that loading routine.
|
||||
// Try to detect door animations in SP11_01.ANI and SP11_02.ANI that are .SET files.
|
||||
// These are on Dr. Why's island the opening and closing doors.
|
||||
if (hacksEnabled && scumm_stricmp(animHeader.idString, "SET") == 0 &&
|
||||
idx >= 161 && idx <= 164 && animHeader.frameHeight == 0) {
|
||||
free(dataPtr);
|
||||
return loadSet(resourceName, idx, frameIndex);
|
||||
}
|
||||
|
||||
int16 startFrame = 0;
|
||||
int16 endFrame = animHeader.numFrames;
|
||||
|
||||
if (frameIndex >= 0) {
|
||||
startFrame = frameIndex;
|
||||
endFrame = frameIndex + 1;
|
||||
ptr += frameIndex * animHeader.frameWidth * animHeader.frameHeight;
|
||||
}
|
||||
|
||||
transparentColor = getAnimTransparentColor(resourceName);
|
||||
|
||||
// TODO: Merge this special case hack into getAnimTransparentColor somehow.
|
||||
// HACK: Amiga and Atari ST versions of ALPHA.ANI in Future Wars use 0 instead of 0xF for transparency.
|
||||
// Fixes transparency of page number and grid position (e.g. 04 and D2) in the copy protection scene
|
||||
// of Amiga and Atari ST versions of Future Wars.
|
||||
if (hacksEnabled && g_cine->getGameType() == Cine::GType_FW &&
|
||||
(g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) &&
|
||||
scumm_stricmp(resourceName, "ALPHA.ANI") == 0) {
|
||||
transparentColor = 0;
|
||||
}
|
||||
|
||||
// TODO: Merge this special case hack into getAnimTransparentColor somehow.
|
||||
// HACK: Versions of TITRE.ANI with height 37 use color 0xF for transparency.
|
||||
// Versions of TITRE.ANI with height 57 use color 0x0 for transparency.
|
||||
// Fixes bug #3875: FW: Glitches in title display of demo (regression).
|
||||
if (hacksEnabled && scumm_stricmp(resourceName, "TITRE.ANI") == 0 && animHeader.frameHeight == 37) {
|
||||
transparentColor = 0xF;
|
||||
}
|
||||
|
||||
entry = idx < 0 ? emptyAnimSpace() : idx;
|
||||
endFrame = fixAnimDataTableEndFrame(entry, startFrame, endFrame);
|
||||
|
||||
for (int16 i = startFrame; i < endFrame; i++, entry++) {
|
||||
// special case transparency handling
|
||||
if (!strcmp(resourceName, "L2202.ANI")) {
|
||||
transparentColor = i < 2 ? 0 : 7;
|
||||
} else if (!strcmp(resourceName, "L4601.ANI")) {
|
||||
transparentColor = i < 1 ? 0xE : 0;
|
||||
}
|
||||
|
||||
g_cine->_animDataTable[entry].load(ptr, ANIM_MASKSPRITE, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName, transparentColor);
|
||||
ptr += animHeader.frameWidth * animHeader.frameHeight;
|
||||
}
|
||||
|
||||
free(dataPtr);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode 16 color image with palette
|
||||
* @param[out] dest Decoded image
|
||||
* @param[in] source Encoded image
|
||||
* @param width Image width
|
||||
* @param height Image height
|
||||
*/
|
||||
void convert8BBP(byte *dest, const byte *source, int16 width, int16 height) {
|
||||
const byte *table = source;
|
||||
byte color;
|
||||
|
||||
source += 16;
|
||||
|
||||
for (uint16 i = 0; i < width * height; i++) {
|
||||
color = *(source++);
|
||||
|
||||
*(dest++) = table[color >> 4];
|
||||
*(dest++) = table[color & 0xF];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode 8bit image
|
||||
* @param[out] dest Decoded image
|
||||
* @param[in] source Encoded image
|
||||
* @param width Image width
|
||||
* @param height Image height
|
||||
* \attention Data in source are destroyed during decoding
|
||||
*/
|
||||
void convert8BBP2(byte *dest, byte *source, int16 width, int16 height) {
|
||||
uint16 i, j;
|
||||
int k, m;
|
||||
byte color;
|
||||
|
||||
for (j = 0; j < (width * height) / 16; j++) {
|
||||
// m = 0: even bits, m = 1: odd bits
|
||||
for (m = 0; m <= 1; m++) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
color = 0;
|
||||
for (k = 14 + m; k >= 0; k -= 2) {
|
||||
color |= ((*(source + k) & 0x080) >> 7);
|
||||
*(source + k) <<= 1;
|
||||
if (k > 0 + m)
|
||||
color <<= 1;
|
||||
} // end k
|
||||
*(dest++) = color;
|
||||
} // end i
|
||||
} // end m
|
||||
|
||||
source += 0x10;
|
||||
} // end j
|
||||
}
|
||||
|
||||
/**
|
||||
* Load image set
|
||||
* @param resourceName Image set filename
|
||||
* @param idx Target index in animDataTable (-1 if any empty space will do)
|
||||
* @param frameIndex frame of animation to load (-1 for all frames)
|
||||
* @return The number of the animDataTable entry after the loaded image set (-1 if error)
|
||||
*/
|
||||
int loadSet(const char *resourceName, int16 idx, int16 frameIndex) {
|
||||
AnimHeader2Struct header2;
|
||||
uint16 numSpriteInAnim;
|
||||
int16 foundFileIdx = findFileInBundle(resourceName);
|
||||
int16 entry;
|
||||
byte *ptr, *startOfDataPtr, *dataPtr, *origDataPtr;
|
||||
int type;
|
||||
|
||||
if (foundFileIdx < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
origDataPtr = dataPtr = readBundleFile(foundFileIdx);
|
||||
assert(!memcmp(dataPtr, "SET", 3));
|
||||
ptr = dataPtr + 4;
|
||||
|
||||
numSpriteInAnim = READ_BE_UINT16(ptr);
|
||||
ptr += 2;
|
||||
|
||||
startOfDataPtr = ptr + numSpriteInAnim * 0x10;
|
||||
|
||||
entry = idx < 0 ? emptyAnimSpace() : idx;
|
||||
assert(entry >= 0);
|
||||
|
||||
int16 startFrame = 0;
|
||||
int16 endFrame = numSpriteInAnim;
|
||||
|
||||
if (frameIndex >= 0) {
|
||||
startFrame = frameIndex;
|
||||
endFrame = frameIndex + 1;
|
||||
ptr += 0x10 * frameIndex;
|
||||
}
|
||||
|
||||
endFrame = fixAnimDataTableEndFrame(entry, startFrame, endFrame);
|
||||
for (int16 i = startFrame; i < endFrame; i++, entry++) {
|
||||
Common::MemoryReadStream readS(ptr, 0x10);
|
||||
|
||||
header2.field_0 = readS.readUint32BE();
|
||||
header2.width = readS.readUint16BE();
|
||||
header2.height = readS.readUint16BE();
|
||||
header2.type = readS.readUint16BE();
|
||||
header2.field_A = readS.readUint16BE();
|
||||
header2.field_C = readS.readUint16BE();
|
||||
header2.field_E = readS.readUint16BE();
|
||||
|
||||
ptr += 0x10;
|
||||
|
||||
dataPtr = startOfDataPtr + header2.field_0;
|
||||
|
||||
if (header2.type == 1) {
|
||||
type = ANIM_MASK;
|
||||
} else if (header2.type == 4) {
|
||||
type = ANIM_SPRITE;
|
||||
} else if (header2.type == 5) {
|
||||
type = ANIM_PALSPRITE;
|
||||
} else {
|
||||
type = ANIM_FULLSPRITE;
|
||||
}
|
||||
|
||||
g_cine->_animDataTable[entry].load(dataPtr, type, header2.width, header2.height, foundFileIdx, i, currentPartName);
|
||||
}
|
||||
|
||||
free(origDataPtr);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load SEQ data into animDataTable
|
||||
* @param resourceName SEQ data filename
|
||||
* @param idx Target index in animDataTable (-1 if any empty space will do)
|
||||
* @return The number of the animDataTable entry after the loaded SEQ data (-1 if error)
|
||||
*/
|
||||
int loadSeq(const char *resourceName, int16 idx) {
|
||||
int16 foundFileIdx = findFileInBundle(resourceName);
|
||||
if (foundFileIdx < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
byte *dataPtr = readBundleFile(foundFileIdx);
|
||||
int entry = idx < 0 ? emptyAnimSpace() : idx;
|
||||
checkAnimDataTableBounds(entry);
|
||||
g_cine->_animDataTable[entry].load(dataPtr + ANIM_HEADER_SIZE, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize - 0x16, 1, foundFileIdx, 0, currentPartName);
|
||||
free(dataPtr);
|
||||
return entry + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a resource into animDataTable
|
||||
* @param resourceName Resource's filename
|
||||
* @param idx Target index in animDataTable (-1 if any empty space will do)
|
||||
* @return The number of the animDataTable entry after the loaded resource (-1 if error)
|
||||
* @todo Implement loading of all resource types
|
||||
*/
|
||||
int loadResource(const char *resourceName, int16 idx, int16 frameIndex) {
|
||||
int result = -1; // Return an error by default
|
||||
|
||||
if (g_cine->getGameType() == Cine::GType_OS &&
|
||||
g_cine->getPlatform() == Common::kPlatformDOS &&
|
||||
g_sound->musicType() != MT_MT32 &&
|
||||
(strstr(resourceName, ".SPL") || strstr(resourceName, ".H32"))) {
|
||||
char base[20];
|
||||
removeExtension(base, resourceName, sizeof(base));
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE(resNameMapping); i++) {
|
||||
if (scumm_stricmp(base, resNameMapping[i].from) == 0) {
|
||||
Common::strlcpy(base, resNameMapping[i].to, sizeof(base));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ext = (g_sound->musicType() == MT_ADLIB) ? ".ADL" : ".HP";
|
||||
Common::strlcat(base, ext, sizeof(base));
|
||||
return loadResource(base, idx, frameIndex);
|
||||
}
|
||||
|
||||
bool preferSeq = (g_cine->getGameType() == Cine::GType_OS && g_sound->musicType() == MT_MT32);
|
||||
|
||||
if (strstr(resourceName, ".SPL")) {
|
||||
if (preferSeq)
|
||||
result = loadSeq(resourceName, idx);
|
||||
else
|
||||
result = loadSpl(resourceName, idx);
|
||||
} else if (strstr(resourceName, ".MSK")) {
|
||||
result = loadMsk(resourceName, idx, frameIndex);
|
||||
} else if (strstr(resourceName, ".ANI")) {
|
||||
result = loadAni(resourceName, idx, frameIndex);
|
||||
} else if (strstr(resourceName, ".ANM")) {
|
||||
result = loadAni(resourceName, idx, frameIndex);
|
||||
} else if (strstr(resourceName, ".SET")) {
|
||||
result = loadSet(resourceName, idx, frameIndex);
|
||||
} else if (strstr(resourceName, ".SEQ")) {
|
||||
result = loadSeq(resourceName, idx);
|
||||
} else if (strstr(resourceName, ".H32")) {
|
||||
if (preferSeq)
|
||||
result = loadSeq(resourceName, idx);
|
||||
else
|
||||
result = loadSpl(resourceName, idx);
|
||||
} else if (strstr(resourceName, ".HP")) {
|
||||
result = loadSpl(resourceName, idx);
|
||||
} else if (strstr(resourceName, ".ADL")) {
|
||||
result = loadSpl(resourceName, idx);
|
||||
} else if (strstr(resourceName, ".AMI")) {
|
||||
result = loadSpl(resourceName, idx);
|
||||
} else if (strstr(resourceName, "ECHEC")) { // Echec (French) means failure
|
||||
g_cine->quitGame();
|
||||
} else {
|
||||
error("loadResource: Cannot determine type for '%s'", resourceName);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
113
engines/cine/anim.h
Normal file
113
engines/cine/anim.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* 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 CINE_ANIM_H
|
||||
#define CINE_ANIM_H
|
||||
|
||||
#include "common/endian.h"
|
||||
|
||||
#include "cine/saveload.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
// Size of AnimHeaderStruct payload in bytes
|
||||
#define ANIM_HEADER_SIZE 0x16
|
||||
|
||||
struct AnimHeaderStruct {
|
||||
char idString[4];
|
||||
int16 frameWidth;
|
||||
int16 frameHeight;
|
||||
byte field_8;
|
||||
byte field_9;
|
||||
byte field_A;
|
||||
byte field_B;
|
||||
byte field_C;
|
||||
byte field_D;
|
||||
int16 numFrames;
|
||||
byte field_10;
|
||||
byte field_11;
|
||||
byte field_12;
|
||||
byte field_13;
|
||||
uint16 field_14;
|
||||
};
|
||||
|
||||
struct AnimDataEntry {
|
||||
char name[9];
|
||||
byte color;
|
||||
};
|
||||
|
||||
struct AnimDataMapping {
|
||||
char from[9];
|
||||
char to[9];
|
||||
};
|
||||
|
||||
#define ANIM_RAW 0 // memcpy
|
||||
#define ANIM_MASK 1 // convertMask
|
||||
#define ANIM_SPRITE 2 // gfxConvertSpriteToRaw
|
||||
#define ANIM_MASKSPRITE 3 // gfxConvertSpriteToRaw + generateMask
|
||||
#define ANIM_PALSPRITE 5 // convert8BBP
|
||||
#define ANIM_FULLSPRITE 8 // convert8BBP2
|
||||
|
||||
class AnimData {
|
||||
private:
|
||||
byte *_data; ///< Image data
|
||||
byte *_mask; ///< Image mask (may be NULL)
|
||||
int16 _fileIdx; ///< Source file index in bundle
|
||||
int16 _frameIdx; ///< Frame number in animation
|
||||
char _name[10]; ///< Part filename
|
||||
int _size; ///< _data/_mask size, internal only
|
||||
|
||||
public:
|
||||
uint16 _width; ///< Image width (usually twice the real size)
|
||||
uint16 _height; ///< Image height
|
||||
uint16 _bpp; ///< Bit depth/type information
|
||||
uint16 _var1; ///< Something related to width
|
||||
int _realWidth; ///< Real image width in bytes
|
||||
|
||||
AnimData();
|
||||
AnimData(const AnimData &src);
|
||||
~AnimData();
|
||||
|
||||
AnimData &operator=(const AnimData &src);
|
||||
|
||||
int size() { return _size; }
|
||||
int16 frameIndex() { return _frameIdx; }
|
||||
const byte *data() const { return _data; } ///< Image data
|
||||
const byte *mask() const { return _mask; } ///< Image mask (may be NULL)
|
||||
byte getColor(int x, int y);
|
||||
|
||||
void load(byte *d, int type, uint16 w, uint16 h, int16 file, int16 frame, const char *n, byte transparent = 0);
|
||||
void clear();
|
||||
|
||||
void save(Common::OutSaveFile &fHandle) const;
|
||||
};
|
||||
|
||||
#define NUM_MAX_ANIMDATA 255
|
||||
|
||||
void freeAnimDataTable();
|
||||
void freeAnimDataRange(byte startIdx, byte numIdx);
|
||||
int loadResource(const char *resourceName, int16 idx = -1, int16 frameIndex = -1);
|
||||
void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGameFormat saveGameFormat);
|
||||
void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
117
engines/cine/bg.cpp
Normal file
117
engines/cine/bg.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/* 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/endian.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/various.h"
|
||||
#include "cine/bg.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
uint16 bgVar0;
|
||||
byte *additionalBgTable[9];
|
||||
|
||||
int16 loadCtFW(const char *ctName) {
|
||||
debugC(1, kCineDebugCollision, "loadCtFW(\"%s\")", ctName);
|
||||
byte *ptr, *dataPtr;
|
||||
|
||||
int16 foundFileIdx = findFileInBundle(ctName);
|
||||
if (foundFileIdx < 0) {
|
||||
warning("loadCtFW: Unable to find collision data file '%s'", ctName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (currentCtName != ctName)
|
||||
Common::strlcpy(currentCtName, ctName, sizeof(currentCtName));
|
||||
|
||||
ptr = dataPtr = readBundleFile(foundFileIdx);
|
||||
|
||||
loadRelatedPalette(ctName);
|
||||
|
||||
assert(strstr(ctName, ".NEO"));
|
||||
|
||||
gfxConvertSpriteToRaw(collisionPage, ptr + 0x80, 160, 200);
|
||||
|
||||
free(dataPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16 loadCtOS(const char *ctName) {
|
||||
debugC(1, kCineDebugCollision, "loadCtOS(\"%s\")", ctName);
|
||||
byte *ptr, *dataPtr;
|
||||
|
||||
int16 foundFileIdx = findFileInBundle(ctName);
|
||||
if (foundFileIdx < 0) {
|
||||
warning("loadCtOS: Unable to find collision data file '%s'", ctName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (currentCtName != ctName)
|
||||
Common::strlcpy(currentCtName, ctName, sizeof(currentCtName));
|
||||
|
||||
ptr = dataPtr = readBundleFile(foundFileIdx);
|
||||
|
||||
uint16 bpp = READ_BE_UINT16(ptr);
|
||||
ptr += 2;
|
||||
|
||||
if (bpp == 8) {
|
||||
renderer->loadCt256(ptr, ctName);
|
||||
} else {
|
||||
renderer->loadCt16(ptr, ctName);
|
||||
}
|
||||
|
||||
free(dataPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16 loadBg(const char *bgName) {
|
||||
byte *ptr, *dataPtr;
|
||||
|
||||
int16 fileIdx = findFileInBundle(bgName);
|
||||
if (fileIdx < 0) {
|
||||
warning("loadBg(\"%s\"): Could not find background in file bundle.", bgName);
|
||||
return -1;
|
||||
}
|
||||
checkDataDisk(-1);
|
||||
ptr = dataPtr = readBundleFile(fileIdx);
|
||||
|
||||
uint16 bpp = READ_BE_UINT16(ptr);
|
||||
ptr += 2;
|
||||
|
||||
if (bpp == 8) {
|
||||
renderer->loadBg256(ptr, bgName);
|
||||
} else {
|
||||
if (g_cine->getGameType() == Cine::GType_FW) {
|
||||
loadRelatedPalette(bgName);
|
||||
}
|
||||
|
||||
renderer->loadBg16(ptr, bgName);
|
||||
}
|
||||
free(dataPtr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
34
engines/cine/bg.h
Normal file
34
engines/cine/bg.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 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 CINE_BG_H
|
||||
#define CINE_BG_H
|
||||
|
||||
namespace Cine {
|
||||
int16 loadBg(const char *bgName);
|
||||
int16 loadCtFW(const char *bgName);
|
||||
int16 loadCtOS(const char *bgName);
|
||||
|
||||
extern uint16 bgVar0;
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
125
engines/cine/bg_list.cpp
Normal file
125
engines/cine/bg_list.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 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/endian.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/main_loop.h"
|
||||
#include "cine/object.h"
|
||||
#include "cine/various.h"
|
||||
#include "cine/bg_list.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
uint32 var8;
|
||||
|
||||
/**
|
||||
* Add masked sprite to the background
|
||||
* @param objIdx Sprite description
|
||||
*/
|
||||
void addToBGList(int16 objIdx) {
|
||||
createBgIncrustListElement(objIdx, 0);
|
||||
|
||||
renderer->incrustSprite(g_cine->_bgIncrustList.back());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add filled sprite to the background
|
||||
* @param objIdx Sprite description
|
||||
*/
|
||||
void addSpriteFilledToBGList(int16 objIdx) {
|
||||
createBgIncrustListElement(objIdx, 1);
|
||||
|
||||
renderer->incrustMask(g_cine->_bgIncrustList.back());
|
||||
}
|
||||
|
||||
void removeBgIncrustsWithBgIdx(int16 bgIdx) {
|
||||
Common::List<BGIncrust>::iterator it;
|
||||
for (it = g_cine->_bgIncrustList.begin(); it != g_cine->_bgIncrustList.end();) {
|
||||
if (it->bgIdx == bgIdx) {
|
||||
it = g_cine->_bgIncrustList.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new element to incrust list
|
||||
* @param objIdx Element description
|
||||
* @param param Type of element
|
||||
*/
|
||||
void createBgIncrustListElement(int16 objIdx, int16 param) {
|
||||
BGIncrust tmp;
|
||||
|
||||
tmp.unkPtr = nullptr;
|
||||
tmp.objIdx = objIdx;
|
||||
tmp.param = param;
|
||||
tmp.x = g_cine->_objectTable[objIdx].x;
|
||||
tmp.y = g_cine->_objectTable[objIdx].y;
|
||||
tmp.frame = g_cine->_objectTable[objIdx].frame;
|
||||
tmp.part = g_cine->_objectTable[objIdx].part & 0x0f;
|
||||
tmp.bgIdx = renderer->currentBg();
|
||||
|
||||
g_cine->_bgIncrustList.push_back(tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset var8 (probably something related to bgIncrustList)
|
||||
*/
|
||||
void resetBgIncrustList() {
|
||||
var8 = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore incrust list from savefile
|
||||
* @param fHandle Savefile open for reading
|
||||
*/
|
||||
void loadBgIncrustFromSave(Common::SeekableReadStream &fHandle, bool hasBgIdx) {
|
||||
BGIncrust tmp;
|
||||
int size = fHandle.readSint16BE();
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
fHandle.readUint32BE();
|
||||
fHandle.readUint32BE();
|
||||
|
||||
tmp.unkPtr = nullptr;
|
||||
tmp.objIdx = fHandle.readUint16BE();
|
||||
tmp.param = fHandle.readUint16BE();
|
||||
tmp.x = fHandle.readUint16BE();
|
||||
tmp.y = fHandle.readUint16BE();
|
||||
tmp.frame = fHandle.readUint16BE();
|
||||
tmp.part = fHandle.readUint16BE();
|
||||
tmp.bgIdx = (hasBgIdx ? fHandle.readUint16BE() : 0);
|
||||
|
||||
g_cine->_bgIncrustList.push_back(tmp);
|
||||
|
||||
if (tmp.param == 0) {
|
||||
renderer->incrustSprite(tmp);
|
||||
} else {
|
||||
renderer->incrustMask(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
54
engines/cine/bg_list.h
Normal file
54
engines/cine/bg_list.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 CINE_BGLIST_H
|
||||
#define CINE_BGLIST_H
|
||||
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/list.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
struct BGIncrust {
|
||||
byte *unkPtr;
|
||||
int16 objIdx;
|
||||
int16 param;
|
||||
int16 x;
|
||||
int16 y;
|
||||
int16 frame;
|
||||
int16 part;
|
||||
int16 bgIdx;
|
||||
};
|
||||
|
||||
extern uint32 var8;
|
||||
|
||||
void addToBGList(int16 objIdx);
|
||||
void addSpriteFilledToBGList(int16 idx);
|
||||
void removeBgIncrustsWithBgIdx(int16 bgIdx);
|
||||
|
||||
void createBgIncrustListElement(int16 objIdx, int16 param);
|
||||
void resetBgIncrustList();
|
||||
void loadBgIncrustFromSave(Common::SeekableReadStream &fHandle, bool hasBgIdx = false);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
623
engines/cine/cine.cpp
Normal file
623
engines/cine/cine.cpp
Normal file
@@ -0,0 +1,623 @@
|
||||
/* 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/config-manager.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/events.h"
|
||||
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
|
||||
#include "engines/util.h"
|
||||
|
||||
#include "graphics/cursorman.h"
|
||||
#include "graphics/paletteman.h"
|
||||
|
||||
#include "image/iff.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/bg_list.h"
|
||||
#include "cine/main_loop.h"
|
||||
#include "cine/object.h"
|
||||
#include "cine/texte.h"
|
||||
#include "cine/sound.h"
|
||||
#include "cine/various.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
// The color names for the copy protection screens are images, so they are transcribed here for TTS
|
||||
static const char *copyProtectionColorsFWEnglish[] = {
|
||||
"White",
|
||||
"Yellow",
|
||||
"Red",
|
||||
"Orange",
|
||||
"Black",
|
||||
"Blue",
|
||||
"Brown",
|
||||
"Green"
|
||||
};
|
||||
|
||||
static const char *copyProtectionColorsFWFrench[] = {
|
||||
"Blanc",
|
||||
"Jaune",
|
||||
"Rouge",
|
||||
"Orange",
|
||||
"Noir",
|
||||
"Bleu",
|
||||
"Marron",
|
||||
"Vert"
|
||||
};
|
||||
|
||||
static const char *copyProtectionColorsFWGerman[] = {
|
||||
"Wei\236",
|
||||
"Gelb",
|
||||
"Rot",
|
||||
"Orange",
|
||||
"Schwarz",
|
||||
"Blau",
|
||||
"Braun",
|
||||
"Grun"
|
||||
};
|
||||
|
||||
static const char *copyProtectionColorsFWSpanish[] = {
|
||||
"Blanco",
|
||||
"Amarillo",
|
||||
"Rojo",
|
||||
"Naranja",
|
||||
"Negro",
|
||||
"Azul",
|
||||
"Marr\242n",
|
||||
"Verde"
|
||||
};
|
||||
|
||||
static const char *copyProtectionColorsOSEnglish[] = {
|
||||
"Black",
|
||||
"White",
|
||||
"Yellow",
|
||||
"Orange",
|
||||
"Red",
|
||||
"Brown",
|
||||
"Grey",
|
||||
"Pink",
|
||||
"Purple",
|
||||
"Light Blue",
|
||||
"Dark Blue",
|
||||
"Light Green",
|
||||
"Dark Green"
|
||||
};
|
||||
|
||||
static const char *copyProtectionColorsOSFrench[] = {
|
||||
"Noir",
|
||||
"Blanc",
|
||||
"Jaune",
|
||||
"Orange",
|
||||
"Rouge",
|
||||
"Marron",
|
||||
"Gris",
|
||||
"Rose",
|
||||
"Violet",
|
||||
"Bleu Clair",
|
||||
"Bleu Fonc\202",
|
||||
"Vert Clair",
|
||||
"Vert Fonc\202"
|
||||
};
|
||||
|
||||
static const char *copyProtectionColorsOSGerman[] = {
|
||||
"Schwarz",
|
||||
"Wei\236",
|
||||
"Gelb",
|
||||
"Orange",
|
||||
"Rot",
|
||||
"Braun",
|
||||
"Grau",
|
||||
"Pink",
|
||||
"Violett",
|
||||
"Hellblau",
|
||||
"Dunkelblau",
|
||||
"Hellgr\201n",
|
||||
"Dunkelgr\201n"
|
||||
};
|
||||
|
||||
static const char *copyProtectionColorsOSSpanish[] = {
|
||||
"Negro",
|
||||
"Blanco",
|
||||
"Amarillo",
|
||||
"Naranja",
|
||||
"Rojo",
|
||||
"Marr\242n",
|
||||
"Gris",
|
||||
"Rosa",
|
||||
"Morado",
|
||||
"Azul Claro",
|
||||
"Azul Oscuro",
|
||||
"Verde Claro",
|
||||
"Verde Oscuro"
|
||||
};
|
||||
|
||||
static const char *copyProtectionColorsOSItalian[] = {
|
||||
"Nero",
|
||||
"Bianco",
|
||||
"Giallo",
|
||||
"Arancione",
|
||||
"Rosso",
|
||||
"Marrone",
|
||||
"Grigio",
|
||||
"Rosa",
|
||||
"Viola",
|
||||
"Blu Chiaro",
|
||||
"Blu Scuro",
|
||||
"Verde Chiaro",
|
||||
"Verde Scuro"
|
||||
};
|
||||
|
||||
static const int kNumOfFWColors = 8;
|
||||
static const int kNumOfOSColors = 13;
|
||||
|
||||
#endif
|
||||
|
||||
Sound *g_sound = nullptr;
|
||||
|
||||
CineEngine *g_cine = nullptr;
|
||||
|
||||
CineEngine::CineEngine(OSystem *syst, const CINEGameDescription *gameDesc)
|
||||
: Engine(syst),
|
||||
_gameDescription(gameDesc),
|
||||
_rnd("cine") {
|
||||
|
||||
// Setup mixer
|
||||
syncSoundSettings();
|
||||
|
||||
setDebugger(new CineConsole(this));
|
||||
|
||||
g_cine = this;
|
||||
|
||||
for (int i = 0; i < NUM_FONT_CHARS; i++) {
|
||||
_textHandler.fontParamTable[i].characterIdx = 0;
|
||||
_textHandler.fontParamTable[i].characterWidth = 0;
|
||||
}
|
||||
_restartRequested = false;
|
||||
_preLoad = false;
|
||||
setDefaultGameSpeed();
|
||||
}
|
||||
|
||||
CineEngine::~CineEngine() {
|
||||
if (getGameType() == Cine::GType_OS) {
|
||||
freeErrmessDat();
|
||||
}
|
||||
}
|
||||
|
||||
void CineEngine::syncSoundSettings() {
|
||||
Engine::syncSoundSettings();
|
||||
|
||||
bool mute = false;
|
||||
if (ConfMan.hasKey("mute"))
|
||||
mute = ConfMan.getBool("mute");
|
||||
|
||||
// Use music volume for plain sound types (At least the AdLib player uses a plain sound type
|
||||
// so previously the music and sfx volume controls didn't affect it at all).
|
||||
// FIXME: Make AdLib player differentiate between playing sound effects and music and remove this.
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType,
|
||||
mute ? 0 : ConfMan.getInt("music_volume"));
|
||||
}
|
||||
|
||||
Common::Error CineEngine::run() {
|
||||
Graphics::ModeList modes;
|
||||
modes.push_back(Graphics::Mode(320, 200));
|
||||
if (g_cine->getGameType() == GType_FW && (g_cine->getFeatures() & GF_CD)) {
|
||||
modes.push_back(Graphics::Mode(640, 480));
|
||||
initGraphicsModes(modes);
|
||||
showSplashScreen();
|
||||
} else {
|
||||
initGraphicsModes(modes);
|
||||
}
|
||||
|
||||
// Initialize backend
|
||||
initGraphics(320, 200);
|
||||
|
||||
if (g_cine->getGameType() == GType_FW && (g_cine->getFeatures() & GF_CD)) {
|
||||
if (!existExtractedCDAudioFiles(19) // tracks <19 are not used
|
||||
&& !isDataAndCDAudioReadFromSameCD()) {
|
||||
warnMissingExtractedCDAudio();
|
||||
}
|
||||
}
|
||||
|
||||
if (getPlatform() == Common::kPlatformDOS) {
|
||||
g_sound = new PCSound(_mixer, this);
|
||||
} else {
|
||||
// Paula chipset for Amiga and Atari versions
|
||||
g_sound = new PaulaSound(_mixer, this);
|
||||
}
|
||||
|
||||
_restartRequested = false;
|
||||
|
||||
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
|
||||
if (ttsMan != nullptr) {
|
||||
ttsMan->setLanguage(ConfMan.get("language"));
|
||||
ttsMan->enable(ConfMan.getBool("tts_enabled"));
|
||||
}
|
||||
|
||||
switch (getLanguage()) {
|
||||
case Common::EN_ANY:
|
||||
case Common::EN_USA:
|
||||
case Common::EN_GRB:
|
||||
_ttsLanguage = kEnglish;
|
||||
break;
|
||||
case Common::FR_FRA:
|
||||
_ttsLanguage = kFrench;
|
||||
break;
|
||||
case Common::DE_DEU:
|
||||
_ttsLanguage = kGerman;
|
||||
break;
|
||||
case Common::ES_ESP:
|
||||
_ttsLanguage = kSpanish;
|
||||
break;
|
||||
case Common::IT_ITA:
|
||||
_ttsLanguage = kItalian;
|
||||
break;
|
||||
default:
|
||||
_ttsLanguage = kEnglish;
|
||||
break;
|
||||
}
|
||||
|
||||
_copyProtectionColorScreen = false;
|
||||
_copyProtectionTextScreen = false;
|
||||
_saveInputMenuOpen = false;
|
||||
|
||||
do {
|
||||
initialize();
|
||||
|
||||
_restartRequested = false;
|
||||
|
||||
CursorMan.showMouse(true);
|
||||
mainLoop(BOOT_SCRIPT_INDEX);
|
||||
|
||||
delete renderer;
|
||||
delete[] collisionPage;
|
||||
delete _scriptInfo;
|
||||
} while (_restartRequested);
|
||||
|
||||
delete g_sound;
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
uint32 CineEngine::getTimerDelay() const {
|
||||
return (10923000 * _timerDelayMultiplier) / 1193180;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify game speed
|
||||
* @param speedChange Negative values slow game down, positive values speed it up, zero does nothing
|
||||
* @return Timer delay multiplier's value after the game speed change
|
||||
*/
|
||||
int CineEngine::modifyGameSpeed(int speedChange) {
|
||||
// If we want more speed we decrement the timer delay multiplier and vice versa.
|
||||
_timerDelayMultiplier = CLIP(_timerDelayMultiplier - speedChange, 1, 50);
|
||||
return _timerDelayMultiplier;
|
||||
}
|
||||
|
||||
void CineEngine::setDefaultGameSpeed() {
|
||||
_timerDelayMultiplier = 12;
|
||||
}
|
||||
|
||||
void CineEngine::initialize() {
|
||||
setTotalPlayTime(0); // Reset total play time
|
||||
_globalVars.reinit(NUM_MAX_VAR + 1);
|
||||
|
||||
// Initialize all savegames' descriptions to empty strings
|
||||
memset(currentSaveName, 0, sizeof(currentSaveName));
|
||||
|
||||
// Resize object table to its correct size and reset all its elements
|
||||
g_cine->_objectTable.resize(NUM_MAX_OBJECT);
|
||||
resetObjectTable();
|
||||
|
||||
// Resize animation data table to its correct size and reset all its elements
|
||||
g_cine->_animDataTable.resize(NUM_MAX_ANIMDATA);
|
||||
freeAnimDataTable();
|
||||
|
||||
// Resize zone data table to its correct size and reset all its elements
|
||||
g_cine->_zoneData.resize(NUM_MAX_ZONE);
|
||||
Common::fill(g_cine->_zoneData.begin(), g_cine->_zoneData.end(), 0);
|
||||
|
||||
// Resize zone query table to its correct size and reset all its elements
|
||||
g_cine->_zoneQuery.resize(NUM_MAX_ZONE);
|
||||
Common::fill(g_cine->_zoneQuery.begin(), g_cine->_zoneQuery.end(), 0);
|
||||
|
||||
setDefaultGameSpeed();
|
||||
_scriptInfo = setupOpcodes();
|
||||
|
||||
initLanguage(getLanguage());
|
||||
|
||||
if (getGameType() == Cine::GType_OS) {
|
||||
renderer = new OSRenderer;
|
||||
} else {
|
||||
renderer = new FWRenderer;
|
||||
}
|
||||
|
||||
renderer->initialize();
|
||||
forbidBgPalReload = 0;
|
||||
reloadBgPalOnNextFlip = 0;
|
||||
gfxFadeOutCompleted = 0;
|
||||
gfxFadeInRequested = 0;
|
||||
safeControlsLastAccessedMs = 0;
|
||||
lastSafeControlObjIdx = -1;
|
||||
currentDisk = 1;
|
||||
|
||||
collisionPage = new byte[320 * 200]();
|
||||
|
||||
// Clear part buffer as there's nothing loaded into it yet.
|
||||
// Its size will change when loading data into it with the loadPart function.
|
||||
g_cine->_partBuffer.clear();
|
||||
|
||||
if (getGameType() == Cine::GType_OS) {
|
||||
readVolCnf();
|
||||
}
|
||||
|
||||
loadTextData("texte.dat");
|
||||
|
||||
if (getGameType() == Cine::GType_OS && !(getFeatures() & GF_DEMO)) {
|
||||
loadPoldatDat("poldat.dat");
|
||||
loadErrmessDat("errmess.dat");
|
||||
}
|
||||
|
||||
// in case ScummVM engines can be restarted in the future
|
||||
g_cine->_scriptTable.clear();
|
||||
g_cine->_relTable.clear();
|
||||
g_cine->_objectScripts.clear();
|
||||
g_cine->_globalScripts.clear();
|
||||
g_cine->_bgIncrustList.clear();
|
||||
freeAnimDataTable();
|
||||
g_cine->_overlayList.clear();
|
||||
g_cine->_messageTable.clear();
|
||||
resetObjectTable();
|
||||
g_cine->_seqList.clear();
|
||||
|
||||
if (getGameType() == Cine::GType_OS) {
|
||||
disableSystemMenu = 1;
|
||||
} else {
|
||||
// WORKAROUND: We do not save this variable in FW's savegames.
|
||||
// Initializing this to 1, like we do it in the OS case, will
|
||||
// cause the menu disabled when loading from the launcher or
|
||||
// command line.
|
||||
// A proper fix here would be to save this variable in FW's saves.
|
||||
// Since it seems these are unversioned so far, there would be need
|
||||
// to properly add versioning to them first.
|
||||
//
|
||||
// Adding versioning to FW saves didn't solve this problem. Setting
|
||||
// disableSystemMenu according to the saved value still caused the
|
||||
// action menu (EXAMINE, TAKE, INVENTORY, ...) sometimes to be
|
||||
// disabled when it wasn't supposed to be disabled when
|
||||
// loading from the launcher or command line.
|
||||
disableSystemMenu = 0;
|
||||
}
|
||||
|
||||
var8 = 0;
|
||||
bgVar0 = 0;
|
||||
var2 = var3 = var4 = lastType20OverlayBgIdx = 0;
|
||||
musicIsPlaying = 0;
|
||||
currentDatName[0] = 0;
|
||||
_keyInputList.clear();
|
||||
|
||||
// Used for making sound effects work using Roland MT-32 and AdLib in
|
||||
// Operation Stealth after loading a savegame. The sound effects are loaded
|
||||
// in AUTO00.PRC using a combination of o2_loadAbs and o2_playSample(1, ...)
|
||||
// before o1_freePartRange(0, 200). In the original game AUTO00.PRC
|
||||
// was run when starting or restarting the game and one could not load a savegame
|
||||
// before passing the copy protection. Thus, we try to emulate that behaviour by
|
||||
// running at least part of AUTO00.PRC before loading a savegame.
|
||||
//
|
||||
// Confirmed that DOS and Atari ST versions do have these commands in their AUTO00.PRC files.
|
||||
// Confirmed that Amiga and demo versions do not have these commands in their AUTO00.PRC files.
|
||||
if (getGameType() == Cine::GType_OS && !(getFeatures() & GF_DEMO) &&
|
||||
(getPlatform() == Common::kPlatformDOS || getPlatform() == Common::kPlatformAtariST)) {
|
||||
loadPrc(BOOT_PRC_NAME);
|
||||
Common::strcpy_s(currentPrcName, BOOT_PRC_NAME);
|
||||
addScriptToGlobalScripts(BOOT_SCRIPT_INDEX);
|
||||
runOnlyUntilFreePartRangeFirst200 = true;
|
||||
executeGlobalScripts();
|
||||
}
|
||||
|
||||
_preLoad = false;
|
||||
if (ConfMan.hasKey("save_slot") && !_restartRequested) {
|
||||
Common::Error loadError = loadGameState(ConfMan.getInt("save_slot"));
|
||||
|
||||
if (loadError.getCode() == Common::kNoError)
|
||||
_preLoad = true;
|
||||
}
|
||||
|
||||
if (!_preLoad) {
|
||||
loadPrc(BOOT_PRC_NAME);
|
||||
Common::strcpy_s(currentPrcName, BOOT_PRC_NAME);
|
||||
setMouseCursor(MOUSE_CURSOR_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void CineEngine::showSplashScreen() {
|
||||
Common::File file;
|
||||
if (!file.open("sony.lbm"))
|
||||
return;
|
||||
|
||||
Image::IFFDecoder decoder;
|
||||
if (!decoder.loadStream(file))
|
||||
return;
|
||||
|
||||
const Graphics::Surface *surface = decoder.getSurface();
|
||||
if (surface->w == 640 && surface->h == 480) {
|
||||
initGraphics(640, 480);
|
||||
|
||||
const Graphics::Palette &palette = decoder.getPalette();
|
||||
g_system->getPaletteManager()->setPalette(palette.data(), 0, palette.size());
|
||||
|
||||
g_system->copyRectToScreen(surface->getPixels(), 640, 0, 0, 640, 480);
|
||||
g_system->updateScreen();
|
||||
|
||||
Common::EventManager *eventMan = g_system->getEventManager();
|
||||
|
||||
bool done = false;
|
||||
uint32 now = g_system->getMillis();
|
||||
|
||||
while (!done && g_system->getMillis() - now < 2000) {
|
||||
Common::Keymapper *keymapper = _eventMan->getKeymapper();
|
||||
keymapper->getKeymap("intro-shortcuts")->setEnabled(true);
|
||||
|
||||
Common::Event event;
|
||||
while (eventMan->pollEvent(event)) {
|
||||
if (event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START && event.customType == kActionExitSonyScreen) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if (shouldQuit())
|
||||
done = true;
|
||||
}
|
||||
keymapper->getKeymap("intro-shortcuts")->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
decoder.destroy();
|
||||
}
|
||||
|
||||
void CineEngine::sayText(const Common::String &text, Common::TextToSpeechManager::Action action) {
|
||||
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
|
||||
// _previousSaid is used to prevent the TTS from looping when sayText is called inside a loop,
|
||||
// for example when the cursor stays on a button. Without it when the text ends it would speak
|
||||
// the same text again.
|
||||
// _previousSaid is cleared when appropriate to allow for repeat requests
|
||||
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled") && text != _previousSaid) {
|
||||
if (getLanguage() == Common::DE_DEU) {
|
||||
// German translation encodes ß as 0x9e, but it's 0xe1 in codepage 850
|
||||
Common::String ttsMessage = text;
|
||||
ttsMessage.replace('\x9e', '\xe1');
|
||||
ttsMan->say(ttsMessage, action, Common::CodePage::kDos850);
|
||||
} else if (getLanguage() == Common::FR_FRA && getGameType() == GType_FW) {
|
||||
// French translation for Future Wars encodes ê as 0x97, but it's 0x88 in codepage 850
|
||||
Common::String ttsMessage = text;
|
||||
ttsMessage.replace('\x97', '\x88');
|
||||
ttsMan->say(ttsMessage, action, Common::CodePage::kDos850);
|
||||
} else {
|
||||
ttsMan->say(text, action, Common::CodePage::kDos850);
|
||||
}
|
||||
|
||||
_previousSaid = text;
|
||||
}
|
||||
}
|
||||
|
||||
void CineEngine::stopTextToSpeech() {
|
||||
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
|
||||
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled") && ttsMan->isSpeaking()) {
|
||||
ttsMan->stop();
|
||||
_previousSaid.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void CineEngine::mouseOverButton() {
|
||||
if (!_copyProtectionTextScreen && !_copyProtectionColorScreen) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 mouseX, mouseY, mouseButton;
|
||||
getMouseData(mouseUpdateStatus, &mouseButton, &mouseX, &mouseY);
|
||||
|
||||
int16 objIdx = getObjectUnderCursor(mouseX, mouseY);
|
||||
|
||||
if (objIdx != -1) {
|
||||
if (_copyProtectionTextScreen) {
|
||||
// Operation Stealth has other objects than just the "Ok" button in this screen
|
||||
if (getGameType() == GType_OS && _objectTable[objIdx].frame != 151) {
|
||||
return;
|
||||
}
|
||||
|
||||
sayText("Ok", Common::TextToSpeechManager::INTERRUPT);
|
||||
} else if (_copyProtectionColorScreen) {
|
||||
const char **colors;
|
||||
|
||||
if (getGameType() == GType_FW) {
|
||||
// The Amiga and Atari versions use a different copy protection screen from the DOS version
|
||||
// and don't have these color buttons
|
||||
// The only exception is the US Amiga version, which uses the color screen
|
||||
if (getPlatform() != Common::kPlatformDOS && getLanguage() != Common::EN_USA) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16 index = objIdx - 150;
|
||||
|
||||
if (index < 0 || index >= kNumOfFWColors) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_ttsLanguage) {
|
||||
case kEnglish:
|
||||
colors = copyProtectionColorsFWEnglish;
|
||||
break;
|
||||
case kFrench:
|
||||
colors = copyProtectionColorsFWFrench;
|
||||
break;
|
||||
case kGerman:
|
||||
colors = copyProtectionColorsFWGerman;
|
||||
break;
|
||||
case kSpanish:
|
||||
colors = copyProtectionColorsFWSpanish;
|
||||
break;
|
||||
default:
|
||||
colors = copyProtectionColorsFWEnglish;
|
||||
break;
|
||||
}
|
||||
sayText(colors[index], Common::TextToSpeechManager::INTERRUPT);
|
||||
} else {
|
||||
int16 index = objIdx - 240;
|
||||
|
||||
if (index < 0 || index >= kNumOfOSColors) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_ttsLanguage) {
|
||||
case kEnglish:
|
||||
colors = copyProtectionColorsOSEnglish;
|
||||
break;
|
||||
case kFrench:
|
||||
colors = copyProtectionColorsOSFrench;
|
||||
break;
|
||||
case kItalian:
|
||||
colors = copyProtectionColorsOSItalian;
|
||||
break;
|
||||
case kGerman:
|
||||
colors = copyProtectionColorsOSGerman;
|
||||
break;
|
||||
case kSpanish:
|
||||
colors = copyProtectionColorsOSSpanish;
|
||||
break;
|
||||
default:
|
||||
colors = copyProtectionColorsOSEnglish;
|
||||
break;
|
||||
}
|
||||
sayText(colors[index], Common::TextToSpeechManager::INTERRUPT);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_previousSaid.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Cine
|
||||
292
engines/cine/cine.h
Normal file
292
engines/cine/cine.h
Normal file
@@ -0,0 +1,292 @@
|
||||
/* 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 CINE_CINE_H
|
||||
#define CINE_CINE_H
|
||||
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/file.h"
|
||||
#include "common/util.h"
|
||||
#include "common/str.h"
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/random.h"
|
||||
#include "common/events.h"
|
||||
#include "common/text-to-speech.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
#include "cine/texte.h"
|
||||
#include "cine/rel.h"
|
||||
#include "cine/script.h"
|
||||
#include "cine/part.h"
|
||||
#include "cine/prc.h"
|
||||
#include "cine/msg.h"
|
||||
#include "cine/bg.h"
|
||||
#include "cine/pal.h"
|
||||
#include "cine/gfx.h"
|
||||
#include "cine/anim.h"
|
||||
#include "cine/bg_list.h"
|
||||
#include "cine/various.h"
|
||||
#include "cine/console.h"
|
||||
#include "cine/sound.h"
|
||||
#include "cine/detection.h"
|
||||
|
||||
//#define DUMP_SCRIPTS
|
||||
|
||||
/**
|
||||
* This is the namespace of the Cine engine.
|
||||
*
|
||||
* Status of this engine:
|
||||
*
|
||||
* This enigne has 2 generations Cinematique evo.1 and Cinematique evo.2
|
||||
* first generation is fairly complete, and second one is under development
|
||||
*
|
||||
* Cinematique evo.1 status:
|
||||
* The engine supports Future Wars and is basically complete with support of
|
||||
* all known game variants. Based on Yaz0r's engine.
|
||||
*
|
||||
* Cinematique evo.2 status:
|
||||
* This generation supports Operation Stealth, originally developed by Yaz0r,
|
||||
* for a french variant of the game which was said to be completable.
|
||||
* Later the work was renewed as part of GSoC'08, by Kari Salminen, but it has not
|
||||
* yet been finished. The game is not completable.
|
||||
*
|
||||
*
|
||||
* Games using this engine:
|
||||
*
|
||||
* Cinematique evo.1
|
||||
* - Future Wars
|
||||
*
|
||||
* Cinematique evo.2
|
||||
* - Operation Stealth
|
||||
*
|
||||
*/
|
||||
namespace Cine {
|
||||
|
||||
struct SeqListElement;
|
||||
|
||||
struct VolumeResource {
|
||||
char name[10];
|
||||
uint32 pNamesList;
|
||||
int16 diskNum;
|
||||
int32 sizeOfNamesList;
|
||||
};
|
||||
|
||||
typedef Common::HashMap<Common::String, Common::Array<VolumeResource> > StringToVolumeResourceArrayHashMap;
|
||||
|
||||
enum CINEAction {
|
||||
kActionNone,
|
||||
kActionMoveUp,
|
||||
kActionMoveDown,
|
||||
kActionMoveLeft,
|
||||
kActionMoveRight,
|
||||
kActionMoveUpLeft,
|
||||
kActionMoveUpRight,
|
||||
kActionMoveDownLeft,
|
||||
kActionMoveDownRight,
|
||||
kActionGameSpeedDefault,
|
||||
kActionGameSpeedSlower,
|
||||
kActionGameSpeedFaster,
|
||||
kActionExamine,
|
||||
kActionTake,
|
||||
kActionInventory,
|
||||
kActionUse,
|
||||
kActionActivate,
|
||||
kActionSpeak,
|
||||
kActionActionMenu,
|
||||
kActionSystemMenu,
|
||||
kActionCollisionPage,
|
||||
kActionMouseLeft,
|
||||
kActionMouseRight,
|
||||
kActionExitSonyScreen,
|
||||
kActionMenuOptionUp,
|
||||
kActionMenuOptionDown
|
||||
};
|
||||
|
||||
enum TTSLanguage {
|
||||
kEnglish = 0,
|
||||
kFrench = 1,
|
||||
kGerman = 2,
|
||||
kSpanish = 3,
|
||||
kItalian = 4
|
||||
};
|
||||
|
||||
class CineConsole;
|
||||
|
||||
class CineEngine : public Engine {
|
||||
|
||||
protected:
|
||||
// Engine APIs
|
||||
Common::Error run() override;
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
|
||||
void shutdown();
|
||||
|
||||
bool initGame();
|
||||
|
||||
public:
|
||||
CineEngine(OSystem *syst, const CINEGameDescription *gameDesc);
|
||||
~CineEngine() override;
|
||||
|
||||
void syncSoundSettings() override;
|
||||
|
||||
bool mayHave256Colors() const;
|
||||
int getGameType() const;
|
||||
uint32 getFeatures() const;
|
||||
Common::Language getLanguage() const;
|
||||
Common::Platform getPlatform() const;
|
||||
|
||||
bool loadSaveDirectory();
|
||||
void makeSystemMenu();
|
||||
int scummVMSaveLoadDialog(bool isSave);
|
||||
int modifyGameSpeed(int speedChange);
|
||||
void setDefaultGameSpeed();
|
||||
uint32 getTimerDelay() const;
|
||||
Common::Error loadGameState(int slot) override;
|
||||
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
|
||||
Common::String getSaveStateName(int slot) const override;
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
|
||||
void sayText(const Common::String &text, Common::TextToSpeechManager::Action action);
|
||||
void stopTextToSpeech();
|
||||
#ifdef USE_TTS
|
||||
void mouseOverButton();
|
||||
#endif
|
||||
|
||||
const CINEGameDescription *_gameDescription;
|
||||
Common::File _partFileHandle;
|
||||
|
||||
Common::RandomSource _rnd;
|
||||
|
||||
StringToVolumeResourceArrayHashMap _volumeEntriesMap;
|
||||
|
||||
TextHandler _textHandler;
|
||||
|
||||
bool _restartRequested;
|
||||
|
||||
Common::String _previousSaid;
|
||||
TTSLanguage _ttsLanguage;
|
||||
bool _copyProtectionTextScreen;
|
||||
bool _copyProtectionColorScreen;
|
||||
bool _saveInputMenuOpen;
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
void showSplashScreen();
|
||||
void resetEngine();
|
||||
bool checkSaveHeaderData(const ChunkHeader& hdr);
|
||||
bool loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFormat saveGameFormat, uint32 version);
|
||||
bool loadVersionedSaveFW(Common::SeekableReadStream &in);
|
||||
bool loadVersionedSaveOS(Common::SeekableReadStream &in);
|
||||
bool makeLoad(const Common::String &saveName);
|
||||
void writeSaveHeader(Common::OutSaveFile &out, uint32 headerId);
|
||||
void makeSaveFW(Common::OutSaveFile &out);
|
||||
void makeSaveOS(Common::OutSaveFile &out);
|
||||
void makeSave(const Common::String &saveFileName, uint32 playtime,
|
||||
Common::String desc, bool isAutosave);
|
||||
void mainLoop(int bootScriptIdx);
|
||||
void readVolCnf();
|
||||
Common::String getTargetSaveStateName(Common::String target, int slot) const;
|
||||
|
||||
bool _preLoad;
|
||||
int _timerDelayMultiplier;
|
||||
|
||||
public:
|
||||
// TODO: These are pseudo-global vars
|
||||
// They better belong to appropriate classes
|
||||
Common::Array<AnimData> _animDataTable;
|
||||
Common::List<BGIncrust> _bgIncrustList;
|
||||
Common::StringArray _messageTable;
|
||||
Common::Array<ObjectStruct> _objectTable;
|
||||
Common::List<overlay> _overlayList;
|
||||
Common::Array<PalEntry> _palArray;
|
||||
Common::Array<PartBuffer> _partBuffer;
|
||||
ScriptList _globalScripts;
|
||||
ScriptList _objectScripts;
|
||||
RawObjectScriptArray _relTable; ///< Object script bytecode table
|
||||
|
||||
/**
|
||||
* Global variables.
|
||||
* 255 of these are saved, but there's one more that's used for bypassing the copy protection.
|
||||
* In CineEngine::mainLoop(int bootScriptIdx) there's this code: globalVars[VAR_BYPASS_PROTECTION] = 0;
|
||||
* And as VAR_BYPASS_PROTECTION is 255 that's why we're allocating one more than we otherwise would.
|
||||
*/
|
||||
ScriptVars _globalVars;
|
||||
RawScriptArray _scriptTable; ///< Table of script bytecode
|
||||
FWScriptInfo *_scriptInfo;
|
||||
|
||||
Common::Array<int16> _zoneData;
|
||||
Common::Array<uint16> _zoneQuery; ///< Only exists in Operation Stealth
|
||||
|
||||
Common::List<SeqListElement> _seqList;
|
||||
|
||||
Common::String _commandBuffer;
|
||||
Common::Array<Common::KeyState> _keyInputList;
|
||||
Common::Array<Common::CustomEventType> _actionList;
|
||||
};
|
||||
|
||||
extern CineEngine *g_cine;
|
||||
extern Sound *g_sound;
|
||||
|
||||
#define BOOT_PRC_NAME "AUTO00.PRC"
|
||||
#define BOOT_SCRIPT_INDEX 1
|
||||
#define COPY_PROT_FAIL_PRC_NAME "L201.ANI"
|
||||
|
||||
enum {
|
||||
// Both FW and OS
|
||||
VAR_MOUSE_X_POS = 249,
|
||||
VAR_MOUSE_Y_POS = 250,
|
||||
// FW only
|
||||
VAR_MOUSE_X_MODE = 253,
|
||||
VAR_MOUSE_Y_MODE = 251,
|
||||
// OS only
|
||||
VAR_MOUSE_X_POS_2ND = 251, // Many times used in conjunction with VAR_MOUSE_X_POS
|
||||
VAR_MOUSE_Y_POS_2ND = 252, // Many times used in conjunction with VAR_MOUSE_Y_POS
|
||||
VAR_BYPASS_PROTECTION = 255,
|
||||
VAR_LOW_MEMORY = 0
|
||||
};
|
||||
|
||||
enum {
|
||||
MOUSE_CURSOR_NORMAL = 0,
|
||||
MOUSE_CURSOR_DISK,
|
||||
MOUSE_CURSOR_CROSS
|
||||
};
|
||||
|
||||
enum {
|
||||
kCineDebugScript = 1,
|
||||
kCineDebugPart,
|
||||
kCineDebugSound,
|
||||
kCineDebugCollision,
|
||||
};
|
||||
|
||||
enum {
|
||||
kCmpEQ = (1 << 0),
|
||||
kCmpGT = (1 << 1),
|
||||
kCmpLT = (1 << 2)
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
3
engines/cine/configure.engine
Normal file
3
engines/cine/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 cine "Cinematique evo 1" yes "" "" "" "midi"
|
||||
66
engines/cine/console.cpp
Normal file
66
engines/cine/console.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/* 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 "cine/console.h"
|
||||
#include "cine/cine.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
bool labyrinthCheat;
|
||||
bool hacksEnabled;
|
||||
|
||||
CineConsole::CineConsole(CineEngine *vm) : GUI::Debugger(), _vm(vm) {
|
||||
assert(_vm);
|
||||
registerCmd("labyrinthCheat", WRAP_METHOD(CineConsole, Cmd_LabyrinthCheat));
|
||||
registerCmd("disableLabyrinthCheat", WRAP_METHOD(CineConsole, Cmd_DisableLabyrinthCheat));
|
||||
registerCmd("disableHacks", WRAP_METHOD(CineConsole, Cmd_DisableHacks));
|
||||
registerCmd("enableHacks", WRAP_METHOD(CineConsole, Cmd_EnableHacks));
|
||||
|
||||
labyrinthCheat = false;
|
||||
hacksEnabled = true;
|
||||
}
|
||||
|
||||
CineConsole::~CineConsole() {
|
||||
}
|
||||
|
||||
// Activate Cheat during Scene 6 Labyrinth chased by Guards in Otto's Mansion
|
||||
// This puzzle is hard, especially without save/load so this will aid playtesting.
|
||||
bool CineConsole::Cmd_LabyrinthCheat(int argc, const char **argv) {
|
||||
labyrinthCheat = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CineConsole::Cmd_DisableLabyrinthCheat(int argc, const char **argv) {
|
||||
labyrinthCheat = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CineConsole::Cmd_DisableHacks(int argc, const char **argv) {
|
||||
hacksEnabled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CineConsole::Cmd_EnableHacks(int argc, const char **argv) {
|
||||
hacksEnabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
50
engines/cine/console.h
Normal file
50
engines/cine/console.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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 CINE_CONSOLE_H
|
||||
#define CINE_CONSOLE_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
extern bool labyrinthCheat;
|
||||
extern bool hacksEnabled;
|
||||
|
||||
class CineEngine;
|
||||
|
||||
class CineConsole : public GUI::Debugger {
|
||||
public:
|
||||
CineConsole(CineEngine *vm);
|
||||
~CineConsole(void) override;
|
||||
|
||||
private:
|
||||
CineEngine *_vm;
|
||||
|
||||
bool Cmd_LabyrinthCheat(int argc, const char **argv);
|
||||
bool Cmd_DisableLabyrinthCheat(int argc, const char **argv);
|
||||
bool Cmd_DisableHacks(int argc, const char **argv);
|
||||
bool Cmd_EnableHacks(int argc, const char **argv);
|
||||
};
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
7
engines/cine/credits.pl
Normal file
7
engines/cine/credits.pl
Normal file
@@ -0,0 +1,7 @@
|
||||
begin_section("Cine");
|
||||
add_person("Vincent Hamm", "yaz0r", "(retired)");
|
||||
add_person("Paweł Kołodziejski", "aquadran", "");
|
||||
add_person("Gregory Montoir", "cyx", "(retired)");
|
||||
add_person("Kari Salminen", "Buddha^", "");
|
||||
add_person("Eugene Sandulenko", "sev", "");
|
||||
end_section();
|
||||
68
engines/cine/detection.cpp
Normal file
68
engines/cine/detection.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 "base/plugins.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "cine/detection.h"
|
||||
#include "cine/cine.h"
|
||||
|
||||
static const PlainGameDescriptor cineGames[] = {
|
||||
{"fw", "Future Wars"},
|
||||
{"os", "Operation Stealth"},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
#include "cine/detection_tables.h"
|
||||
|
||||
static const DebugChannelDef debugFlagList[] = {
|
||||
{Cine::kCineDebugScript, "Script", "Script debug level"},
|
||||
{Cine::kCineDebugPart, "Part", "Part debug level"},
|
||||
{Cine::kCineDebugSound, "Sound", "Sound debug level"},
|
||||
{Cine::kCineDebugCollision, "Collision", "Collision debug level"},
|
||||
DEBUG_CHANNEL_END
|
||||
};
|
||||
|
||||
class CineMetaEngineDetection : public AdvancedMetaEngineDetection<Cine::CINEGameDescription> {
|
||||
public:
|
||||
CineMetaEngineDetection() : AdvancedMetaEngineDetection(Cine::gameDescriptions, cineGames) {
|
||||
_guiOptions = GUIO4(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_TRANSPARENT_DIALOG_BOXES, GAMEOPTION_TTS);
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "cine";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Cinematique evo 1";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "Cinematique evo 1 (C) Delphine Software";
|
||||
}
|
||||
|
||||
const DebugChannelDef *getDebugChannels() const override {
|
||||
return debugFlagList;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN_STATIC(CINE_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, CineMetaEngineDetection);
|
||||
56
engines/cine/detection.h
Normal file
56
engines/cine/detection.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 CINE_DETECTION_H
|
||||
#define CINE_DETECTION_H
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
enum CineGameType {
|
||||
GType_FW = 1,
|
||||
GType_OS
|
||||
};
|
||||
|
||||
enum CineGameFeatures {
|
||||
GF_CD = 1 << 0,
|
||||
GF_DEMO = 1 << 1,
|
||||
GF_ALT_FONT = 1 << 2,
|
||||
GF_CRYPTED_BOOT_PRC = 1 << 3
|
||||
};
|
||||
|
||||
struct CINEGameDescription {
|
||||
AD_GAME_DESCRIPTION_HELPERS(desc);
|
||||
|
||||
ADGameDescription desc;
|
||||
|
||||
int gameType;
|
||||
uint32 features;
|
||||
};
|
||||
|
||||
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1
|
||||
#define GAMEOPTION_TRANSPARENT_DIALOG_BOXES GUIO_GAMEOPTIONS2
|
||||
#define GAMEOPTION_TTS GUIO_GAMEOPTIONS3
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif // CINE_DETECTION_H
|
||||
580
engines/cine/detection_tables.h
Normal file
580
engines/cine/detection_tables.h
Normal file
@@ -0,0 +1,580 @@
|
||||
/* 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 Cine {
|
||||
|
||||
static const CINEGameDescription gameDescriptions[] = {
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "61d003202d301c29dd399acfb1354310"),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
// This is a CD version of Future Wars published by Sony.
|
||||
// This version has a crypted AUTO00.PRC.
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"Sony CD version",
|
||||
AD_ENTRY2s("AUTO00.PRC", "4fe1e7930b38e3c63f0f2474d471bf8f", AD_NO_SIZE,
|
||||
"PART01", "61d003202d301c29dd399acfb1354310", AD_NO_SIZE),
|
||||
Common::EN_USA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO0()
|
||||
},
|
||||
GType_FW,
|
||||
GF_CD | GF_CRYPTED_BOOT_PRC,
|
||||
},
|
||||
|
||||
{
|
||||
// This is the Future Wars CD version
|
||||
// with a French translation patch (#12490).
|
||||
{
|
||||
"fw",
|
||||
"Sony CD version with French translation patch",
|
||||
AD_ENTRY2s("AUTO00.PRC", "4fe1e7930b38e3c63f0f2474d471bf8f", AD_NO_SIZE,
|
||||
"PART01", "5d1acb97abe9591f9008e00d07add95a", AD_NO_SIZE),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO0()
|
||||
},
|
||||
GType_FW,
|
||||
GF_CD | GF_CRYPTED_BOOT_PRC,
|
||||
},
|
||||
|
||||
{
|
||||
// This is the version included in the UK "Classic Collection"
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "91d7271155520eae6915a9dd2dac120c"),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "f5e98fcca3fb5e7afa284c81c39d8b14"),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_FW,
|
||||
GF_ALT_FONT,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "570109f965c7f53984b98c83d86eb206"),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_FW,
|
||||
GF_ALT_FONT,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "5d1acb97abe9591f9008e00d07add95a"),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "57afd280b598b4180fda6689fbedc4b8"),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
{ // Amiga "Interplay" labeled version
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "a17a5eb15200c63276d486a88263ccd0"),
|
||||
Common::EN_USA,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "3a87a913e0e33963a48a7f822ca0eb0e"),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_FW,
|
||||
GF_ALT_FONT,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "5ad0007ccd5f7b3dd6b15ea7f281f9e1"),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "460f2da8793bc581a2d4b6fc19ccb5ae"),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "1c8e5207743172134409ac58860021af"),
|
||||
Common::IT_ITA,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"Demo",
|
||||
AD_ENTRY2s("demo", "0f50767cd964e302d3af0ba2528df8c4", AD_NO_SIZE,
|
||||
"demo.prc", "d2ac3a743d288359c63644ea7071edae", AD_NO_SIZE),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_DEMO,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "36050db13af57e462ca1adc4df99de4e"),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformAtariST,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"fw",
|
||||
"",
|
||||
AD_ENTRY1("part01", "ef245573b7dab0d4825ceb98e37cef4d"),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformAtariST,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_FW,
|
||||
0,
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// ___ _ _ ____ _ _ _ _ //
|
||||
// / _ \ _ __ ___ _ __ __ _| |_(_) ___ _ __ / ___|| |_ ___ __ _| | |_| |__ //
|
||||
// | | | | '_ \ / _ \ '__/ _` | __| |/ _ \| '_ \ \___ \| __/ _ \/ _` | | __| '_ \ //
|
||||
// | |_| | |_) | __/ | | (_| | |_| | (_) | | | | ___) | || __/ (_| | | |_| | | | //
|
||||
// \___/| .__/ \___|_| \__,_|\__|_|\___/|_| |_| |____/ \__\___|\__,_|_|\__|_| |_| //
|
||||
// |_| //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"256 colors",
|
||||
AD_ENTRY1("procs00", "d6752e7d25924cb866b61eb7cb0c8b56"),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
// This is a 16 color PC version (It came on three 720kB 3.5" disks).
|
||||
// The protagonist is named John Glames in this version.
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs1", "9629129b86979fa592c1787385bf3695"),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs1", "d8c3a9d05a63e4cfa801826a7063a126"),
|
||||
Common::EN_USA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"256 colors",
|
||||
AD_ENTRY1("procs00", "862a75d76fb7fffec30e52be9ad1c474"),
|
||||
Common::EN_USA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
GF_CD,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs1", "39b91ae35d1297ce0a76a1a803ca1593"),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs1", "74c2dabd9d212525fca8875a5f6d8994"),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"256 colors",
|
||||
AD_ENTRY2s("procs1", "74c2dabd9d212525fca8875a5f6d8994", AD_NO_SIZE,
|
||||
"sds1", "75443ba39cdc95667e07d7118e5c151c", AD_NO_SIZE),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
GF_CD,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"256 colors",
|
||||
AD_ENTRY1("procs00", "f143567f08cfd1a9b1c9a41c89eadfef"),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{ // Submitted by Kurufinwe21 in #11617 (16 color French floppy version)
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1s("procs1", "3f9edde60ccb380f716942c5b059d1d5", 14116),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{ // Submitted by laenion in #11466 (German Atari ST version)
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1s("procs1", "b67af92a92ac5fd4add55893c15df76e", 63402),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformAtariST,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs1", "da066e6b8dd93f2502c2a3755f08dc12"),
|
||||
Common::IT_ITA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{ // Submitted by Nyarlathotep7777 in #12812 (Italian Amiga version)
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1s("procs1", "d7458be2b14d77410e6330148ca6c371", 61682),
|
||||
Common::IT_ITA,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"Demo",
|
||||
AD_ENTRY1("demo_os", "043859e4cfe3977ad95b6efd00b21c62"),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_DEMO,
|
||||
GUIO0()
|
||||
},
|
||||
GType_OS,
|
||||
GF_DEMO,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs0", "a9da5531ead0ebf9ad387fa588c0cbb0"),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"alt",
|
||||
AD_ENTRY1("procs0", "8a429ced2f4acff8a15ae125174042e8"),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs0", "d5f27e33fc29c879f36f15b86ccfa58c"),
|
||||
Common::EN_USA,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs0", "8b7dce249821d3a62b314399c4334347"),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs0", "35fc295ddd0af9da932d256ba799a4b0"),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs0", "d4ea4a97e01fa67ea066f9e785050ed2"),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"Demo",
|
||||
AD_ENTRY1("demo_os", "dfc30c6a57998a56e8980f7ea3413867"),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_DEMO,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_OS,
|
||||
GF_DEMO,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs0", "1501d5ae364b2814a33ed19347c3fcae"),
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformAtariST,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"os",
|
||||
"",
|
||||
AD_ENTRY1("procs0", "2148d25de3219dd4a36580ca735d0afa"),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformAtariST,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
GType_OS,
|
||||
0,
|
||||
},
|
||||
|
||||
{ AD_TABLE_END_MARKER, 0, 0 }
|
||||
};
|
||||
|
||||
} // End of namespace Cine
|
||||
2967
engines/cine/gfx.cpp
Normal file
2967
engines/cine/gfx.cpp
Normal file
File diff suppressed because it is too large
Load Diff
346
engines/cine/gfx.h
Normal file
346
engines/cine/gfx.h
Normal file
@@ -0,0 +1,346 @@
|
||||
/* 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 CINE_GFX_H
|
||||
#define CINE_GFX_H
|
||||
|
||||
#include "common/noncopyable.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/stack.h"
|
||||
#include "cine/object.h"
|
||||
#include "cine/bg_list.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
extern byte *collisionPage;
|
||||
static const int kCollisionPageBgIdxAlias = 8;
|
||||
|
||||
enum BackBufferSource {
|
||||
BEFORE_OPENING_MENU = 0,
|
||||
BEFORE_TAKING_THUMBNAIL,
|
||||
MAX_BACK_BUFFER_SOURCES
|
||||
};
|
||||
|
||||
/**
|
||||
* Background with palette
|
||||
*/
|
||||
struct palBg {
|
||||
byte *bg; ///< Background data
|
||||
Cine::Palette pal; ///< Background color palette
|
||||
char name[15]; ///< Background filename
|
||||
|
||||
/** @brief Default constructor. */
|
||||
palBg() : bg(NULL), pal(), name() {
|
||||
// Make sure the name is empty (Maybe this is not needed?)
|
||||
memset(this->name, 0, sizeof(this->name));
|
||||
}
|
||||
|
||||
/** @brief Clears the struct (Releases allocated memory etc). */
|
||||
void clear() {
|
||||
// In Operation Stealth the 9th background is sometimes aliased to
|
||||
// the collision page so we should take care not to double delete it
|
||||
// (The collision page is deleted elsewhere).
|
||||
if (this->bg != collisionPage) {
|
||||
delete[] this->bg;
|
||||
}
|
||||
this->bg = NULL;
|
||||
this->pal.clear();
|
||||
memset(this->name, 0, sizeof(this->name));
|
||||
}
|
||||
};
|
||||
|
||||
class FWRenderer;
|
||||
|
||||
class Menu {
|
||||
public:
|
||||
enum Type {
|
||||
kSelectionMenu,
|
||||
kTextInputMenu
|
||||
};
|
||||
|
||||
Menu(Type t) : _type(t) {}
|
||||
virtual ~Menu() {}
|
||||
|
||||
Type getType() const { return _type; }
|
||||
|
||||
virtual void drawMenu(FWRenderer &r, bool top) = 0;
|
||||
private:
|
||||
const Type _type;
|
||||
};
|
||||
|
||||
class SelectionMenu : public Menu {
|
||||
public:
|
||||
SelectionMenu(Common::Point p, int width, Common::StringArray elements);
|
||||
|
||||
int getElementCount() const { return _elements.size(); }
|
||||
|
||||
void setSelection(int selection);
|
||||
|
||||
void drawMenu(FWRenderer &r, bool top) override;
|
||||
private:
|
||||
const Common::Point _pos;
|
||||
const int _width;
|
||||
const Common::StringArray _elements;
|
||||
|
||||
int _selection;
|
||||
};
|
||||
|
||||
class TextInputMenu : public Menu {
|
||||
public:
|
||||
TextInputMenu(Common::Point p, int width, const char *info);
|
||||
|
||||
void setInput(const char *input, int cursor);
|
||||
|
||||
void drawMenu(FWRenderer &r, bool top) override;
|
||||
private:
|
||||
const Common::Point _pos;
|
||||
const int _width;
|
||||
const Common::String _info;
|
||||
|
||||
Common::String _input;
|
||||
int _cursor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Future Wars renderer
|
||||
*
|
||||
* Screen backbuffer is not cleared between frames.
|
||||
*/
|
||||
class FWRenderer : public Common::NonCopyable {
|
||||
// TODO: Consider getting rid of this
|
||||
friend class SelectionMenu;
|
||||
friend class TextInputMenu;
|
||||
private:
|
||||
byte * _savedBackBuffers[MAX_BACK_BUFFER_SOURCES];
|
||||
byte *_background; ///< Current background
|
||||
char _bgName[13]; ///< Background filename
|
||||
|
||||
Common::String _cmd; ///< Player command string
|
||||
|
||||
protected:
|
||||
static const int _screenSize = 320 * 200; ///< Screen size
|
||||
static const int _screenWidth = 320; ///< Screen width
|
||||
static const int _screenHeight = 200; ///< Screen height
|
||||
|
||||
byte *_backBuffer; ///< Screen backbuffer
|
||||
Cine::Palette _backupPal; ///< The backup color palette
|
||||
Cine::Palette _activePal; ///< The active color palette
|
||||
Common::Stack<Menu *> _menuStack; ///< All displayed menus
|
||||
int _changePal; ///< Load active palette to video backend on next frame
|
||||
bool _showCollisionPage; ///< Should we show the collision page instead of the back buffer? Used for debugging.
|
||||
uint32 _fadeToBlackLastCalledMs;
|
||||
|
||||
virtual const Cine::Palette& getFadeInSourcePalette();
|
||||
void fillSprite(const ObjectStruct &obj, uint8 color = 0);
|
||||
void drawMaskedSprite(const ObjectStruct &obj, const byte *mask);
|
||||
virtual void drawSprite(const ObjectStruct &obj);
|
||||
|
||||
int drawMessage(const char *str, int x, int y, int width, int color, bool draw = true);
|
||||
void drawPlainBox(int x, int y, int width, int height, byte color);
|
||||
byte transparentDialogBoxStartColor();
|
||||
void drawTransparentBox(int x, int y, int width, int height);
|
||||
void drawBorder(int x, int y, int width, int height, byte color);
|
||||
void drawDoubleBorder(int x, int y, int width, int height, byte color);
|
||||
virtual int drawChar(char character, int x, int y, bool draw = true);
|
||||
virtual int undrawChar(char character, int x, int y);
|
||||
void drawLine(int x, int y, int width, int height, byte color);
|
||||
void remaskSprite(byte *mask, Common::List<overlay>::iterator it);
|
||||
virtual void drawBackground();
|
||||
virtual void clearBackBuffer();
|
||||
virtual void removeSavedBackBuffers();
|
||||
|
||||
virtual void renderOverlay(const Common::List<overlay>::iterator &it);
|
||||
void drawOverlays();
|
||||
virtual void blit(bool useCollisionPage);
|
||||
|
||||
public:
|
||||
uint16 _messageBg; ///< Message box background color
|
||||
uint16 _cmdY; ///< Player command string position on screen
|
||||
|
||||
FWRenderer();
|
||||
virtual ~FWRenderer();
|
||||
|
||||
virtual bool initialize();
|
||||
|
||||
/** Test if renderer is ready to draw */
|
||||
virtual bool ready() { return _background != NULL; }
|
||||
virtual unsigned int currentBg() { return 0; };
|
||||
virtual unsigned int scrollBg() { return 0; }
|
||||
virtual bool useTransparentDialogBoxes();
|
||||
|
||||
virtual void clear();
|
||||
|
||||
void drawFrame(bool wait = false);
|
||||
void drawCommand();
|
||||
void setCommand(Common::String cmd);
|
||||
Common::String getCommand();
|
||||
virtual void blit();
|
||||
virtual void blitBackBuffer();
|
||||
|
||||
virtual void incrustMask(const BGIncrust &incrust, uint8 color = 0);
|
||||
virtual void incrustSprite(const BGIncrust &incrust);
|
||||
|
||||
virtual bool hasSavedBackBuffer(BackBufferSource source);
|
||||
|
||||
/** Saves back buffer content without palette. */
|
||||
virtual void saveBackBuffer(BackBufferSource source);
|
||||
|
||||
virtual void popSavedBackBuffer(BackBufferSource source);
|
||||
|
||||
/** Restores back buffer content without palette. */
|
||||
virtual void restoreSavedBackBuffer(BackBufferSource source);
|
||||
|
||||
virtual void removeSavedBackBuffer(BackBufferSource source);
|
||||
|
||||
virtual int16 addBackground(const char *bgName, uint16 bgIdx);
|
||||
virtual void loadBg16(const byte *bg, const char *name, unsigned int idx = 0);
|
||||
virtual void loadCt16(const byte *ct, const char *name);
|
||||
virtual void loadBg256(const byte *bg, const char *name, unsigned int idx = 0);
|
||||
virtual void loadCt256(const byte *ct, const char *name);
|
||||
virtual void selectBg(unsigned int idx);
|
||||
virtual void selectScrollBg(unsigned int idx);
|
||||
virtual void setScroll(unsigned int shift);
|
||||
virtual uint getScroll() const;
|
||||
virtual void removeBg(unsigned int idx);
|
||||
virtual void saveBgNames(Common::OutSaveFile &fHandle);
|
||||
virtual const char *getBgName(uint idx = 0) const;
|
||||
|
||||
virtual void setBlackPalette(bool updateChangePal);
|
||||
virtual void setPalette();
|
||||
virtual void restorePalette(Common::SeekableReadStream &fHandle, int version);
|
||||
virtual void savePalette(Common::OutSaveFile &fHandle);
|
||||
virtual void rotatePalette(int firstIndex, int lastIndex, int mode);
|
||||
virtual void transformPalette(int first, int last, int r, int g, int b);
|
||||
|
||||
void pushMenu(Menu *menu);
|
||||
Menu *popMenu();
|
||||
void clearMenuStack();
|
||||
|
||||
virtual uint fadeDelayMs();
|
||||
virtual uint fadeToBlackMinMs();
|
||||
virtual void fadeToBlack();
|
||||
virtual void fadeFromBlack();
|
||||
void showCollisionPage(bool state);
|
||||
|
||||
void drawString(const char *string, byte param);
|
||||
int getStringWidth(const char *str);
|
||||
};
|
||||
|
||||
/**
|
||||
* Operation Stealth renderer
|
||||
*/
|
||||
class OSRenderer : public FWRenderer {
|
||||
private:
|
||||
Common::Array<palBg> _bgTable; ///< Table of backgrounds loaded into renderer (Maximum is 9)
|
||||
unsigned int _currentBg; ///< Current background
|
||||
unsigned int _scrollBg; ///< Current scroll background
|
||||
unsigned int _bgShift; ///< Background shift
|
||||
|
||||
protected:
|
||||
void setBackground8ToCollisionPage();
|
||||
const Cine::Palette& getFadeInSourcePalette() override;
|
||||
void drawSprite(const ObjectStruct &obj) override;
|
||||
void drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 width, int16 height, byte *page, int16 x, int16 y, byte transparentColor, byte bpp);
|
||||
int drawChar(char character, int x, int y, bool draw = true) override;
|
||||
void drawBackground() override;
|
||||
void renderOverlay(const Common::List<overlay>::iterator &it) override;
|
||||
|
||||
public:
|
||||
OSRenderer();
|
||||
~OSRenderer() override;
|
||||
|
||||
bool initialize() override;
|
||||
|
||||
/** Test if renderer is ready to draw */
|
||||
bool ready() override { return _bgTable[_currentBg].bg != NULL; }
|
||||
unsigned int currentBg() override { return _currentBg; };
|
||||
unsigned int scrollBg() override { return _scrollBg; }
|
||||
|
||||
void clear() override;
|
||||
|
||||
void incrustMask(const BGIncrust &incrust, uint8 color = 0) override;
|
||||
void incrustSprite(const BGIncrust &incrust) override;
|
||||
|
||||
int16 addBackground(const char *bgName, uint16 bgIdx) override;
|
||||
void loadBg16(const byte *bg, const char *name, unsigned int idx = 0) override;
|
||||
void loadCt16(const byte *ct, const char *name) override;
|
||||
void loadBg256(const byte *bg, const char *name, unsigned int idx = 0) override;
|
||||
void loadCt256(const byte *ct, const char *name) override;
|
||||
void selectBg(unsigned int idx) override;
|
||||
void selectScrollBg(unsigned int idx) override;
|
||||
void setScroll(unsigned int shift) override;
|
||||
uint getScroll() const override;
|
||||
void removeBg(unsigned int idx) override;
|
||||
void saveBgNames(Common::OutSaveFile &fHandle) override;
|
||||
const char *getBgName(uint idx = 0) const override;
|
||||
|
||||
void restorePalette(Common::SeekableReadStream &fHandle, int version) override;
|
||||
void savePalette(Common::OutSaveFile &fHandle) override;
|
||||
void rotatePalette(int firstIndex, int lastIndex, int mode) override;
|
||||
void transformPalette(int first, int last, int r, int g, int b) override;
|
||||
};
|
||||
|
||||
void gfxDrawSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy);
|
||||
|
||||
extern FWRenderer *renderer;
|
||||
|
||||
void setMouseCursor(int cursor);
|
||||
void gfxCopyPage(byte *source, byte *dest);
|
||||
|
||||
void transformPaletteRange(byte startColor, byte numColor, int8 r, int8 g, int8 b);
|
||||
void gfxFlipPage();
|
||||
|
||||
void gfxDrawMaskedSprite(const byte *ptr, const byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y);
|
||||
void gfxFillSprite(const byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0);
|
||||
|
||||
void gfxUpdateSpriteMask(byte *destMask, int16 x, int16 y, int16 width, int16 height, const byte *maskPtr, int16 xm, int16 ym, int16 maskWidth, int16 maskHeight);
|
||||
|
||||
void gfxDrawLine(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
|
||||
void gfxDrawPlainBox(int16 x1, int16 y1, int16 x2, int16 y2, byte color);
|
||||
|
||||
void gfxResetPage(byte *pagePtr);
|
||||
|
||||
int16 gfxGetBit(int16 x, int16 y, const byte *ptr, int16 width);
|
||||
byte gfxGetColor(int16 x, int16 y, const byte *ptr, int16 width);
|
||||
|
||||
void gfxResetRawPage(byte *pageRaw);
|
||||
void gfxConvertSpriteToRaw(byte *dst, const byte *src, uint16 w, uint16 h);
|
||||
void gfxCopyRawPage(byte *source, byte *dest);
|
||||
void gfxFlipRawPage(byte *frontBuffer);
|
||||
void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
|
||||
void gfxDrawPlainBoxRaw(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
|
||||
void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y);
|
||||
void maskBgOverlay(int targetBgIdx, const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
|
||||
|
||||
void fadeFromBlack();
|
||||
void fadeToBlack();
|
||||
|
||||
//void gfxDrawMaskedSprite(byte *param1, byte *param2, byte *param3, byte *param4, int16 param5);
|
||||
void gfxWaitVBL();
|
||||
void gfxRedrawMouseCursor();
|
||||
|
||||
void blitScreen(byte *frontBuffer, byte *backbuffer);
|
||||
void blitRawScreen(byte *frontBuffer);
|
||||
void flip();
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
571
engines/cine/main_loop.cpp
Normal file
571
engines/cine/main_loop.cpp
Normal file
@@ -0,0 +1,571 @@
|
||||
/* 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"
|
||||
#include "common/events.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "cine/main_loop.h"
|
||||
#include "cine/object.h"
|
||||
#include "cine/various.h"
|
||||
#include "cine/bg_list.h"
|
||||
#include "cine/sound.h"
|
||||
|
||||
#include "backends/audiocd/audiocd.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
struct MouseStatusStruct {
|
||||
int left;
|
||||
int right;
|
||||
};
|
||||
|
||||
MouseStatusStruct mouseData;
|
||||
|
||||
uint16 mouseRight = 0;
|
||||
uint16 mouseLeft = 0;
|
||||
|
||||
uint16 mouseUpdateStatus;
|
||||
uint16 dummyU16;
|
||||
|
||||
static void processEvent(Common::Event &event) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
mouseLeft = 1;
|
||||
break;
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
mouseRight = 1;
|
||||
break;
|
||||
case Common::EVENT_MBUTTONDOWN:
|
||||
mouseLeft = mouseRight = 1;
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
mouseLeft = 0;
|
||||
break;
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
mouseRight = 0;
|
||||
break;
|
||||
case Common::EVENT_MBUTTONUP:
|
||||
mouseLeft = mouseRight = 0;
|
||||
break;
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
#ifdef USE_TTS
|
||||
g_cine->mouseOverButton();
|
||||
#endif
|
||||
break;
|
||||
case Common::EVENT_WHEELUP:
|
||||
g_cine->_actionList.push_back(Common::CustomEventType(kActionMenuOptionUp));
|
||||
break;
|
||||
case Common::EVENT_WHEELDOWN:
|
||||
g_cine->_actionList.push_back(Common::CustomEventType(kActionMenuOptionDown));
|
||||
break;
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
|
||||
g_cine->_actionList.push_back(event.customType);
|
||||
switch (event.customType) {
|
||||
case kActionMouseLeft:
|
||||
if (allowPlayerInput) {
|
||||
mouseLeft = 1;
|
||||
}
|
||||
break;
|
||||
case kActionMouseRight:
|
||||
if (allowPlayerInput) {
|
||||
mouseRight = 1;
|
||||
}
|
||||
break;
|
||||
case kActionExamine:
|
||||
if (allowPlayerInput) {
|
||||
playerCommand = 0; // EXAMINE
|
||||
makeCommandLine();
|
||||
}
|
||||
break;
|
||||
case kActionTake:
|
||||
if (allowPlayerInput) {
|
||||
playerCommand = 1; // TAKE
|
||||
makeCommandLine();
|
||||
}
|
||||
break;
|
||||
case kActionInventory:
|
||||
if (allowPlayerInput && !inMenu) {
|
||||
playerCommand = 2; // INVENTORY
|
||||
g_cine->sayText(defaultActionCommand[playerCommand], Common::TextToSpeechManager::INTERRUPT);
|
||||
makeCommandLine();
|
||||
}
|
||||
break;
|
||||
case kActionUse:
|
||||
if (allowPlayerInput && !inMenu) {
|
||||
playerCommand = 3; // USE
|
||||
g_cine->sayText(defaultActionCommand[playerCommand], Common::TextToSpeechManager::INTERRUPT);
|
||||
makeCommandLine();
|
||||
}
|
||||
break;
|
||||
case kActionActivate:
|
||||
if (allowPlayerInput) {
|
||||
playerCommand = 4; // ACTIVATE
|
||||
makeCommandLine();
|
||||
}
|
||||
break;
|
||||
case kActionSpeak:
|
||||
if (allowPlayerInput) {
|
||||
playerCommand = 5; // SPEAK
|
||||
makeCommandLine();
|
||||
}
|
||||
break;
|
||||
case kActionActionMenu:
|
||||
if (allowPlayerInput && !inMenu) {
|
||||
makeActionMenu();
|
||||
makeCommandLine();
|
||||
}
|
||||
break;
|
||||
case kActionSystemMenu:
|
||||
if (!inMenu) {
|
||||
g_cine->makeSystemMenu();
|
||||
}
|
||||
break;
|
||||
case kActionCollisionPage:
|
||||
renderer->showCollisionPage(true);
|
||||
break;
|
||||
case kActionGameSpeedDefault:
|
||||
g_cine->setDefaultGameSpeed();
|
||||
break;
|
||||
case kActionGameSpeedSlower:
|
||||
g_cine->modifyGameSpeed(-1); // Slower
|
||||
break;
|
||||
case kActionGameSpeedFaster:
|
||||
g_cine->modifyGameSpeed(+1); // Faster
|
||||
break;
|
||||
case kActionMoveLeft:
|
||||
moveUsingKeyboard(-1, 0); // Left
|
||||
break;
|
||||
case kActionMoveRight:
|
||||
moveUsingKeyboard(+1, 0); // Right
|
||||
break;
|
||||
case kActionMoveUp:
|
||||
moveUsingKeyboard(0, +1); // Up
|
||||
break;
|
||||
case kActionMoveDown:
|
||||
moveUsingKeyboard(0, -1); // Down
|
||||
break;
|
||||
case kActionMoveUpRight:
|
||||
moveUsingKeyboard(+1, +1); // Up & Right
|
||||
break;
|
||||
case kActionMoveUpLeft:
|
||||
moveUsingKeyboard(-1, +1); // Up & Left
|
||||
break;
|
||||
case kActionMoveDownLeft:
|
||||
moveUsingKeyboard(-1, -1); // Down & Left
|
||||
break;
|
||||
case kActionMoveDownRight:
|
||||
moveUsingKeyboard(+1, -1); // Down & Right
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
|
||||
switch (event.customType) {
|
||||
case kActionMouseLeft:
|
||||
if (allowPlayerInput) {
|
||||
mouseLeft = 0;
|
||||
}
|
||||
break;
|
||||
case kActionMouseRight:
|
||||
if (allowPlayerInput) {
|
||||
mouseRight = 0;
|
||||
}
|
||||
break;
|
||||
case kActionMoveUp:
|
||||
case kActionMoveDown:
|
||||
case kActionMoveLeft:
|
||||
case kActionMoveRight:
|
||||
case kActionMoveUpLeft:
|
||||
case kActionMoveUpRight:
|
||||
case kActionMoveDownLeft:
|
||||
case kActionMoveDownRight:
|
||||
// Stop ego movement made with keyboard when releasing a known key
|
||||
moveUsingKeyboard(0, 0);
|
||||
break;
|
||||
case kActionCollisionPage:
|
||||
renderer->showCollisionPage(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Common::EVENT_KEYDOWN:
|
||||
g_cine->_keyInputList.push_back(event.kbd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void manageEvents(CallSource callSource, EventTarget eventTarget, bool useMaxMouseButtonState, Common::Array<Common::Rect> rects) {
|
||||
Common::EventManager *eventMan = g_system->getEventManager();
|
||||
Common::Point mousePos;
|
||||
uint keysPressed = g_cine->_keyInputList.size();
|
||||
bool foundTarget = false;
|
||||
int eventsChecked = 0;
|
||||
uint16 maxMouseLeft = mouseLeft;
|
||||
uint16 maxMouseRight = mouseRight;
|
||||
uint32 waitStart = g_system->getMillis();
|
||||
uint32 waitEnd = waitStart + g_cine->getTimerDelay();
|
||||
uint32 frameEnd = waitStart + 20;
|
||||
bool frameEnded = false;
|
||||
bool waitEnded = false;
|
||||
bool checkWaitEnd = (eventTarget == UNTIL_WAIT_ENDED);
|
||||
bool updateScreen = false;
|
||||
bool updateAudio = false;
|
||||
|
||||
do {
|
||||
Common::Event event = Common::Event();
|
||||
int eventsCheckedBeforePolling = eventsChecked;
|
||||
while (!foundTarget && !frameEnded && (eventMan->pollEvent(event) || eventsChecked == 0)) {
|
||||
processEvent(event);
|
||||
eventsChecked++;
|
||||
maxMouseLeft = MAX<uint16>(mouseLeft, maxMouseLeft);
|
||||
maxMouseRight = MAX<uint16>(mouseRight, maxMouseRight);
|
||||
|
||||
bool mouseButtonDown = (mouseLeft != 0 || mouseRight != 0);
|
||||
bool mouseButtonUp = !mouseButtonDown;
|
||||
|
||||
switch (eventTarget) {
|
||||
case UNTIL_MOUSE_BUTTON_UP_DOWN_UP:
|
||||
// fall through
|
||||
case UNTIL_MOUSE_BUTTON_UP_DOWN:
|
||||
// fall through
|
||||
case UNTIL_MOUSE_BUTTON_UP:
|
||||
// fall through
|
||||
case UNTIL_MOUSE_BUTTON_UP_AND_WAIT_ENDED:
|
||||
foundTarget = mouseButtonUp;
|
||||
break;
|
||||
case UNTIL_MOUSE_BUTTON_DOWN_UP:
|
||||
// fall through
|
||||
case UNTIL_MOUSE_BUTTON_DOWN:
|
||||
foundTarget = mouseButtonDown;
|
||||
break;
|
||||
case UNTIL_MOUSE_BUTTON_DOWN_OR_KEY_UP_OR_DOWN_OR_IN_RECTS:
|
||||
foundTarget = mouseButtonDown;
|
||||
if (!g_cine->_actionList.empty()) {
|
||||
Common::CustomEventType customType = g_cine->_actionList.back();
|
||||
if (customType == kActionMenuOptionUp || customType == kActionMenuOptionDown) {
|
||||
foundTarget = true;
|
||||
}
|
||||
}
|
||||
mousePos = g_system->getEventManager()->getMousePos();
|
||||
for (auto &r : rects) {
|
||||
if (r.contains(mousePos)) {
|
||||
foundTarget = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UNTIL_MOUSE_BUTTON_DOWN_OR_KEY_INPUT:
|
||||
foundTarget = mouseButtonDown || keysPressed < g_cine->_keyInputList.size();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
uint32 now = g_system->getMillis();
|
||||
frameEnded = (now >= frameEnd);
|
||||
waitEnded = (now >= waitEnd);
|
||||
|
||||
if (foundTarget) {
|
||||
switch (eventTarget) {
|
||||
case UNTIL_MOUSE_BUTTON_UP_DOWN_UP:
|
||||
eventTarget = UNTIL_MOUSE_BUTTON_DOWN_UP;
|
||||
foundTarget = false;
|
||||
break;
|
||||
case UNTIL_MOUSE_BUTTON_UP_DOWN:
|
||||
eventTarget = UNTIL_MOUSE_BUTTON_DOWN;
|
||||
foundTarget = false;
|
||||
break;
|
||||
case UNTIL_MOUSE_BUTTON_DOWN_UP:
|
||||
eventTarget = UNTIL_MOUSE_BUTTON_UP;
|
||||
foundTarget = false;
|
||||
break;
|
||||
case UNTIL_MOUSE_BUTTON_UP_AND_WAIT_ENDED:
|
||||
eventTarget = UNTIL_WAIT_ENDED;
|
||||
checkWaitEnd = true;
|
||||
foundTarget = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foundTarget |= (checkWaitEnd && waitEnded);
|
||||
}
|
||||
int eventsCheckedAfterPolling = eventsChecked;
|
||||
|
||||
bool eventQueueEmpty = (eventsCheckedBeforePolling == eventsCheckedAfterPolling);
|
||||
|
||||
if (eventQueueEmpty) {
|
||||
uint32 now = g_system->getMillis();
|
||||
frameEnded = (now >= frameEnd);
|
||||
waitEnded = (now >= waitEnd);
|
||||
}
|
||||
|
||||
if (eventTarget == UNTIL_WAIT_ENDED) {
|
||||
foundTarget = waitEnded;
|
||||
}
|
||||
|
||||
if (eventTarget == EMPTY_EVENT_QUEUE) {
|
||||
foundTarget = eventQueueEmpty;
|
||||
}
|
||||
|
||||
foundTarget |= (checkWaitEnd && waitEnded);
|
||||
updateScreen = updateAudio = (foundTarget || frameEnded);
|
||||
|
||||
if (updateScreen) {
|
||||
if (callSource != EXECUTE_PLAYER_INPUT) {
|
||||
g_system->updateScreen();
|
||||
} else {
|
||||
// Make the command line (e.g. "EXAMINE DOOR" -> "EXAMINE BUTTON")
|
||||
// responsive by updating it here.
|
||||
if (allowPlayerInput && playerCommand != -1 && !mouseLeft && !mouseRight) {
|
||||
// A player command is given, left and right mouse buttons are up
|
||||
mousePos = eventMan->getMousePos();
|
||||
playerCommandMouseLeftRightUp(mousePos.x, mousePos.y);
|
||||
renderer->drawCommand();
|
||||
}
|
||||
|
||||
renderer->blit();
|
||||
}
|
||||
}
|
||||
|
||||
if (updateAudio) {
|
||||
g_system->getAudioCDManager()->update(); // For Future Wars CD version
|
||||
}
|
||||
|
||||
if (frameEnded) {
|
||||
frameEnd += 20;
|
||||
}
|
||||
|
||||
g_system->delayMillis(10);
|
||||
} while (!foundTarget && !g_cine->shouldQuit());
|
||||
|
||||
if (useMaxMouseButtonState) {
|
||||
mouseData.left = maxMouseLeft;
|
||||
mouseData.right = maxMouseRight;
|
||||
} else {
|
||||
mouseData.left = mouseLeft;
|
||||
mouseData.right = mouseRight;
|
||||
}
|
||||
}
|
||||
|
||||
void getMouseData(uint16 param, uint16 *pButton, uint16 *pX, uint16 *pY) {
|
||||
Common::Point mouse = g_system->getEventManager()->getMousePos();
|
||||
*pX = mouse.x;
|
||||
*pY = mouse.y;
|
||||
|
||||
*pButton = 0;
|
||||
|
||||
if (mouseData.right) {
|
||||
(*pButton) |= 2;
|
||||
}
|
||||
|
||||
if (mouseData.left) {
|
||||
(*pButton) |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Removes elements from seqList that have their member variable var4 set to value -1. */
|
||||
void purgeSeqList() {
|
||||
Common::List<SeqListElement>::iterator it = g_cine->_seqList.begin();
|
||||
while (it != g_cine->_seqList.end()) {
|
||||
if (it->var4 == -1) {
|
||||
// Erase the element and jump to the next element
|
||||
it = g_cine->_seqList.erase(it);
|
||||
} else {
|
||||
// Let the element be and jump to the next element
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CineEngine::mainLoop(int bootScriptIdx) {
|
||||
byte di;
|
||||
|
||||
if (_preLoad == false) {
|
||||
resetBgIncrustList();
|
||||
|
||||
setTextWindow(0, 0, 20, 200);
|
||||
|
||||
errorVar = 0;
|
||||
|
||||
addScriptToGlobalScripts(bootScriptIdx);
|
||||
|
||||
menuVar = 0;
|
||||
|
||||
// gfxRedrawPage(page0c, page0, page0c, page0, -1);
|
||||
// gfxWaitVBL();
|
||||
// gfxRedrawMouseCursor();
|
||||
|
||||
inMenu = false;
|
||||
allowPlayerInput = 0;
|
||||
checkForPendingDataLoadSwitch = 0;
|
||||
|
||||
reloadBgPalOnNextFlip = 0;
|
||||
forbidBgPalReload = 0;
|
||||
gfxFadeOutCompleted = 0;
|
||||
gfxFadeInRequested = 0;
|
||||
safeControlsLastAccessedMs = 0;
|
||||
lastSafeControlObjIdx = -1;
|
||||
isDrawCommandEnabled = 0;
|
||||
waitForPlayerClick = 0;
|
||||
menuCommandLen = 0;
|
||||
|
||||
playerCommand = -1;
|
||||
g_cine->_commandBuffer = "";
|
||||
|
||||
g_cine->_globalVars[VAR_MOUSE_X_POS] = 0;
|
||||
g_cine->_globalVars[VAR_MOUSE_Y_POS] = 0;
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
g_cine->_globalVars[VAR_MOUSE_X_POS_2ND] = 0;
|
||||
g_cine->_globalVars[VAR_MOUSE_Y_POS_2ND] = 0;
|
||||
g_cine->_globalVars[VAR_BYPASS_PROTECTION] = 0; // set to 1 to bypass the copy protection
|
||||
g_cine->_globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc.
|
||||
}
|
||||
|
||||
renderer->setBlackPalette(true); // Sets _changePal = true
|
||||
|
||||
newPrcName[0] = '\0';
|
||||
newRelName[0] = '\0';
|
||||
newObjectName[0] = '\0';
|
||||
newMsgName[0] = '\0';
|
||||
currentCtName[0] = '\0';
|
||||
currentPartName[0] = '\0';
|
||||
|
||||
g_sound->stopMusic();
|
||||
}
|
||||
|
||||
do {
|
||||
// HACK: Force amount of oxygen left to maximum during Operation Stealth's first arcade sequence.
|
||||
// This makes it possible to pass the arcade sequence for now.
|
||||
// FIXME: Remove the hack and make the first arcade sequence normally playable.
|
||||
/*
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
Common::String bgName(renderer->getBgName());
|
||||
// Check if the background is one of the three backgrounds
|
||||
// that are only used during the first arcade sequence.
|
||||
if (bgName == "28.PI1" || bgName == "29.PI1" || bgName == "30.PI1") {
|
||||
static const uint oxygenObjNum = 202, maxOxygen = 264;
|
||||
// Force the amount of oxygen left to the maximum.
|
||||
g_cine->_objectTable[oxygenObjNum].x = maxOxygen;
|
||||
}
|
||||
}*/
|
||||
|
||||
// HACK: In Operation Stealth after the first arcade sequence jump player's position to avoid getting stuck.
|
||||
// After the first arcade sequence the player comes up stairs from
|
||||
// the water in Santa Paragua's downtown in front of the flower shop.
|
||||
// Previously he was completely stuck after getting up the stairs.
|
||||
// If the background is the one used in the flower shop scene ("21.PI1")
|
||||
// and the player is at the exact location after getting up the stairs
|
||||
// then we just nudge him a tiny bit away from the stairs and voila, he's free!
|
||||
// Maybe the real problem behind all this is collision data related as it looks
|
||||
// like there's some boundary right there near position (204, 110) which we can
|
||||
// jump over by moving the character to (204, 109). The script handling the
|
||||
// flower shop scene is AIRPORT.PRC's 13th script.
|
||||
// FIXME: Remove the hack and solve what's really causing the problem in the first place.
|
||||
if (hacksEnabled && g_cine->getGameType() == Cine::GType_OS) {
|
||||
if (scumm_stricmp(renderer->getBgName(), "21.PI1") == 0 && g_cine->_objectTable[1].x == 204 && g_cine->_objectTable[1].y == 110) {
|
||||
g_cine->_objectTable[1].y--; // Move the player character upward on-screen by one pixel
|
||||
}
|
||||
}
|
||||
|
||||
stopMusicAfterFadeOut();
|
||||
di = executePlayerInput();
|
||||
|
||||
// Clear the zoneQuery table (Operation Stealth specific)
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
Common::fill(g_cine->_zoneQuery.begin(), g_cine->_zoneQuery.end(), 0);
|
||||
}
|
||||
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
processSeqList();
|
||||
}
|
||||
executeObjectScripts();
|
||||
executeGlobalScripts();
|
||||
|
||||
purgeObjectScripts();
|
||||
purgeGlobalScripts();
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
purgeSeqList();
|
||||
}
|
||||
|
||||
if (playerCommand == -1) {
|
||||
setMouseCursor(MOUSE_CURSOR_NORMAL);
|
||||
} else {
|
||||
setMouseCursor(MOUSE_CURSOR_CROSS);
|
||||
}
|
||||
|
||||
if (gfxFadeInRequested) {
|
||||
gfxFadeOutCompleted = 0;
|
||||
}
|
||||
|
||||
if (renderer->ready()) {
|
||||
renderer->drawFrame(true);
|
||||
}
|
||||
|
||||
// NOTE: In the original Future Wars and Operation Stealth messages
|
||||
// were removed when running the drawOverlays function which is
|
||||
// currently called from the renderer's drawFrame function.
|
||||
removeMessages();
|
||||
|
||||
if (waitForPlayerClick) {
|
||||
_messageLen <<= 3;
|
||||
if (_messageLen < 800)
|
||||
_messageLen = 800;
|
||||
|
||||
manageEvents(MAIN_LOOP_WAIT_FOR_PLAYER_CLICK, UNTIL_MOUSE_BUTTON_UP_DOWN_UP);
|
||||
stopTextToSpeech();
|
||||
waitForPlayerClick = 0;
|
||||
}
|
||||
|
||||
if (checkForPendingDataLoadSwitch) {
|
||||
checkForPendingDataLoad();
|
||||
|
||||
checkForPendingDataLoadSwitch = 0;
|
||||
}
|
||||
|
||||
if (di) {
|
||||
if ("quit"[menuCommandLen] == (char)di) {
|
||||
++menuCommandLen;
|
||||
if (menuCommandLen == 4) {
|
||||
quitGame();
|
||||
}
|
||||
} else {
|
||||
menuCommandLen = 0;
|
||||
}
|
||||
}
|
||||
} while (!shouldQuit() && !_restartRequested);
|
||||
|
||||
hideMouse();
|
||||
g_sound->stopMusic();
|
||||
//if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
// freeUnkList();
|
||||
//}
|
||||
closePart();
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
55
engines/cine/main_loop.h
Normal file
55
engines/cine/main_loop.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 CINE_MAINLOOP_H
|
||||
#define CINE_MAINLOOP_H
|
||||
|
||||
namespace Cine {
|
||||
|
||||
enum CallSource {
|
||||
EXECUTE_PLAYER_INPUT, ///< Called from executePlayerInput function.
|
||||
MAIN_LOOP_WAIT_FOR_PLAYER_CLICK, ///< Called from mainLoop function's waiting for player click section.
|
||||
MAKE_MENU_CHOICE, ///< Called from makeMenuChoice function.
|
||||
MAKE_SYSTEM_MENU, ///< Called from makeSystemMenu function.
|
||||
MAKE_TEXT_ENTRY_MENU, ///< Called from makeTextEntryMenu function.
|
||||
PROCESS_INVENTORY, ///< Called from processInventory function.
|
||||
WAIT_PLAYER_INPUT ///< Called from waitPlayerInput function.
|
||||
};
|
||||
|
||||
enum EventTarget {
|
||||
UNTIL_MOUSE_BUTTON_UP_DOWN_UP, ///< Wait until first mouse buttons all up, then at least one down, finally all up.
|
||||
UNTIL_MOUSE_BUTTON_DOWN_UP, ///< Wait until first at least one mouse button down, finally all up.
|
||||
UNTIL_MOUSE_BUTTON_UP, ///< Wait until all mouse buttons up.
|
||||
UNTIL_MOUSE_BUTTON_UP_AND_WAIT_ENDED, ///< Wait until all mouse buttons up and wait period (getTimerDelay()) ended.
|
||||
UNTIL_MOUSE_BUTTON_UP_DOWN, ///< Wait until first all mouse buttons up, finally at least one down.
|
||||
UNTIL_MOUSE_BUTTON_DOWN, ///< Wait until at least one mouse button down.
|
||||
UNTIL_MOUSE_BUTTON_DOWN_OR_KEY_UP_OR_DOWN_OR_IN_RECTS, ///< Wait until at least one mouse button down, up key pressed, down key pressed or mouse position in at least one of the given rectangles.
|
||||
UNTIL_MOUSE_BUTTON_DOWN_OR_KEY_INPUT, ///< Wait until at least one mouse button down or a key pressed.
|
||||
UNTIL_WAIT_ENDED, ///< Wait until wait period (getTimerDelay()) ended.
|
||||
EMPTY_EVENT_QUEUE ///< Empty the event queue.
|
||||
};
|
||||
|
||||
void mainLoop(int bootScriptIdx);
|
||||
void manageEvents(CallSource callSource, EventTarget eventTarget, bool useMaxMouseButtonState = false, Common::Array<Common::Rect> rects = Common::Array<Common::Rect>());
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
553
engines/cine/metaengine.cpp
Normal file
553
engines/cine/metaengine.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
/* 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 "base/plugins.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "common/translation.h"
|
||||
#include "common/util.h"
|
||||
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
#include "backends/keymapper/standard-actions.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/various.h"
|
||||
|
||||
#include "cine/detection.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
static const ADExtraGuiOptionsMap optionsList[] = {
|
||||
{
|
||||
GAMEOPTION_ORIGINAL_SAVELOAD,
|
||||
{
|
||||
_s("Use original save/load screens"),
|
||||
_s("Use the original save/load screens instead of the ScummVM ones"),
|
||||
"originalsaveload",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
{
|
||||
GAMEOPTION_TRANSPARENT_DIALOG_BOXES,
|
||||
{
|
||||
_s("Use transparent dialog boxes in 16 color scenes"),
|
||||
_s("Use transparent dialog boxes in 16 color scenes even if the original game version did not support them"),
|
||||
"transparentdialogboxes",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
#ifdef USE_TTS
|
||||
{
|
||||
GAMEOPTION_TTS,
|
||||
{
|
||||
_s("Enable Text to Speech"),
|
||||
_s("Use TTS to read text in the game (if TTS is available)"),
|
||||
"tts_enabled",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
#endif
|
||||
|
||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||
};
|
||||
|
||||
#define MAX_SAVEGAMES (ARRAYSIZE(Cine::currentSaveName))
|
||||
#define SAVEGAME_NAME_LEN (sizeof(Cine::currentSaveName[0]))
|
||||
#define SAVELIST_SIZE (MAX_SAVEGAMES * SAVEGAME_NAME_LEN)
|
||||
|
||||
bool CineEngine::mayHave256Colors() const { return getGameType() == Cine::GType_OS && getPlatform() == Common::kPlatformDOS; }
|
||||
int CineEngine::getGameType() const { return _gameDescription->gameType; }
|
||||
uint32 CineEngine::getFeatures() const { return _gameDescription->features; }
|
||||
Common::Language CineEngine::getLanguage() const { return _gameDescription->desc.language; }
|
||||
Common::Platform CineEngine::getPlatform() const { return _gameDescription->desc.platform; }
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
class CineMetaEngine : public AdvancedMetaEngine<Cine::CINEGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "cine";
|
||||
}
|
||||
|
||||
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
|
||||
return Cine::optionsList;
|
||||
}
|
||||
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const Cine::CINEGameDescription *desc) const override;
|
||||
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
SaveStateList listSaves(const char *target) const override;
|
||||
int getMaximumSaveSlot() const override;
|
||||
bool removeSaveState(const char *target, int slot) const override;
|
||||
Common::String getSavegameFile(int saveGameIdx, const char *target = nullptr) const override;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
|
||||
|
||||
Common::KeymapArray initKeymaps(const char *target) const override;
|
||||
};
|
||||
|
||||
bool CineMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsLoadingDuringStartup) ||
|
||||
checkExtendedSaves(f);
|
||||
}
|
||||
|
||||
bool Cine::CineEngine::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsReturnToLauncher) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
Common::Error CineMetaEngine::createInstance(OSystem *syst, Engine **engine, const Cine::CINEGameDescription *desc) const {
|
||||
*engine = new Cine::CineEngine(syst,desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
SaveStateList CineMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
SaveStateList saveList;
|
||||
|
||||
Common::String pattern;
|
||||
|
||||
Common::String filename = target;
|
||||
filename += ".dir";
|
||||
Common::InSaveFile *in = saveFileMan->openForLoading(filename);
|
||||
bool foundAutosave = false;
|
||||
|
||||
if (in) {
|
||||
typedef char CommandeType[SAVEGAME_NAME_LEN];
|
||||
CommandeType saveNames[MAX_SAVEGAMES];
|
||||
|
||||
// Initialize all savegames' descriptions to empty strings
|
||||
// so that if the savegames' descriptions can only be partially read from file
|
||||
// then the missing ones are correctly set to empty strings.
|
||||
memset(saveNames, 0, sizeof(saveNames));
|
||||
|
||||
in->read(saveNames, SAVELIST_SIZE);
|
||||
CommandeType saveDesc;
|
||||
|
||||
pattern = target;
|
||||
pattern += ".#*";
|
||||
Common::StringArray filenames = saveFileMan->listSavefiles(pattern);
|
||||
|
||||
for (const auto &file : filenames) {
|
||||
// Obtain the extension part of the filename, since it corresponds to the save slot number
|
||||
Common::String ext = Common::lastPathComponent(file, '.');
|
||||
int slotNum = (int)ext.asUint64();
|
||||
|
||||
if (ext.equals(Common::String::format("%d", slotNum)) &&
|
||||
slotNum >= 0 && slotNum < MAX_SAVEGAMES) {
|
||||
// Copy the savegame description making sure it ends with a trailing zero
|
||||
strncpy(saveDesc, saveNames[slotNum], SAVEGAME_NAME_LEN);
|
||||
saveDesc[sizeof(CommandeType) - 1] = 0;
|
||||
|
||||
SaveStateDescriptor saveStateDesc(this, slotNum, saveDesc);
|
||||
|
||||
if (saveStateDesc.getDescription().empty()) {
|
||||
if (slotNum == getAutosaveSlot()) {
|
||||
saveStateDesc.setDescription(_("Unnamed autosave"));
|
||||
} else {
|
||||
saveStateDesc.setDescription(_("Unnamed savegame"));
|
||||
}
|
||||
}
|
||||
|
||||
if (slotNum == getAutosaveSlot()) {
|
||||
foundAutosave = true;
|
||||
}
|
||||
|
||||
saveList.push_back(saveStateDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete in;
|
||||
|
||||
// No saving on empty autosave slot
|
||||
if (!foundAutosave) {
|
||||
SaveStateDescriptor desc(this, getAutosaveSlot(), _("Empty autosave"));
|
||||
saveList.push_back(desc);
|
||||
}
|
||||
|
||||
// Sort saves based on slot number.
|
||||
Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
|
||||
return saveList;
|
||||
}
|
||||
|
||||
int CineMetaEngine::getMaximumSaveSlot() const { return MAX_SAVEGAMES - 1; }
|
||||
|
||||
Common::String CineMetaEngine::getSavegameFile(int saveGameIdx, const char *target) const {
|
||||
return Common::String::format("%s.%d", target == nullptr ? getName() : target, saveGameIdx);
|
||||
}
|
||||
|
||||
SaveStateDescriptor CineMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
if (slot < 0 || slot > getMaximumSaveSlot()) {
|
||||
// HACK: Try to make SaveLoadChooserGrid::open() not use save slot
|
||||
// numbers over the maximum save slot number for "New save".
|
||||
SaveStateDescriptor desc;
|
||||
desc.setWriteProtectedFlag(true);
|
||||
return desc;
|
||||
}
|
||||
|
||||
Common::ScopedPtr<Common::InSaveFile> f(g_system->getSavefileManager()->openForLoading(
|
||||
getSavegameFile(slot, target)));
|
||||
|
||||
if (f) {
|
||||
// Create the return descriptor
|
||||
SaveStateDescriptor desc(this, slot, Common::U32String());
|
||||
|
||||
ExtendedSavegameHeader header;
|
||||
if (readSavegameHeader(f.get(), &header, false)) {
|
||||
parseSavegameHeader(&header, &desc);
|
||||
desc.setThumbnail(header.thumbnail);
|
||||
} else {
|
||||
// Load savegame descriptions from index file
|
||||
typedef char CommandeType[SAVEGAME_NAME_LEN];
|
||||
CommandeType saveNames[MAX_SAVEGAMES];
|
||||
memset(saveNames, 0, sizeof(saveNames));
|
||||
|
||||
Common::InSaveFile *in;
|
||||
in = g_system->getSavefileManager()->openForLoading(Common::String::format("%s.dir", target));
|
||||
|
||||
if (in) {
|
||||
in->read(saveNames, SAVELIST_SIZE);
|
||||
delete in;
|
||||
}
|
||||
|
||||
saveNames[slot][SAVEGAME_NAME_LEN - 1] = 0;
|
||||
Common::String saveNameStr((const char *)saveNames[slot]);
|
||||
desc.setDescription(saveNameStr);
|
||||
}
|
||||
|
||||
if (desc.getDescription().empty()) {
|
||||
desc.setDescription(_("Unnamed savegame"));
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
// No saving on empty autosave slot
|
||||
if (slot == getAutosaveSlot()) {
|
||||
SaveStateDescriptor desc(this, slot, _("Empty autosave"));
|
||||
desc.setAutosave(true);
|
||||
return desc;
|
||||
}
|
||||
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
Common::KeymapArray CineMetaEngine::initKeymaps(const char *target) const {
|
||||
using namespace Common;
|
||||
using namespace Cine;
|
||||
|
||||
Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "cine-default", _("Default keymappings"));
|
||||
Keymap *gameKeyMap = new Keymap(Keymap::kKeymapTypeGame, "game-shortcuts", _("Game keymappings"));
|
||||
Keymap *mouseKeyMap = new Keymap(Keymap::kKeymapTypeGame, "mouse-shortcuts", _("Key to mouse keymappings"));
|
||||
Keymap *introKeyMap = new Keymap(Keymap::kKeymapTypeGame, "intro-shortcuts", _("Exit screen keymappings"));
|
||||
|
||||
Action *act;
|
||||
|
||||
act = new Action(kStandardActionLeftClick, _("Left click"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Right click"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SKIPSONY", _("Exit Sony intro screen"));
|
||||
act->setCustomEngineActionEvent(kActionExitSonyScreen);
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
introKeyMap->addAction(act);
|
||||
|
||||
act = new Action("MOUSELEFT", _("Select option / Click in game"));
|
||||
act->setCustomEngineActionEvent(kActionMouseLeft);
|
||||
act->addDefaultInputMapping("RETURN");
|
||||
act->addDefaultInputMapping("KP_ENTER");
|
||||
act->addDefaultInputMapping("KP5");
|
||||
mouseKeyMap->addAction(act);
|
||||
|
||||
act = new Action("MOUSERIGHT", _("Open action menu / Close menu"));
|
||||
act->setCustomEngineActionEvent(kActionMouseRight);
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
mouseKeyMap->addAction(act);
|
||||
|
||||
act = new Action("DEFAULTSPEED", _("Default game speed"));
|
||||
act->setCustomEngineActionEvent(kActionGameSpeedDefault);
|
||||
act->addDefaultInputMapping("KP0");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SLOWERSPEED", _("Slower game speed"));
|
||||
act->setCustomEngineActionEvent(kActionGameSpeedSlower);
|
||||
act->addDefaultInputMapping("MINUS");
|
||||
act->addDefaultInputMapping("KP_MINUS");
|
||||
act->allowKbdRepeats();
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("FASTERSPEED", _("Faster game speed"));
|
||||
act->setCustomEngineActionEvent(kActionGameSpeedFaster);
|
||||
act->addDefaultInputMapping("PLUS");
|
||||
act->addDefaultInputMapping("KP_PLUS");
|
||||
act->addDefaultInputMapping("S+EQUALS");
|
||||
act->allowKbdRepeats();
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("EXAMINE", _("Examine"));
|
||||
act->setCustomEngineActionEvent(kActionExamine);
|
||||
act->addDefaultInputMapping("F1");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("TAKE", _("Take"));
|
||||
act->setCustomEngineActionEvent(kActionTake);
|
||||
act->addDefaultInputMapping("F2");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("INVENTORY", _("Inventory"));
|
||||
act->setCustomEngineActionEvent(kActionInventory);
|
||||
act->addDefaultInputMapping("F3");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("USE", _("Use"));
|
||||
act->setCustomEngineActionEvent(kActionUse);
|
||||
act->addDefaultInputMapping("F4");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("ACTIVATE", _("Activate"));
|
||||
act->setCustomEngineActionEvent(kActionActivate);
|
||||
act->addDefaultInputMapping("F5");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SPEAK", _("Speak"));
|
||||
act->setCustomEngineActionEvent(kActionSpeak);
|
||||
act->addDefaultInputMapping("F6");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("ACTMENU", _("Action menu"));
|
||||
act->setCustomEngineActionEvent(kActionActionMenu);
|
||||
act->addDefaultInputMapping("F9");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SYSMENU", _("System menu"));
|
||||
act->setCustomEngineActionEvent(kActionSystemMenu);
|
||||
act->addDefaultInputMapping("F10");
|
||||
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
// I18N: Opens collision map of where the actor can freely move
|
||||
act = new Action("COLLISIONPAGE", _("Show collisions"));
|
||||
act->setCustomEngineActionEvent(kActionCollisionPage);
|
||||
act->addDefaultInputMapping("F11");
|
||||
act->addDefaultInputMapping("JOY_Y");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
// I18N: Move Actor to upwards direction
|
||||
act = new Action("MOVEUP", _("Move up"));
|
||||
act->setCustomEngineActionEvent(kActionMoveUp);
|
||||
act->addDefaultInputMapping("KP8");
|
||||
act->addDefaultInputMapping("JOY_UP");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
// I18N: Move Actor to downwards direction
|
||||
act = new Action("MOVEDOWN", _("Move down"));
|
||||
act->setCustomEngineActionEvent(kActionMoveDown);
|
||||
act->addDefaultInputMapping("KP2");
|
||||
act->addDefaultInputMapping("JOY_DOWN");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
// I18N: Move Actor to left direction
|
||||
act = new Action("MOVELEFT", _("Move left"));
|
||||
act->setCustomEngineActionEvent(kActionMoveLeft);
|
||||
act->addDefaultInputMapping("KP4");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
// I18N: Move Actor to right direction
|
||||
act = new Action("MOVERIGHT", _("Move right"));
|
||||
act->setCustomEngineActionEvent(kActionMoveRight);
|
||||
act->addDefaultInputMapping("KP6");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
// I18N: Move Actor to top-left direction
|
||||
act = new Action("MOVEUPLEFT", _("Move up-left"));
|
||||
act->setCustomEngineActionEvent(kActionMoveUpLeft);
|
||||
act->addDefaultInputMapping("KP7");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
// I18N: Move Actor to top-right direction
|
||||
act = new Action("MOVEUPRIGHT", _("Move up-right"));
|
||||
act->setCustomEngineActionEvent(kActionMoveUpRight);
|
||||
act->addDefaultInputMapping("KP9");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
// I18N: Move Actor to bottom-left direction
|
||||
act = new Action("MOVEDOWNLEFT", _("Move down-left"));
|
||||
act->setCustomEngineActionEvent(kActionMoveDownLeft);
|
||||
act->addDefaultInputMapping("KP1");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
// I18N: Move Actor to bottom-right direction
|
||||
act = new Action("MOVEDOWNRIGHT", _("Move down-right"));
|
||||
act->setCustomEngineActionEvent(kActionMoveDownRight);
|
||||
act->addDefaultInputMapping("KP3");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("MENUUP", _("Menu option up"));
|
||||
act->setCustomEngineActionEvent(kActionMenuOptionUp);
|
||||
act->addDefaultInputMapping("UP");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("MENUDOWN", _("Menu option down"));
|
||||
act->setCustomEngineActionEvent(kActionMenuOptionDown);
|
||||
act->addDefaultInputMapping("DOWN");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
|
||||
KeymapArray keymaps(4);
|
||||
keymaps[0] = engineKeyMap;
|
||||
keymaps[1] = mouseKeyMap;
|
||||
keymaps[2] = gameKeyMap;
|
||||
keymaps[3] = introKeyMap;
|
||||
|
||||
introKeyMap->setEnabled(false);
|
||||
|
||||
return keymaps;
|
||||
}
|
||||
|
||||
bool CineMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
if (slot < 0 || slot >= MAX_SAVEGAMES) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load savegame descriptions from index file
|
||||
typedef char CommandeType[SAVEGAME_NAME_LEN];
|
||||
CommandeType saveNames[MAX_SAVEGAMES];
|
||||
|
||||
// Initialize all savegames' descriptions to empty strings
|
||||
// so that if the savegames' descriptions can only be partially read from file
|
||||
// then the missing ones are correctly set to empty strings.
|
||||
memset(saveNames, 0, sizeof(saveNames));
|
||||
|
||||
Common::InSaveFile *in;
|
||||
in = g_system->getSavefileManager()->openForLoading(Common::String::format("%s.dir", target));
|
||||
|
||||
if (!in)
|
||||
return false;
|
||||
|
||||
in->read(saveNames, SAVELIST_SIZE);
|
||||
delete in;
|
||||
|
||||
// Set description for selected slot
|
||||
char slotName[SAVEGAME_NAME_LEN];
|
||||
slotName[0] = 0;
|
||||
Common::strlcpy(saveNames[slot], slotName, SAVEGAME_NAME_LEN);
|
||||
|
||||
// Update savegame descriptions
|
||||
Common::String indexFile = Common::String::format("%s.dir", target);
|
||||
Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving(indexFile);
|
||||
if (!out) {
|
||||
warning("Unable to open file %s for saving", indexFile.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
out->write(saveNames, SAVELIST_SIZE);
|
||||
delete out;
|
||||
|
||||
// Delete save file
|
||||
Common::String saveFileName = getSavegameFile(slot, target);
|
||||
|
||||
return g_system->getSavefileManager()->removeSavefile(saveFileName);
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(CINE)
|
||||
REGISTER_PLUGIN_DYNAMIC(CINE, PLUGIN_TYPE_ENGINE, CineMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(CINE, PLUGIN_TYPE_ENGINE, CineMetaEngine);
|
||||
#endif
|
||||
|
||||
namespace Cine {
|
||||
|
||||
Common::Error CineEngine::loadGameState(int slot) {
|
||||
bool gameLoaded = makeLoad(getSaveStateName(slot));
|
||||
|
||||
return gameLoaded ? Common::kNoError : Common::kUnknownError;
|
||||
}
|
||||
|
||||
Common::Error CineEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
||||
if (slot < 0 || slot >= MAX_SAVEGAMES) {
|
||||
return Common::kCreatingFileFailed;
|
||||
}
|
||||
|
||||
// Load savegame descriptions from index file
|
||||
loadSaveDirectory();
|
||||
|
||||
// Set description for selected slot making sure it ends with a trailing zero
|
||||
strncpy(currentSaveName[slot], desc.c_str(), sizeof(CommandeType));
|
||||
currentSaveName[slot][sizeof(CommandeType) - 1] = 0;
|
||||
|
||||
// Update savegame descriptions
|
||||
Common::String indexFile = _targetName + ".dir";
|
||||
|
||||
Common::OutSaveFile *fHandle = _saveFileMan->openForSaving(indexFile);
|
||||
if (!fHandle) {
|
||||
warning("Unable to open file %s for saving", indexFile.c_str());
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
|
||||
fHandle->write(currentSaveName, SAVELIST_SIZE);
|
||||
delete fHandle;
|
||||
|
||||
// Save game
|
||||
makeSave(getSaveStateName(slot), getTotalPlayTime() / 1000, desc, isAutosave);
|
||||
|
||||
checkDataDisk(-1);
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::String CineEngine::getSaveStateName(int slot) const {
|
||||
return getMetaEngine()->getSavegameFile(slot, _targetName.c_str());
|
||||
}
|
||||
|
||||
bool CineEngine::canLoadGameStateCurrently(Common::U32String *msg) {
|
||||
return (!disableSystemMenu && !inMenu);
|
||||
}
|
||||
|
||||
bool CineEngine::canSaveGameStateCurrently(Common::U32String *msg) {
|
||||
return (allowPlayerInput && !disableSystemMenu && !inMenu);
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
35
engines/cine/module.mk
Normal file
35
engines/cine/module.mk
Normal file
@@ -0,0 +1,35 @@
|
||||
MODULE := engines/cine
|
||||
|
||||
MODULE_OBJS := \
|
||||
anim.o \
|
||||
bg.o \
|
||||
bg_list.o \
|
||||
console.o \
|
||||
cine.o \
|
||||
gfx.o \
|
||||
main_loop.o \
|
||||
metaengine.o \
|
||||
msg.o \
|
||||
object.o \
|
||||
pal.o \
|
||||
part.o \
|
||||
prc.o \
|
||||
rel.o \
|
||||
saveload.o \
|
||||
script_fw.o \
|
||||
script_os.o \
|
||||
sound.o \
|
||||
texte.o \
|
||||
unpack.o \
|
||||
various.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_CINE), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
79
engines/cine/msg.cpp
Normal file
79
engines/cine/msg.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/* 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/debug.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "cine/msg.h"
|
||||
#include "cine/various.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
int16 loadMsg(char *pMsgName) {
|
||||
uint32 sourceSize;
|
||||
|
||||
checkDataDisk(-1);
|
||||
g_cine->_messageTable.clear();
|
||||
|
||||
int16 foundFileIdx = findFileInBundle(pMsgName);
|
||||
if (foundFileIdx < 0) {
|
||||
warning("loadMsg(\"%s\"): Could not find file in bundle.", pMsgName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
byte *dataPtr = readBundleFile(foundFileIdx, &sourceSize);
|
||||
|
||||
setMouseCursor(MOUSE_CURSOR_DISK);
|
||||
|
||||
uint count = READ_BE_UINT16(dataPtr);
|
||||
uint messageLenPos = 2;
|
||||
uint messageDataPos = messageLenPos + 2 * count;
|
||||
|
||||
// Read in the messages
|
||||
for (uint i = 0; i < count; i++) {
|
||||
// Read message's length
|
||||
uint messageLen = READ_BE_UINT16(dataPtr + messageLenPos);
|
||||
messageLenPos += 2;
|
||||
|
||||
// Store the read message.
|
||||
// This code works around input data that has empty strings residing outside the input
|
||||
// buffer (e.g. message indices 58-254 in BATEAU.MSG in PROCS08 in Operation Stealth).
|
||||
if (messageDataPos < sourceSize) {
|
||||
g_cine->_messageTable.push_back((const char *)(dataPtr + messageDataPos));
|
||||
} else {
|
||||
if (messageLen > 0) { // Only warn about overflowing non-empty strings
|
||||
warning("loadMsg(%s): message (%d. / %d) is overflowing the input buffer. Replacing it with an empty string", pMsgName, i + 1, count);
|
||||
} else {
|
||||
debugC(5, kCineDebugPart, "loadMsg(%s): empty message (%d. / %d) resides outside input buffer", pMsgName, i + 1, count);
|
||||
}
|
||||
// Message resides outside the input buffer so we replace it with an empty string
|
||||
g_cine->_messageTable.push_back("");
|
||||
}
|
||||
// Jump to the next message
|
||||
messageDataPos += messageLen;
|
||||
}
|
||||
|
||||
free(dataPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
35
engines/cine/msg.h
Normal file
35
engines/cine/msg.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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 CINE_MSG_H
|
||||
#define CINE_MSG_H
|
||||
|
||||
#include "common/str-array.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
#define NUM_MAX_MESSAGE 255
|
||||
|
||||
int16 loadMsg(char *pMsgName);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
343
engines/cine/object.cpp
Normal file
343
engines/cine/object.cpp
Normal file
@@ -0,0 +1,343 @@
|
||||
/* 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/endian.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/util.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/object.h"
|
||||
#include "cine/part.h"
|
||||
#include "cine/various.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
/** Resets all elements in the object table. */
|
||||
void resetObjectTable() {
|
||||
for (auto &obj : g_cine->_objectTable) {
|
||||
obj.clear();
|
||||
}
|
||||
}
|
||||
|
||||
int16 loadObject(char *pObjectName) {
|
||||
debug(5, "loadObject(\"%s\")", pObjectName);
|
||||
uint16 numEntry;
|
||||
uint16 entrySize;
|
||||
uint16 i;
|
||||
byte *ptr, *dataPtr;
|
||||
|
||||
checkDataDisk(-1);
|
||||
|
||||
int16 foundFileIdx = findFileInBundle(pObjectName);
|
||||
if (foundFileIdx < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = dataPtr = readBundleFile(foundFileIdx);
|
||||
|
||||
setMouseCursor(MOUSE_CURSOR_DISK);
|
||||
|
||||
numEntry = READ_BE_UINT16(ptr); ptr += 2;
|
||||
|
||||
entrySize = READ_BE_UINT16(ptr); ptr += 2;
|
||||
|
||||
assert(numEntry <= NUM_MAX_OBJECT);
|
||||
|
||||
for (i = 0; i < numEntry; i++) {
|
||||
bool overwrite =
|
||||
(g_cine->getGameType() == Cine::GType_FW && g_cine->_objectTable[i].costume != -2) ||
|
||||
(g_cine->getGameType() == Cine::GType_OS && g_cine->_objectTable[i].costume != -3);
|
||||
|
||||
// HACK: Fix handling of electric razor and cable in Amiga version of Operation Stealth
|
||||
// when entering the Dr. Why's control room.
|
||||
if (hacksEnabled && g_cine->getPlatform() == Common::kPlatformAmiga &&
|
||||
g_cine->getGameType() == Cine::GType_OS && (i == 231 || i == 232) &&
|
||||
scumm_stricmp(pObjectName, "SALLE59.REL") == 0) {
|
||||
overwrite = false;
|
||||
}
|
||||
|
||||
if (overwrite) {
|
||||
Common::MemoryReadStream readS(ptr, entrySize);
|
||||
|
||||
g_cine->_objectTable[i].x = readS.readSint16BE();
|
||||
g_cine->_objectTable[i].y = readS.readSint16BE();
|
||||
g_cine->_objectTable[i].mask = readS.readUint16BE();
|
||||
g_cine->_objectTable[i].frame = readS.readSint16BE();
|
||||
g_cine->_objectTable[i].costume = readS.readSint16BE();
|
||||
readS.read(g_cine->_objectTable[i].name, 20);
|
||||
g_cine->_objectTable[i].part = readS.readUint16BE();
|
||||
}
|
||||
ptr += entrySize;
|
||||
}
|
||||
|
||||
if (!strcmp(pObjectName, "INTRO.OBJ")) {
|
||||
for (i = 0; i < 10; i++) {
|
||||
g_cine->_objectTable[i].costume = 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(dataPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove overlay sprite from the list
|
||||
* @param objIdx Remove overlay associated with this object
|
||||
* @param param Remove overlay of this type
|
||||
*/
|
||||
int removeOverlay(uint16 objIdx, uint16 param) {
|
||||
Common::List<overlay>::iterator it;
|
||||
|
||||
for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
|
||||
if (it->objIdx == objIdx && it->type == param) {
|
||||
g_cine->_overlayList.erase(it);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new overlay sprite to the list
|
||||
* @param objIdx Associate the overlay with this object
|
||||
* @param type Type of new overlay
|
||||
* @todo Why are x, y, width and color left uninitialized?
|
||||
*/
|
||||
void addOverlay(uint16 objIdx, uint16 type) {
|
||||
Common::List<overlay>::iterator it;
|
||||
overlay tmp;
|
||||
|
||||
for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
|
||||
// This is done for both Future Wars and Operation Stealth
|
||||
if (g_cine->_objectTable[it->objIdx].mask >= g_cine->_objectTable[objIdx].mask) {
|
||||
break;
|
||||
}
|
||||
|
||||
// There are additional checks in Operation Stealth's implementation
|
||||
if (g_cine->getGameType() == Cine::GType_OS && (it->type == 2 || it->type == 3)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// In Operation Stealth's implementation we might bail out early
|
||||
if (g_cine->getGameType() == Cine::GType_OS && it != g_cine->_overlayList.end() && it->objIdx == objIdx && it->type == type) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_cine->getGameType() == Cine::GType_OS && g_cine->_objectTable[it->objIdx].frame == 22 && scumm_stricmp(currentPrcName, "STARTA.PRC") == 0) {
|
||||
g_cine->sayText("Washington D.C.\nCIA Headquarters", Common::TextToSpeechManager::QUEUE);
|
||||
}
|
||||
|
||||
tmp.objIdx = objIdx;
|
||||
tmp.type = type;
|
||||
tmp.x = 0;
|
||||
tmp.y = 0;
|
||||
tmp.width = 0;
|
||||
tmp.color = 0;
|
||||
|
||||
g_cine->_overlayList.insert(it, tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new background mask overlay
|
||||
* @param objIdx Associate the overlay with this object
|
||||
* @param param source background index
|
||||
*/
|
||||
void addGfxElement(int16 objIdx, int16 param, int16 type) {
|
||||
Common::List<overlay>::iterator it;
|
||||
overlay tmp;
|
||||
|
||||
for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
|
||||
if (g_cine->_objectTable[it->objIdx].mask >= g_cine->_objectTable[objIdx].mask || it->type == 2 || it->type == 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (it != g_cine->_overlayList.end() && it->objIdx == objIdx && it->type == type && it->x == param) {
|
||||
return;
|
||||
}
|
||||
|
||||
tmp.objIdx = objIdx;
|
||||
tmp.type = type;
|
||||
tmp.x = param;
|
||||
tmp.y = 0;
|
||||
tmp.width = 0;
|
||||
tmp.color = 0;
|
||||
|
||||
g_cine->_overlayList.insert(it, tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove background mask overlay
|
||||
* @param objIdx Remove overlay associated with this object
|
||||
* @param param Remove overlay using this background
|
||||
* @todo Check that it works
|
||||
*/
|
||||
void removeGfxElement(int16 objIdx, int16 param, int16 type) {
|
||||
Common::List<overlay>::iterator it;
|
||||
|
||||
for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
|
||||
if (it->objIdx == objIdx && it->type == type && it->x == param) {
|
||||
g_cine->_overlayList.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4) {
|
||||
g_cine->_objectTable[objIdx].x = param1;
|
||||
g_cine->_objectTable[objIdx].y = param2;
|
||||
g_cine->_objectTable[objIdx].mask = param3;
|
||||
g_cine->_objectTable[objIdx].frame = param4;
|
||||
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
resetGfxEntityEntry(objIdx);
|
||||
} else { // Future Wars
|
||||
if (removeOverlay(objIdx, 0)) {
|
||||
addOverlay(objIdx, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subObjectParam(byte objIdx, byte paramIdx, int16 newValue) {
|
||||
addObjectParam(objIdx, paramIdx, -newValue);
|
||||
}
|
||||
|
||||
void addObjectParam(byte objIdx, byte paramIdx, int16 newValue) {
|
||||
int16 currentValue = getObjectParam(objIdx, paramIdx);
|
||||
modifyObjectParam(objIdx, paramIdx, currentValue + newValue);
|
||||
}
|
||||
|
||||
void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue) {
|
||||
// Operation Stealth checks object index range, Future Wars doesn't.
|
||||
if (g_cine->getGameType() == Cine::GType_OS && objIdx >= NUM_MAX_OBJECT)
|
||||
return;
|
||||
|
||||
switch (paramIdx) {
|
||||
case 1:
|
||||
g_cine->_objectTable[objIdx].x = newValue;
|
||||
break;
|
||||
case 2:
|
||||
g_cine->_objectTable[objIdx].y = newValue;
|
||||
break;
|
||||
case 3:
|
||||
g_cine->_objectTable[objIdx].mask = newValue;
|
||||
|
||||
if (g_cine->getGameType() == Cine::GType_OS) { // Operation Stealth specific
|
||||
resetGfxEntityEntry(objIdx);
|
||||
} else { // Future Wars specific
|
||||
if (removeOverlay(objIdx, 0)) {
|
||||
addOverlay(objIdx, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
g_cine->_objectTable[objIdx].frame = newValue;
|
||||
break;
|
||||
case 5:
|
||||
// TODO: Test if this really breaks the newspaper machine on the airport in Operation Stealth.
|
||||
if (g_cine->getGameType() == Cine::GType_FW && newValue == -1) {
|
||||
g_cine->_objectTable[objIdx].costume = g_cine->_globalVars[0];
|
||||
} else {
|
||||
g_cine->_objectTable[objIdx].costume = newValue;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
g_cine->_objectTable[objIdx].part = newValue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if at least one of the range B's endpoints is inside range A,
|
||||
* not counting the starting and ending points of range A.
|
||||
* Used at least by Operation Stealth's opcode 0x8D i.e. 141.
|
||||
*/
|
||||
bool compareRanges(uint16 aStart, uint16 aEnd, uint16 bStart, uint16 bEnd) {
|
||||
return (bStart > aStart && bStart < aEnd) || (bEnd > aStart && bEnd < aEnd);
|
||||
}
|
||||
|
||||
uint16 compareObjectParamRanges(uint16 objIdx1, uint16 xAdd1, uint16 yAdd1, uint16 maskAdd1, uint16 objIdx2, uint16 xAdd2, uint16 yAdd2, uint16 maskAdd2) {
|
||||
assert(objIdx1 < NUM_MAX_OBJECT && objIdx2 < NUM_MAX_OBJECT);
|
||||
const ObjectStruct &obj1 = g_cine->_objectTable[objIdx1];
|
||||
const ObjectStruct &obj2 = g_cine->_objectTable[objIdx2];
|
||||
|
||||
if (compareRanges(obj1.x, obj1.x + xAdd1, obj2.x, obj2.x + xAdd2) &&
|
||||
compareRanges(obj1.y, obj1.y + yAdd1, obj2.y, obj2.y + yAdd2) &&
|
||||
compareRanges(obj1.mask, obj1.mask + maskAdd1, obj2.mask, obj2.mask + maskAdd2)) {
|
||||
return kCmpEQ;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 compareObjectParam(byte objIdx, byte type, int16 value) {
|
||||
uint16 compareResult = 0;
|
||||
int16 objectParam = getObjectParam(objIdx, type);
|
||||
|
||||
if (objectParam > value) {
|
||||
compareResult |= kCmpGT;
|
||||
} else if (objectParam < value) {
|
||||
compareResult |= kCmpLT;
|
||||
} else {
|
||||
compareResult |= kCmpEQ;
|
||||
}
|
||||
|
||||
return compareResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @bug In Operation Stealth, if you try to go downstairs to the sea in the
|
||||
* location between bank and hotel, getObjectParam is called with paramIdx 16
|
||||
* and crashes
|
||||
*/
|
||||
int16 getObjectParam(uint16 objIdx, uint16 paramIdx) {
|
||||
assert(objIdx <= NUM_MAX_OBJECT);
|
||||
|
||||
paramIdx--;
|
||||
|
||||
assert(paramIdx <= 5);
|
||||
|
||||
switch (paramIdx) {
|
||||
case 0:
|
||||
return g_cine->_objectTable[objIdx].x;
|
||||
case 1:
|
||||
return g_cine->_objectTable[objIdx].y;
|
||||
case 2:
|
||||
return g_cine->_objectTable[objIdx].mask;
|
||||
case 3:
|
||||
return g_cine->_objectTable[objIdx].frame;
|
||||
case 4:
|
||||
return g_cine->_objectTable[objIdx].costume;
|
||||
case 5:
|
||||
return g_cine->_objectTable[objIdx].part;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
82
engines/cine/object.h
Normal file
82
engines/cine/object.h
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CINE_OBJECT_H
|
||||
#define CINE_OBJECT_H
|
||||
|
||||
#include "script.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
struct ObjectStruct {
|
||||
int16 x;
|
||||
int16 y;
|
||||
uint16 mask;
|
||||
int16 frame;
|
||||
int16 costume;
|
||||
char name[20];
|
||||
uint16 part;
|
||||
|
||||
/** Sets all member variables to zero. */
|
||||
void clear() {
|
||||
this->x = 0;
|
||||
this->y = 0;
|
||||
this->mask = 0;
|
||||
this->frame = 0;
|
||||
this->costume = 0;
|
||||
memset(this->name, 0, sizeof(this->name));
|
||||
this->part = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct overlay {
|
||||
uint16 objIdx;
|
||||
uint16 type;
|
||||
int16 x;
|
||||
int16 y;
|
||||
int16 width;
|
||||
int16 color;
|
||||
};
|
||||
|
||||
#define NUM_MAX_OBJECT 255
|
||||
#define NUM_MAX_VAR 255
|
||||
|
||||
void resetObjectTable();
|
||||
int16 loadObject(char *pObjectName);
|
||||
void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4);
|
||||
void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue);
|
||||
|
||||
void addOverlay(uint16 objIdx, uint16 type);
|
||||
int removeOverlay(uint16 objIdx, uint16 param);
|
||||
void addGfxElement(int16 objIdx, int16 param, int16 type);
|
||||
void removeGfxElement(int16 objIdx, int16 param, int16 type);
|
||||
|
||||
int16 getObjectParam(uint16 objIdx, uint16 paramIdx);
|
||||
|
||||
void addObjectParam(byte objIdx, byte paramIdx, int16 newValue);
|
||||
void subObjectParam(byte objIdx, byte paramIdx, int16 newValue);
|
||||
bool compareRanges(uint16 aStart, uint16 aEnd, uint16 bStart, uint16 bEnd);
|
||||
uint16 compareObjectParamRanges(uint16 objIdx1, uint16 xAdd1, uint16 yAdd1, uint16 maskAdd1, uint16 objIdx2, uint16 xAdd2, uint16 yAdd2, uint16 maskAdd2);
|
||||
uint16 compareObjectParam(byte objIdx, byte param1, int16 param2);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
423
engines/cine/pal.cpp
Normal file
423
engines/cine/pal.cpp
Normal file
@@ -0,0 +1,423 @@
|
||||
/* 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 "cine/cine.h"
|
||||
#include "cine/various.h"
|
||||
#include "cine/pal.h"
|
||||
#include "common/system.h" // For g_system->getPaletteManager()->setPalette
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "graphics/paletteman.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
static byte paletteBuffer1[16];
|
||||
static byte paletteBuffer2[16];
|
||||
|
||||
void loadPal(const char *fileName) {
|
||||
char buffer[20];
|
||||
|
||||
removeExtension(buffer, fileName, sizeof(buffer));
|
||||
|
||||
Common::strcat_s(buffer, ".PAL");
|
||||
g_cine->_palArray.clear();
|
||||
|
||||
Common::File palFileHandle;
|
||||
if (!palFileHandle.open(buffer))
|
||||
error("loadPal(): Cannot open file %s", fileName);
|
||||
|
||||
uint16 palEntriesCount = palFileHandle.readUint16LE();
|
||||
palFileHandle.readUint16LE(); // entry size
|
||||
|
||||
g_cine->_palArray.resize(palEntriesCount);
|
||||
for (uint i = 0; i < g_cine->_palArray.size(); ++i) {
|
||||
palFileHandle.read(g_cine->_palArray[i].name, 10);
|
||||
palFileHandle.read(g_cine->_palArray[i].pal1, 16);
|
||||
palFileHandle.read(g_cine->_palArray[i].pal2, 16);
|
||||
}
|
||||
palFileHandle.close();
|
||||
}
|
||||
|
||||
int16 findPaletteFromName(const char *fileName) {
|
||||
char buffer[10];
|
||||
uint16 position = 0;
|
||||
uint16 i;
|
||||
|
||||
Common::strlcpy(buffer, fileName, sizeof(buffer));
|
||||
|
||||
while (position < strlen(buffer)) {
|
||||
if (buffer[position] > 'a' && buffer[position] < 'z') {
|
||||
buffer[position] += 'A' - 'a';
|
||||
}
|
||||
|
||||
position++;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_cine->_palArray.size(); i++) {
|
||||
if (!strcmp(buffer, g_cine->_palArray[i].name)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
void loadRelatedPalette(const char *fileName) {
|
||||
char localName[16];
|
||||
byte i;
|
||||
int16 paletteIndex;
|
||||
|
||||
removeExtension(localName, fileName, sizeof(localName));
|
||||
|
||||
paletteIndex = findPaletteFromName(localName);
|
||||
|
||||
if (paletteIndex == -1) {
|
||||
// generate default palette
|
||||
for (i = 0; i < 16; i++) {
|
||||
paletteBuffer1[i] = paletteBuffer2[i] = (i << 4) + i;
|
||||
}
|
||||
} else {
|
||||
assert(paletteIndex < (int32)g_cine->_palArray.size());
|
||||
memcpy(paletteBuffer1, g_cine->_palArray[paletteIndex].pal1, 16);
|
||||
memcpy(paletteBuffer2, g_cine->_palArray[paletteIndex].pal2, 16);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
/** Is given endian type big endian? (Handles native endian type too, otherwise this would be trivial). */
|
||||
bool isBigEndian(const EndianType endian) {
|
||||
assert(endian == CINE_NATIVE_ENDIAN || endian == CINE_LITTLE_ENDIAN || endian == CINE_BIG_ENDIAN);
|
||||
|
||||
// Handle explicit little and big endian types here
|
||||
if (endian != CINE_NATIVE_ENDIAN) {
|
||||
return (endian == CINE_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
// Handle native endian type here
|
||||
#if defined(SCUMM_BIG_ENDIAN)
|
||||
return true;
|
||||
#elif defined(SCUMM_LITTLE_ENDIAN)
|
||||
return false;
|
||||
#else
|
||||
#error No endianness defined
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Calculate byte position of given bit position in a multibyte variable using defined endianness. */
|
||||
int bytePos(const int bitPos, const int numBytes, const bool bigEndian) {
|
||||
if (bigEndian)
|
||||
return (numBytes - 1) - (bitPos / 8);
|
||||
else // little endian
|
||||
return bitPos / 8;
|
||||
}
|
||||
|
||||
/** Calculate the value of "base" to the power of "power". */
|
||||
int power(int base, int power) {
|
||||
int result = 1;
|
||||
while (power--)
|
||||
result *= base;
|
||||
return result;
|
||||
}
|
||||
} // end of anonymous namespace
|
||||
|
||||
Palette &Palette::rotateRight(byte firstIndex, byte lastIndex) {
|
||||
debug(1, "Palette::rotateRight(firstIndex: %d, lastIndex: %d)", firstIndex, lastIndex);
|
||||
|
||||
const Color lastColor = _colors[lastIndex];
|
||||
|
||||
for (uint i = lastIndex; i > firstIndex; i--)
|
||||
_colors[i] = _colors[i - 1];
|
||||
|
||||
_colors[firstIndex] = lastColor;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Palette &Palette::rotateLeft(byte firstIndex, byte lastIndex) {
|
||||
debug(1, "Palette::rotateLeft(firstIndex: %d, lastIndex: %d)", firstIndex, lastIndex);
|
||||
|
||||
const Color firstColor = _colors[firstIndex];
|
||||
|
||||
for (uint i = firstIndex; i < lastIndex; i++)
|
||||
_colors[i] = _colors[i + 1];
|
||||
|
||||
_colors[lastIndex] = firstColor;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Palette::empty() const {
|
||||
return _colors.empty();
|
||||
}
|
||||
|
||||
uint Palette::colorCount() const {
|
||||
return _colors.size();
|
||||
}
|
||||
|
||||
byte Palette::brightness(byte colorIndex) {
|
||||
return (byte) ((_colors[colorIndex].r*19 +
|
||||
_colors[colorIndex].g*38 +
|
||||
_colors[colorIndex].b*7) / 64);
|
||||
}
|
||||
|
||||
bool Palette::isEqual(byte index1, byte index2) {
|
||||
return _colors[index1].r == _colors[index2].r &&
|
||||
_colors[index1].g == _colors[index2].g &&
|
||||
_colors[index1].b == _colors[index2].b;
|
||||
}
|
||||
|
||||
int Palette::findMinBrightnessColorIndex(uint minColorIndex) {
|
||||
int minFoundBrightness = 999;
|
||||
int foundColorIndex = 0;
|
||||
for (uint i = minColorIndex; i < colorCount(); i++) {
|
||||
byte currColorBrightness = brightness(i);
|
||||
if (currColorBrightness < minFoundBrightness) {
|
||||
minFoundBrightness = currColorBrightness;
|
||||
foundColorIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return (_colors.size() >= 3 && isEqual(2, foundColorIndex)) ? 0 : foundColorIndex;
|
||||
}
|
||||
|
||||
bool Palette::ensureContrast(byte &minBrightnessColorIndex) {
|
||||
minBrightnessColorIndex = findMinBrightnessColorIndex();
|
||||
if (_colors.size() >= 3 && isEqual(2, minBrightnessColorIndex)) {
|
||||
Color black = {0, 0, 0};
|
||||
Color white = {static_cast<uint8>(_format.rMax()), static_cast<uint8>(_format.gMax()), static_cast<uint8>(_format.bMax())};
|
||||
|
||||
_colors[2] = white;
|
||||
if (isEqual(2, minBrightnessColorIndex)) {
|
||||
_colors[minBrightnessColorIndex] = black;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Palette &Palette::fillWithBlack() {
|
||||
for (uint i = 0; i < _colors.size(); i++) {
|
||||
_colors[i].r = 0;
|
||||
_colors[i].g = 0;
|
||||
_colors[i].b = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO: Add better heuristic for checking whether the color format is valid
|
||||
bool Palette::isValid() const {
|
||||
// Check that the color format has been actually set and not just default constructed.
|
||||
// Also check that the alpha channel is discarded.
|
||||
return _format != Graphics::PixelFormat() && _format.aLoss == 8;
|
||||
}
|
||||
|
||||
const Graphics::PixelFormat &Palette::colorFormat() const {
|
||||
return _format;
|
||||
}
|
||||
|
||||
void Palette::setGlobalOSystemPalette() const {
|
||||
byte buf[256 * 3]; // Allocate space for the largest possible palette
|
||||
|
||||
if (g_cine->mayHave256Colors()) {
|
||||
memset(buf, 0, sizeof(buf)); // Clear whole palette
|
||||
}
|
||||
|
||||
// The color format used by OSystem's setPalette-function:
|
||||
save(buf, sizeof(buf), Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0), CINE_LITTLE_ENDIAN);
|
||||
|
||||
if (renderer->useTransparentDialogBoxes() && colorCount() == 16) {
|
||||
// The Amiga version of Future Wars does use the upper 16 colors for a darkened
|
||||
// game palette to allow transparent dialog boxes. To support that in our code
|
||||
// we do calculate that palette over here and append it to the screen palette.
|
||||
for (uint i = 0; i < 16 * 3; ++i)
|
||||
buf[16 * 3 + i] = buf[i] >> 1;
|
||||
|
||||
g_system->getPaletteManager()->setPalette(buf, 0, colorCount() * 2);
|
||||
} else if (g_cine->mayHave256Colors()) {
|
||||
// If 256 colors are possible then always set 256 colors
|
||||
// because resources may be a combination of 16 colors and 256 colors
|
||||
// and going from a 16 color screen to a 256 color screen (e.g. when leaving
|
||||
// the rat maze on Dr. Why's island in Operation Stealth) may leave
|
||||
// the upper 240 colors not faded out.
|
||||
g_system->getPaletteManager()->setPalette(buf, 0, 256);
|
||||
} else {
|
||||
g_system->getPaletteManager()->setPalette(buf, 0, colorCount());
|
||||
}
|
||||
}
|
||||
|
||||
Cine::Palette::Color Palette::getColor(byte index) const {
|
||||
return _colors[index];
|
||||
}
|
||||
|
||||
uint8 Palette::getR(byte index) const {
|
||||
return _colors[index].r;
|
||||
}
|
||||
|
||||
uint8 Palette::getG(byte index) const {
|
||||
return _colors[index].g;
|
||||
}
|
||||
|
||||
uint8 Palette::getB(byte index) const {
|
||||
return _colors[index].b;
|
||||
}
|
||||
|
||||
void Palette::setColorFormat(const Graphics::PixelFormat &format) {
|
||||
_format = format;
|
||||
}
|
||||
|
||||
// a.k.a. transformPaletteRange
|
||||
Palette &Palette::saturatedAddColor(Palette &output, byte firstIndex, byte lastIndex, signed r, signed g, signed b) const {
|
||||
assert(firstIndex < colorCount() && lastIndex < colorCount());
|
||||
assert(firstIndex < output.colorCount() && lastIndex < output.colorCount());
|
||||
assert(output.colorFormat() == colorFormat());
|
||||
|
||||
for (uint i = firstIndex; i <= lastIndex; i++)
|
||||
saturatedAddColor(output._colors[i], _colors[i], r, g, b);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
Palette &Palette::saturatedAddColor(Palette &output, byte firstIndex, byte lastIndex, signed rSource, signed gSource, signed bSource, const Graphics::PixelFormat &sourceFormat) const {
|
||||
// Convert the source color to the internal color format ensuring that no divide by zero will happen
|
||||
const signed r = ((signed) _format.rMax()) * rSource / MAX<int>(sourceFormat.rMax(), 1);
|
||||
const signed g = ((signed) _format.gMax()) * gSource / MAX<int>(sourceFormat.gMax(), 1);
|
||||
const signed b = ((signed) _format.bMax()) * bSource / MAX<int>(sourceFormat.bMax(), 1);
|
||||
|
||||
return saturatedAddColor(output, firstIndex, lastIndex, r, g, b);
|
||||
}
|
||||
|
||||
Palette &Palette::saturatedAddNormalizedGray(Palette &output, byte firstIndex, byte lastIndex, int grayDividend, int grayDenominator) const {
|
||||
assert(grayDenominator != 0);
|
||||
const signed r = ((signed) _format.rMax()) * grayDividend / grayDenominator;
|
||||
const signed g = ((signed) _format.gMax()) * grayDividend / grayDenominator;
|
||||
const signed b = ((signed) _format.bMax()) * grayDividend / grayDenominator;
|
||||
|
||||
return saturatedAddColor(output, firstIndex, lastIndex, r, g, b);
|
||||
}
|
||||
|
||||
// a.k.a. transformColor
|
||||
void Palette::saturatedAddColor(Color &result, const Color &baseColor, signed r, signed g, signed b) const {
|
||||
result.r = CLIP<int>(baseColor.r + r, 0, _format.rMax());
|
||||
result.g = CLIP<int>(baseColor.g + g, 0, _format.gMax());
|
||||
result.b = CLIP<int>(baseColor.b + b, 0, _format.bMax());
|
||||
}
|
||||
|
||||
Palette::Palette(const Graphics::PixelFormat &format, const uint numColors) : _format(format), _colors() {
|
||||
_colors.resize(numColors);
|
||||
fillWithBlack();
|
||||
}
|
||||
|
||||
Palette::Palette(const Palette& other) :
|
||||
_format(other._format),
|
||||
_colors(other._colors) {
|
||||
}
|
||||
|
||||
Palette& Palette::operator=(const Palette& other) {
|
||||
if (this != &other) {
|
||||
_format = other._format;
|
||||
_colors = other._colors;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Palette &Palette::clear() {
|
||||
_format = Graphics::PixelFormat();
|
||||
_colors.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Palette &Palette::load(const byte *buf, const uint size, const Graphics::PixelFormat &format, const uint numColors, const EndianType endian) {
|
||||
assert(format.bytesPerPixel * numColors <= size); // Make sure there's enough input space
|
||||
assert(format.aLoss == 8); // No alpha
|
||||
assert(format.rShift / 8 == (format.rShift + MAX<int>(0, format.rBits() - 1)) / 8); // R must be inside one byte
|
||||
assert(format.gShift / 8 == (format.gShift + MAX<int>(0, format.gBits() - 1)) / 8); // G must be inside one byte
|
||||
assert(format.bShift / 8 == (format.bShift + MAX<int>(0, format.bBits() - 1)) / 8); // B must be inside one byte
|
||||
|
||||
setColorFormat(format);
|
||||
|
||||
_colors.clear();
|
||||
_colors.resize(numColors);
|
||||
|
||||
const int rBytePos = bytePos(format.rShift, format.bytesPerPixel, isBigEndian(endian));
|
||||
const int gBytePos = bytePos(format.gShift, format.bytesPerPixel, isBigEndian(endian));
|
||||
const int bBytePos = bytePos(format.bShift, format.bytesPerPixel, isBigEndian(endian));
|
||||
|
||||
for (uint i = 0; i < numColors; i++) {
|
||||
// format.rMax(), format.gMax(), format.bMax() are also used as masks here
|
||||
_colors[i].r = (buf[i * format.bytesPerPixel + rBytePos] >> (format.rShift % 8)) & format.rMax();
|
||||
_colors[i].g = (buf[i * format.bytesPerPixel + gBytePos] >> (format.gShift % 8)) & format.gMax();
|
||||
_colors[i].b = (buf[i * format.bytesPerPixel + bBytePos] >> (format.bShift % 8)) & format.bMax();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
byte *Palette::save(byte *buf, const uint size, const EndianType endian) const {
|
||||
return save(buf, size, colorFormat(), colorCount(), endian);
|
||||
}
|
||||
|
||||
byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat &format, const EndianType endian) const {
|
||||
return save(buf, size, format, colorCount(), endian);
|
||||
}
|
||||
|
||||
byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat &format, const uint numColors, const EndianType endian, const byte firstIndex) const {
|
||||
assert(format.bytesPerPixel * numColors <= size); // Make sure there's enough output space
|
||||
assert(format.aLoss == 8); // No alpha
|
||||
assert(format.rShift / 8 == (format.rShift + MAX<int>(0, format.rBits() - 1)) / 8); // R must be inside one byte
|
||||
assert(format.gShift / 8 == (format.gShift + MAX<int>(0, format.gBits() - 1)) / 8); // G must be inside one byte
|
||||
assert(format.bShift / 8 == (format.bShift + MAX<int>(0, format.bBits() - 1)) / 8); // B must be inside one byte
|
||||
|
||||
// Clear the part of the output palette we're going to be writing to with all black
|
||||
memset(buf, 0, format.bytesPerPixel * numColors);
|
||||
|
||||
// Calculate original R/G/B max values
|
||||
const int rOrigMax = power(2, 8 - colorFormat().rLoss) - 1;
|
||||
const int gOrigMax = power(2, 8 - colorFormat().gLoss) - 1;
|
||||
const int bOrigMax = power(2, 8 - colorFormat().bLoss) - 1;
|
||||
|
||||
// Calculate new R/G/B max values
|
||||
const int rNewMax = power(2, 8 - format.rLoss) - 1;
|
||||
const int gNewMax = power(2, 8 - format.gLoss) - 1;
|
||||
const int bNewMax = power(2, 8 - format.bLoss) - 1;
|
||||
|
||||
// Calculate the byte position
|
||||
const int rBytePos = bytePos(format.rShift, format.bytesPerPixel, isBigEndian(endian));
|
||||
const int gBytePos = bytePos(format.gShift, format.bytesPerPixel, isBigEndian(endian));
|
||||
const int bBytePos = bytePos(format.bShift, format.bytesPerPixel, isBigEndian(endian));
|
||||
|
||||
// Save the palette to the output in the specified format
|
||||
for (uint i = firstIndex; i < firstIndex + numColors; i++) {
|
||||
const uint r = (_colors[i].r * rNewMax) / (rOrigMax == 0 ? 1 : rOrigMax);
|
||||
const uint g = (_colors[i].g * gNewMax) / (gOrigMax == 0 ? 1 : gOrigMax);
|
||||
const uint b = (_colors[i].b * bNewMax) / (bOrigMax == 0 ? 1 : bOrigMax);
|
||||
|
||||
buf[i * format.bytesPerPixel + rBytePos] |= r << (format.rShift % 8);
|
||||
buf[i * format.bytesPerPixel + gBytePos] |= g << (format.gShift % 8);
|
||||
buf[i * format.bytesPerPixel + bBytePos] |= b << (format.bShift % 8);
|
||||
}
|
||||
|
||||
// Return the pointer to the output palette
|
||||
return buf;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
190
engines/cine/pal.h
Normal file
190
engines/cine/pal.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/* 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 CINE_PAL_H
|
||||
#define CINE_PAL_H
|
||||
|
||||
#include "graphics/pixelformat.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
/**
|
||||
* Endian types. Used at least by Palette class's load and save functions.
|
||||
* TODO: Move somewhere more general as this is definitely not Cine-engine specific
|
||||
*
|
||||
* NOTE: It seems LITTLE_ENDIAN and/or BIG_ENDIAN were defined already on some platforms so
|
||||
* therefore renamed the enumerations to something not clashing by giving them "CINE_"-prefixes.
|
||||
*/
|
||||
enum EndianType {
|
||||
CINE_NATIVE_ENDIAN,
|
||||
CINE_LITTLE_ENDIAN,
|
||||
CINE_BIG_ENDIAN
|
||||
};
|
||||
|
||||
struct PalEntry {
|
||||
char name[10];
|
||||
byte pal1[16];
|
||||
byte pal2[16];
|
||||
};
|
||||
|
||||
void loadPal(const char *fileName);
|
||||
|
||||
void loadRelatedPalette(const char *fileName);
|
||||
|
||||
/**
|
||||
* A class for handling Cine-engine's palettes.
|
||||
* TODO: Test a bit more
|
||||
*/
|
||||
class Palette {
|
||||
public:
|
||||
struct Color {
|
||||
uint8 r, g, b;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an initially black palette with the given color format and number of colors.
|
||||
* @param format Color format
|
||||
* @param numColors Number of colors
|
||||
* @note For the default constructed object (i.e. no parameters given) this will hold: empty() && !isValid()
|
||||
*/
|
||||
Palette(const Graphics::PixelFormat &format = Graphics::PixelFormat(), const uint numColors = 0);
|
||||
Palette(const Palette& other);
|
||||
Palette& operator=(const Palette& other);
|
||||
|
||||
/**
|
||||
* Clear the palette (Set color count to zero, release memory, overwrite color format with default value).
|
||||
* @note This is very different from using fillWithBlack-function which fills the palette with black.
|
||||
*/
|
||||
Palette &clear();
|
||||
|
||||
/**
|
||||
* Load palette from buffer with given color format, endianness and number of colors.
|
||||
* @param buf Input buffer
|
||||
* @param size Input buffer size in bytes
|
||||
* @param format Input color format
|
||||
* @param numColors Number of colors to load
|
||||
* @param endian The endianness of the colors in the input buffer
|
||||
*/
|
||||
Palette &load(const byte *buf, const uint size, const Graphics::PixelFormat &format, const uint numColors, const EndianType endian);
|
||||
|
||||
/**
|
||||
* Save the whole palette to buffer in original color format using defined endianness.
|
||||
* @param buf Output buffer
|
||||
* @param size Output buffer size in bytes
|
||||
* @param endian The endian type to use
|
||||
*/
|
||||
byte *save(byte *buf, const uint size, const EndianType endian) const;
|
||||
|
||||
/**
|
||||
* Save the whole palette to buffer in given color format using defined endianness.
|
||||
* @param buf Output buffer
|
||||
* @param size Output buffer size in bytes
|
||||
* @param format Output color format
|
||||
* @param endian The endian type to use
|
||||
*/
|
||||
byte *save(byte *buf, const uint size, const Graphics::PixelFormat &format, const EndianType endian) const;
|
||||
|
||||
/**
|
||||
* Save (partial) palette to buffer in given color format using defined endianness.
|
||||
* @param buf Output buffer
|
||||
* @param size Output buffer size in bytes
|
||||
* @param format Output color format
|
||||
* @param numColors Number of colors to save
|
||||
* @param endian The endian type to use
|
||||
* @param firstIndex Starting color index (from which onwards to save the colors)
|
||||
*/
|
||||
byte *save(byte *buf, const uint size, const Graphics::PixelFormat &format, const uint numColors, const EndianType endian, const byte firstIndex = 0) const;
|
||||
|
||||
/**
|
||||
* Rotate the palette in color range [firstIndex, lastIndex] to the right by one.
|
||||
*/
|
||||
Palette &rotateRight(byte firstIndex, byte lastIndex);
|
||||
Palette &rotateLeft(byte firstIndex, byte lastIndex);
|
||||
Palette &saturatedAddColor(Palette &output, byte firstIndex, byte lastIndex, signed r, signed g, signed b) const;
|
||||
|
||||
/**
|
||||
* Saturated add an RGB color in given color format to current palette's subset and save the modified colors in the given output palette.
|
||||
* @param output The output palette (Only this palette is modified)
|
||||
* @param firstIndex First color index of the palette's subset (Inclusive range)
|
||||
* @param lastIndex Last color index of the palette's subset (Inclusive range)
|
||||
* @param rSource The red color component in the source color format
|
||||
* @param gSource The green color component in the source color format
|
||||
* @param bSource The blue color component in the source color format
|
||||
* @param sourceFormat The source color format (i.e. the color format of the given RGB color)
|
||||
* @note This function basically converts the given color to the palette's internal color format
|
||||
* and adds that using the normal saturatedAddColor-function.
|
||||
*/
|
||||
Palette &saturatedAddColor(Palette &output, byte firstIndex, byte lastIndex, signed rSource, signed gSource, signed bSource, const Graphics::PixelFormat &sourceFormat) const;
|
||||
|
||||
/**
|
||||
* Saturated add a normalized gray value to current palette's subset and save the modified colors in the given output palette.
|
||||
* @param output The output palette (Only this palette is modified)
|
||||
* @param firstIndex First color index of the palette's subset (Inclusive range)
|
||||
* @param lastIndex Last color index of the palette's subset (Inclusive range)
|
||||
* @param grayDividend Dividend of the normalized gray value
|
||||
* @param grayDenominator Denominator of the normalized gray value
|
||||
* @note The normalized gray value (i.e. in range [-1, +1]) is given as a fractional number
|
||||
* (i.e. the normalized gray value is calculated by dividing grayDividend by grayDenominator).
|
||||
*/
|
||||
Palette &saturatedAddNormalizedGray(Palette &output, byte firstIndex, byte lastIndex, signed grayDividend, signed grayDenominator) const;
|
||||
|
||||
bool empty() const;
|
||||
uint colorCount() const;
|
||||
Palette &fillWithBlack();
|
||||
|
||||
/** Is the palette valid? (Mostly just checks the color format for correctness) */
|
||||
bool isValid() const;
|
||||
|
||||
/** The original color format in which this palette was loaded. */
|
||||
const Graphics::PixelFormat &colorFormat() const;
|
||||
|
||||
/** Sets current palette to global OSystem's palette using g_system->getPaletteManager()->setPalette. */
|
||||
void setGlobalOSystemPalette() const;
|
||||
|
||||
/** Get the color at the given palette index. */
|
||||
Color getColor(byte index) const;
|
||||
|
||||
/** Get the red color component of the color at the given palette index. */
|
||||
uint8 getR(byte index) const;
|
||||
|
||||
/** Get the green color component of the color at the given palette index. */
|
||||
uint8 getG(byte index) const;
|
||||
|
||||
/** Get the blue color component of the color at the given palette index. */
|
||||
uint8 getB(byte index) const;
|
||||
|
||||
bool ensureContrast(byte &minBrightnessColorIndex);
|
||||
bool isEqual(byte index1, byte index2);
|
||||
|
||||
private:
|
||||
int findMinBrightnessColorIndex(uint minColorIndex = 1);
|
||||
byte brightness(byte colorIndex);
|
||||
void setColorFormat(const Graphics::PixelFormat &format);
|
||||
void saturatedAddColor(Color &result, const Color &baseColor, signed r, signed g, signed b) const;
|
||||
|
||||
private:
|
||||
Graphics::PixelFormat _format; ///< The used source color format
|
||||
Common::Array<Color> _colors; ///< The actual palette data
|
||||
};
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
377
engines/cine/part.cpp
Normal file
377
engines/cine/part.cpp
Normal file
@@ -0,0 +1,377 @@
|
||||
/* 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/debug.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/unpack.h"
|
||||
#include "cine/various.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
void loadPart(const char *partName) {
|
||||
g_cine->_partBuffer.clear();
|
||||
|
||||
g_cine->_partFileHandle.close();
|
||||
|
||||
checkDataDisk(-1);
|
||||
|
||||
if (!g_cine->_partFileHandle.open(partName))
|
||||
error("loadPart(): Cannot open file %s", partName);
|
||||
|
||||
setMouseCursor(MOUSE_CURSOR_DISK);
|
||||
|
||||
uint16 numElementInPart = g_cine->_partFileHandle.readUint16BE();
|
||||
g_cine->_partBuffer.resize(numElementInPart);
|
||||
g_cine->_partFileHandle.readUint16BE(); // entry size
|
||||
|
||||
if (currentPartName != partName)
|
||||
Common::strlcpy(currentPartName, partName, sizeof(currentPartName));
|
||||
|
||||
for (uint16 i = 0; i < g_cine->_partBuffer.size(); i++) {
|
||||
g_cine->_partFileHandle.read(g_cine->_partBuffer[i].partName, 14);
|
||||
g_cine->_partBuffer[i].offset = g_cine->_partFileHandle.readUint32BE();
|
||||
g_cine->_partBuffer[i].packedSize = g_cine->_partFileHandle.readUint32BE();
|
||||
g_cine->_partBuffer[i].unpackedSize = g_cine->_partFileHandle.readUint32BE();
|
||||
g_cine->_partFileHandle.readUint32BE(); // unused
|
||||
}
|
||||
|
||||
if (g_cine->getGameType() == Cine::GType_FW && g_cine->getPlatform() == Common::kPlatformDOS && strcmp(partName, "BASESON.SND") != 0)
|
||||
loadPal(partName);
|
||||
}
|
||||
|
||||
void closePart() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
static Common::String fixVolCnfFileName(const uint8 *src, uint len) {
|
||||
assert(len == 11 || len == 13);
|
||||
// Copy source to a temporary buffer and force a trailing zero for string manipulation
|
||||
char tmp[14];
|
||||
memcpy(tmp, src, len);
|
||||
tmp[len] = 0;
|
||||
Common::String result;
|
||||
|
||||
if (len == 11) {
|
||||
// Filenames of length 11 have no separation of the extension and the basename
|
||||
// so that's why we have to convert them first. There's no trailing zero in them
|
||||
// either and they're always of the full length 11 with padding spaces. Extension
|
||||
// can be always found at offset 8 onwards.
|
||||
//
|
||||
// Examples of filename mappings:
|
||||
// "AEROPORTMSG" -> "AEROPORT.MSG"
|
||||
// "MITRAILLHP " -> "MITRAILL.HP" (Notice the trailing space after the extension)
|
||||
// "BOND10 " -> "BOND10"
|
||||
// "GIRL SET" -> "GIRL.SET"
|
||||
|
||||
// Replace all space characters with zeroes
|
||||
for (uint i = 0; i < len; i++)
|
||||
if (tmp[i] == ' ')
|
||||
tmp[i] = 0;
|
||||
// Extract the filename's extension
|
||||
Common::String extension(tmp + 8);
|
||||
tmp[8] = 0; // Force separation of extension and basename
|
||||
Common::String basename(tmp);
|
||||
if (extension.empty()) {
|
||||
result = basename;
|
||||
} else {
|
||||
result = basename + "." + extension;
|
||||
}
|
||||
} else {
|
||||
// Filenames of length 13 are okay as they are, no need for conversion
|
||||
result = Common::String(tmp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void CineEngine::readVolCnf() {
|
||||
Common::File f;
|
||||
if (!f.open("vol.cnf")) {
|
||||
error("Unable to open 'vol.cnf'");
|
||||
}
|
||||
uint32 unpackedSize, packedSize;
|
||||
char hdr[8];
|
||||
f.read(hdr, 8);
|
||||
bool compressed = (memcmp(hdr, "ABASECP", 7) == 0);
|
||||
if (compressed) {
|
||||
unpackedSize = f.readUint32BE();
|
||||
packedSize = f.readUint32BE();
|
||||
} else {
|
||||
f.seek(0);
|
||||
unpackedSize = packedSize = f.size();
|
||||
}
|
||||
uint8 *buf = new uint8[unpackedSize];
|
||||
uint8 *packedBuf = new uint8[packedSize];
|
||||
f.read(packedBuf, packedSize);
|
||||
CineUnpacker cineUnpacker;
|
||||
if (!cineUnpacker.unpack(packedBuf, packedSize, buf, unpackedSize)) {
|
||||
error("Error while unpacking 'vol.cnf' data");
|
||||
}
|
||||
delete[] packedBuf;
|
||||
Common::Array<VolumeResource> volumeResourceFiles;
|
||||
uint8 *p = buf;
|
||||
int resourceFilesCount = READ_BE_INT16(p); p += 2;
|
||||
int entrySize = READ_BE_INT16(p); p += 2;
|
||||
for (int i = 0; i < resourceFilesCount; ++i) {
|
||||
Common::MemoryReadStream readS(p, 0x14);
|
||||
VolumeResource res;
|
||||
readS.read(res.name, sizeof(res.name));
|
||||
res.name[sizeof(res.name) - 1] = 0;
|
||||
res.pNamesList = readS.readUint32BE();
|
||||
res.diskNum = readS.readSint16BE();
|
||||
res.sizeOfNamesList = readS.readUint32BE();
|
||||
volumeResourceFiles.push_back(res);
|
||||
p += entrySize;
|
||||
}
|
||||
|
||||
// Check file name blocks' sizes
|
||||
bool fileNameLenMod11, fileNameLenMod13;
|
||||
fileNameLenMod11 = fileNameLenMod13 = true;
|
||||
for (int i = 0; i < resourceFilesCount; ++i) {
|
||||
int size = READ_BE_UINT32(p); p += 4;
|
||||
fileNameLenMod11 &= ((size % 11) == 0);
|
||||
fileNameLenMod13 &= ((size % 13) == 0);
|
||||
p += size;
|
||||
}
|
||||
// Make sure at least one of the candidates for file name length fits the data
|
||||
assert(fileNameLenMod11 || fileNameLenMod13);
|
||||
|
||||
// File name length used to be deduced from the fact whether the file
|
||||
// was compressed or not. Compressed files used file name length 11,
|
||||
// uncompressed files used file name length 13. It worked almost always,
|
||||
// but not with the game entry that's detected as the Operation Stealth's
|
||||
// US Amiga release. It uses a compressed 'vol.cnf' file but still uses
|
||||
// file names of length 13. So we try to deduce the file name length from
|
||||
// the data in the 'vol.cnf' file.
|
||||
int fileNameLength;
|
||||
if (fileNameLenMod11 != fileNameLenMod13) {
|
||||
// All file name blocks' sizes were divisible by either 11 or 13, but not with both.
|
||||
fileNameLength = (fileNameLenMod11 ? 11 : 13);
|
||||
} else {
|
||||
warning("Couldn't deduce file name length from data in 'vol.cnf', using a backup deduction scheme");
|
||||
// Here we use the former file name length detection method
|
||||
// if we couldn't deduce the file name length from the data.
|
||||
fileNameLength = (compressed ? 11 : 13);
|
||||
}
|
||||
|
||||
p = buf + 4 + resourceFilesCount * entrySize;
|
||||
for (int i = 0; i < resourceFilesCount; ++i) {
|
||||
const VolumeResource& volRes = volumeResourceFiles[i];
|
||||
int count = READ_BE_UINT32(p) / fileNameLength; p += 4;
|
||||
while (count--) {
|
||||
Common::String volumeEntryName = fixVolCnfFileName(p, fileNameLength);
|
||||
if (!_volumeEntriesMap.contains(volumeEntryName)) {
|
||||
_volumeEntriesMap.setVal(volumeEntryName, Common::Array<VolumeResource>());
|
||||
}
|
||||
_volumeEntriesMap.find(volumeEntryName)->_value.push_back(volRes);
|
||||
debugC(5, kCineDebugPart, "Added volume entry name '%s', disk number %d, resource file '%s'", volumeEntryName.c_str(), volRes.diskNum, volRes.name);
|
||||
p += fileNameLength;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
int16 findFileInBundle(const char *fileName) {
|
||||
// HACK: Fix underwater background palette by reading it from correct file
|
||||
if (hacksEnabled && g_cine->getGameType() == Cine::GType_OS &&
|
||||
scumm_stricmp(currentPrcName, "SOUSMAR2.PRC") == 0 &&
|
||||
g_cine->_volumeEntriesMap.contains(fileName)) {
|
||||
Common::Array<VolumeResource> volRes = g_cine->_volumeEntriesMap.find(fileName)->_value;
|
||||
if (volRes.size() == 2 && scumm_stricmp(volRes[0].name, "rsc12") == 0 &&
|
||||
scumm_stricmp(volRes[1].name, "rsc08") == 0 &&
|
||||
(scumm_stricmp(fileName, "39.PI1") == 0 ||
|
||||
scumm_stricmp(fileName, "SP39_11.SET") == 0 ||
|
||||
scumm_stricmp(fileName, "SP39_12.SET") == 0)) {
|
||||
debugC(5, kCineDebugPart, "Reading underwater background and fish from file rsc12 for the original (broken) palette.");
|
||||
loadPart("rsc08");
|
||||
}
|
||||
}
|
||||
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
for (uint i = 0; i < g_cine->_partBuffer.size(); i++) {
|
||||
if (!scumm_stricmp(fileName, g_cine->_partBuffer[i].partName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
StringToVolumeResourceArrayHashMap::const_iterator it = g_cine->_volumeEntriesMap.find(fileName);
|
||||
if (it == g_cine->_volumeEntriesMap.end()) {
|
||||
warning("Unable to find part file for filename '%s'", fileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Prefer current disk's resource file
|
||||
Common::Array<VolumeResource> volRes = it->_value;
|
||||
VolumeResource match = volRes[0];
|
||||
for (uint i = 0; i < volRes.size(); i++) {
|
||||
if (volRes[i].diskNum == currentDisk) {
|
||||
match = volRes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
checkDataDisk(match.diskNum);
|
||||
loadPart(match.name);
|
||||
}
|
||||
for (uint i = 0; i < g_cine->_partBuffer.size(); i++) {
|
||||
if (!scumm_stricmp(fileName, g_cine->_partBuffer[i].partName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void readFromPart(int16 idx, byte *dataPtr, uint32 maxSize) {
|
||||
assert(maxSize >= g_cine->_partBuffer[idx].packedSize);
|
||||
setMouseCursor(MOUSE_CURSOR_DISK);
|
||||
|
||||
g_cine->_partFileHandle.seek(g_cine->_partBuffer[idx].offset, SEEK_SET);
|
||||
g_cine->_partFileHandle.read(dataPtr, g_cine->_partBuffer[idx].packedSize);
|
||||
}
|
||||
|
||||
byte *readBundleFile(int16 foundFileIdx, uint32 *size) {
|
||||
assert(foundFileIdx >= 0 && foundFileIdx < (int32)g_cine->_partBuffer.size());
|
||||
bool error = false;
|
||||
byte *dataPtr = (byte *)calloc(g_cine->_partBuffer[foundFileIdx].unpackedSize, 1);
|
||||
byte *packedData = (byte *)calloc(g_cine->_partBuffer[foundFileIdx].packedSize, 1);
|
||||
assert(dataPtr && packedData);
|
||||
readFromPart(foundFileIdx, packedData, g_cine->_partBuffer[foundFileIdx].packedSize);
|
||||
CineUnpacker cineUnpacker;
|
||||
error = !cineUnpacker.unpack(packedData, g_cine->_partBuffer[foundFileIdx].packedSize, dataPtr, g_cine->_partBuffer[foundFileIdx].unpackedSize);
|
||||
free(packedData);
|
||||
|
||||
if (error) {
|
||||
warning("Error unpacking '%s' from bundle file '%s'", g_cine->_partBuffer[foundFileIdx].partName, currentPartName);
|
||||
}
|
||||
|
||||
// Set the size variable if a pointer to it has been given
|
||||
if (size != nullptr) {
|
||||
*size = g_cine->_partBuffer[foundFileIdx].unpackedSize;
|
||||
}
|
||||
|
||||
return dataPtr;
|
||||
}
|
||||
|
||||
byte *readBundleSoundFileOS(const char *entryName, uint32 *size) {
|
||||
int16 index = findFileInBundle(entryName);
|
||||
if (index == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return readBundleFile(index, size);
|
||||
}
|
||||
|
||||
byte *readBundleSoundFileFW(const char *entryName, uint32 *size) {
|
||||
int16 index;
|
||||
byte *data = nullptr;
|
||||
char previousPartName[15] = "";
|
||||
|
||||
if (g_cine->getGameType() == Cine::GType_FW) {
|
||||
Common::strcpy_s(previousPartName, currentPartName);
|
||||
loadPart("BASESON.SND");
|
||||
}
|
||||
index = findFileInBundle((const char *)entryName);
|
||||
if (index != -1) {
|
||||
data = readBundleFile(index);
|
||||
if (size) {
|
||||
*size = g_cine->_partBuffer[index].unpackedSize;
|
||||
}
|
||||
}
|
||||
if (g_cine->getGameType() == Cine::GType_FW) {
|
||||
loadPart(previousPartName);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
byte *readBundleSoundFile(const char *entryName, uint32 *size) {
|
||||
if (g_cine->getGameType() == Cine::GType_FW) {
|
||||
return readBundleSoundFileFW(entryName, size);
|
||||
} else {
|
||||
return readBundleSoundFileOS(entryName, size);
|
||||
}
|
||||
}
|
||||
|
||||
/** Rotate byte value to the left by n bits */
|
||||
byte rolByte(byte value, uint n) {
|
||||
n %= 8;
|
||||
return (byte)((value << n) | (value >> (8 - n)));
|
||||
}
|
||||
|
||||
byte *readFile(const char *filename, bool crypted) {
|
||||
Common::File in;
|
||||
|
||||
in.open(filename);
|
||||
|
||||
if (!in.isOpen())
|
||||
error("readFile(): Cannot open file %s", filename);
|
||||
|
||||
uint32 size = in.size();
|
||||
|
||||
byte *dataPtr = (byte *)malloc(size);
|
||||
in.read(dataPtr, size);
|
||||
|
||||
// The Sony published CD version of Future Wars has its
|
||||
// AUTO00.PRC file's bytes rotated to the right by one.
|
||||
// So we decode the so called crypting by rotating all
|
||||
// the bytes to the left by one.
|
||||
if (crypted) {
|
||||
for (uint index = 0; index < size; index++) {
|
||||
dataPtr[index] = rolByte(dataPtr[index], 1);
|
||||
}
|
||||
}
|
||||
|
||||
return dataPtr;
|
||||
}
|
||||
|
||||
void checkDataDisk(int16 diskNum) {
|
||||
if (diskNum != -1) {
|
||||
currentDisk = diskNum;
|
||||
}
|
||||
}
|
||||
|
||||
void dumpBundle(const char *fileName) {
|
||||
char tmpPart[15];
|
||||
|
||||
Common::strcpy_s(tmpPart, currentPartName);
|
||||
|
||||
loadPart(fileName);
|
||||
for (uint i = 0; i < g_cine->_partBuffer.size(); i++) {
|
||||
byte *data = readBundleFile(i);
|
||||
|
||||
debug(0, "%s", g_cine->_partBuffer[i].partName);
|
||||
|
||||
Common::DumpFile out;
|
||||
if (out.open(Common::Path("dumps/").appendInPlace(g_cine->_partBuffer[i].partName))) {
|
||||
out.write(data, g_cine->_partBuffer[i].unpackedSize);
|
||||
out.close();
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
loadPart(tmpPart);
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
53
engines/cine/part.h
Normal file
53
engines/cine/part.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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 CINE_PART_H
|
||||
#define CINE_PART_H
|
||||
|
||||
namespace Cine {
|
||||
|
||||
struct PartBuffer {
|
||||
char partName[14];
|
||||
uint32 offset;
|
||||
uint32 packedSize;
|
||||
uint32 unpackedSize;
|
||||
};
|
||||
|
||||
#define NUM_MAX_PARTDATA 255
|
||||
|
||||
void loadPart(const char *partName);
|
||||
void closePart();
|
||||
|
||||
int16 findFileInBundle(const char *fileName);
|
||||
|
||||
void readFromPart(int16 idx, byte *dataPtr, uint32 maxSize);
|
||||
|
||||
byte *readBundleFile(int16 foundFileIdx, uint32 *size = NULL);
|
||||
byte *readBundleSoundFile(const char *entryName, uint32 *size = 0);
|
||||
byte *readFile(const char *filename, bool crypted = false);
|
||||
|
||||
void checkDataDisk(int16 param);
|
||||
|
||||
void dumpBundle(const char *filename);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
114
engines/cine/prc.cpp
Normal file
114
engines/cine/prc.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/* 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/endian.h"
|
||||
#include "common/events.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/system.h" // for g_system->getEventManager()
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/various.h"
|
||||
|
||||
|
||||
namespace Cine {
|
||||
|
||||
//char currentPrcName[20];
|
||||
|
||||
/**
|
||||
* @todo Is script size of 0 valid?
|
||||
* @todo Fix script dump code
|
||||
* @return Was the loading successful?
|
||||
*/
|
||||
bool loadPrc(const char *pPrcName) {
|
||||
byte i;
|
||||
uint16 numScripts;
|
||||
byte *scriptPtr, *dataPtr;
|
||||
|
||||
assert(pPrcName);
|
||||
|
||||
g_cine->_globalScripts.clear();
|
||||
g_cine->_scriptTable.clear();
|
||||
|
||||
// This is copy protection. Used to hang the machine
|
||||
if (!scumm_stricmp(pPrcName, COPY_PROT_FAIL_PRC_NAME)) {
|
||||
Common::Event event;
|
||||
event.type = Common::EVENT_RETURN_TO_LAUNCHER;
|
||||
g_system->getEventManager()->pushEvent(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
checkDataDisk(-1);
|
||||
if ((g_cine->getGameType() == Cine::GType_FW) &&
|
||||
(!scumm_stricmp(pPrcName, BOOT_PRC_NAME) || !scumm_stricmp(pPrcName, "demo.prc"))) {
|
||||
scriptPtr = dataPtr = readFile(pPrcName, (g_cine->getFeatures() & GF_CRYPTED_BOOT_PRC) != 0);
|
||||
} else {
|
||||
checkDataDisk(-1);
|
||||
scriptPtr = dataPtr = readBundleFile(findFileInBundle(pPrcName));
|
||||
}
|
||||
|
||||
assert(scriptPtr);
|
||||
|
||||
setMouseCursor(MOUSE_CURSOR_DISK);
|
||||
|
||||
numScripts = READ_BE_UINT16(scriptPtr);
|
||||
scriptPtr += 2;
|
||||
assert(numScripts <= NUM_MAX_SCRIPT);
|
||||
|
||||
for (i = 0; i < numScripts; i++) {
|
||||
RawScriptPtr tmp(new RawScript(READ_BE_UINT16(scriptPtr)));
|
||||
scriptPtr += 2;
|
||||
assert(tmp);
|
||||
g_cine->_scriptTable.push_back(tmp);
|
||||
}
|
||||
|
||||
for (i = 0; i < numScripts; i++) {
|
||||
uint16 size = g_cine->_scriptTable[i]->_size;
|
||||
// TODO: delete the test?
|
||||
if (size) {
|
||||
g_cine->_scriptTable[i]->setData(*g_cine->_scriptInfo, scriptPtr);
|
||||
scriptPtr += size;
|
||||
}
|
||||
}
|
||||
|
||||
free(dataPtr);
|
||||
|
||||
#ifdef DUMP_SCRIPTS
|
||||
|
||||
{
|
||||
uint16 s;
|
||||
char buffer[256];
|
||||
|
||||
for (s = 0; s < numScripts; s++) {
|
||||
if (g_cine->_scriptTable[s]->_size) {
|
||||
Common::sprintf_s(buffer, "%s_%03d.txt", pPrcName, s);
|
||||
|
||||
decompileScript((const byte *)g_cine->_scriptTable[s]->getString(0), g_cine->_scriptTable[s]->_size, s);
|
||||
dumpScript(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
31
engines/cine/prc.h
Normal file
31
engines/cine/prc.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* 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 CINE_PRC_H
|
||||
#define CINE_PRC_H
|
||||
|
||||
namespace Cine {
|
||||
|
||||
bool loadPrc(const char *pPrcName);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
90
engines/cine/rel.cpp
Normal file
90
engines/cine/rel.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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/endian.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/various.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
/**
|
||||
* @todo Is script size of 0 valid?
|
||||
* @todo Fix script dump code
|
||||
*/
|
||||
void loadRel(char *pRelName) {
|
||||
uint16 numEntry;
|
||||
uint16 i;
|
||||
uint16 size, p1, p2, p3;
|
||||
byte *ptr, *dataPtr;
|
||||
|
||||
checkDataDisk(-1);
|
||||
|
||||
g_cine->_objectScripts.clear();
|
||||
g_cine->_relTable.clear();
|
||||
|
||||
ptr = dataPtr = readBundleFile(findFileInBundle(pRelName));
|
||||
|
||||
setMouseCursor(MOUSE_CURSOR_DISK);
|
||||
|
||||
numEntry = READ_BE_UINT16(ptr); ptr += 2;
|
||||
|
||||
for (i = 0; i < numEntry; i++) {
|
||||
size = READ_BE_UINT16(ptr); ptr += 2;
|
||||
p1 = READ_BE_UINT16(ptr); ptr += 2;
|
||||
p2 = READ_BE_UINT16(ptr); ptr += 2;
|
||||
p3 = READ_BE_UINT16(ptr); ptr += 2;
|
||||
RawObjectScriptPtr tmp(new RawObjectScript(size, p1, p2, p3));
|
||||
assert(tmp);
|
||||
g_cine->_relTable.push_back(tmp);
|
||||
}
|
||||
|
||||
for (i = 0; i < numEntry; i++) {
|
||||
size = g_cine->_relTable[i]->_size;
|
||||
// TODO: delete the test?
|
||||
if (size) {
|
||||
g_cine->_relTable[i]->setData(*g_cine->_scriptInfo, ptr);
|
||||
ptr += size;
|
||||
}
|
||||
}
|
||||
|
||||
free(dataPtr);
|
||||
|
||||
#ifdef DUMP_SCRIPTS
|
||||
|
||||
{
|
||||
uint16 s;
|
||||
char buffer[256];
|
||||
|
||||
for (s = 0; s < numEntry; s++) {
|
||||
if (g_cine->_relTable[s]->_size) {
|
||||
Common::sprintf_s(buffer, "%s_%03d.txt", pRelName, s);
|
||||
|
||||
decompileScript((const byte *)g_cine->_relTable[s]->getString(0), g_cine->_relTable[s]->_size, s);
|
||||
dumpScript(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
32
engines/cine/rel.h
Normal file
32
engines/cine/rel.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* 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 CINE_REL_H
|
||||
#define CINE_REL_H
|
||||
|
||||
#include "cine/script.h"
|
||||
namespace Cine {
|
||||
|
||||
void loadRel(char *pRelName);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
1102
engines/cine/saveload.cpp
Normal file
1102
engines/cine/saveload.cpp
Normal file
File diff suppressed because it is too large
Load Diff
104
engines/cine/saveload.h
Normal file
104
engines/cine/saveload.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* 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 CINE_SAVELOAD_H
|
||||
#define CINE_SAVELOAD_H
|
||||
|
||||
#include "common/endian.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
extern int16 currentDisk;
|
||||
|
||||
/**
|
||||
* Cine engine's save game formats.
|
||||
* Enumeration entries (Excluding the one used as an error)
|
||||
* are sorted according to age (i.e. top one is oldest, last one newest etc).
|
||||
*
|
||||
* ANIMSIZE_UNKNOWN:
|
||||
* - Animation data entry size is unknown (Used as an error).
|
||||
*
|
||||
* ANIMSIZE_23:
|
||||
* - Animation data entry size is 23 bytes.
|
||||
* - Used at least by 0.11.0 and 0.11.1 releases of ScummVM.
|
||||
* - Introduced in revision 21772, stopped using in revision 31444.
|
||||
*
|
||||
* ANIMSIZE_30_PTRS_BROKEN:
|
||||
* - Animation data entry size is 30 bytes.
|
||||
* - Data and mask pointers in the saved structs are always NULL.
|
||||
* - Introduced in revision 31453, stopped using in revision 32073.
|
||||
*
|
||||
* ANIMSIZE_30_PTRS_INTACT:
|
||||
* - Animation data entry size is 30 bytes.
|
||||
* - Data and mask pointers in the saved structs are intact,
|
||||
* so you can test them for equality or inequality with NULL
|
||||
* but don't try using them for anything else, it won't work.
|
||||
* - Introduced in revision 31444, got broken in revision 31453,
|
||||
* got fixed in revision 32073 and used after that.
|
||||
*
|
||||
* TEMP_OS_FORMAT:
|
||||
* - Temporary Operation Stealth savegame format.
|
||||
* - NOT backward compatible and NOT to be supported in the future.
|
||||
* This format should ONLY be used during development and abandoned
|
||||
* later in favor of a better format!
|
||||
*/
|
||||
enum CineSaveGameFormat {
|
||||
ANIMSIZE_UNKNOWN,
|
||||
ANIMSIZE_23,
|
||||
ANIMSIZE_30_PTRS_BROKEN,
|
||||
ANIMSIZE_30_PTRS_INTACT,
|
||||
TEMP_OS_FORMAT,
|
||||
VERSIONED_FW_FORMAT,
|
||||
VERSIONED_OS_FORMAT
|
||||
};
|
||||
|
||||
/** Identifier for the temporary Operation Stealth savegame format. */
|
||||
static const uint32 TEMP_OS_FORMAT_ID = MKTAG('T', 'E', 'M', 'P');
|
||||
|
||||
/** Identifiers for versioned Future Wars and Operation Stealth savegame formats. */
|
||||
static const uint32 VERSIONED_FW_FORMAT_ID = MKTAG('C', '1', 'F', 'W');
|
||||
static const uint32 VERSIONED_OS_FORMAT_ID = MKTAG('C', '2', 'O', 'S');
|
||||
|
||||
/** The current version number of versioned Future Wars and Operation Stealth savegame formats.
|
||||
Version 4: First version used. Added disableSystemMenu to Future Wars savegame format.
|
||||
*/
|
||||
static const uint32 CURRENT_SAVE_VER = 4;
|
||||
|
||||
/** The last version number of temporary Operation Stealth's savegame format.
|
||||
Version 0: Color count was not saved, was assumed to be 256. BGIncrust.bgIdx does not exist, _currentBg was used.
|
||||
Version 1: Saving of real color count was added but still 256 colors were always saved.
|
||||
Version 2: BGIncrust.bgIdx was added.
|
||||
Version 3: Saving real values for current music name, music playing status, current background index,
|
||||
scroll background index and background scrolling was added.
|
||||
*/
|
||||
static const uint32 LAST_TEMP_OS_SAVE_VER = 3;
|
||||
|
||||
/** Chunk header used by the temporary Operation Stealth savegame format. */
|
||||
struct ChunkHeader {
|
||||
uint32 id; ///< Identifier (e.g. MKTAG('T','E','M','P'))
|
||||
uint32 version; ///< Version number
|
||||
uint32 size; ///< Size of the chunk after this header in bytes
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
392
engines/cine/script.h
Normal file
392
engines/cine/script.h
Normal file
@@ -0,0 +1,392 @@
|
||||
/* 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 CINE_SCRIPT_H
|
||||
#define CINE_SCRIPT_H
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/array.h"
|
||||
#include "common/list.h"
|
||||
#include "common/ptr.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
#define SCRIPT_STACK_SIZE 50
|
||||
#define LOCAL_VARS_SIZE 50
|
||||
|
||||
/**
|
||||
* Fixed size array of script variables.
|
||||
*
|
||||
* Array size can be set in constructors, once the instance is created,
|
||||
* it cannot be changed directly.
|
||||
*/
|
||||
|
||||
class FWScript;
|
||||
|
||||
typedef int (FWScript::*OpFunc)();
|
||||
|
||||
struct Opcode {
|
||||
OpFunc proc;
|
||||
const char *args;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fixed size array for script variables
|
||||
*/
|
||||
class ScriptVars {
|
||||
private:
|
||||
unsigned int _size; ///< Size of array
|
||||
int16 *_vars; ///< Variable values
|
||||
|
||||
public:
|
||||
// Explicit to prevent var=0 instead of var[i]=0 typos.
|
||||
explicit ScriptVars(unsigned int len = 50);
|
||||
ScriptVars(Common::SeekableReadStream &fHandle, unsigned int len = 50);
|
||||
ScriptVars(const ScriptVars &src);
|
||||
~ScriptVars();
|
||||
|
||||
void reinit(unsigned int len);
|
||||
ScriptVars &operator=(const ScriptVars &src);
|
||||
int16 &operator[](unsigned int idx);
|
||||
int16 operator[](unsigned int idx) const;
|
||||
|
||||
void save(Common::OutSaveFile &fHandle) const;
|
||||
void save(Common::OutSaveFile &fHandle, unsigned int len) const;
|
||||
void load(Common::SeekableReadStream &fHandle);
|
||||
void load(Common::SeekableReadStream &fHandle, unsigned int len);
|
||||
void reset();
|
||||
};
|
||||
|
||||
class FWScriptInfo;
|
||||
|
||||
/**
|
||||
* Script bytecode and initial labels, ScriptStruct replacement.
|
||||
*
|
||||
* _data is one byte longer to make sure strings in bytecode are properly
|
||||
* terminated
|
||||
*/
|
||||
class RawScript {
|
||||
private:
|
||||
byte *_data; ///< Script bytecode
|
||||
ScriptVars _labels; ///< Initial script labels
|
||||
|
||||
protected:
|
||||
void computeLabels(const FWScriptInfo &info);
|
||||
int getNextLabel(const FWScriptInfo &info, int offset) const;
|
||||
|
||||
public:
|
||||
uint16 _size; ///< Bytecode length
|
||||
|
||||
explicit RawScript(uint16 size);
|
||||
RawScript(const FWScriptInfo &info, const byte *data, uint16 size);
|
||||
RawScript(const RawScript &src);
|
||||
~RawScript();
|
||||
|
||||
RawScript &operator=(const RawScript &src);
|
||||
|
||||
void setData(const FWScriptInfo &info, const byte *data);
|
||||
const ScriptVars &labels() const;
|
||||
byte getByte(unsigned int pos) const;
|
||||
uint16 getWord(unsigned int pos) const;
|
||||
const char *getString(unsigned int pos) const;
|
||||
uint16 getLabel(const FWScriptInfo &info, byte index, uint16 offset) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Object script class, RelObjectScript replacement
|
||||
*
|
||||
* Script parameters are not used, this class is required by different
|
||||
* script initialization of object scripts
|
||||
*/
|
||||
class RawObjectScript : public RawScript {
|
||||
public:
|
||||
int16 _runCount; ///< How many times the script was used
|
||||
uint16 _param1; ///< Additional parameter not used at the moment
|
||||
uint16 _param2; ///< Additional parameter not used at the moment
|
||||
uint16 _param3; ///< Additional parameter not used at the moment
|
||||
|
||||
RawObjectScript(uint16 size, uint16 p1, uint16 p2, uint16 p3);
|
||||
RawObjectScript(const FWScriptInfo &info, const byte *data, uint16 size, uint16 p1, uint16 p2, uint16 p3);
|
||||
|
||||
/**
|
||||
* Run the script one more time.
|
||||
* @return Run count before incrementation
|
||||
*/
|
||||
int16 run() { return _runCount++; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Future Wars script, prcLinkedListStruct replacement.
|
||||
* @todo Rewrite _globalVars initialization
|
||||
*/
|
||||
class FWScript {
|
||||
private:
|
||||
const RawScript &_script; ///< Script bytecode reference
|
||||
uint16 _pos; ///< Current position in script
|
||||
uint16 _line; ///< Current opcode index in bytecode for debugging
|
||||
uint16 _compare; ///< Last compare result
|
||||
ScriptVars _labels; ///< Current script labels
|
||||
ScriptVars _localVars; ///< Local script variables
|
||||
ScriptVars &_globalVars; ///< Global variables reference
|
||||
FWScriptInfo *_info; ///< Script info
|
||||
|
||||
protected:
|
||||
static const Opcode *_opcodeTable;
|
||||
static unsigned int _numOpcodes;
|
||||
|
||||
int o1_modifyObjectParam();
|
||||
int o1_getObjectParam();
|
||||
int o1_addObjectParam();
|
||||
int o1_subObjectParam();
|
||||
int o1_mulObjectParam();
|
||||
int o1_divObjectParam();
|
||||
int o1_compareObjectParam();
|
||||
int o1_setupObject();
|
||||
int o1_checkCollision();
|
||||
int o1_loadVar();
|
||||
int o1_addVar();
|
||||
int o1_subVar();
|
||||
int o1_mulVar();
|
||||
int o1_divVar();
|
||||
int o1_compareVar();
|
||||
int o1_modifyObjectParam2();
|
||||
int o1_loadMask0();
|
||||
int o1_unloadMask0();
|
||||
int o1_addToBgList();
|
||||
int o1_loadMask1();
|
||||
int o1_unloadMask1();
|
||||
int o1_loadMask4();
|
||||
int o1_unloadMask4();
|
||||
int o1_addSpriteFilledToBgList();
|
||||
int o1_clearBgIncrustList();
|
||||
int o1_label();
|
||||
int o1_goto();
|
||||
int o1_gotoIfSup();
|
||||
int o1_gotoIfSupEqu();
|
||||
int o1_gotoIfInf();
|
||||
int o1_gotoIfInfEqu();
|
||||
int o1_gotoIfEqu();
|
||||
int o1_gotoIfDiff();
|
||||
int o1_removeLabel();
|
||||
int o1_loop();
|
||||
int o1_startGlobalScript();
|
||||
int o1_endGlobalScript();
|
||||
int o1_loadAnim();
|
||||
int o1_loadBg();
|
||||
int o1_loadCt();
|
||||
int o1_loadPart();
|
||||
int o1_closePart();
|
||||
int o1_loadNewPrcName();
|
||||
int o1_requestCheckPendingDataLoad();
|
||||
int o1_blitAndFade();
|
||||
int o1_fadeToBlack();
|
||||
int o1_transformPaletteRange();
|
||||
int o1_setDefaultMenuBgColor();
|
||||
int o1_palRotate();
|
||||
int o1_break();
|
||||
int o1_endScript();
|
||||
int o1_message();
|
||||
int o1_loadGlobalVar();
|
||||
int o1_compareGlobalVar();
|
||||
int o1_declareFunctionName();
|
||||
int o1_freePartRange();
|
||||
int o1_unloadAllMasks();
|
||||
int o1_setScreenDimensions();
|
||||
int o1_displayBackground();
|
||||
int o1_initializeZoneData();
|
||||
int o1_setZoneDataEntry();
|
||||
int o1_getZoneDataEntry();
|
||||
int o1_setPlayerCommandPosY();
|
||||
int o1_allowPlayerInput();
|
||||
int o1_disallowPlayerInput();
|
||||
int o1_changeDataDisk();
|
||||
int o1_loadMusic();
|
||||
int o1_playMusic();
|
||||
int o1_fadeOutMusic();
|
||||
int o1_stopSample();
|
||||
int o1_op71();
|
||||
int o1_op72();
|
||||
int o1_op73();
|
||||
int o1_playSample();
|
||||
int o1_playSampleSwapped();
|
||||
int o1_disableSystemMenu();
|
||||
int o1_loadMask5();
|
||||
int o1_unloadMask5();
|
||||
|
||||
// pointers to member functions in C++ suck...
|
||||
int o2_loadCt();
|
||||
int o2_loadPart();
|
||||
int o2_addSeqListElement();
|
||||
int o2_removeSeq();
|
||||
int o2_playSample();
|
||||
int o2_playSampleAlt();
|
||||
int o2_clearSeqList();
|
||||
int o2_modifySeqListElement();
|
||||
int o2_isSeqRunning();
|
||||
int o2_gotoIfSupNearest();
|
||||
int o2_gotoIfSupEquNearest();
|
||||
int o2_gotoIfInfNearest();
|
||||
int o2_gotoIfInfEquNearest();
|
||||
int o2_gotoIfEquNearest();
|
||||
int o2_gotoIfDiffNearest();
|
||||
int o2_startObjectScript();
|
||||
int o2_stopObjectScript();
|
||||
int o2_op8D();
|
||||
int o2_addBackground();
|
||||
int o2_removeBackground();
|
||||
int o2_loadAbs();
|
||||
int o2_loadBg();
|
||||
int o2_wasZoneChecked();
|
||||
int o2_op9B();
|
||||
int o2_op9C();
|
||||
int o2_useBgScroll();
|
||||
int o2_setAdditionalBgVScroll();
|
||||
int o2_op9F();
|
||||
int o2_addGfxElementType20();
|
||||
int o2_removeGfxElementType20();
|
||||
int o2_addGfxElementType21();
|
||||
int o2_removeGfxElementType21();
|
||||
int o2_loadMask22();
|
||||
int o2_unloadMask22();
|
||||
|
||||
byte getNextByte();
|
||||
uint16 getNextWord();
|
||||
const char *getNextString();
|
||||
|
||||
void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);
|
||||
|
||||
FWScript(const RawScript &script, int16 index, FWScriptInfo *info);
|
||||
FWScript(RawObjectScript &script, int16 index, FWScriptInfo *info);
|
||||
FWScript(const FWScript &src, FWScriptInfo *info);
|
||||
|
||||
public:
|
||||
int16 _index; ///< Index in script table
|
||||
|
||||
static void setupTable();
|
||||
|
||||
FWScript(const RawScript &script, int16 index);
|
||||
// FWScript(const RawObjectScript &script, int16 index);
|
||||
FWScript(const FWScript &src);
|
||||
~FWScript();
|
||||
|
||||
int execute();
|
||||
void save(Common::OutSaveFile &fHandle) const;
|
||||
|
||||
friend class FWScriptInfo;
|
||||
|
||||
// workaround for bug in g++ which prevents protected member functions
|
||||
// of FWScript from being used in OSScript::_opcodeTable[]
|
||||
// initialization ("error: protected within this context")
|
||||
friend class OSScript;
|
||||
};
|
||||
|
||||
/**
|
||||
* Operation Stealth script, prcLinkedListStruct replacement
|
||||
*/
|
||||
class OSScript : public FWScript {
|
||||
private:
|
||||
static const Opcode *_opcodeTable;
|
||||
static unsigned int _numOpcodes;
|
||||
|
||||
protected:
|
||||
void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);
|
||||
|
||||
public:
|
||||
static void setupTable();
|
||||
|
||||
OSScript(const RawScript &script, int16 index);
|
||||
OSScript(RawObjectScript &script, int16 index);
|
||||
OSScript(const OSScript &src);
|
||||
|
||||
friend class OSScriptInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Future Wars script factory and info
|
||||
*/
|
||||
class FWScriptInfo {
|
||||
protected:
|
||||
virtual OpFunc opcodeHandler(byte opcode) const;
|
||||
|
||||
public:
|
||||
virtual ~FWScriptInfo() {}
|
||||
|
||||
virtual const char *opcodeInfo(byte opcode) const;
|
||||
virtual FWScript *create(const RawScript &script, int16 index) const;
|
||||
virtual FWScript *create(const RawObjectScript &script, int16 index) const;
|
||||
virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
|
||||
virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
|
||||
|
||||
friend class FWScript;
|
||||
};
|
||||
|
||||
/**
|
||||
* Operation Stealth script factory and info
|
||||
*/
|
||||
class OSScriptInfo : public FWScriptInfo {
|
||||
protected:
|
||||
OpFunc opcodeHandler(byte opcode) const override;
|
||||
|
||||
public:
|
||||
~OSScriptInfo() override {}
|
||||
|
||||
const char *opcodeInfo(byte opcode) const override;
|
||||
FWScript *create(const RawScript &script, int16 index) const override;
|
||||
FWScript *create(const RawObjectScript &script, int16 index) const override;
|
||||
FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const override;
|
||||
FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const override;
|
||||
|
||||
friend class FWScript;
|
||||
};
|
||||
|
||||
typedef Common::SharedPtr<FWScript> ScriptPtr;
|
||||
typedef Common::SharedPtr<RawScript> RawScriptPtr;
|
||||
typedef Common::SharedPtr<RawObjectScript> RawObjectScriptPtr;
|
||||
typedef Common::List<ScriptPtr> ScriptList;
|
||||
typedef Common::Array<RawScriptPtr> RawScriptArray;
|
||||
typedef Common::Array<RawObjectScriptPtr> RawObjectScriptArray;
|
||||
|
||||
#define NUM_MAX_SCRIPT 50
|
||||
|
||||
FWScriptInfo *setupOpcodes();
|
||||
|
||||
void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx);
|
||||
void dumpScript(char *dumpName);
|
||||
|
||||
#define OP_loadPart 0x3F
|
||||
#define OP_loadNewPrcName 0x41
|
||||
#define OP_requestCheckPendingDataLoad 0x42
|
||||
#define OP_endScript 0x50
|
||||
|
||||
void addScriptToGlobalScripts(uint16 idx);
|
||||
int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx);
|
||||
|
||||
void runObjectScript(int16 entryIdx);
|
||||
|
||||
void executeObjectScripts();
|
||||
void executeGlobalScripts();
|
||||
|
||||
void purgeObjectScripts();
|
||||
void purgeGlobalScripts();
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
3250
engines/cine/script_fw.cpp
Normal file
3250
engines/cine/script_fw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
881
engines/cine/script_os.cpp
Normal file
881
engines/cine/script_os.cpp
Normal file
@@ -0,0 +1,881 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Operation Stealth script interpreter file
|
||||
*/
|
||||
|
||||
#include "common/endian.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/bg_list.h"
|
||||
#include "cine/object.h"
|
||||
#include "cine/sound.h"
|
||||
#include "cine/various.h"
|
||||
#include "cine/script.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
const Opcode *OSScript::_opcodeTable = nullptr;
|
||||
unsigned int OSScript::_numOpcodes = 0;
|
||||
|
||||
void OSScript::setupTable() {
|
||||
static const Opcode opcodeTable[] = {
|
||||
/* 00 */
|
||||
{ &FWScript::o1_modifyObjectParam, "bbw" },
|
||||
{ &FWScript::o1_getObjectParam, "bbb" },
|
||||
{ &FWScript::o1_addObjectParam, "bbw" },
|
||||
{ &FWScript::o1_subObjectParam, "bbw" },
|
||||
/* 04 */
|
||||
{ &FWScript::o1_mulObjectParam, "bbw" },
|
||||
{ &FWScript::o1_divObjectParam, "bbw" },
|
||||
{ &FWScript::o1_compareObjectParam, "bbw" },
|
||||
{ &FWScript::o1_setupObject, "bwwww" },
|
||||
/* 08 */
|
||||
{ &FWScript::o1_checkCollision, "bwwww" },
|
||||
{ &FWScript::o1_loadVar, "bc" },
|
||||
{ &FWScript::o1_addVar, "bc" },
|
||||
{ &FWScript::o1_subVar, "bc" },
|
||||
/* 0C */
|
||||
{ &FWScript::o1_mulVar, "bc" },
|
||||
{ &FWScript::o1_divVar, "bc" },
|
||||
{ &FWScript::o1_compareVar, "bc" },
|
||||
{ &FWScript::o1_modifyObjectParam2, "bbb" },
|
||||
/* 10 */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_loadMask0, "b" },
|
||||
/* 14 */
|
||||
{ &FWScript::o1_unloadMask0, "b" },
|
||||
{ &FWScript::o1_addToBgList, "b" },
|
||||
{ &FWScript::o1_loadMask1, "b" },
|
||||
{ &FWScript::o1_unloadMask1, "b" },
|
||||
/* 18 */
|
||||
{ &FWScript::o1_loadMask4, "b" },
|
||||
{ &FWScript::o1_unloadMask4, "b" },
|
||||
{ &FWScript::o1_addSpriteFilledToBgList, "b" },
|
||||
{ &FWScript::o1_clearBgIncrustList, "" },
|
||||
/* 1C */
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_label, "l" },
|
||||
{ &FWScript::o1_goto, "b" },
|
||||
{ &FWScript::o1_gotoIfSup, "b" },
|
||||
/* 20 */
|
||||
{ &FWScript::o1_gotoIfSupEqu, "b" },
|
||||
{ &FWScript::o1_gotoIfInf, "b" },
|
||||
{ &FWScript::o1_gotoIfInfEqu, "b" },
|
||||
{ &FWScript::o1_gotoIfEqu, "b" },
|
||||
/* 24 */
|
||||
{ &FWScript::o1_gotoIfDiff, "b" },
|
||||
{ &FWScript::o1_removeLabel, "b" },
|
||||
{ &FWScript::o1_loop, "bb" },
|
||||
{ nullptr, nullptr },
|
||||
/* 28 */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
/* 2C */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
/* 30 */
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_startGlobalScript, "b" },
|
||||
{ &FWScript::o1_endGlobalScript, "b" },
|
||||
{ nullptr, nullptr },
|
||||
/* 34 */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
/* 38 */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_loadAnim, "s" },
|
||||
/* 3C */
|
||||
{ &FWScript::o1_loadBg, "s" },
|
||||
{ &FWScript::o2_loadCt, "s" },
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o2_loadPart, "s" },
|
||||
/* 40 */
|
||||
{ &FWScript::o1_closePart, "" },
|
||||
{ &FWScript::o1_loadNewPrcName, "bs" },
|
||||
{ &FWScript::o1_requestCheckPendingDataLoad, "" },
|
||||
{ nullptr, nullptr },
|
||||
/* 44 */
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_blitAndFade, "" },
|
||||
{ &FWScript::o1_fadeToBlack, "" },
|
||||
{ &FWScript::o1_transformPaletteRange, "bbwww" },
|
||||
/* 48 */
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_setDefaultMenuBgColor, "b" },
|
||||
{ &FWScript::o1_palRotate, "bbb" },
|
||||
{ nullptr, nullptr },
|
||||
/* 4C */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_break, "" },
|
||||
/* 50 */
|
||||
{ &FWScript::o1_endScript, "x" },
|
||||
{ &FWScript::o1_message, "bwwww" },
|
||||
{ &FWScript::o1_loadGlobalVar, "bc" },
|
||||
{ &FWScript::o1_compareGlobalVar, "bc" },
|
||||
/* 54 */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
/* 58 */
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_declareFunctionName, "s" },
|
||||
{ &FWScript::o1_freePartRange, "bb" },
|
||||
{ &FWScript::o1_unloadAllMasks, "" },
|
||||
/* 5C */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
/* 60 */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_setScreenDimensions, "wwww" },
|
||||
/* 64 */
|
||||
{ &FWScript::o1_displayBackground, "" },
|
||||
{ &FWScript::o1_initializeZoneData, "" },
|
||||
{ &FWScript::o1_setZoneDataEntry, "bw" },
|
||||
{ &FWScript::o1_getZoneDataEntry, "bb" },
|
||||
/* 68 */
|
||||
{ &FWScript::o1_setPlayerCommandPosY, "b" },
|
||||
{ &FWScript::o1_allowPlayerInput, "" },
|
||||
{ &FWScript::o1_disallowPlayerInput, "" },
|
||||
{ &FWScript::o1_changeDataDisk, "b" }, /* Same as opcodes 0x95 and 0xA9. */
|
||||
/* 6C */
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_loadMusic, "s" },
|
||||
{ &FWScript::o1_playMusic, "" },
|
||||
{ &FWScript::o1_fadeOutMusic, "" },
|
||||
/* 70 */
|
||||
{ &FWScript::o1_stopSample, "" },
|
||||
{ &FWScript::o1_op71, "bw" }, /* TODO: Name this opcode properly. */
|
||||
{ &FWScript::o1_op72, "wbw" }, /* Same as opcode 0x73. TODO: Name this opcode properly. */
|
||||
{ &FWScript::o1_op72, "wbw" }, /* Same as opcode 0x72. */
|
||||
/* 74 */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o2_playSample, "bbwbww" },
|
||||
/* 78 */
|
||||
{ &FWScript::o2_playSampleAlt, "bbwbww" },
|
||||
{ &FWScript::o1_disableSystemMenu, "b" },
|
||||
{ &FWScript::o1_loadMask5, "b" },
|
||||
{ &FWScript::o1_unloadMask5, "b" }, /* Last opcode used by Future Wars. */
|
||||
/* 7C */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o2_addSeqListElement, "bbbbwww" },
|
||||
/* 80 */
|
||||
{ &FWScript::o2_removeSeq, "bb" },
|
||||
{ &FWScript::o2_clearSeqList, "" },
|
||||
{ &FWScript::o2_modifySeqListElement, "bbwwb" },
|
||||
{ &FWScript::o2_isSeqRunning, "bb" },
|
||||
/* 84 */
|
||||
{ &FWScript::o2_gotoIfSupNearest, "b" },
|
||||
{ &FWScript::o2_gotoIfSupEquNearest, "b" },
|
||||
{ &FWScript::o2_gotoIfInfNearest, "b" },
|
||||
{ &FWScript::o2_gotoIfInfEquNearest, "b" },
|
||||
/* 88 */
|
||||
{ &FWScript::o2_gotoIfEquNearest, "b" },
|
||||
{ &FWScript::o2_gotoIfDiffNearest, "b" },
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o2_startObjectScript, "b" },
|
||||
/* 8C */
|
||||
{ &FWScript::o2_stopObjectScript, "b" },
|
||||
{ &FWScript::o2_op8D, "wwwwwwww" }, /* TODO: Name this opcode properly. */
|
||||
{ &FWScript::o2_addBackground, "bs" },
|
||||
{ &FWScript::o2_removeBackground, "b" },
|
||||
/* 90 */
|
||||
{ &FWScript::o2_loadAbs, "bs" },
|
||||
{ &FWScript::o2_loadBg, "b" },
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
/* 94 */
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_changeDataDisk, "b" }, /* Same as opcodes 0x6B and 0xA9. */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
/* 98 */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o2_wasZoneChecked, "b" },
|
||||
{ &FWScript::o2_op9B, "wwwwwwww" }, /* TODO: Name this opcode properly. */
|
||||
/* 9C */
|
||||
{ &FWScript::o2_op9C, "wwww" }, /* TODO: Name this opcode properly. */
|
||||
{ &FWScript::o2_useBgScroll, "b" },
|
||||
{ &FWScript::o2_setAdditionalBgVScroll, "c" },
|
||||
{ &FWScript::o2_op9F, "ww" }, /* TODO: Name this opcode properly. */
|
||||
/* A0 */
|
||||
{ &FWScript::o2_addGfxElementType20, "ww" }, /* TODO: Name this opcode properly. */
|
||||
{ &FWScript::o2_removeGfxElementType20, "ww" }, /* TODO: Name this opcode properly. */
|
||||
{ &FWScript::o2_addGfxElementType21, "ww" }, /* TODO: Name this opcode properly. */
|
||||
{ &FWScript::o2_removeGfxElementType21, "ww" }, /* TODO: Name this opcode properly. */
|
||||
/* A4 */
|
||||
{ &FWScript::o2_loadMask22, "b" }, /* TODO: Name this opcode properly. */
|
||||
{ &FWScript::o2_unloadMask22, "b" }, /* TODO: Name this opcode properly. */
|
||||
{ nullptr, nullptr },
|
||||
{ nullptr, nullptr },
|
||||
/* A8 */
|
||||
{ nullptr, nullptr },
|
||||
{ &FWScript::o1_changeDataDisk, "b" } /* Same as opcodes 0x6B and 0x95. */
|
||||
};
|
||||
OSScript::_opcodeTable = (const Opcode *)opcodeTable;
|
||||
OSScript::_numOpcodes = ARRAYSIZE(opcodeTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contructor for global scripts
|
||||
* @param script Script bytecode reference
|
||||
* @param idx Script bytecode index
|
||||
*/
|
||||
OSScript::OSScript(const RawScript &script, int16 idx) :
|
||||
FWScript(script, idx, new OSScriptInfo) {}
|
||||
|
||||
/**
|
||||
* Constructor for object scripts
|
||||
* @param script Script bytecode reference
|
||||
* @param idx Script bytecode index
|
||||
*/
|
||||
OSScript::OSScript(RawObjectScript &script, int16 idx) :
|
||||
FWScript(script, idx, new OSScriptInfo) {}
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {}
|
||||
|
||||
/**
|
||||
* Restore script state from savefile
|
||||
* @param labels Restored script labels
|
||||
* @param local Restored local script variables
|
||||
* @param compare Restored last comparison result
|
||||
* @param pos Restored script position
|
||||
*/
|
||||
void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
|
||||
FWScript::load(labels, local, compare, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get opcode info string
|
||||
* @param opcode Opcode to look for in opcode table
|
||||
*/
|
||||
const char *OSScriptInfo::opcodeInfo(byte opcode) const {
|
||||
if (opcode == 0 || opcode > OSScript::_numOpcodes) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!OSScript::_opcodeTable[opcode - 1].args) {
|
||||
warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return OSScript::_opcodeTable[opcode - 1].args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get opcode handler pointer
|
||||
* @param opcode Opcode to look for in opcode table
|
||||
*/
|
||||
OpFunc OSScriptInfo::opcodeHandler(byte opcode) const {
|
||||
if (opcode == 0 || opcode > OSScript::_numOpcodes) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!OSScript::_opcodeTable[opcode - 1].proc) {
|
||||
warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return OSScript::_opcodeTable[opcode - 1].proc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new OSScript instance
|
||||
* @param script Script bytecode
|
||||
* @param index Bytecode index
|
||||
*/
|
||||
FWScript *OSScriptInfo::create(const RawScript &script, int16 index) const {
|
||||
return new OSScript(script, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new OSScript instance
|
||||
* @param script Object script bytecode
|
||||
* @param index Bytecode index
|
||||
*/
|
||||
FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index) const {
|
||||
return new OSScript(script, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load saved OSScript instance
|
||||
* @param script Script bytecode
|
||||
* @param index Bytecode index
|
||||
* @param local Local variables
|
||||
* @param labels Script labels
|
||||
* @param compare Last compare result
|
||||
* @param pos Position in script
|
||||
*/
|
||||
FWScript *OSScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
|
||||
OSScript *tmp = new OSScript(script, index);
|
||||
assert(tmp);
|
||||
tmp->load(labels, local, compare, pos);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load saved OSScript instance
|
||||
* @param script Object script bytecode
|
||||
* @param index Bytecode index
|
||||
* @param local Local variables
|
||||
* @param labels Script labels
|
||||
* @param compare Last compare result
|
||||
* @param pos Position in script
|
||||
*/
|
||||
FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
|
||||
OSScript *tmp = new OSScript(script, index);
|
||||
assert(tmp);
|
||||
tmp->load(labels, local, compare, pos);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// OPERATION STEALTH opcodes
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Load collision table data */
|
||||
int FWScript::o2_loadCt() {
|
||||
const char *param = getNextString();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
|
||||
loadCtOS(param);
|
||||
removeBgIncrustsWithBgIdx(kCollisionPageBgIdxAlias);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_loadPart() {
|
||||
const char *param = getNextString();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_playSample() {
|
||||
if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
|
||||
// no-op in these versions
|
||||
getNextByte();
|
||||
getNextByte();
|
||||
getNextWord();
|
||||
getNextByte();
|
||||
getNextWord();
|
||||
getNextWord();
|
||||
return 0;
|
||||
}
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: o2_playSample()", _line);
|
||||
|
||||
byte mode = getNextByte();
|
||||
byte channel = getNextByte();
|
||||
|
||||
int16 param3 = getNextWord();
|
||||
int16 param4 = getNextByte();
|
||||
|
||||
int16 param5 = getNextWord();
|
||||
uint16 size = getNextWord();
|
||||
|
||||
if (mode == 2) {
|
||||
switch (param4) {
|
||||
case 0:
|
||||
param4 = param5;
|
||||
break;
|
||||
case 1:
|
||||
param4 = _localVars[param5];
|
||||
break;
|
||||
case 2:
|
||||
param4 = _globalVars[param5];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_sound->playSound(mode, channel, param3, param4, param5, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_playSampleAlt() {
|
||||
byte num = getNextByte();
|
||||
byte channel = getNextByte();
|
||||
uint16 frequency = getNextWord();
|
||||
/* byte param4 = */getNextByte();
|
||||
/* uint16 param5 = */getNextWord();
|
||||
uint16 size = getNextWord();
|
||||
|
||||
if (size == 0xFFFF) {
|
||||
size = g_cine->_animDataTable[num]._width * g_cine->_animDataTable[num]._height;
|
||||
}
|
||||
if (g_cine->_animDataTable[num].data()) {
|
||||
if (g_cine->getPlatform() == Common::kPlatformDOS) {
|
||||
// if speaker output is available, play sound on it
|
||||
// if it's another device, don't play anything
|
||||
// TODO: implement this, it's used in the introduction for example
|
||||
// on each letter displayed
|
||||
} else {
|
||||
g_sound->playSound(channel, frequency, g_cine->_animDataTable[num].data(), size, 0, 0, 63, 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_addSeqListElement() {
|
||||
byte param1 = getNextByte();
|
||||
byte param2 = getNextByte();
|
||||
byte param3 = getNextByte();
|
||||
byte param4 = getNextByte();
|
||||
uint16 param5 = getNextWord();
|
||||
uint16 param6 = getNextWord();
|
||||
uint16 param7 = getNextWord();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5, param6, param7);
|
||||
addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_removeSeq() {
|
||||
byte a = getNextByte();
|
||||
byte b = getNextByte();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d)", _line, a, b);
|
||||
removeSeq(a, 0, b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @note According to the scripts' opcode usage comparison this opcode isn't used at all.
|
||||
*/
|
||||
int FWScript::o2_clearSeqList() {
|
||||
debugC(5, kCineDebugScript, "Line: %d: clearSeqList()", _line);
|
||||
g_cine->_seqList.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_modifySeqListElement() {
|
||||
byte a = getNextByte();
|
||||
byte b = getNextByte();
|
||||
uint16 c = getNextWord();
|
||||
uint16 d = getNextWord();
|
||||
byte e = getNextByte();
|
||||
debugC(5, kCineDebugScript, "Line: %d: o2_modifySeqListElement(%d,%d,%d,%d,%d)", _line, a, b, c, d, e);
|
||||
|
||||
modifySeqListElement(a, 0, b, c, d, e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Check whether this opcode's name is backwards (i.e. should it be o2_isSeqNotRunning?)
|
||||
*/
|
||||
int FWScript::o2_isSeqRunning() {
|
||||
byte a = getNextByte();
|
||||
byte b = getNextByte();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: o2_isSeqRunning(%d,%d)", _line, a, b);
|
||||
|
||||
if (isSeqRunning(a, 0, b)) {
|
||||
_compare = 1;
|
||||
} else {
|
||||
_compare = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo The assert may produce false positives and requires testing
|
||||
*/
|
||||
int FWScript::o2_gotoIfSupNearest() {
|
||||
byte labelIdx = getNextByte();
|
||||
|
||||
if (_compare == kCmpGT) {
|
||||
assert(_labels[labelIdx] != -1);
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _line, labelIdx);
|
||||
_pos = _script.getLabel(*_info, labelIdx, _pos);
|
||||
} else {
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo The assert may produce false positives and requires testing
|
||||
*/
|
||||
int FWScript::o2_gotoIfSupEquNearest() {
|
||||
byte labelIdx = getNextByte();
|
||||
|
||||
if (_compare & (kCmpGT | kCmpEQ)) {
|
||||
assert(_labels[labelIdx] != -1);
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _line, labelIdx);
|
||||
_pos = _script.getLabel(*_info, labelIdx, _pos);
|
||||
} else {
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo The assert may produce false positives and requires testing
|
||||
*/
|
||||
int FWScript::o2_gotoIfInfNearest() {
|
||||
byte labelIdx = getNextByte();
|
||||
|
||||
if (_compare == kCmpLT) {
|
||||
assert(_labels[labelIdx] != -1);
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _line, labelIdx);
|
||||
_pos = _script.getLabel(*_info, labelIdx, _pos);
|
||||
} else {
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo The assert may produce false positives and requires testing
|
||||
*/
|
||||
int FWScript::o2_gotoIfInfEquNearest() {
|
||||
byte labelIdx = getNextByte();
|
||||
|
||||
if (_compare & (kCmpLT | kCmpEQ)) {
|
||||
assert(_labels[labelIdx] != -1);
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _line, labelIdx);
|
||||
_pos = _script.getLabel(*_info, labelIdx, _pos);
|
||||
} else {
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo The assert may produce false positives and requires testing
|
||||
*/
|
||||
int FWScript::o2_gotoIfEquNearest() {
|
||||
byte labelIdx = getNextByte();
|
||||
|
||||
if (_compare == kCmpEQ) {
|
||||
assert(_labels[labelIdx] != -1);
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _line, labelIdx);
|
||||
_pos = _script.getLabel(*_info, labelIdx, _pos);
|
||||
} else {
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo The assert may produce false positives and requires testing
|
||||
*/
|
||||
int FWScript::o2_gotoIfDiffNearest() {
|
||||
byte labelIdx = getNextByte();
|
||||
|
||||
if (_compare != kCmpEQ) {
|
||||
assert(_labels[labelIdx] != -1);
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _line, labelIdx);
|
||||
_pos = _script.getLabel(*_info, labelIdx, _pos);
|
||||
} else {
|
||||
debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_startObjectScript() {
|
||||
byte param = getNextByte();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
|
||||
runObjectScript(param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_stopObjectScript() {
|
||||
byte param = getNextByte();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param);
|
||||
|
||||
for (auto &script : g_cine->_objectScripts) {
|
||||
if (script->_index == param) {
|
||||
script->_index = -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_op8D() {
|
||||
uint16 objIdx1 = getNextWord();
|
||||
uint16 xAdd1 = getNextWord();
|
||||
uint16 yAdd1 = getNextWord();
|
||||
uint16 maskAdd1 = getNextWord();
|
||||
uint16 objIdx2 = getNextWord();
|
||||
uint16 xAdd2 = getNextWord();
|
||||
uint16 yAdd2 = getNextWord();
|
||||
uint16 maskAdd2 = getNextWord();
|
||||
debugC(5, kCineDebugScript, "Line: %d: o2_op8D(%d, %d, %d, %d, %d, %d, %d, %d)", _line, objIdx1, xAdd1, yAdd1, maskAdd1, objIdx2, xAdd2, yAdd2, maskAdd2);
|
||||
|
||||
_compare = compareObjectParamRanges(objIdx1, xAdd1, yAdd1, maskAdd1, objIdx2, xAdd2, yAdd2, maskAdd2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_addBackground() {
|
||||
byte param1 = getNextByte();
|
||||
const char *param2 = getNextString();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
|
||||
renderer->addBackground(param2, param1);
|
||||
removeBgIncrustsWithBgIdx(param1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_removeBackground() {
|
||||
byte param = getNextByte();
|
||||
|
||||
assert(param);
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
|
||||
|
||||
renderer->removeBg(param);
|
||||
removeBgIncrustsWithBgIdx(param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_loadAbs() {
|
||||
byte param1 = getNextByte();
|
||||
const char *param2 = getNextString();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
|
||||
// Load the resource to an absolute position
|
||||
if (loadResource(param2, param1) == -1) { // Check if the loading failed
|
||||
// WORKAROUND: In the 256 color PC version of Operation Stealth when
|
||||
// walking out of the airport in Santa Paragua to the street the
|
||||
// player character should be seen as a grey silhuette while walking
|
||||
// behind the glass. But actually the player character is completely
|
||||
// invisible when walking behind the glass because the animation files
|
||||
// used are wrongly loaded. In AIRPORT.PRC's 6th script there are
|
||||
// calls loadAbs("JOHN01.ANI", 73) and loadAbs("JOHN02.ANI", 37) to
|
||||
// load the animations involved but no such files are found with the
|
||||
// game. Corresponding SET-files are found though. As it worked and
|
||||
// looked fine when I tried loading them instead of the missing ANI
|
||||
// files I'm doing so here. NOTE: At least the German Amiga version
|
||||
// of Operation Stealth seems to have all the files involved
|
||||
// (JOHN01.ANI, JOHN02.ANI, JOHN01.SET and JOHN02.SET).
|
||||
if (scumm_stricmp(param2, "JOHN01.ANI") == 0 && param1 == 73) {
|
||||
loadResource("JOHN01.SET", param1);
|
||||
} else if (scumm_stricmp(param2, "JOHN02.ANI") == 0 && param1 == 37) {
|
||||
loadResource("JOHN02.SET", param1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_loadBg() {
|
||||
byte param = getNextByte();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param);
|
||||
|
||||
if (param <= 8) {
|
||||
renderer->selectBg(param);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_wasZoneChecked() {
|
||||
byte param = getNextByte();
|
||||
_compare = (param < NUM_MAX_ZONE && g_cine->_zoneQuery[param]) ? 1 : 0;
|
||||
debugC(5, kCineDebugScript, "Line: %d: o2_wasZoneChecked(%d)", _line, param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implement this instruction
|
||||
* @note According to the scripts' opcode usage comparison this opcode isn't used at all.
|
||||
* @note In Operation Stealth 16 color DOS version this calculates temporary values and discards them.
|
||||
*/
|
||||
int FWScript::o2_op9B() {
|
||||
uint16 a = getNextWord();
|
||||
uint16 b = getNextWord();
|
||||
uint16 c = getNextWord();
|
||||
uint16 d = getNextWord();
|
||||
uint16 e = getNextWord();
|
||||
uint16 f = getNextWord();
|
||||
uint16 g = getNextWord();
|
||||
uint16 h = getNextWord();
|
||||
warning("STUB: o2_op9B(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implement this instruction
|
||||
* @note According to the scripts' opcode usage comparison this opcode isn't used at all.
|
||||
* @note In Operation Stealth 16 color DOS version this calculates temporary values and discards them.
|
||||
*/
|
||||
int FWScript::o2_op9C() {
|
||||
uint16 a = getNextWord();
|
||||
uint16 b = getNextWord();
|
||||
uint16 c = getNextWord();
|
||||
uint16 d = getNextWord();
|
||||
warning("STUB: o2_op9C(%x, %x, %x, %x)", a, b, c, d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_useBgScroll() {
|
||||
byte param = getNextByte();
|
||||
|
||||
assert(param < 9);
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
|
||||
|
||||
if (param <= 8) {
|
||||
renderer->selectScrollBg(param);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_setAdditionalBgVScroll() {
|
||||
uint16 mouseX, mouseY;
|
||||
unsigned int scroll = renderer->getScroll();
|
||||
byte param1 = getNextByte();
|
||||
|
||||
if (param1) {
|
||||
byte param2 = getNextByte();
|
||||
|
||||
switch (param1) {
|
||||
case 1:
|
||||
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
|
||||
scroll = _localVars[param2];
|
||||
break;
|
||||
case 2:
|
||||
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = globalVar[%d]", _line, param2);
|
||||
scroll = _globalVars[param2];
|
||||
break;
|
||||
case 3:
|
||||
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = mouseX", _line);
|
||||
getMouseData(mouseUpdateStatus, &dummyU16, &mouseX, &mouseY);
|
||||
scroll = mouseX;
|
||||
break;
|
||||
case 4:
|
||||
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = mouseY", _line);
|
||||
getMouseData(mouseUpdateStatus, &dummyU16, &mouseX, &mouseY);
|
||||
scroll = mouseY;
|
||||
break;
|
||||
case 5:
|
||||
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = rand() %% %d", _line, param2);
|
||||
scroll = ((param2 == 0) ? 0 : g_cine->_rnd.getRandomNumber(param2 - 1));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
uint16 param2 = getNextWord();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
|
||||
scroll = param2;
|
||||
}
|
||||
|
||||
renderer->setScroll(scroll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implement this instruction
|
||||
* @note According to the scripts' opcode usage comparison this opcode isn't used at all.
|
||||
* @note In Operation Stealth 16 color DOS version this calculates temporary values and discards them.
|
||||
*/
|
||||
int FWScript::o2_op9F() {
|
||||
warning("o2_op9F()");
|
||||
/* uint16 param1 = */getNextWord();
|
||||
/* uint16 param2 = */getNextWord();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_addGfxElementType20() {
|
||||
uint16 param1 = getNextWord();
|
||||
uint16 param2 = getNextWord();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: o2_addGfxElementType20(%d,%d)", _line, param1, param2);
|
||||
addGfxElement(param1, param2, 20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_removeGfxElementType20() {
|
||||
uint16 idx = getNextWord();
|
||||
uint16 param = getNextWord();
|
||||
debugC(5, kCineDebugScript, "Line: %d: o2_removeGfxElementType20(%d,%d)", _line, idx, param);
|
||||
removeGfxElement(idx, param, 20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_addGfxElementType21() {
|
||||
uint16 a = getNextWord();
|
||||
uint16 b = getNextWord();
|
||||
debugC(5, kCineDebugScript, "Line: %d: o2_addGfxElementType21(%d,%d)", _line, a, b);
|
||||
addGfxElement(a, b, 21);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_removeGfxElementType21() {
|
||||
uint16 a = getNextWord();
|
||||
uint16 b = getNextWord();
|
||||
debugC(5, kCineDebugScript, "Line: %d: o2_removeGfxElementType21(%d,%d)", _line, a, b);
|
||||
removeGfxElement(a, b, 21);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_loadMask22() {
|
||||
byte param = getNextByte();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
|
||||
addOverlay(param, 22);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FWScript::o2_unloadMask22() {
|
||||
byte param = getNextByte();
|
||||
|
||||
debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
|
||||
removeOverlay(param, 22);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
1574
engines/cine/sound.cpp
Normal file
1574
engines/cine/sound.cpp
Normal file
File diff suppressed because it is too large
Load Diff
145
engines/cine/sound.h
Normal file
145
engines/cine/sound.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/* 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 CINE_SOUND_H_
|
||||
#define CINE_SOUND_H_
|
||||
|
||||
#include "common/util.h"
|
||||
#include "common/mutex.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "audio/mididrv.h"
|
||||
|
||||
namespace Audio {
|
||||
class AudioStream;
|
||||
}
|
||||
|
||||
namespace Cine {
|
||||
|
||||
class CineEngine;
|
||||
|
||||
class Sound {
|
||||
public:
|
||||
|
||||
Sound(Audio::Mixer *mixer, CineEngine *vm) : _mixer(mixer), _vm(vm), _musicType(MT_INVALID) {}
|
||||
virtual ~Sound() {}
|
||||
|
||||
virtual MusicType musicType();
|
||||
virtual void loadMusic(const char *name) = 0;
|
||||
virtual void playMusic() = 0;
|
||||
virtual void stopMusic() = 0;
|
||||
virtual void fadeOutMusic() = 0;
|
||||
|
||||
virtual void playSound(int mode, int channel, int param3, int param4, int param5, int size) = 0;
|
||||
virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) = 0;
|
||||
virtual void stopSound(int channel) = 0;
|
||||
virtual void setBgMusic(int num) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
Audio::Mixer *_mixer;
|
||||
CineEngine *_vm;
|
||||
MusicType _musicType;
|
||||
};
|
||||
|
||||
class PCSoundDriver;
|
||||
class PCSoundFxPlayer;
|
||||
|
||||
class PCSound : public Sound {
|
||||
public:
|
||||
|
||||
PCSound(Audio::Mixer *mixer, CineEngine *vm);
|
||||
~PCSound() override;
|
||||
|
||||
void loadMusic(const char *name) override;
|
||||
void playMusic() override;
|
||||
void stopMusic() override;
|
||||
void fadeOutMusic() override;
|
||||
|
||||
void playSound(int mode, int channel, int param3, int param4, int param5, int size) override;
|
||||
void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) override;
|
||||
void stopSound(int channel) override;
|
||||
void setBgMusic(int num) override;
|
||||
|
||||
protected:
|
||||
|
||||
PCSoundDriver *_soundDriver;
|
||||
PCSoundFxPlayer *_player;
|
||||
|
||||
uint8 _currentMusic, _currentMusicStatus, _currentBgSlot;
|
||||
};
|
||||
|
||||
class PaulaSound : public Sound {
|
||||
public:
|
||||
|
||||
PaulaSound(Audio::Mixer *mixer, CineEngine *vm);
|
||||
~PaulaSound() override;
|
||||
|
||||
void loadMusic(const char *name) override;
|
||||
void playMusic() override;
|
||||
void stopMusic() override;
|
||||
void fadeOutMusic() override;
|
||||
|
||||
void playSound(int mode, int channel, int param3, int param4, int param5, int size) override;
|
||||
void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) override;
|
||||
void stopSound(int channel) override;
|
||||
void setBgMusic(int num) override;
|
||||
|
||||
enum {
|
||||
PAULA_FREQ = 3579545,
|
||||
NUM_CHANNELS = 4
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
struct SfxChannel {
|
||||
Audio::SoundHandle handle;
|
||||
int volume;
|
||||
int volumeStep;
|
||||
int curStep;
|
||||
int stepCount;
|
||||
|
||||
void initialize(int vol, int volStep, int stepCnt) {
|
||||
volume = vol;
|
||||
volumeStep = volStep;
|
||||
curStep = stepCount = stepCnt;
|
||||
}
|
||||
};
|
||||
SfxChannel _channelsTable[NUM_CHANNELS];
|
||||
static const int _channelBalance[NUM_CHANNELS];
|
||||
Common::Mutex _sfxMutex;
|
||||
int _sfxTimer;
|
||||
static void sfxTimerProc(void *param);
|
||||
void sfxTimerCallback();
|
||||
|
||||
Common::Mutex _musicMutex;
|
||||
int _musicTimer;
|
||||
int _musicFadeTimer;
|
||||
static void musicTimerProc(void *param);
|
||||
void musicTimerCallback();
|
||||
Audio::SoundHandle _moduleHandle;
|
||||
Audio::AudioStream *_moduleStream;
|
||||
};
|
||||
|
||||
extern Sound *g_sound;
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif /* CINE_SOUND_H_ */
|
||||
863
engines/cine/texte.cpp
Normal file
863
engines/cine/texte.cpp
Normal file
@@ -0,0 +1,863 @@
|
||||
/* 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/file.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
#include "cine/various.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
bool allocatedFailureMessages = false;
|
||||
const char *const *failureMessages;
|
||||
const CommandeType *defaultActionCommand;
|
||||
const CommandeType *systemMenu;
|
||||
const CommandeType *confirmMenu;
|
||||
const char *const *otherMessages;
|
||||
const char *defaultCommandPreposition;
|
||||
const char *const *commandPrepositionTable;
|
||||
|
||||
/**
|
||||
* Loads font data from the given file.
|
||||
* The number of characters used in the font varies between game versions:
|
||||
* 78 (Most PC, Amiga and Atari ST versions of Future Wars, but also Operation Stealth's Amiga demo),
|
||||
* 85 (All observed versions of German Future Wars (Amiga and PC), possibly Spanish Future Wars too),
|
||||
* 90 (Most PC, Amiga and Atari ST versions of Operation Stealth),
|
||||
* 93 (All observed versions of German Operation Stealth (Amiga and PC)).
|
||||
*/
|
||||
void loadTextData(const char *filename) {
|
||||
Common::File fileHandle;
|
||||
assert(filename);
|
||||
|
||||
if (!fileHandle.open(filename))
|
||||
error("loadTextData(): Cannot open file %s", filename);
|
||||
|
||||
static const uint headerSize = 2 + 2; // The entry size (16-bit) and entry count (16-bit).
|
||||
const uint entrySize = fileHandle.readUint16BE(); // Observed values: 8.
|
||||
const uint entryCount = fileHandle.readUint16BE(); // Observed values: 624, 680, 720, 744.
|
||||
const uint fontDataSize = entryCount * entrySize; // Observed values: 4992, 5440, 5760, 5952.
|
||||
const uint numChars = entryCount / entrySize; // Observed values: 78, 85, 90, 93.
|
||||
const uint bytesPerChar = fontDataSize / numChars; // Observed values: 64.
|
||||
static const uint bytesPerRow = FONT_WIDTH / 2; // The input font data is 4-bit so it takes only half the space
|
||||
|
||||
if (headerSize + fontDataSize != (uint)fileHandle.size()) {
|
||||
warning("loadTextData: file '%s' (entrySize = %d, entryCount = %d) is of incorrect size %d", filename, entrySize, entryCount, (int)fileHandle.size());
|
||||
}
|
||||
|
||||
Common::Array<byte> source;
|
||||
source.resize(fontDataSize);
|
||||
fileHandle.read(source.begin(), fontDataSize);
|
||||
|
||||
if (g_cine->getGameType() == Cine::GType_FW) {
|
||||
loadRelatedPalette(filename);
|
||||
}
|
||||
|
||||
for (uint i = 0; i < numChars; i++) {
|
||||
gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][FONT_DATA], &source[i * bytesPerChar], bytesPerRow, FONT_HEIGHT);
|
||||
generateMask(g_cine->_textHandler.textTable[i][FONT_DATA], g_cine->_textHandler.textTable[i][FONT_MASK], FONT_WIDTH * FONT_HEIGHT, 0);
|
||||
}
|
||||
|
||||
fileHandle.close();
|
||||
}
|
||||
|
||||
static const CharacterEntry fontParamTable_standard[NUM_FONT_CHARS] = {
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, {63, 1}, {69, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {68, 3},
|
||||
{64, 3}, {65, 3}, { 0, 0}, { 0, 0}, {62, 2}, {74, 6}, {66, 1}, {67, 6},
|
||||
{52, 6}, {53, 6}, {54, 6}, {55, 6}, {56, 6}, {57, 6}, {58, 6}, {59, 6},
|
||||
{60, 6}, {61, 6}, {76, 3}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {75, 6},
|
||||
{ 0, 0}, { 0, 6}, //a
|
||||
{ 1, 6}, { 2, 6}, { 3, 6}, { 4, 6}, { 5, 6}, { 6, 6},
|
||||
{ 7, 6}, { 8, 3}, { 9, 6}, {10, 6}, {11, 6}, {12, 7}, {13, 6}, {14, 6},
|
||||
{15, 6}, {16, 6}, {17, 6}, {18, 6}, {19, 6}, {20, 6}, {21, 6}, {22, 7},
|
||||
{23, 6}, {24, 6}, {25, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, {26, 6}, //a
|
||||
{27, 6}, {28, 5}, {29, 6}, {30, 6}, {31, 5}, {32, 6},
|
||||
{33, 6}, {34, 4}, {35, 4}, {36, 5}, {37, 3}, {38, 7}, {39, 6}, {40, 6},
|
||||
{41, 6}, {42, 6}, {43, 6}, {44, 6}, {45, 6}, {46, 6}, {47, 6}, {48, 7},
|
||||
{49, 6}, {50, 6}, {51, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, {70, 6}, { 0, 0}, { 0, 0}, {72, 6}, { 0, 0}, {73, 5},
|
||||
{77, 6}, { 0, 0}, {71, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {77, 6},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}
|
||||
};
|
||||
|
||||
static const CharacterEntry fontParamTable_alt[NUM_FONT_CHARS] = {
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, {63, 1}, {69, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {68, 3},
|
||||
{64, 3}, {65, 3}, { 0, 0}, { 0, 0}, {62, 2}, {74, 6}, {66, 1}, {67, 6},
|
||||
{52, 6}, {53, 6}, {54, 6}, {55, 6}, {56, 6}, {57, 6}, {58, 6}, {59, 6},
|
||||
{60, 6}, {61, 6}, {76, 3}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {75, 6},
|
||||
{ 0, 0}, { 0, 6}, { 1, 6}, { 2, 6}, { 3, 6}, { 4, 6}, { 5, 6}, { 6, 6},
|
||||
{ 7, 6}, { 8, 3}, { 9, 6}, {10, 6}, {11, 6}, {12, 7}, {13, 6}, {14, 6},
|
||||
{15, 6}, {16, 6}, {17, 6}, {18, 6}, {19, 6}, {20, 6}, {21, 6}, {22, 7},
|
||||
{23, 6}, {24, 6}, {25, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, {26, 6}, {27, 6}, {28, 5}, {29, 6}, {30, 6}, {31, 5}, {32, 6},
|
||||
{33, 6}, {34, 4}, {35, 4}, {36, 5}, {37, 3}, {38, 7}, {39, 6}, {40, 6},
|
||||
{41, 6}, {42, 6}, {43, 6}, {44, 6}, {45, 6}, {46, 6}, {47, 6}, {48, 7},
|
||||
{49, 6}, {50, 6}, {51, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, {82, 6}, {70, 6}, { 0, 0}, {78, 6}, {72, 6}, { 0, 0}, {73, 5},
|
||||
{77, 6}, {79, 6}, {71, 6}, {80, 4}, { 0, 0}, { 0, 0}, {78, 6}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {81, 6}, { 0, 0}, { 0, 0}, {77, 6},
|
||||
{83, 6}, {81, 6}, {82, 6}, { 0, 0}, { 0, 0}, { 0, 0}, {84, 6}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, {84, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
|
||||
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}
|
||||
};
|
||||
|
||||
void initLanguage(Common::Language lang) {
|
||||
static const char *const failureMessages_EN[] = {
|
||||
// EXAMINE
|
||||
"I don't see anything unusual.",
|
||||
"There's nothing of interest here.",
|
||||
"This isn't particularly interesting.",
|
||||
"You won't find anything.",
|
||||
// TAKE
|
||||
"I can't take that.",
|
||||
"I find it difficult.",
|
||||
"I don't see what I am supposed to take.",
|
||||
"I have difficulty in following you.",
|
||||
// INVENTORY
|
||||
"There's no point.",
|
||||
"You have better things to do.",
|
||||
"Come on, don't let's waste any time.",
|
||||
"That doesn't seem to me to be a good idea.",
|
||||
// USE
|
||||
"I don't see why I should do that.",
|
||||
"It's had no effect whatsoever.",
|
||||
"It won't produce any results.",
|
||||
"Try and find something else.",
|
||||
// OPERATE
|
||||
"It doesn't work.",
|
||||
"Let suppose you are trying and don't let's mention it again.",
|
||||
"Nothing happens.",
|
||||
"You have better things to do.",
|
||||
// SPEAK
|
||||
"No answer.",
|
||||
"More action , less talking !",
|
||||
"I'd be very surprised if you got an answer",
|
||||
"A wall of silence ..."
|
||||
};
|
||||
|
||||
/**
|
||||
* British English error messages for Operation Stealth.
|
||||
*/
|
||||
static const char *const failureMessages_OS_EN[] = {
|
||||
// EXAMINE
|
||||
"You haven't noticed anything special.",
|
||||
"Nothing interesting.",
|
||||
"Nothing to say about it.",
|
||||
"You find nothing.",
|
||||
// TAKE
|
||||
"Let's forget about it.",
|
||||
"I could if I wanted, but I don't.",
|
||||
"There are so many things to take and you want this one!",
|
||||
"No need.",
|
||||
// INVENTORY
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
// USE
|
||||
"That won't do anything.",
|
||||
"Nothing's happening.",
|
||||
"If you have anything else like this, go ahead and finish it.",
|
||||
"It's like you did nothing.",
|
||||
// OPERATE
|
||||
"You do it, nothing happens.",
|
||||
"Why don't you try it and we won't talk about it anymore.",
|
||||
"Nothing's happening.",
|
||||
"No result.",
|
||||
// SPEAK
|
||||
"You speak with him. No answer.",
|
||||
"More action and less talk.",
|
||||
"My name is GLAMES... JOHN GLAMES.",
|
||||
"A wall of silence..."
|
||||
};
|
||||
|
||||
/**
|
||||
* American English error messages for Operation Stealth.
|
||||
*/
|
||||
static const char *const failureMessages_OS_US[] = {
|
||||
// EXAMINE
|
||||
"You haven't noticed anything special.",
|
||||
"Nothing interesting.",
|
||||
"Nothing to say about it.",
|
||||
"You find nothing.",
|
||||
// TAKE
|
||||
"Let's forget about it.",
|
||||
"I could if I wanted, but I don't.",
|
||||
"There are so many things to take and you want this one!",
|
||||
"No need.",
|
||||
// INVENTORY
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
// USE
|
||||
"That won't do anything.",
|
||||
"Nothing's happening.",
|
||||
"If you have anything else like this, go ahead and finish it.",
|
||||
"It's like you did nothing.",
|
||||
// OPERATE
|
||||
"You do it, nothing happens.",
|
||||
"Absolutely not! It would be a waste of my valuable time.",
|
||||
"Nothing's happening.",
|
||||
"No result.",
|
||||
// SPEAK
|
||||
"You speak with him. No answer.",
|
||||
"More action and less talk.",
|
||||
"My name is BOND... JAMES BOND. ",
|
||||
"A wall of silence..."
|
||||
};
|
||||
|
||||
static const CommandeType defaultActionCommand_EN[] = {
|
||||
"EXAMINE",
|
||||
"TAKE",
|
||||
"INVENTORY",
|
||||
"USE",
|
||||
"OPERATE",
|
||||
"SPEAK",
|
||||
"NOACTION"
|
||||
};
|
||||
|
||||
static const char *const commandPrepositionTable_EN[] = {
|
||||
"", // EXAMINE
|
||||
"", // TAKE
|
||||
"", // INVENTORY
|
||||
"on", // USE
|
||||
"", // OPERATE
|
||||
"to", // SPEAK
|
||||
"" // NOACTION
|
||||
};
|
||||
|
||||
static const CommandeType systemMenu_EN[] = {
|
||||
"Pause",
|
||||
"Restart Game",
|
||||
"Quit",
|
||||
"Backup Drive is A:",
|
||||
"Restore game",
|
||||
"Save game"
|
||||
};
|
||||
|
||||
static const char *const otherMessages_EN[] = {
|
||||
"This backup doesn't exist ...",
|
||||
"Could not create save file ...",
|
||||
"PAUSE",
|
||||
"Loading | %s",
|
||||
"Loading canceled ...",
|
||||
"No backup in the drive...",
|
||||
"Please enter the backup name"
|
||||
};
|
||||
|
||||
static const CommandeType confirmMenu_EN[] = {
|
||||
"Ok, go ahead ...",
|
||||
"Absolutely Not!"
|
||||
};
|
||||
|
||||
static const char *const failureMessages_FR[] = {
|
||||
// EXAMINER
|
||||
"Je ne vois rien de special.",
|
||||
"Il n'y a rien d'int\x82ressant.",
|
||||
"Cela pr\x82sente peu d'int\x82r\x88ts.",
|
||||
"Vous ne trouvez rien.",
|
||||
// PRENDRE
|
||||
"Je ne peux pas prendre cela.",
|
||||
"Cela me semble difficile",
|
||||
"Je ne vois pas ce qu'il y a \x85 prendre",
|
||||
"j'ai du mal \x85 vous suivre.",
|
||||
// INVENTAIRE
|
||||
"C'est inutile",
|
||||
"Vous avez mieux \x85 faire",
|
||||
"Allons, ne perdons pas de temps",
|
||||
"\x87""a ne me semble pas \x88tre une bonne id\x82""e",
|
||||
// UTILISER
|
||||
"Je ne vois pas pourquoi je ferais cela.",
|
||||
"C'est absolument sans effets",
|
||||
"Cela n'amenerait \x85 rien",
|
||||
"Essayez de trouver autre chose.",
|
||||
// ACTIONNER
|
||||
"Ca ne marche pas",
|
||||
"Supposons que vous essayez et n'en parlons plus.",
|
||||
"Rien n'y fait.",
|
||||
"Vous avez mieux \x85 faire.",
|
||||
// PARLER
|
||||
"Vous lui parlez . Sans r\x82ponse.",
|
||||
"Plus d'actes et moins de Paroles !",
|
||||
"Je serais bien surpris si vous obteniez une r\x82ponse.",
|
||||
"Un mur de silence ..."
|
||||
};
|
||||
|
||||
/**
|
||||
* French error messages for Operation Stealth.
|
||||
*/
|
||||
static const char *const failureMessages_OS_FR[] = {
|
||||
// EXAMINER
|
||||
"Vous ne remarquez rien de sp\x82""cial.",
|
||||
"Rien d'int\x82ressant.",
|
||||
"Peu de choses \x85 dire l\x85-dessus.",
|
||||
"Vous ne trouvez rien.",
|
||||
// PRENDRE
|
||||
"N'en parlons plus...",
|
||||
"Je pourrais si je le voulais! MAIS JE NE VEUX PAS!",
|
||||
"Il y a des tas de choses \x85 prendre et vous voulez celle l\x85!",
|
||||
"C'est inutile!",
|
||||
// INVENTAIRE
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
// UTILISER
|
||||
"C'est absolument sans effet.",
|
||||
"Il ne se passe rien.",
|
||||
"Si vous en avez d'autres comme \x87""a, allez-y qu'on en finisse.",
|
||||
"C'est comme si vous n'aviez rien fait!",
|
||||
// ACTIONNER
|
||||
"OK! vous l'actionnez. Il ne se passe rien.",
|
||||
"Supposons que vous essayiez et n'en parlons plus.",
|
||||
"Rien n'y fait.",
|
||||
"Aucun r\x82sultat.",
|
||||
// PARLER
|
||||
"Vous lui parlez . Pas de r\x82ponse.",
|
||||
"Plus d'actes et moins de Paroles !",
|
||||
"Mon nom est GLAMES... JOHN GLAMES.",
|
||||
"Un mur de silence ..."
|
||||
};
|
||||
|
||||
static const CommandeType defaultActionCommand_FR[] = {
|
||||
"EXAMINER",
|
||||
"PRENDRE",
|
||||
"INVENTAIRE",
|
||||
"UTILISER",
|
||||
"ACTIONNER",
|
||||
"PARLER",
|
||||
"NOACTION"
|
||||
};
|
||||
|
||||
static const char *const commandPrepositionTable_FR[] = {
|
||||
"", // EXAMINER
|
||||
"", // PRENDRE
|
||||
"", // INVENTAIRE
|
||||
"sur", // UTILISER
|
||||
"", // ACTIONNER
|
||||
"a", // PARLER
|
||||
"" // NOACTION
|
||||
};
|
||||
|
||||
static const CommandeType systemMenu_FR[] = {
|
||||
"Pause",
|
||||
"Nouvelle partie",
|
||||
"Quitter",
|
||||
"Lecteur de Svg. A:",
|
||||
"Charger une partie",
|
||||
"Sauver la partie"
|
||||
};
|
||||
|
||||
static const CommandeType confirmMenu_FR[] = {
|
||||
"Ok , Vas-y ...",
|
||||
"Surtout Pas !"
|
||||
};
|
||||
|
||||
static const char *const otherMessages_FR[] = {
|
||||
"Cette sauvegarde n'existe pas ...",
|
||||
"Could not create save file ...", //
|
||||
"PAUSE",
|
||||
"Sauvegarde de | %s",
|
||||
("Sauvegarde Annul\x82""e ..."),
|
||||
"Aucune sauvegarde dans le lecteur ...",
|
||||
"Veuillez entrer le Nom de la Sauvegarde ."
|
||||
};
|
||||
|
||||
static const char *const failureMessages_ES[] = {
|
||||
// EXAMINE
|
||||
"No veo nada especial",
|
||||
"No hay nada interesante",
|
||||
"No tiene mucho interes",
|
||||
"No encuentras nada",
|
||||
// TAKE
|
||||
"No puedo coger eso",
|
||||
"Eso parece dificil",
|
||||
"No veo nada mas para coger",
|
||||
"No he debido entenderte",
|
||||
// INVENTORY
|
||||
"Es inutil",
|
||||
"Tienes algo mejor que hacer",
|
||||
"Vamos. No perdamos tiempo",
|
||||
"Esa no es una buena idea",
|
||||
// USE
|
||||
"No veo porque hacerlo",
|
||||
"No ha tenido efecto",
|
||||
"Eso no arreglara nada",
|
||||
"Intenta encontrar otra cosa",
|
||||
// OPERATE
|
||||
"Eso no funciona",
|
||||
"Suponfamos que pruebas y no hablamos mas",
|
||||
"Nada ha pasado",
|
||||
"Tienes cosas mejores que hacer",
|
||||
// SPEAK
|
||||
"Le hablas. Sin respuesta.",
|
||||
"Menos hablar y mas trabajar",
|
||||
"Me sorprenderia si tuvieras otra repuesta",
|
||||
"Un muro de silencio ..."
|
||||
};
|
||||
|
||||
static const CommandeType defaultActionCommand_ES[] = {
|
||||
"EXAMINAR",
|
||||
"COGER",
|
||||
"INVENTARIO",
|
||||
"USAR",
|
||||
"ACCIONAR",
|
||||
"HABLAR",
|
||||
"NOACTION"
|
||||
};
|
||||
|
||||
static const char *const commandPrepositionTable_ES[] = {
|
||||
"", // EXAMINAR
|
||||
"", // COGER
|
||||
"", // INVENTARIO
|
||||
"donde", // USAR
|
||||
"", // ACCIONAR
|
||||
"a", // HABLAR
|
||||
"" // NOACTION
|
||||
};
|
||||
|
||||
static const CommandeType systemMenu_ES[] = {
|
||||
"Pause",
|
||||
"Nueva partida",
|
||||
"Abandonar",
|
||||
"Unidad grabar. A:",
|
||||
"Cargar una partida",
|
||||
"Salvar la partida"
|
||||
};
|
||||
|
||||
static const CommandeType confirmMenu_ES[] = {
|
||||
"Ok , Vas a ...",
|
||||
"Nade de nada !"
|
||||
};
|
||||
|
||||
static const char *const otherMessages_ES[] = {
|
||||
"Esta granacion no existe",
|
||||
"Could not create save file ...", //
|
||||
"PAUSE",
|
||||
"Gabacion de| %s",
|
||||
"Rrabacion anulada",
|
||||
"No hay partidas grabadas en este disco...",
|
||||
"Teclea el nombre de la partida grabada"
|
||||
};
|
||||
|
||||
static const char *const failureMessages_DE[] = {
|
||||
// EXAMINE
|
||||
"Ich sehe nichts Besonderes",
|
||||
"Es gibt hier nichts Interessantes",
|
||||
"Das ist nicht besonders interessant",
|
||||
"Sie werden nichts finden",
|
||||
// TAKE
|
||||
"Ich Kann das nicht nehmen",
|
||||
"Das finde ich schwierig'",
|
||||
"Ich wei\x9e nicht, was ich nehmen soll",
|
||||
"Ich kann Ihnen nicht folgen",
|
||||
// INVENTORY
|
||||
"Das bringt nichts",
|
||||
"Sie haben wirklich was Besseres zu tun",
|
||||
"Los, wir sollten keine Zeit verschwenden",
|
||||
"Das scheint mir eine gute Idee zu sein",
|
||||
// USE
|
||||
"Ich wei\x9e nicht, warum ich das tun soll",
|
||||
"Es hat so oder so nichts begracht",
|
||||
"Davon haben wir nichts",
|
||||
"Versuchen Sie, etwas anderes zu finden",
|
||||
// OPERATE
|
||||
"Es geht nicht",
|
||||
("Sagen wir, das war ein Versuch, und reden wir nicht mehr dr\x81""ber"),
|
||||
"Nichts passiert",
|
||||
"Sie haben wirklich was Besseres zu tun",
|
||||
// SPEAK
|
||||
"Sie sprechen m it ihm. Keine Antwort",
|
||||
"Nicht reden, sondern handeln!",
|
||||
"Wenn Sie eine Antwork bek\x84men, w\x81rde es mich sehr wundern",
|
||||
"Eine Wand des Schweigens..."
|
||||
};
|
||||
|
||||
/**
|
||||
* German error messages for Operation Stealth.
|
||||
*/
|
||||
static const char *const failureMessages_OS_DE[] = {
|
||||
// EXAMINE
|
||||
"Ich sehe nichts Besonderes",
|
||||
"Es gibt hier nichts Interessantes",
|
||||
"Das ist nicht besonders interessant",
|
||||
"Sie werden nichts finden",
|
||||
// TAKE
|
||||
"Ich Kann das nicht nehmen",
|
||||
"Das finde ich schwierig",
|
||||
"Ich wei\x9e nicht, was ich nehmen soll",
|
||||
"Ich kann Ihnen nicht folgen",
|
||||
// INVENTORY
|
||||
"Das bringt nichts",
|
||||
"Sie haben wirklich was Besseres zu tun",
|
||||
"Los, wir sollten keine Zeit verschwenden",
|
||||
"Das scheint mir eine gute Idee zu sein",
|
||||
// USE
|
||||
"Ich wei\x9e nicht, warum ich das tun soll",
|
||||
"Es hat so oder so nichts begracht",
|
||||
"Davon haben wir nichts",
|
||||
"Versuchen Sie, etwas anderes zu finden",
|
||||
// OPERATE
|
||||
"Es geht nicht",
|
||||
"Nichts passiert",
|
||||
"Nichts passiert",
|
||||
"Sie haben wirklich was Besseres zu tun",
|
||||
// SPEAK
|
||||
"Sie sprechen mit ihm. Keine Antwort",
|
||||
"Nicht reden, sondern handeln!",
|
||||
"Wenn Sie eine Antwork bek\x84men, w\x81rde es mich sehr wundern",
|
||||
"Eine Wand des Schweigens..."
|
||||
};
|
||||
|
||||
static const CommandeType defaultActionCommand_DE[] = {
|
||||
("Pr\x81""fe"), // FIXME? The third letter should be Latin Small Letter U with diaeresis
|
||||
"Nimm",
|
||||
"Bestand",
|
||||
"Benutze",
|
||||
"Bet\x84tige", // FIXME? The fourth letter should be Latin Small Letter A with diaeresis
|
||||
"Sprich",
|
||||
"NOACTION"
|
||||
};
|
||||
|
||||
static const char *const commandPrepositionTable_DE[] = {
|
||||
"", // Prufe
|
||||
"", // Nimm
|
||||
"", // Bestand
|
||||
"gegen", // Benutze
|
||||
"", // Betatige
|
||||
"a", // Sprich
|
||||
"" // NOACTION
|
||||
};
|
||||
|
||||
static const CommandeType systemMenu_DE[] = {
|
||||
"Pause",
|
||||
"Spiel Neu Starten",
|
||||
"Lassen",
|
||||
"Backuplaufwerk A:",
|
||||
"Spiel Laden",
|
||||
"Spiel Speichern"
|
||||
};
|
||||
|
||||
static const CommandeType confirmMenu_DE[] = {
|
||||
"Gut, Weitermachen",
|
||||
"Absolut Nicht!"
|
||||
};
|
||||
|
||||
static const char *const otherMessages_DE[] = {
|
||||
"Diese Sicherungskopie gibt es nicht",
|
||||
"Could not create save file ...", //
|
||||
"PAUSE",
|
||||
("Er L\x84""dt | %s"),
|
||||
"Ladevorgang Abgebrochen...",
|
||||
"Kein Backup im Laufwerk...",
|
||||
"Geben Sie den Namen|der Sicherungsdiskette ein"
|
||||
};
|
||||
|
||||
static const char *const failureMessages_IT[] = {
|
||||
// EXAMINE
|
||||
"Non vedo nula di speciale",
|
||||
"Non c'\x8a niente di interessante",
|
||||
"E' di poco interesse",
|
||||
"Non trovate nulla",
|
||||
// TAKE
|
||||
"Non poso prendere quello",
|
||||
"Quello mi sembra difficile",
|
||||
"Non vedo cosa ci sia da prendere",
|
||||
"Faccio fatica a seguirvi",
|
||||
// INVENTORY
|
||||
"E' inutile",
|
||||
"Avete di meglio da fare",
|
||||
"Allora, no perdiamo tempo",
|
||||
"Non mi pare che sia una buona idea",
|
||||
// USE
|
||||
"Non vedo perch\x82 dovrei farlo",
|
||||
"E' assolutamente privo di effetti",
|
||||
"Cio non portera a nulla",
|
||||
"Provate a trovare qualcosa d'altro",
|
||||
// OPERATE
|
||||
"Non funziona",
|
||||
"Supponiamo che voi proviate e non ne parliamo piu",
|
||||
"Niente di fatto",
|
||||
"Avete di meglio da fare",
|
||||
// SPEAK
|
||||
"Gli parlate. Senza risposta",
|
||||
"Piu fatti e meno parole",
|
||||
"Sarei sorpreso se voi otterreste una risposta",
|
||||
"Un muro di silenzio ..."
|
||||
};
|
||||
|
||||
static const CommandeType defaultActionCommand_IT[] = {
|
||||
"ESAMINARE",
|
||||
"PRENDERE",
|
||||
"INVENTARIO",
|
||||
"UTILIZZARE",
|
||||
"AZIONARE",
|
||||
"PARLARE",
|
||||
"NOACTION"
|
||||
};
|
||||
|
||||
static const char *const commandPrepositionTable_IT[] = {
|
||||
"", // ESAMINARE
|
||||
"", // PRENDERE
|
||||
"", // INVENTARIO
|
||||
"su", // UTILIZZARE
|
||||
"", // AZIONARE
|
||||
"a", // PARLARE
|
||||
"" // NOACTION
|
||||
};
|
||||
|
||||
static const CommandeType systemMenu_IT[] = {
|
||||
"Pausa",
|
||||
"Parte nuova",
|
||||
"Quit",
|
||||
"Drive di svg. A:",
|
||||
"Caricare una parte",
|
||||
"Salvare una parte"
|
||||
};
|
||||
|
||||
static const CommandeType confirmMenu_IT[] = {
|
||||
"Ok, vacci ...",
|
||||
"Supratutto non!"
|
||||
};
|
||||
|
||||
static const char *const otherMessages_IT[] = {
|
||||
"Questo salvataggio non esiste...",
|
||||
"Could not create save file ...", //
|
||||
"PAUSE",
|
||||
"Caricamento di| %s",
|
||||
"Caricamento annullato...",
|
||||
"Nessun salvataggio su questo disco...",
|
||||
"Vogliate accedere con il nome del salvataggio"
|
||||
};
|
||||
|
||||
switch (lang) {
|
||||
case Common::FR_FRA:
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
setFailureMessages(failureMessages_OS_FR, false);
|
||||
} else {
|
||||
setFailureMessages(failureMessages_FR, false);
|
||||
}
|
||||
defaultActionCommand = defaultActionCommand_FR;
|
||||
systemMenu = systemMenu_FR;
|
||||
confirmMenu = confirmMenu_FR;
|
||||
otherMessages = otherMessages_FR;
|
||||
defaultCommandPreposition = commandPrepositionTable_FR[3];
|
||||
commandPrepositionTable = commandPrepositionTable_FR;
|
||||
break;
|
||||
|
||||
case Common::ES_ESP:
|
||||
setFailureMessages(failureMessages_ES, false);
|
||||
defaultActionCommand = defaultActionCommand_ES;
|
||||
systemMenu = systemMenu_ES;
|
||||
confirmMenu = confirmMenu_ES;
|
||||
otherMessages = otherMessages_ES;
|
||||
defaultCommandPreposition = commandPrepositionTable_ES[3];
|
||||
commandPrepositionTable = commandPrepositionTable_ES;
|
||||
break;
|
||||
|
||||
case Common::DE_DEU:
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
setFailureMessages(failureMessages_OS_DE, false);
|
||||
} else {
|
||||
setFailureMessages(failureMessages_DE, false);
|
||||
}
|
||||
defaultActionCommand = defaultActionCommand_DE;
|
||||
systemMenu = systemMenu_DE;
|
||||
confirmMenu = confirmMenu_DE;
|
||||
otherMessages = otherMessages_DE;
|
||||
defaultCommandPreposition = commandPrepositionTable_DE[3];
|
||||
commandPrepositionTable = commandPrepositionTable_DE;
|
||||
break;
|
||||
|
||||
case Common::IT_ITA:
|
||||
setFailureMessages(failureMessages_IT, false);
|
||||
defaultActionCommand = defaultActionCommand_IT;
|
||||
systemMenu = systemMenu_IT;
|
||||
confirmMenu = confirmMenu_IT;
|
||||
otherMessages = otherMessages_IT;
|
||||
defaultCommandPreposition = commandPrepositionTable_IT[3];
|
||||
commandPrepositionTable = commandPrepositionTable_IT;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (g_cine->getGameType() == Cine::GType_OS) {
|
||||
if (lang == Common::EN_USA) {
|
||||
setFailureMessages(failureMessages_OS_US, false);
|
||||
} else {
|
||||
setFailureMessages(failureMessages_OS_EN, false);
|
||||
}
|
||||
} else {
|
||||
setFailureMessages(failureMessages_EN, false);
|
||||
}
|
||||
defaultActionCommand = defaultActionCommand_EN;
|
||||
systemMenu = systemMenu_EN;
|
||||
confirmMenu = confirmMenu_EN;
|
||||
otherMessages = otherMessages_EN;
|
||||
defaultCommandPreposition = commandPrepositionTable_EN[3];
|
||||
commandPrepositionTable = commandPrepositionTable_EN;
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_cine->getFeatures() & GF_ALT_FONT) {
|
||||
// Copy alternative font parameter table to the current font parameter table
|
||||
Common::copy(fontParamTable_alt, fontParamTable_alt + NUM_FONT_CHARS, g_cine->_textHandler.fontParamTable);
|
||||
} else {
|
||||
// Copy standard font parameter to the current font parameter table
|
||||
Common::copy(fontParamTable_standard, fontParamTable_standard + NUM_FONT_CHARS, g_cine->_textHandler.fontParamTable);
|
||||
}
|
||||
}
|
||||
|
||||
void loadErrmessDat(const char *fname) {
|
||||
Common::File in;
|
||||
|
||||
in.open(fname);
|
||||
|
||||
if (in.isOpen()) {
|
||||
if (allocatedFailureMessages) {
|
||||
freeErrmessDat();
|
||||
}
|
||||
|
||||
char **ptr = (char **)malloc(sizeof(char *) * 6 * 4 + 60 * 6 * 4);
|
||||
|
||||
for (int i = 0; i < 6 * 4; i++) {
|
||||
ptr[i] = (char *)ptr + (sizeof(char *) * 6 * 4) + 60 * i;
|
||||
in.read(ptr[i], 60);
|
||||
}
|
||||
setFailureMessages(const_cast<const char *const *>(ptr), true);
|
||||
|
||||
in.close();
|
||||
} else {
|
||||
warning("Cannot read error messages from '%s'. Using default values. Error messages may be incorrect!", fname);
|
||||
}
|
||||
}
|
||||
|
||||
void setFailureMessages(const char *const *messages, bool allocated) {
|
||||
if (allocatedFailureMessages) {
|
||||
freeErrmessDat();
|
||||
}
|
||||
failureMessages = messages;
|
||||
allocatedFailureMessages = allocated;
|
||||
}
|
||||
|
||||
void freeErrmessDat() {
|
||||
if (allocatedFailureMessages) {
|
||||
free(const_cast<const char **>(failureMessages));
|
||||
}
|
||||
failureMessages = nullptr;
|
||||
allocatedFailureMessages = false;
|
||||
}
|
||||
|
||||
void loadPoldatDat(const char *fname) {
|
||||
Common::File in;
|
||||
|
||||
in.open(fname);
|
||||
|
||||
if (in.isOpen()) {
|
||||
for (int i = 0; i < NUM_FONT_CHARS; i++) {
|
||||
g_cine->_textHandler.fontParamTable[i].characterIdx = in.readByte();
|
||||
g_cine->_textHandler.fontParamTable[i].characterWidth = in.readByte();
|
||||
}
|
||||
in.close();
|
||||
} else {
|
||||
error("Cannot open file %s for reading", fname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fit a substring of text into one line of fixed width text box
|
||||
* @param str Text to fit
|
||||
* @param maxWidth Text box width
|
||||
* @param[out] words Number of words that fit
|
||||
* @param[out] width Total width of nonblank characters that fit
|
||||
* @return Length of substring which fits
|
||||
*/
|
||||
int fitLine(const char *str, int maxWidth, int &words, int &width) {
|
||||
int i, bkpWords = 0, bkpWidth = 0, bkpLen = 0;
|
||||
int charWidth = 0, fullWidth = 0;
|
||||
|
||||
words = 0;
|
||||
width = 0;
|
||||
|
||||
for (i = 0; str[i]; i++) {
|
||||
if (str[i] == 0x7C) {
|
||||
i++;
|
||||
break;
|
||||
} else if (str[i] == ' ') {
|
||||
charWidth = 5;
|
||||
bkpWords = words++;
|
||||
bkpWidth = width;
|
||||
bkpLen = i + 1;
|
||||
} else {
|
||||
charWidth = g_cine->_textHandler.fontParamTable[(unsigned char)str[i]].characterWidth + 1;
|
||||
width += charWidth;
|
||||
}
|
||||
|
||||
if (!charWidth) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fullWidth + charWidth < maxWidth) {
|
||||
fullWidth += charWidth;
|
||||
} else if (fullWidth) {
|
||||
words = bkpWords;
|
||||
width = bkpWidth;
|
||||
i = bkpLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
70
engines/cine/texte.h
Normal file
70
engines/cine/texte.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* 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 CINE_TEXTE_H
|
||||
#define CINE_TEXTE_H
|
||||
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
typedef char CommandeType[20];
|
||||
|
||||
// Number of characters in a font
|
||||
#define NUM_FONT_CHARS 256
|
||||
|
||||
#define FONT_WIDTH 16
|
||||
#define FONT_HEIGHT 8
|
||||
|
||||
// Used for choosing between font's data and font's mask
|
||||
#define FONT_DATA 0
|
||||
#define FONT_MASK 1
|
||||
|
||||
struct CharacterEntry {
|
||||
byte characterIdx;
|
||||
byte characterWidth;
|
||||
};
|
||||
|
||||
struct TextHandler {
|
||||
byte textTable[NUM_FONT_CHARS][2][FONT_WIDTH *FONT_HEIGHT];
|
||||
CharacterEntry fontParamTable[NUM_FONT_CHARS];
|
||||
};
|
||||
|
||||
extern const char *const *failureMessages;
|
||||
extern const CommandeType *defaultActionCommand;
|
||||
extern const CommandeType *systemMenu;
|
||||
extern const CommandeType *confirmMenu;
|
||||
extern const char *const *otherMessages;
|
||||
extern const char *defaultCommandPreposition;
|
||||
extern const char *const *commandPrepositionTable;
|
||||
|
||||
void loadTextData(const char *filename);
|
||||
void loadErrmessDat(const char *fname);
|
||||
void setFailureMessages(const char *const *messages, bool allocated);
|
||||
void freeErrmessDat();
|
||||
void loadPoldatDat(const char *fname);
|
||||
|
||||
int fitLine(const char *ptr, int maxWidth, int &words, int &width);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
153
engines/cine/unpack.cpp
Normal file
153
engines/cine/unpack.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 "common/endian.h"
|
||||
|
||||
#include "cine/unpack.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
uint32 CineUnpacker::readSource() {
|
||||
if (_src < _srcBegin || _src + 4 > _srcEnd) {
|
||||
_error = true;
|
||||
return 0; // The source pointer is out of bounds, returning a default value
|
||||
}
|
||||
uint32 value = READ_BE_UINT32(_src);
|
||||
_src -= 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
uint CineUnpacker::rcr(bool inputCarry) {
|
||||
uint outputCarry = (_chunk32b & 1);
|
||||
_chunk32b >>= 1;
|
||||
if (inputCarry) {
|
||||
_chunk32b |= 0x80000000;
|
||||
}
|
||||
return outputCarry;
|
||||
}
|
||||
|
||||
uint CineUnpacker::nextBit() {
|
||||
uint carry = rcr(false);
|
||||
// Normally if the chunk becomes zero then the carry is one as
|
||||
// the end of chunk marker is always the last to be shifted out.
|
||||
if (_chunk32b == 0) {
|
||||
_chunk32b = readSource();
|
||||
_crc ^= _chunk32b;
|
||||
carry = rcr(true); // Put the end of chunk marker in the most significant bit
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
uint CineUnpacker::getBits(uint numBits) {
|
||||
uint c = 0;
|
||||
while (numBits--) {
|
||||
c <<= 1;
|
||||
c |= nextBit();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void CineUnpacker::unpackRawBytes(uint numBytes) {
|
||||
if (_dst >= _dstEnd || _dst - numBytes + 1 < _dstBegin) {
|
||||
_error = true;
|
||||
return; // Destination pointer is out of bounds for this operation
|
||||
}
|
||||
while (numBytes--) {
|
||||
*_dst = (byte)getBits(8);
|
||||
--_dst;
|
||||
}
|
||||
}
|
||||
|
||||
void CineUnpacker::copyRelocatedBytes(uint offset, uint numBytes) {
|
||||
if (_dst + offset >= _dstEnd || _dst - numBytes + 1 < _dstBegin) {
|
||||
_error = true;
|
||||
return; // Destination pointer is out of bounds for this operation
|
||||
}
|
||||
while (numBytes--) {
|
||||
*_dst = *(_dst + offset);
|
||||
--_dst;
|
||||
}
|
||||
}
|
||||
|
||||
bool CineUnpacker::unpack(const byte *src, uint srcLen, byte *dst, uint dstLen) {
|
||||
// Initialize variables used for detecting errors during unpacking
|
||||
_error = false;
|
||||
_srcBegin = src;
|
||||
_srcEnd = src + srcLen;
|
||||
_dstBegin = dst;
|
||||
_dstEnd = dst + dstLen;
|
||||
|
||||
// Handle already unpacked data here
|
||||
if (srcLen == dstLen) {
|
||||
// Source length is same as destination length so the source
|
||||
// data is already unpacked. Let's just copy it then.
|
||||
memcpy(dst, src, srcLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize other variables
|
||||
_src = _srcBegin + srcLen - 4;
|
||||
uint32 unpackedLength = readSource(); // Unpacked length in bytes
|
||||
_dst = _dstBegin + unpackedLength - 1;
|
||||
_crc = readSource();
|
||||
_chunk32b = readSource();
|
||||
_crc ^= _chunk32b;
|
||||
|
||||
while (_dst >= _dstBegin && !_error) {
|
||||
/*
|
||||
Bits => Action:
|
||||
0 0 => unpackRawBytes(3 bits + 1) i.e. unpackRawBytes(1..8)
|
||||
1 1 1 => unpackRawBytes(8 bits + 9) i.e. unpackRawBytes(9..264)
|
||||
0 1 => copyRelocatedBytes(8 bits, 2) i.e. copyRelocatedBytes(0..255, 2)
|
||||
1 0 0 => copyRelocatedBytes(9 bits, 3) i.e. copyRelocatedBytes(0..511, 3)
|
||||
1 0 1 => copyRelocatedBytes(10 bits, 4) i.e. copyRelocatedBytes(0..1023, 4)
|
||||
1 1 0 => copyRelocatedBytes(12 bits, 8 bits + 1) i.e. copyRelocatedBytes(0..4095, 1..256)
|
||||
*/
|
||||
if (!nextBit()) { // 0...
|
||||
if (!nextBit()) { // 0 0
|
||||
uint numBytes = getBits(3) + 1;
|
||||
unpackRawBytes(numBytes);
|
||||
} else { // 0 1
|
||||
uint numBytes = 2;
|
||||
uint offset = getBits(8);
|
||||
copyRelocatedBytes(offset, numBytes);
|
||||
}
|
||||
} else { // 1...
|
||||
uint c = getBits(2);
|
||||
if (c == 3) { // 1 1 1
|
||||
uint numBytes = getBits(8) + 9;
|
||||
unpackRawBytes(numBytes);
|
||||
} else if (c < 2) { // 1 0 x
|
||||
uint numBytes = c + 3;
|
||||
uint offset = getBits(c + 9);
|
||||
copyRelocatedBytes(offset, numBytes);
|
||||
} else { // 1 1 0
|
||||
uint numBytes = getBits(8) + 1;
|
||||
uint offset = getBits(12);
|
||||
copyRelocatedBytes(offset, numBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return !_error && (_crc == 0);
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
113
engines/cine/unpack.h
Normal file
113
engines/cine/unpack.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* 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 CINE_UNPACK_H
|
||||
#define CINE_UNPACK_H
|
||||
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
/**
|
||||
* A LZ77 style decompressor for Delphine's data files
|
||||
* used in at least Future Wars and Operation Stealth.
|
||||
* @note Works backwards in the source and destination buffers.
|
||||
* @warning Having the source and destination in the same buffer when unpacking can cause errors!
|
||||
*/
|
||||
class CineUnpacker {
|
||||
public:
|
||||
/**
|
||||
* Unpacks packed data from the source buffer to the destination buffer.
|
||||
* @note You may call this on already unpacked data but then source length must be equal to destination length.
|
||||
* @warning The source and destination should not point to the same buffer. If they do, errors may occur!
|
||||
* @param src Pointer to the source buffer.
|
||||
* @param srcLen Length of the source buffer.
|
||||
* @param dst Pointer to the destination buffer.
|
||||
* @param dstLen Length of the destination buffer.
|
||||
* @return True if no errors were detected in the source data and unpacking was successful, otherwise false.
|
||||
*/
|
||||
bool unpack(const byte *src, uint srcLen, byte *dst, uint dstLen);
|
||||
private:
|
||||
/**
|
||||
* Reads an unsigned big endian 32-bit integer from the source stream and goes backwards 4 bytes.
|
||||
* @return If the operation is valid, an unsigned big endian 32-bit integer read from the source stream.
|
||||
* @return If the operation is invalid, zero.
|
||||
* @note Sets internal error state if the read operation would be out of source bounds.
|
||||
*/
|
||||
uint32 readSource();
|
||||
|
||||
/**
|
||||
* Shifts the current internal 32-bit chunk to the right by one.
|
||||
* Puts input carry into internal chunk's topmost (i.e. leftmost) bit.
|
||||
* @return The least significant bit that was shifted out from the chunk.
|
||||
*/
|
||||
uint rcr(bool inputCarry);
|
||||
|
||||
/**
|
||||
* Get the next bit from the source stream.
|
||||
* @note Changes the bit position in the source stream.
|
||||
* @return The next bit from the source stream.
|
||||
*/
|
||||
uint nextBit();
|
||||
|
||||
/**
|
||||
* Get bits from the source stream.
|
||||
* @note Changes the bit position in the source stream.
|
||||
* @param numBits Number of bits to read from the source stream.
|
||||
* @return Integer value consisting of the bits read from the source stream (In range [0, (2 ** numBits) - 1]).
|
||||
* @return Later the bit was read from the source, the less significant it is in the return value.
|
||||
*/
|
||||
uint getBits(uint numBits);
|
||||
|
||||
/**
|
||||
* Copy raw bytes from the input stream and write them to the destination stream.
|
||||
* This is used when no adequately long match is found in the sliding window.
|
||||
* @note Sets internal error state if the operation would be out of bounds.
|
||||
* @param numBytes Amount of bytes to copy from the input stream
|
||||
*/
|
||||
void unpackRawBytes(uint numBytes);
|
||||
|
||||
/**
|
||||
* Copy bytes from the sliding window in the destination buffer.
|
||||
* This is used when a match of two bytes or longer is found.
|
||||
* @note Sets internal error state if the operation would be out of bounds.
|
||||
* @param offset Offset in the sliding window
|
||||
* @param numBytes Amount of bytes to copy
|
||||
*/
|
||||
void copyRelocatedBytes(uint offset, uint numBytes);
|
||||
private:
|
||||
uint32 _crc; ///< Error-detecting code (This should be zero after successful unpacking)
|
||||
uint32 _chunk32b; ///< The current internal 32-bit chunk of source data
|
||||
byte *_dst; ///< Pointer to the current position in the destination buffer
|
||||
const byte *_src; ///< Pointer to the current position in the source buffer
|
||||
|
||||
// These are used for detecting errors (e.g. out of bounds issues) during unpacking
|
||||
bool _error; ///< Did an error occur during unpacking?
|
||||
const byte *_srcBegin; ///< Source buffer's beginning
|
||||
const byte *_srcEnd; ///< Source buffer's end
|
||||
byte *_dstBegin; ///< Destination buffer's beginning
|
||||
byte *_dstEnd; ///< Destination buffer's end
|
||||
};
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
2022
engines/cine/various.cpp
Normal file
2022
engines/cine/various.cpp
Normal file
File diff suppressed because it is too large
Load Diff
163
engines/cine/various.h
Normal file
163
engines/cine/various.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/* 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 CINE_VARIOUS_H
|
||||
#define CINE_VARIOUS_H
|
||||
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/keyboard.h"
|
||||
|
||||
#include "cine/cine.h"
|
||||
|
||||
namespace Cine {
|
||||
|
||||
#define kMaxSavegames 100
|
||||
#define kMaxOrigUiSavegames 20 // 20 fit on screen using original save/load interface
|
||||
|
||||
// Maximum size of the command buffer including the trailing zero
|
||||
#define kMaxCommandBufferSize 80
|
||||
|
||||
void initLanguage(Common::Language lang);
|
||||
|
||||
int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, uint16 width, int minY = 0, bool recheckValue = false, bool allowEmpty = false);
|
||||
void makeCommandLine();
|
||||
void makeFWCommandLine();
|
||||
void makeOSCommandLine();
|
||||
void makeActionMenu();
|
||||
void waitPlayerInput();
|
||||
void setTextWindow(uint16 param1, uint16 param2, uint16 param3, uint16 param4);
|
||||
|
||||
extern int16 disableSystemMenu;
|
||||
extern bool inMenu;
|
||||
extern bool runOnlyUntilFreePartRangeFirst200;
|
||||
|
||||
extern CommandeType currentSaveName[kMaxSavegames];
|
||||
|
||||
struct SeqListElement {
|
||||
int16 var4;
|
||||
uint16 objIdx; ///< Is this really unsigned?
|
||||
int16 var8;
|
||||
int16 frame;
|
||||
int16 varC;
|
||||
int16 varE;
|
||||
int16 var10;
|
||||
int16 var12;
|
||||
int16 var14;
|
||||
int16 var16;
|
||||
int16 var18;
|
||||
int16 var1A;
|
||||
int16 var1C;
|
||||
int16 var1E;
|
||||
};
|
||||
|
||||
extern uint16 var2;
|
||||
extern uint16 var3;
|
||||
extern uint16 var4;
|
||||
extern uint16 lastType20OverlayBgIdx;
|
||||
extern uint16 reloadBgPalOnNextFlip;
|
||||
extern uint16 forbidBgPalReload;
|
||||
extern uint16 gfxFadeOutCompleted;
|
||||
extern uint16 gfxFadeInRequested;
|
||||
extern uint32 safeControlsLastAccessedMs; ///< Time in milliseconds when safe controls were last accessed.
|
||||
extern int16 lastSafeControlObjIdx; ///< Object index of the last safe control accessed.
|
||||
extern int16 commandVar1;
|
||||
extern int16 commandVar2;
|
||||
extern int16 commandVar3[4];
|
||||
|
||||
extern char currentDatName[30];
|
||||
extern uint16 musicIsPlaying;
|
||||
|
||||
extern uint16 errorVar;
|
||||
extern byte menuVar;
|
||||
|
||||
extern uint16 allowPlayerInput;
|
||||
|
||||
extern uint16 checkForPendingDataLoadSwitch;
|
||||
|
||||
extern uint16 isDrawCommandEnabled;
|
||||
extern uint16 waitForPlayerClick;
|
||||
extern uint16 menuCommandLen;
|
||||
extern bool _paletteNeedUpdate;
|
||||
extern uint16 _messageLen;
|
||||
|
||||
extern int16 playerCommand;
|
||||
|
||||
extern char currentPrcName[20];
|
||||
extern char currentRelName[20];
|
||||
extern char currentObjectName[20];
|
||||
extern char currentMsgName[20];
|
||||
extern char newPrcName[20];
|
||||
extern char newRelName[20];
|
||||
extern char newObjectName[20];
|
||||
extern char newMsgName[20];
|
||||
|
||||
extern char currentCtName[15];
|
||||
extern char currentPartName[15];
|
||||
|
||||
void stopSample();
|
||||
void stopMusicAfterFadeOut();
|
||||
void playerCommandMouseLeftRightUp(uint16 mouseX, uint16 mouseY);
|
||||
uint16 executePlayerInput();
|
||||
|
||||
void drawOverlays();
|
||||
|
||||
extern uint16 mouseUpdateStatus;
|
||||
extern uint16 dummyU16;
|
||||
|
||||
void getMouseData(uint16 param, uint16 *pButton, uint16 *pX, uint16 *pY);
|
||||
|
||||
uint16 processKeyboard(uint16 param);
|
||||
|
||||
void mainLoopSub6();
|
||||
|
||||
void checkForPendingDataLoad();
|
||||
|
||||
void hideMouse();
|
||||
|
||||
void removeExtension(char *dest, const char *source, size_t sz);
|
||||
|
||||
struct SelectedObjStruct {
|
||||
int16 idx;
|
||||
int16 param;
|
||||
};
|
||||
|
||||
#define NUM_MAX_ZONE 16
|
||||
|
||||
void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 param5);
|
||||
|
||||
void removeMessages();
|
||||
|
||||
void removeSeq(uint16 param1, uint16 param2, uint16 param3);
|
||||
bool isSeqRunning(uint16 param1, uint16 param2, uint16 param3);
|
||||
void addSeqListElement(uint16 objIdx, int16 param1, int16 param2, int16 frame, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8);
|
||||
void modifySeqListElement(uint16 objIdx, int16 var4Test, int16 param1, int16 param2, int16 param3, int16 param4);
|
||||
void processSeqList();
|
||||
|
||||
void resetGfxEntityEntry(uint16 objIdx);
|
||||
|
||||
bool makeTextEntryMenu(const char *caption, char *string, int strLen, int y);
|
||||
void moveUsingKeyboard(int x, int y);
|
||||
int16 getObjectUnderCursor(uint16 x, uint16 y);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
#endif
|
||||
184
engines/cine/xref.txt
Normal file
184
engines/cine/xref.txt
Normal file
@@ -0,0 +1,184 @@
|
||||
script_fw.cpp:
|
||||
setupOpcodes() - replaced with FWScript/OSScript class members
|
||||
getNextByte() - replaced with RawScript/FWScript class members
|
||||
getNextWord() - replaced with RawScript/FWScript class members
|
||||
getNextString() - replaced with RawScript/FWScript class members
|
||||
computeScriptStackSub() - replaced with RawScript::getNextLabel()
|
||||
computeScriptStack() - replaced with RawScript::computeLabels()
|
||||
computeScriptStackFromScript() - replaced with RawScript::getLabel()
|
||||
executeScript() - replaced with FWScript::execute()
|
||||
endScript0() - removed (obsoleted by new executeList0() implementation)
|
||||
endScript1() - removed (obsoleted by new executeList1() implementation)
|
||||
|
||||
o1_modifyObjectParam() - replaced with FWScript::o1_modifyObjectParam()
|
||||
o1_getObjectParam() - replaced with FWScript::o1_getObjectParam()
|
||||
o1_addObjectParam() - replaced with FWScript::o1_addObjectParam()
|
||||
o1_subObjectParam() - replaced with FWScript::o1_subObjectParam()
|
||||
o1_add2ObjectParam() - replaced with FWScript::o1_add2ObjectParam()
|
||||
o1_sub2ObjectParam() - replaced with FWScript::o1_sub2ObjectParam()
|
||||
o1_compareObjectParam() - replaced with FWScript::o1_compareObjectParam()
|
||||
o1_setupObject() - replaced with FWScript::o1_setupObject()
|
||||
o1_checkCollision() - replaced with FWScript::o1_checkCollision()
|
||||
o1_loadVar() - replaced with FWScript::o1_loadVar()
|
||||
o1_addVar() - replaced with FWScript::o1_addVar()
|
||||
o1_subVar() - replaced with FWScript::o1_subVar()
|
||||
o1_mulVar() - replaced with FWScript::o1_mulVar()
|
||||
o1_divVar() - replaced with FWScript::o1_divVar()
|
||||
o1_compareVar() - replaced with FWScript::o1_compareVar()
|
||||
o1_modifyObjectParam2() - replaced with FWScript::o1_modifyObjectParam2()
|
||||
o1_loadMask0() - replaced with FWScript::o1_loadMask0()
|
||||
o1_unloadMask0() - replaced with FWScript::o1_unloadMask0()
|
||||
o1_addToBgList() - replaced with FWScript::o1_addToBgList()
|
||||
o1_loadMask1() - replaced with FWScript::o1_loadMask1()
|
||||
o1_unloadMask1() - replaced with FWScript::o1_unloadMask1()
|
||||
o1_loadMask4() - replaced with FWScript::o1_loadMask4()
|
||||
o1_unloadMask4() - replaced with FWScript::o1_unloadMask4()
|
||||
o1_addSpriteFilledToBgList() - replaced with FWScript::o1_addSpriteFilledToBgList()
|
||||
o1_op1B() - replaced with FWScript::o1_op1B()
|
||||
o1_label() - replaced with FWScript::o1_label()
|
||||
o1_goto() - replaced with FWScript::o1_goto()
|
||||
o1_gotoIfSup() - replaced with FWScript::o1_gotoIfSup()
|
||||
o1_gotoIfSupEqu() - replaced with FWScript::o1_gotoIfSupEqu()
|
||||
o1_gotoIfInf() - replaced with FWScript::o1_gotoIfInf()
|
||||
o1_gotoIfInfEqu() - replaced with FWScript::o1_gotoIfInfEqu()
|
||||
o1_gotoIfEqu() - replaced with FWScript::o1_gotoIfEqu()
|
||||
o1_gotoIfDiff() - replaced with FWScript::o1_gotoIfDiff()
|
||||
o1_removeLabel() - replaced with FWScript::o1_removeLabel()
|
||||
o1_loop() - replaced with FWScript::o1_loop()
|
||||
o1_startGlobalScript() - replaced with FWScript::o1_startGlobalScript()
|
||||
o1_endGlobalScript() - replaced with FWScript::o1_endGlobalScript()
|
||||
o1_loadAnim() - replaced with FWScript::o1_loadAnim()
|
||||
o1_loadBg() - replaced with FWScript::o1_loadBg()
|
||||
o1_loadCt() - replaced with FWScript::o1_loadCt()
|
||||
o1_loadPart() - replaced with FWScript::o1_loadPart()
|
||||
o1_closePart() - replaced with FWScript::o1_closePart()
|
||||
o1_loadNewPrcName() - replaced with FWScript::o1_loadNewPrcName()
|
||||
o1_requestCheckPendingDataLoad() - replaced with FWScript::o1_requestCheckPendingDataLoad()
|
||||
o1_blitAndFade() - replaced with FWScript::o1_blitAndFade()
|
||||
o1_fadeToBlack() - replaced with FWScript::o1_fadeToBlack()
|
||||
o1_transformPaletteRange() - replaced with FWScript::o1_transformPaletteRange()
|
||||
o1_setDefaultMenuColor2() - replaced with FWScript::o1_setDefaultMenuColor2()
|
||||
o1_palRotate() - replaced with FWScript::o1_palRotate()
|
||||
o1_break() - replaced with FWScript::o1_break()
|
||||
o1_endScript() - replaced with FWScript::o1_endScript()
|
||||
o1_message() - replaced with FWScript::o1_message()
|
||||
o1_loadGlobalVar() - replaced with FWScript::o1_loadGlobalVar()
|
||||
o1_compareGlobalVar() - replaced with FWScript::o1_compareGlobalVar()
|
||||
o1_declareFunctionName() - replaced with FWScript::o1_declareFunctionName()
|
||||
o1_freePartRange() - replaced with FWScript::o1_freePartRange()
|
||||
o1_unloadAllMasks() - replaced with FWScript::o1_unloadAllMasks()
|
||||
o1_setScreenDimensions() - replaced with FWScript::o1_setScreenDimensions()
|
||||
o1_displayBackground() - replaced with FWScript::o1_displayBackground()
|
||||
o1_initializeZoneData() - replaced with FWScript::o1_initializeZoneData()
|
||||
o1_setZoneDataEntry() - replaced with FWScript::o1_setZoneDataEntry()
|
||||
o1_getZoneDataEntry() - replaced with FWScript::o1_getZoneDataEntry()
|
||||
o1_setDefaultMenuColor() - replaced with FWScript::o1_setDefaultMenuColor()
|
||||
o1_allowPlayerInput() - replaced with FWScript::o1_allowPlayerInput()
|
||||
o1_disallowPlayerInput() - replaced with FWScript::o1_disallowPlayerInput()
|
||||
o1_changeDataDisk() - replaced with FWScript::o1_changeDataDisk()
|
||||
o1_loadMusic() - replaced with FWScript::o1_loadMusic()
|
||||
o1_playMusic() - replaced with FWScript::o1_playMusic()
|
||||
o1_fadeOutMusic() - replaced with FWScript::o1_fadeOutMusic()
|
||||
o1_stopSample() - replaced with FWScript::o1_stopSample()
|
||||
o1_op71() - replaced with FWScript::o1_op71()
|
||||
o1_op72() - replaced with FWScript::o1_op72()
|
||||
o1_op73() - replaced with FWScript::o1_op73()
|
||||
o1_playSample() - replaced with FWScript::o1_playSample()
|
||||
o1_playSample() - replaced with FWScript::o1_playSample()
|
||||
o1_disableSystemMenu() - replaced with FWScript::o1_disableSystemMenu()
|
||||
o1_loadMask5() - replaced with FWScript::o1_loadMask5()
|
||||
o1_unloadMask5() - replaced with FWScript::o1_unloadMask5()
|
||||
|
||||
palRotate() - modified and moved to pal.cpp
|
||||
|
||||
script_os.cpp:
|
||||
o2_loadPart() - replaced with FWScript::o2_loadPart()
|
||||
o2_addSeqListElement() - replaced with FWScript::o2_addSeqListElement()
|
||||
o2_removeSeq() - replaced with FWScript::o2_removeSeq()
|
||||
o2_playSample() - replaced with FWScript::o2_playSample()
|
||||
o2_playSampleAlt() - replaced with FWScript::o2_playSampleAlt()
|
||||
o2_op81() - replaced with FWScript::o2_op81()
|
||||
o2_op82() - replaced with FWScript::o2_op82()
|
||||
o2_isSeqRunning() - replaced with FWScript::o2_isSeqRunning()
|
||||
o2_gotoIfSupNearest() - replaced with FWScript::o2_gotoIfSupNearest()
|
||||
o2_gotoIfSupEquNearest() - replaced with FWScript::o2_gotoIfSupEquNearest()
|
||||
o2_gotoIfInfNearest() - replaced with FWScript::o2_gotoIfInfNearest()
|
||||
o2_gotoIfInfEquNearest() - replaced with FWScript::o2_gotoIfInfEquNearest()
|
||||
o2_gotoIfEquNearest() - replaced with FWScript::o2_gotoIfEquNearest()
|
||||
o2_gotoIfDiffNearest() - replaced with FWScript::o2_gotoIfDiffNearest()
|
||||
o2_startObjectScript() - replaced with FWScript::o2_startObjectScript()
|
||||
o2_stopObjectScript() - replaced with FWScript::o2_stopObjectScript()
|
||||
o2_op8D() - replaced with FWScript::o2_op8D()
|
||||
o2_addBackground() - replaced with FWScript::o2_addBackground()
|
||||
o2_removeBackground() - replaced with FWScript::o2_removeBackground()
|
||||
o2_loadAbs() - replaced with FWScript::o2_loadAbs()
|
||||
o2_loadBg() - replaced with FWScript::o2_loadBg()
|
||||
o2_wasZoneChecked() - replaced with FWScript::o2_wasZoneChecked()
|
||||
o2_op9B() - replaced with FWScript::o2_op9B()
|
||||
o2_op9C() - replaced with FWScript::o2_op9C()
|
||||
o2_useBgScroll() - replaced with FWScript::o2_useBgScroll()
|
||||
o2_setAdditionalBgVScroll() - replaced with FWScript::o2_setAdditionalBgVScroll()
|
||||
o2_op9F() - replaced with FWScript::o2_op9F()
|
||||
o2_addGfxElementA0() - replaced with FWScript::o2_addGfxElementA0()
|
||||
o2_opA1() - replaced with FWScript::o2_opA1()
|
||||
o2_opA2() - replaced with FWScript::o2_opA2()
|
||||
o2_opA3() - replaced with FWScript::o2_opA3()
|
||||
o2_loadMask22() - replaced with FWScript::o2_loadMask22()
|
||||
o2_unloadMask22() - replaced with FWScript::o2_unloadMask22()
|
||||
|
||||
prc.cpp:
|
||||
resetGlobalScriptsHead() - removed (obsoleted by Common::List)
|
||||
freePrcLinkedList() - removed (obsoleted by Common::List::clear())
|
||||
|
||||
rel.cpp:
|
||||
resetObjectScriptHead() - removed (obsoleted by Common::List)
|
||||
releaseObjectScripts() - removed (obsoleted by Common::List::clear())
|
||||
|
||||
various.cpp:
|
||||
setupScriptList() - removed (obsoleted by new makeLoad() and
|
||||
loadScriptFromSave() implementation)
|
||||
drawChar() - removed (obsoleted by FWRenderer::drawChar())
|
||||
makeTextEntry() - removed (obsoleted by FWRenderer::drawMenu())
|
||||
drawMenuBox() - removed (obsoleted by FWRenderer::drawCommand())
|
||||
backupOverlayPage() - removed (obsoleted by FWRenderer::drawBackground())
|
||||
drawMessage() - removed (obsoleted by FWRenderer::drawMessage())
|
||||
drawDialogueMessage() - removed (obsoleted by FWRenderer::renderOverlay())
|
||||
drawFailureMessage() - removed (obsoleted by FWRenderer::renderOverlay())
|
||||
drawOverlays() - removed (obsoleted by FWRenderer::drawOverlays())
|
||||
resetSeqList() - removed (obsoleted by Common::List)
|
||||
|
||||
anim.cpp:
|
||||
freeAnimData() - replaced with animData::clear()
|
||||
allocFrame() - replaced with animData::load()
|
||||
reserveFrame() - replaced with animData::load()
|
||||
|
||||
bg_list.cpp:
|
||||
reincrustAllBg() - removed (obsoleted by new loadResourcesFromSave() and
|
||||
loadBgIncrustFromSave() implementation)
|
||||
freeBgIncrustList() - removed (obsoleted by Common::List::clear())
|
||||
|
||||
object.cpp:
|
||||
unloadAllMasks() - removed (obsoleted by Common::List::clear())
|
||||
resetMessageHead() - removed (obsoleted by Common::List)
|
||||
freeOverlay() - removed (duplicate of removeOverlay)
|
||||
removeOverlayElement() - renamed to removeOverlay
|
||||
loadOverlayElement() - renamed to addOverlay
|
||||
|
||||
gfx.cpp:
|
||||
gfxInit() - removed (obsoleted by FWRenderer)
|
||||
gfxDestroy() - removed (obsoleted by FWRenderer)
|
||||
transformColor() - moved to pal.cpp
|
||||
transformPaletteRange() - modified and moved to pal.cpp
|
||||
gfxCopyRawPage() - removed (obsoleted by FWRenderer)
|
||||
gfxFlipRawPage() - removed (obsoleted by FWRenderer::blit() and
|
||||
FWRenderer::refreshPalette())
|
||||
fadeToBlack() - removed (obsoleted by FWRenderer::fadeToBlack())
|
||||
blitRawScreen() - removed (obsoleted by FWRenderer)
|
||||
flip() - removed (obsoleted by FWRenderer::reloadPalette())
|
||||
|
||||
bg.cpp:
|
||||
loadCt() - split into loadCtFW() and loadCtOS()
|
||||
loadBgHigh() - removed (obsoleted by OSRenderer::loadBg256())
|
||||
|
||||
texte.cpp:
|
||||
computeMessageLength() - replaced with fitLine()
|
||||
Reference in New Issue
Block a user