Initial commit
This commit is contained in:
3
engines/dreamweb/POTFILES
Normal file
3
engines/dreamweb/POTFILES
Normal file
@@ -0,0 +1,3 @@
|
||||
engines/dreamweb/metaengine.cpp
|
||||
engines/dreamweb/saveload.cpp
|
||||
|
||||
285
engines/dreamweb/backdrop.cpp
Normal file
285
engines/dreamweb/backdrop.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
/* 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 "dreamweb/dreamweb.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
void DreamWebEngine::doBlocks() {
|
||||
uint16 dstOffset = _mapAdY * kScreenwidth + _mapAdX;
|
||||
uint16 mapOffset = _mapY * kMapWidth + _mapX;
|
||||
const uint8 *mapData = _mapData + mapOffset;
|
||||
uint8 *dstBuffer = workspace() + dstOffset;
|
||||
|
||||
for (uint i = 0; i < 10; ++i) {
|
||||
for (uint j = 0; j < 11; ++j) {
|
||||
uint16 blockType = mapData[j];
|
||||
if (blockType != 0) {
|
||||
uint8 *dst = dstBuffer + i * kScreenwidth * 16 + j * 16;
|
||||
const uint8 *block = _backdropBlocks + blockType * 256;
|
||||
for (uint k = 0; k < 4; ++k) {
|
||||
memcpy(dst, block, 16);
|
||||
block += 16;
|
||||
dst += kScreenwidth;
|
||||
}
|
||||
for (uint k = 0; k < 12; ++k) {
|
||||
memcpy(dst, block, 16);
|
||||
memset(dst + 16, 0xdf, 4);
|
||||
block += 16;
|
||||
dst += kScreenwidth;
|
||||
}
|
||||
dst += 4;
|
||||
memset(dst, 0xdf, 16);
|
||||
dst += kScreenwidth;
|
||||
memset(dst, 0xdf, 16);
|
||||
dst += kScreenwidth;
|
||||
memset(dst, 0xdf, 16);
|
||||
dst += kScreenwidth;
|
||||
memset(dst, 0xdf, 16);
|
||||
}
|
||||
}
|
||||
mapData += kMapWidth;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::getXAd(const uint8 *setData, uint8 *result) {
|
||||
uint8 v0 = setData[0];
|
||||
uint8 v1 = setData[1];
|
||||
uint8 v2 = setData[2];
|
||||
if (v0 != 0)
|
||||
return 0;
|
||||
if (v1 < _mapX)
|
||||
return 0;
|
||||
v1 -= _mapX;
|
||||
if (v1 >= 11)
|
||||
return 0;
|
||||
*result = (v1 << 4) | v2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::getYAd(const uint8 *setData, uint8 *result) {
|
||||
uint8 v0 = setData[3];
|
||||
uint8 v1 = setData[4];
|
||||
if (v0 < _mapY)
|
||||
return 0;
|
||||
v0 -= _mapY;
|
||||
if (v0 >= 10)
|
||||
return 0;
|
||||
*result = (v0 << 4) | v1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::getMapAd(const uint8 *setData, uint16 *x, uint16 *y) {
|
||||
uint8 xad, yad;
|
||||
if (getXAd(setData, &xad) == 0)
|
||||
return 0;
|
||||
*x = xad;
|
||||
if (getYAd(setData, &yad) == 0)
|
||||
return 0;
|
||||
*y = yad;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::calcFrFrame(const Frame &frame, uint8 *width, uint8 *height, uint16 x, uint16 y, ObjPos *objPos) {
|
||||
*width = frame.width;
|
||||
*height = frame.height;
|
||||
|
||||
objPos->xMin = (x + frame.x) & 0xff;
|
||||
objPos->yMin = (y + frame.y) & 0xff;
|
||||
objPos->xMax = objPos->xMin + frame.width;
|
||||
objPos->yMax = objPos->yMin + frame.height;
|
||||
}
|
||||
|
||||
void DreamWebEngine::makeBackOb(SetObject *objData, uint16 x, uint16 y) {
|
||||
if (_vars._newObs == 0)
|
||||
return;
|
||||
uint8 priority = objData->priority;
|
||||
uint8 type = objData->type;
|
||||
Sprite *sprite = makeSprite(x, y, false, &_setFrames);
|
||||
|
||||
sprite->_objData = objData;
|
||||
if (priority == 255)
|
||||
priority = 0;
|
||||
sprite->priority = priority;
|
||||
sprite->type = type;
|
||||
sprite->delay = 0;
|
||||
sprite->animFrame = 0;
|
||||
}
|
||||
|
||||
void DreamWebEngine::showAllObs() {
|
||||
_setList.clear();
|
||||
|
||||
const GraphicsFile &frameBase = _setFrames;
|
||||
for (uint i = 0; i < 128; ++i) {
|
||||
SetObject *setEntry = &_setDat[i];
|
||||
uint16 x, y;
|
||||
if (getMapAd(setEntry->mapad, &x, &y) == 0)
|
||||
continue;
|
||||
uint8 currentFrame = setEntry->frames[0];
|
||||
if (currentFrame == 0xff)
|
||||
continue;
|
||||
uint8 width, height;
|
||||
ObjPos objPos;
|
||||
calcFrFrame(frameBase._frames[currentFrame], &width, &height, x, y, &objPos);
|
||||
setEntry->index = setEntry->frames[0];
|
||||
if ((setEntry->type == 0) && (setEntry->priority != 5) && (setEntry->priority != 6)) {
|
||||
x += _mapAdX;
|
||||
y += _mapAdY;
|
||||
showFrame(frameBase, x, y, currentFrame, 0);
|
||||
} else
|
||||
makeBackOb(setEntry, x, y);
|
||||
|
||||
objPos.index = i;
|
||||
_setList.push_back(objPos);
|
||||
}
|
||||
}
|
||||
|
||||
static bool addAlong(const MapFlag *mapFlags) {
|
||||
for (uint i = 0; i < 11; ++i) {
|
||||
if (mapFlags[i]._flag != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool addLength(const MapFlag *mapFlags) {
|
||||
for (uint i = 0; i < 10; ++i) {
|
||||
if (mapFlags[11 * i]._flag != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DreamWebEngine::getDimension(uint8 *mapXstart, uint8 *mapYstart, uint8 *mapXsize, uint8 *mapYsize) {
|
||||
uint8 yStart = 0;
|
||||
while (! addAlong(_mapFlags + 11 * yStart))
|
||||
++yStart;
|
||||
|
||||
uint8 xStart = 0;
|
||||
while (! addLength(_mapFlags + xStart))
|
||||
++xStart;
|
||||
|
||||
uint8 yEnd = 10;
|
||||
while (! addAlong(_mapFlags + 11 * (yEnd - 1)))
|
||||
--yEnd;
|
||||
|
||||
uint8 xEnd = 11;
|
||||
while (! addLength(_mapFlags + (xEnd - 1)))
|
||||
--xEnd;
|
||||
|
||||
*mapXstart = xStart;
|
||||
*mapYstart = yStart;
|
||||
*mapXsize = xEnd - xStart;
|
||||
*mapYsize = yEnd - yStart;
|
||||
_mapXStart = xStart << 4;
|
||||
_mapYStart = yStart << 4;
|
||||
_mapXSize = *mapXsize << 4;
|
||||
_mapYSize = *mapYsize << 4;
|
||||
}
|
||||
|
||||
void DreamWebEngine::calcMapAd() {
|
||||
uint8 mapXstart, mapYstart;
|
||||
uint8 mapXsize, mapYsize;
|
||||
getDimension(&mapXstart, &mapYstart, &mapXsize, &mapYsize);
|
||||
_mapAdX = _mapOffsetX - 8 * (mapXsize + 2 * mapXstart - 11);
|
||||
_mapAdY = _mapOffsetY - 8 * (mapYsize + 2 * mapYstart - 10);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showAllFree() {
|
||||
const uint count = 80;
|
||||
|
||||
_freeList.clear();
|
||||
|
||||
const DynObject *freeObjects = _freeDat;
|
||||
const GraphicsFile &frameBase = _freeFrames;
|
||||
for (uint i = 0; i < count; ++i) {
|
||||
uint16 x, y;
|
||||
uint8 mapAd = getMapAd(freeObjects[i].mapad, &x, &y);
|
||||
if (mapAd != 0) {
|
||||
uint8 width, height;
|
||||
ObjPos objPos;
|
||||
uint16 currentFrame = 3 * i;
|
||||
calcFrFrame(frameBase._frames[currentFrame], &width, &height, x, y, &objPos);
|
||||
if ((width != 0) || (height != 0)) {
|
||||
x += _mapAdX;
|
||||
y += _mapAdY;
|
||||
assert(currentFrame < 256);
|
||||
showFrame(frameBase, x, y, currentFrame, 0);
|
||||
objPos.index = i;
|
||||
_freeList.push_back(objPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::drawFlags() {
|
||||
MapFlag *mapFlag = _mapFlags;
|
||||
uint16 mapOffset = _mapY * kMapWidth + _mapX;
|
||||
const uint8 *mapData = _mapData + mapOffset;
|
||||
|
||||
for (uint i = 0; i < 10; ++i) {
|
||||
for (uint j = 0; j < 11; ++j) {
|
||||
uint8 tile = mapData[i * kMapWidth + j];
|
||||
mapFlag->_flag = _backdropFlags[tile]._flag;
|
||||
mapFlag->_flagEx = _backdropFlags[tile]._flagEx;
|
||||
mapFlag->_type = tile;
|
||||
mapFlag++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::showAllEx() {
|
||||
const uint count = 100;
|
||||
|
||||
_exList.clear();
|
||||
|
||||
DynObject *objects = _exData;
|
||||
const GraphicsFile &frameBase = _exFrames;
|
||||
for (uint i = 0; i < count; ++i) {
|
||||
DynObject *object = objects + i;
|
||||
if (object->mapad[0] == 0xff)
|
||||
continue;
|
||||
if (object->currentLocation != _realLocation)
|
||||
continue;
|
||||
uint16 x, y;
|
||||
if (getMapAd(object->mapad, &x, &y) == 0)
|
||||
continue;
|
||||
uint8 width, height;
|
||||
ObjPos objPos;
|
||||
uint16 currentFrame = 3 * i;
|
||||
calcFrFrame(frameBase._frames[currentFrame], &width, &height, x, y, &objPos);
|
||||
if ((width != 0) || (height != 0)) {
|
||||
// FIXME: this was an assert() that failed during normal gameplay.
|
||||
// Now it's a warning, because it's unclear if the check is valid.
|
||||
// It could have been a copy/paste mistake from showAllFree,
|
||||
// where there are fewer iterations. See bugs: #15420, #15436
|
||||
if (currentFrame >= 256) {
|
||||
warning("showing extra frame %d >= 256", currentFrame);
|
||||
}
|
||||
|
||||
showFrame(frameBase, x + _mapAdX, y + _mapAdY, currentFrame, 0);
|
||||
objPos.index = i;
|
||||
_exList.push_back(objPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
3
engines/dreamweb/configure.engine
Normal file
3
engines/dreamweb/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 dreamweb "Dreamweb" yes
|
||||
33
engines/dreamweb/console.cpp
Normal file
33
engines/dreamweb/console.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/* 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 "dreamweb/console.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
DreamWebConsole::DreamWebConsole(DreamWebEngine *vm) : GUI::Debugger(), _vm(vm) {
|
||||
assert(_vm);
|
||||
}
|
||||
|
||||
DreamWebConsole::~DreamWebConsole() {
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
42
engines/dreamweb/console.h
Normal file
42
engines/dreamweb/console.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* 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 DREAMWEB_CONSOLE_H
|
||||
#define DREAMWEB_CONSOLE_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
class DreamWebEngine;
|
||||
|
||||
class DreamWebConsole : public GUI::Debugger {
|
||||
public:
|
||||
DreamWebConsole(DreamWebEngine *vm);
|
||||
~DreamWebConsole(void) override;
|
||||
|
||||
private:
|
||||
DreamWebEngine *_vm;
|
||||
};
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
|
||||
#endif
|
||||
7
engines/dreamweb/credits.pl
Normal file
7
engines/dreamweb/credits.pl
Normal file
@@ -0,0 +1,7 @@
|
||||
begin_section("DreamWeb");
|
||||
add_person("Torbjörn Andersson", "eriktorbjorn", "");
|
||||
add_person("Bertrand Augereau", "Tramb", "");
|
||||
add_person("Filippos Karapetis", "bluegr", "");
|
||||
add_person("Vladimir Menshakov", "whoozle", "");
|
||||
add_person("Willem Jan Palenstijn", "wjp", "");
|
||||
end_section();
|
||||
71
engines/dreamweb/detection.cpp
Normal file
71
engines/dreamweb/detection.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/* 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 "common/algorithm.h"
|
||||
#include "common/system.h"
|
||||
#include "common/text-to-speech.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "dreamweb/detection.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
|
||||
static const PlainGameDescriptor dreamWebGames[] = {
|
||||
{ "dreamweb", "DreamWeb" },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
static const DebugChannelDef debugFlagList[] = {
|
||||
{DreamWeb::kDebugAnimation, "Animation", "Animation Debug Flag"},
|
||||
{DreamWeb::kDebugSaveLoad, "SaveLoad", "Track Save/Load Function"},
|
||||
DEBUG_CHANNEL_END
|
||||
};
|
||||
|
||||
#include "dreamweb/detection_tables.h"
|
||||
|
||||
class DreamWebMetaEngineDetection : public AdvancedMetaEngineDetection<DreamWeb::DreamWebGameDescription> {
|
||||
public:
|
||||
DreamWebMetaEngineDetection():
|
||||
AdvancedMetaEngineDetection(DreamWeb::gameDescriptions,
|
||||
dreamWebGames) {
|
||||
_guiOptions = GUIO5(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE, GAMEOPTION_TTS_THINGS, GAMEOPTION_TTS_SPEECH);
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "dreamweb";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "DreamWeb";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "DreamWeb (C) Creative Reality";
|
||||
}
|
||||
|
||||
const DebugChannelDef *getDebugChannels() const override {
|
||||
return debugFlagList;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN_STATIC(DREAMWEB_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, DreamWebMetaEngineDetection);
|
||||
43
engines/dreamweb/detection.h
Normal file
43
engines/dreamweb/detection.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DREAMWEB_DETECTION_H
|
||||
#define DREAMWEB_DETECTION_H
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
struct DreamWebGameDescription {
|
||||
AD_GAME_DESCRIPTION_HELPERS(desc);
|
||||
|
||||
ADGameDescription desc;
|
||||
};
|
||||
|
||||
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1
|
||||
#define GAMEOPTION_BRIGHTPALETTE GUIO_GAMEOPTIONS2
|
||||
#define GAMEOPTION_TTS_THINGS GUIO_GAMEOPTIONS3
|
||||
#define GAMEOPTION_TTS_SPEECH GUIO_GAMEOPTIONS4
|
||||
#define GAMEOPTION_COPY_PROTECTION GUIO_GAMEOPTIONS5
|
||||
|
||||
#define GF_INSTALLER 1
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
|
||||
#endif // DREAMWEB_DETECTION_H
|
||||
346
engines/dreamweb/detection_tables.h
Normal file
346
engines/dreamweb/detection_tables.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 DREAMWEB_DETECTION_TABLES_H
|
||||
#define DREAMWEB_DETECTION_TABLES_H
|
||||
|
||||
#include "dreamweb/detection.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
static const DreamWebGameDescription gameDescriptions[] = {
|
||||
// International floppy release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"Installer",
|
||||
{
|
||||
{"dreamw_1.rnc", 0, "4b8a92191219cc7e84d50837e1acca93", 1400000},
|
||||
{"dreamw_2.rnc", 0, "603e053b763c54c13a1e5e28be2ea839", 1457664},
|
||||
{"dreamw_3.rnc", 0, "1b273aa05a6afb8e7cd3c2defe2e334f", 1457664},
|
||||
{"dreamw_4.rnc", 0, "f7bc7a8e1147d7379272c6dbfb5e7246", 1457664},
|
||||
{"dreamw_5.rnc", 0, "0349950d94fee72b8fd57a22f7c465d1", 1457664},
|
||||
{"dreamw_6.rnc", 0, "c99629c842967e5e41e1c298cb58274f", 662246},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
GF_INSTALLER,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// International floppy release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"",
|
||||
{
|
||||
{"dreamweb.r00", 0, "3b5c87717fc40cc5a5ae19c155662ee3", 152918},
|
||||
{"dreamweb.r02", 0, "28458718167a040d7e988cf7d2298eae", 210466},
|
||||
{"dreamweb.exe", 0, "56b1d73aa56e964b45872ff552402341", 64985},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
0,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// International CD release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
AD_ENTRY2s("dreamweb.r00", "3b5c87717fc40cc5a5ae19c155662ee3", 152918,
|
||||
"dreamweb.r02", "d6fe5e3590ec1eea42ff65c10b023e0f", 198681),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// UK-V (Early UK) CD Release - From bug #6035
|
||||
// Note: r00 and r02 files are identical to international floppy release
|
||||
// so was misidentified as floppy, resulting in disabled CD speech.
|
||||
// Added executable to detection to avoid this.
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
{
|
||||
{"dreamweb.r00", 0, "3b5c87717fc40cc5a5ae19c155662ee3", 152918},
|
||||
{"dreamweb.r02", 0, "28458718167a040d7e988cf7d2298eae", 210466},
|
||||
{"dreamweb.exe", 0, "dd1c7793b151489e67b83cd1ecab51cd", AD_NO_SIZE},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::EN_GRB,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// US CD release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
AD_ENTRY2s("dreamweb.r00", "8acafd7f4418d08d0e16b65b8b10bc50", 152983,
|
||||
"dreamweb.r02", "c0c363715ddf14ab54f2379906a3aa01", 198707),
|
||||
Common::EN_USA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// French CD release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
AD_ENTRY2s("dreamwfr.r00", "e354582a8564faf5c515df92f207e8d1", 154657,
|
||||
"dreamwfr.r02", "57f3f08d5aefd04184eac76927eced80", 200575),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// French CD release
|
||||
// From bug #6030
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
AD_ENTRY2s("dreamwfr.r00", "e354582a8564faf5c515df92f207e8d1", 154657,
|
||||
"dreamwfr.r02", "cb99f08d5aefd04184eac76927eced80", 200575),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// German floppy release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"",
|
||||
AD_ENTRY2s("dreamweb.r00", "9960dc3baddabc6ad2a6fd75292b149c", 155886,
|
||||
"dreamweb.r02", "48e1f42a53402f963ca2d1ed969f4084", 212823),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
0,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// German CD release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
AD_ENTRY2s("dreamweb.r00", "9960dc3baddabc6ad2a6fd75292b149c", 155886,
|
||||
"dreamweb.r02", "076ca7cd326cb2abfb2091c6cf46ae08", 201038),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// Spanish floppy release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"",
|
||||
AD_ENTRY2s("dreamweb.r00", "2df07174321de39c4f17c9ff654b268a", 153608,
|
||||
"dreamweb.r02", "f97d435ad5da08fb1bcf6ea3dd6e0b9e", 199499),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformDOS,
|
||||
0,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// Spanish CD release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
AD_ENTRY2s("dreamwsp.r00", "2df07174321de39c4f17c9ff654b268a", 153608,
|
||||
"dreamwsp.r02", "577d435ad5da08fb1bcf6ea3dd6e0b9e", 199499),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// Spanish CD release
|
||||
// From bug #6030
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
AD_ENTRY2s("dreamwsp.r00", "2df07174321de39c4f17c9ff654b268a", 153608,
|
||||
"dreamwsp.r02", "f97d435ad5da08fb1bcf6ea3dd6e0b9e", 199499),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// Italian floppy release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"",
|
||||
AD_ENTRY2s("dreamweb.r00", "66dcab08354232f423c590156335f819", 155448,
|
||||
"dreamweb.r02", "87a026e9f80ed4f94169381f871ee305", 199676),
|
||||
Common::IT_ITA,
|
||||
Common::kPlatformDOS,
|
||||
0,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// Italian CD release
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
{
|
||||
{"dreamweb.exe", 0, "44d1708535cdb863b9cca372ad0b05dd", 65370},
|
||||
{"dreamweb.r00", 0, "66dcab08354232f423c590156335f819", 155448},
|
||||
{"dreamweb.r02", 0, "87a026e9f80ed4f94169381f871ee305", 199676},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::IT_ITA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// Czech fan-made translation
|
||||
// From bug #7078
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
{
|
||||
{"dreamweb.r00", 0, "3b5c87717fc40cc5a5ae19c155662ee3", 152918},
|
||||
{"dreamweb.r02", 0, "28458718167a040d7e988cf7d2298eae", 210466},
|
||||
{"dreamweb.exe", 0, "40cc15bdc8fa3a785b5fd1ecd6194119", 65440},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::CS_CZE,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// Russian fan-made translation
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD",
|
||||
{
|
||||
{"dreamweb.r00", 0, "b457b515f1042d345c07e4e58a7ef792", 151975},
|
||||
{"dreamweb.r02", 0, "eebf681cef5a06ee12a2630512c5eb83", 197091},
|
||||
{"dreamweb.exe", 0, "9386c192d3bdce2ef4de2135c29fa66d", 65370},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::RU_RUS,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO1(GAMEOPTION_COPY_PROTECTION)
|
||||
},
|
||||
},
|
||||
|
||||
// English floppy demo
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"Demo",
|
||||
{
|
||||
{"dreamweb.r57", 0, "dba78ab266054ad98151db0a9aa845f6", 102904},
|
||||
{"dreamweb.r59", 0, "b1635ce312c7273b343eb0c2946361af", 199262},
|
||||
{"dreamweb.exe", 0, "2362f28683ffe4ae4986c21226e132c9", 63656},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_DEMO,
|
||||
GUIO0()
|
||||
},
|
||||
},
|
||||
|
||||
// English CD demo
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"CD Demo",
|
||||
{
|
||||
{"dreamweb.r60", 0, "45fb1438d165da9f098852cc8e14ad92", 108933},
|
||||
{"dreamweb.r22", 0, "35537525b55837b91b56f2468500ea43", 190222},
|
||||
{"dreamweb.exe", 0, "34218e66ffd0e0d65d71282e57ac4fcc", 64445},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD|ADGF_DEMO,
|
||||
GUIO0()
|
||||
},
|
||||
},
|
||||
|
||||
// English Amiga demo
|
||||
{
|
||||
{
|
||||
"dreamweb",
|
||||
"Demo",
|
||||
{
|
||||
{"dreamweb.r57", 0, "f52b88b8417c7bddc8c63b684c6ad1dd", 117720},
|
||||
{"dreamweb.r59", 0, "996dfe6d963c27a302952c77a297b0fa", 223764},
|
||||
{"dreamweb", 0, "093103deb9712340ee34c4bed94aab12", 51496},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformAmiga,
|
||||
ADGF_DEMO,
|
||||
GUIO0()
|
||||
},
|
||||
},
|
||||
|
||||
{ AD_TABLE_END_MARKER }
|
||||
};
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
|
||||
#endif
|
||||
629
engines/dreamweb/dreamweb.cpp
Normal file
629
engines/dreamweb/dreamweb.cpp
Normal file
@@ -0,0 +1,629 @@
|
||||
/* 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 "common/file.h"
|
||||
#include "common/func.h"
|
||||
#include "common/system.h"
|
||||
#include "common/timer.h"
|
||||
#include "common/util.h"
|
||||
#include "common/concatstream.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "graphics/paletteman.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "dreamweb/detection.h"
|
||||
#include "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
#include "dreamweb/rnca_archive.h"
|
||||
|
||||
#include "common/text-to-speech.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
DreamWebEngine::DreamWebEngine(OSystem *syst, const DreamWebGameDescription *gameDesc) :
|
||||
Engine(syst), _gameDescription(gameDesc), _rnd("dreamweb"),
|
||||
_exText(kNumExTexts),
|
||||
_setDesc(kNumSetTexts), _blockDesc(kNumBlockTexts),
|
||||
_roomDesc(kNumRoomTexts), _freeDesc(kNumFreeTexts),
|
||||
_personText(kNumPersonTexts) {
|
||||
|
||||
_vSyncPrevTick = 0;
|
||||
_sound = nullptr;
|
||||
_speed = 1;
|
||||
_turbo = false;
|
||||
_oldMouseState = 0;
|
||||
|
||||
_ttsMan = g_system->getTextToSpeechManager();
|
||||
|
||||
_datafilePrefix = "DREAMWEB.";
|
||||
_speechDirName = "SPEECH";
|
||||
// ES and FR CD release use a different data file prefix
|
||||
// and speech directory naming.
|
||||
if (isCD()) {
|
||||
switch(getLanguage()) {
|
||||
case Common::ES_ESP:
|
||||
_datafilePrefix = "DREAMWSP.";
|
||||
_speechDirName = "SPANISH";
|
||||
break;
|
||||
case Common::FR_FRA:
|
||||
_datafilePrefix = "DREAMWFR.";
|
||||
_speechDirName = "FRENCH";
|
||||
break;
|
||||
default:
|
||||
// Nothing to do
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_openChangeSize = kInventx+(4*kItempicsize);
|
||||
_quitRequested = false;
|
||||
|
||||
_speechLoaded = false;
|
||||
|
||||
_backdropBlocks = nullptr;
|
||||
_reelList = nullptr;
|
||||
|
||||
_oldSubject._type = 0;
|
||||
_oldSubject._index = 0;
|
||||
|
||||
// misc variables
|
||||
_speechCount = 0;
|
||||
_charShift = 0;
|
||||
_brightPalette = false;
|
||||
_roomLoaded = 0;
|
||||
_didZoom = 0;
|
||||
_lineSpacing = 10;
|
||||
_textAddressX = 13;
|
||||
_textAddressY = 182;
|
||||
_textLen = 0;
|
||||
_lastXPos = 0;
|
||||
_itemFrame = 0;
|
||||
_withObject = 0;
|
||||
_withType = 0;
|
||||
_lookCounter = 0;
|
||||
_command = 0;
|
||||
_commandType = 0;
|
||||
_objectType = 0;
|
||||
_getBack = 0;
|
||||
_invOpen = 0;
|
||||
_mainMode = 0;
|
||||
_pickUp = 0;
|
||||
_lastInvPos = 0;
|
||||
_examAgain = 0;
|
||||
_newTextLine = 0;
|
||||
_openedOb = 0;
|
||||
_openedType = 0;
|
||||
_mapAdX = 0;
|
||||
_mapAdY = 0;
|
||||
_mapOffsetX = 104;
|
||||
_mapOffsetY = 38;
|
||||
_mapXStart = 0;
|
||||
_mapYStart = 0;
|
||||
_mapXSize = 0;
|
||||
_mapYSize = 0;
|
||||
_haveDoneObs = 0;
|
||||
_manIsOffScreen = 0;
|
||||
_facing = 0;
|
||||
_leaveDirection = 0;
|
||||
_turnToFace = 0;
|
||||
_turnDirection = 0;
|
||||
_mainTimer = 0;
|
||||
_introCount = 0;
|
||||
_currentKey = 0;
|
||||
_timerCount = 0;
|
||||
_mapX = 0;
|
||||
_mapY = 0;
|
||||
_ryanX = 0;
|
||||
_ryanY = 0;
|
||||
_lastFlag = 0;
|
||||
_destPos = 0;
|
||||
_realLocation = 0;
|
||||
_roomNum = 0;
|
||||
_nowInNewRoom = 0;
|
||||
_resetManXY = 0;
|
||||
_newLocation = 0xFF;
|
||||
_autoLocation = 0xFF;
|
||||
_mouseX = 0;
|
||||
_mouseY = 0;
|
||||
_mouseButton = 0;
|
||||
_oldButton = 0;
|
||||
_oldX = 0;
|
||||
_oldY = 0;
|
||||
_oldPointerX = 0;
|
||||
_oldPointerY = 0;
|
||||
_delHereX = 0;
|
||||
_delHereY = 0;
|
||||
_pointerXS = 32;
|
||||
_pointerYS = 32;
|
||||
_delXS = 0;
|
||||
_delYS = 0;
|
||||
_pointerFrame = 0;
|
||||
_pointerPower = 0;
|
||||
_pointerMode = 0;
|
||||
_pointerSpeed = 0;
|
||||
_pointerCount = 0;
|
||||
_inMapArea = 0;
|
||||
_talkMode = 0;
|
||||
_talkPos = 0;
|
||||
_character = 0;
|
||||
_watchDump = 0;
|
||||
_logoNum = 0;
|
||||
_oldLogoNum = 0;
|
||||
_pressed = 0;
|
||||
_pressPointer = 0;
|
||||
_graphicPress = 0;
|
||||
_pressCount = 0;
|
||||
_lightCount = 0;
|
||||
_folderPage = 0;
|
||||
_diaryPage = 0;
|
||||
_menuCount = 0;
|
||||
_symbolTopX = 0;
|
||||
_symbolTopNum = 0;
|
||||
_symbolTopDir = 0;
|
||||
_symbolBotX = 0;
|
||||
_symbolBotNum = 0;
|
||||
_symbolBotDir = 0;
|
||||
_walkAndExam = 0;
|
||||
_walkExamType = 0;
|
||||
_walkExamNum = 0;
|
||||
_cursLocX = 0;
|
||||
_cursLocY = 0;
|
||||
_curPos = 0;
|
||||
_monAdX = 0;
|
||||
_monAdY = 0;
|
||||
_timeCount = 0;
|
||||
_needToDumpTimed = 0;
|
||||
_loadingOrSave = 0;
|
||||
_saveLoadPage = 0;
|
||||
_currentSlot = 0;
|
||||
_cursorPos = 0;
|
||||
_colorPos = 0;
|
||||
_fadeDirection = 0;
|
||||
_numToFade = 0;
|
||||
_fadeCount = 0;
|
||||
_addToGreen = 0;
|
||||
_addToRed = 0;
|
||||
_addToBlue = 0;
|
||||
_lastSoundReel = 0;
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
_bufferIn = 0;
|
||||
_bufferOut = 0;
|
||||
_blinkFrame = 23;
|
||||
_blinkCount = 0;
|
||||
_reAssesChanges = 0;
|
||||
_pointersPath = 0;
|
||||
_mansPath = 0;
|
||||
_pointerFirstPath = 0;
|
||||
_finalDest = 0;
|
||||
_destination = 0;
|
||||
_lineStartX = 0;
|
||||
_lineStartY = 0;
|
||||
_lineEndX = 0;
|
||||
_lineEndY = 0;
|
||||
_linePointer = 0;
|
||||
_lineDirection = 0;
|
||||
_lineLength = 0;
|
||||
|
||||
_subtitles = 0;
|
||||
_foreignRelease = 0;
|
||||
_wonGame = 0;
|
||||
_hasSpeech = 0;
|
||||
_roomsSample = 0;
|
||||
_copyProtection = 0;
|
||||
|
||||
for (uint i = 0; i < 128; i++)
|
||||
memset(&_setDat[i], 0, sizeof(SetObject));
|
||||
|
||||
for (uint i = 0; i < 80; i++)
|
||||
memset(&_freeDat[i], 0, sizeof(DynObject));
|
||||
|
||||
for (uint i = 0; i < kNumExObjects; i++)
|
||||
memset(&_exData[i], 0, sizeof(DynObject));
|
||||
|
||||
memset(&_vars, 0, sizeof(GameVars));
|
||||
|
||||
for (uint i = 0; i < 96; i++)
|
||||
memset(&_backdropFlags[i], 0, sizeof(BackdropMapFlag));
|
||||
|
||||
for (uint i = 0; i < kNumReelRoutines+1; i++)
|
||||
memset(&_reelRoutines[i], 0, sizeof(ReelRoutine));
|
||||
|
||||
_personData = nullptr;
|
||||
|
||||
for (uint i = 0; i < 16; i++)
|
||||
memset(&_openInvList[i], 0, sizeof(ObjectRef));
|
||||
|
||||
for (uint i = 0; i < 30; i++)
|
||||
memset(&_ryanInvList[i], 0, sizeof(ObjectRef));
|
||||
|
||||
for (uint i = 0; i < 11*10; i++)
|
||||
memset(&_mapFlags[i], 0, sizeof(MapFlag));
|
||||
|
||||
for (uint i = 0; i < kNumChanges; i++)
|
||||
memset(&_listOfChanges[i], 0, sizeof(Change));
|
||||
|
||||
_currentCharset = nullptr;
|
||||
|
||||
for (uint i = 0; i < 36; i++)
|
||||
memset(&_pathData[i], 0, sizeof(RoomPaths));
|
||||
}
|
||||
|
||||
DreamWebEngine::~DreamWebEngine() {
|
||||
delete _sound;
|
||||
if (_thumbnail.getPixels())
|
||||
_thumbnail.free();
|
||||
}
|
||||
|
||||
void DreamWebEngine::pauseEngineIntern(bool pause) {
|
||||
Engine::pauseEngineIntern(pause);
|
||||
if (!pause)
|
||||
_vSyncPrevTick = _system->getMillis();
|
||||
}
|
||||
|
||||
void DreamWebEngine::waitForVSync() {
|
||||
if (isPaused())
|
||||
return;
|
||||
|
||||
processEvents();
|
||||
|
||||
if (!_turbo) {
|
||||
const uint32 delay = 1000 / 70 / _speed;
|
||||
uint32 elapsed = _system->getMillis() - _vSyncPrevTick;
|
||||
if (elapsed < delay)
|
||||
_system->delayMillis(delay - elapsed);
|
||||
}
|
||||
_vSyncPrevTick = _system->getMillis();
|
||||
|
||||
doShake();
|
||||
doFade();
|
||||
_system->updateScreen();
|
||||
}
|
||||
|
||||
void DreamWebEngine::quit() {
|
||||
_quitRequested = true;
|
||||
_lastHardKey = Common::KEYCODE_ESCAPE;
|
||||
}
|
||||
|
||||
void DreamWebEngine::processEvents(bool processSoundEvents) {
|
||||
if (_eventMan->shouldQuit()) {
|
||||
quit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (processSoundEvents)
|
||||
_sound->soundHandler();
|
||||
|
||||
Common::Event event;
|
||||
int softKey;
|
||||
while (_eventMan->pollEvent(event)) {
|
||||
switch(event.type) {
|
||||
case Common::EVENT_RETURN_TO_LAUNCHER:
|
||||
quit();
|
||||
break;
|
||||
case Common::EVENT_KEYDOWN:
|
||||
if (event.kbd.flags & Common::KBD_CTRL) {
|
||||
switch (event.kbd.keycode) {
|
||||
|
||||
case Common::KEYCODE_f:
|
||||
setSpeed(_speed != 4? 4: 1);
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_g:
|
||||
_turbo = !_turbo;
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_c: //skip statue puzzle
|
||||
_symbolBotNum = 3;
|
||||
_symbolTopNum = 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return; //do not pass ctrl + key to the engine
|
||||
}
|
||||
|
||||
// Some parts of the code uses the hardware key
|
||||
// code directly.
|
||||
|
||||
switch (event.kbd.keycode) {
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
_lastHardKey = Common::KEYCODE_ESCAPE;
|
||||
break;
|
||||
case Common::KEYCODE_SPACE:
|
||||
_lastHardKey = Common::KEYCODE_SPACE;
|
||||
break;
|
||||
default:
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
// The rest of the keys are converted to ASCII. This
|
||||
// is fairly restrictive, and eventually we may want
|
||||
// to let through more keys. I think this is mostly to
|
||||
// keep weird glyphs out of savegame names.
|
||||
|
||||
softKey = 0;
|
||||
|
||||
debug(1, "DreamWebEngine::processEvents() KeyDown keycode:%d ascii:0x%02x", event.kbd.keycode, event.kbd.ascii);
|
||||
if ((event.kbd.ascii >= 'a' && event.kbd.ascii <= 'z') ||
|
||||
(event.kbd.ascii >= 'A' && event.kbd.ascii <= 'Z')) {
|
||||
softKey = event.kbd.ascii & ~0x20; // (& ~0x20) forces ascii codes for a-z to map to A-Z
|
||||
} else if (event.kbd.ascii == '-' ||
|
||||
event.kbd.ascii == ' ' ||
|
||||
(event.kbd.ascii >= '0' && event.kbd.ascii <= '9')) {
|
||||
softKey = event.kbd.ascii;
|
||||
} else if (event.kbd.keycode >= Common::KEYCODE_KP0 && event.kbd.keycode <= Common::KEYCODE_KP9) {
|
||||
softKey = event.kbd.keycode - Common::KEYCODE_KP0 + '0';
|
||||
} else if (event.kbd.keycode == Common::KEYCODE_KP_MINUS) {
|
||||
softKey = '-';
|
||||
} else if (event.kbd.keycode == Common::KEYCODE_BACKSPACE ||
|
||||
event.kbd.keycode == Common::KEYCODE_DELETE) {
|
||||
softKey = 8;
|
||||
} else if (event.kbd.keycode == Common::KEYCODE_RETURN
|
||||
|| event.kbd.keycode == Common::KEYCODE_KP_ENTER) {
|
||||
softKey = 13;
|
||||
}
|
||||
|
||||
if (softKey)
|
||||
keyPressed(softKey);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common::Error DreamWebEngine::run() {
|
||||
if (_gameDescription->desc.flags & GF_INSTALLER) {
|
||||
Common::Array<Common::SharedPtr<Common::SeekableReadStream>> volumes;
|
||||
for (uint i = 0; _gameDescription->desc.filesDescriptions[i].fileName; i++) {
|
||||
Common::File *dw = new Common::File();
|
||||
const char *name = _gameDescription->desc.filesDescriptions[i].fileName;
|
||||
if (!dw->open(name)) {
|
||||
error("Can't open %s", name);
|
||||
}
|
||||
volumes.push_back(Common::SharedPtr<Common::SeekableReadStream>(dw));
|
||||
}
|
||||
Common::ConcatReadStream *concat = new Common::ConcatReadStream(volumes);
|
||||
SearchMan.add("rnca", RNCAArchive::open(concat, DisposeAfterUse::YES));
|
||||
}
|
||||
|
||||
if (_ttsMan != nullptr) {
|
||||
Common::String languageString = Common::getLanguageCode(getLanguage());
|
||||
_ttsMan->setLanguage(languageString);
|
||||
_ttsMan->enable(ConfMan.getBool("tts_enabled_objects") || ConfMan.getBool("tts_enabled_speech"));
|
||||
switch (getLanguage()) {
|
||||
case Common::RU_RUS:
|
||||
_textEncoding = Common::kDos866;
|
||||
break;
|
||||
case Common::CS_CZE:
|
||||
_textEncoding = Common::kWindows1250;
|
||||
break;
|
||||
default:
|
||||
_textEncoding = Common::kDos850;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
syncSoundSettings();
|
||||
setDebugger(new DreamWebConsole(this));
|
||||
_sound = new DreamWebSound(this);
|
||||
|
||||
_hasSpeech = Common::File::exists(_speechDirName.appendComponent("r01c0000.raw")) && !ConfMan.getBool("speech_mute");
|
||||
_brightPalette = ConfMan.getBool("bright_palette");
|
||||
_copyProtection = ConfMan.getBool("copy_protection");
|
||||
|
||||
_vSyncPrevTick = _system->getMillis();
|
||||
dreamweb();
|
||||
dreamwebFinalize();
|
||||
_quitRequested = false;
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
void DreamWebEngine::setSpeed(uint speed) {
|
||||
debug(0, "setting speed %u", speed);
|
||||
_speed = speed;
|
||||
}
|
||||
|
||||
Common::String DreamWebEngine::getSavegameFilename(int slot) const {
|
||||
// TODO: Are saves from all versions of Dreamweb compatible with each other?
|
||||
// Then we can can consider keeping the filenames as DREAMWEB.Dnn.
|
||||
// Otherwise, this must be changed to be target dependent.
|
||||
//Common::String filename = _targetName + Common::String::format(".d%02d", savegameId);
|
||||
Common::String filename = Common::String::format("DREAMWEB.D%02d", slot);
|
||||
return filename;
|
||||
}
|
||||
|
||||
void DreamWebEngine::keyPressed(uint16 ascii) {
|
||||
debug(2, "key pressed = %04x", ascii);
|
||||
uint16 in = (_bufferIn + 1) % ARRAYSIZE(_keyBuffer);
|
||||
uint16 out = _bufferOut;
|
||||
if (in == out) {
|
||||
warning("keyboard buffer is full");
|
||||
return;
|
||||
}
|
||||
_bufferIn = in;
|
||||
_keyBuffer[in] = ascii;
|
||||
}
|
||||
|
||||
void DreamWebEngine::getPalette(uint8 *data, uint start, uint count) {
|
||||
_system->getPaletteManager()->grabPalette(data, start, count);
|
||||
while (count--)
|
||||
*data++ >>= 2;
|
||||
}
|
||||
|
||||
void DreamWebEngine::setPalette(const uint8 *data, uint start, uint count) {
|
||||
assert(start + count <= 256);
|
||||
uint8 fixed[3*256];
|
||||
for (uint i = 0; i < count * 3; ++i) {
|
||||
fixed[i] = data[i] << 2;
|
||||
}
|
||||
_system->getPaletteManager()->setPalette(fixed, start, count);
|
||||
}
|
||||
|
||||
void DreamWebEngine::blit(const uint8 *src, int pitch, int x, int y, int w, int h) {
|
||||
if (y + h > (int)kScreenheight)
|
||||
h = kScreenheight - y;
|
||||
if (x + w > (int)kScreenwidth)
|
||||
w = kScreenwidth - x;
|
||||
if (h <= 0 || w <= 0)
|
||||
return;
|
||||
_system->copyRectToScreen(src, pitch, x, y, w, h);
|
||||
}
|
||||
|
||||
void DreamWebEngine::printUnderMonitor() {
|
||||
uint8 *dst = workspace() + kScreenwidth * 43 + 76;
|
||||
|
||||
Graphics::Surface *s = _system->lockScreen();
|
||||
if (!s)
|
||||
error("lockScreen failed");
|
||||
|
||||
for (uint y = 0; y < 104; ++y) {
|
||||
uint8 *src = (uint8 *)s->getBasePtr(76, 43 + 8 + y);
|
||||
for (uint x = 0; x < 170; ++x) {
|
||||
if (*src < 231)
|
||||
*dst++ = *src++;
|
||||
else {
|
||||
++dst; ++src;
|
||||
}
|
||||
}
|
||||
dst += kScreenwidth - 170;
|
||||
}
|
||||
_system->unlockScreen();
|
||||
}
|
||||
|
||||
void DreamWebEngine::cls() {
|
||||
_system->fillScreen(0);
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::modifyChar(uint8 c) const {
|
||||
switch (getLanguage()) {
|
||||
case Common::DE_DEU:
|
||||
switch (c) {
|
||||
case 129:
|
||||
return 'Z' + 3;
|
||||
case 132:
|
||||
return 'Z' + 1;
|
||||
case 142:
|
||||
return 'Z' + 4;
|
||||
case 154:
|
||||
return 'Z' + 6;
|
||||
case 225:
|
||||
return 'A' - 1;
|
||||
case 153:
|
||||
return 'Z' + 5;
|
||||
case 148:
|
||||
return 'Z' + 2;
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
case Common::ES_ESP:
|
||||
switch(c) {
|
||||
case 160:
|
||||
return 'Z' + 1;
|
||||
case 130:
|
||||
return 'Z' + 2;
|
||||
case 161:
|
||||
return 'Z' + 3;
|
||||
case 162:
|
||||
return 'Z' + 4;
|
||||
case 163:
|
||||
return 'Z' + 5;
|
||||
case 164:
|
||||
return 'Z' + 6;
|
||||
case 165:
|
||||
return ',' - 1;
|
||||
case 168:
|
||||
return 'A' - 1;
|
||||
case 173:
|
||||
return 'A' - 4;
|
||||
case 129:
|
||||
return 'A' - 5;
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
case Common::FR_FRA:
|
||||
case Common::IT_ITA:
|
||||
switch(c) {
|
||||
case 133:
|
||||
return 'Z' + 1;
|
||||
case 130:
|
||||
return 'Z' + 2;
|
||||
case 138:
|
||||
return 'Z' + 3;
|
||||
case 136:
|
||||
return 'Z' + 4;
|
||||
case 140:
|
||||
return 'Z' + 5;
|
||||
case 135:
|
||||
return 'Z' + 6;
|
||||
case 149:
|
||||
return ',' - 1;
|
||||
case 131:
|
||||
return ',' - 2;
|
||||
case 141:
|
||||
return ',' - 3;
|
||||
case 139:
|
||||
return ',' - 4;
|
||||
case 151:
|
||||
return 'A' - 1;
|
||||
case 147:
|
||||
return 'A' - 3;
|
||||
case 150:
|
||||
return 'A' - 4;
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
case Common::RU_RUS:
|
||||
if (c >= 224)
|
||||
c -= 48;
|
||||
// fall through
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
Common::Path DreamWebEngine::modifyFileName(const char *name) {
|
||||
Common::String fileName(name);
|
||||
|
||||
// Sanity check
|
||||
if (!fileName.hasPrefix("DREAMWEB."))
|
||||
return Common::Path(fileName);
|
||||
|
||||
// Make sure we use the correct file name as it differs depending on the game variant
|
||||
fileName = _datafilePrefix;
|
||||
fileName += name + 9;
|
||||
return Common::Path(fileName);
|
||||
}
|
||||
|
||||
bool DreamWebEngine::hasSpeech() {
|
||||
return isCD() && _hasSpeech;
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
1112
engines/dreamweb/dreamweb.h
Normal file
1112
engines/dreamweb/dreamweb.h
Normal file
File diff suppressed because it is too large
Load Diff
867
engines/dreamweb/keypad.cpp
Normal file
867
engines/dreamweb/keypad.cpp
Normal file
@@ -0,0 +1,867 @@
|
||||
/* 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 "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
const uint16 kKeypadx = 36+112;
|
||||
const uint16 kKeypady = 72;
|
||||
|
||||
void DreamWebEngine::enterCode(uint8 digit0, uint8 digit1, uint8 digit2, uint8 digit3) {
|
||||
RectWithCallback keypadList[] = {
|
||||
{ kKeypadx+9,kKeypadx+30,kKeypady+9,kKeypady+22,&DreamWebEngine::buttonOne },
|
||||
{ kKeypadx+31,kKeypadx+52,kKeypady+9,kKeypady+22,&DreamWebEngine::buttonTwo },
|
||||
{ kKeypadx+53,kKeypadx+74,kKeypady+9,kKeypady+22,&DreamWebEngine::buttonThree },
|
||||
{ kKeypadx+9,kKeypadx+30,kKeypady+23,kKeypady+40,&DreamWebEngine::buttonFour },
|
||||
{ kKeypadx+31,kKeypadx+52,kKeypady+23,kKeypady+40,&DreamWebEngine::buttonFive },
|
||||
{ kKeypadx+53,kKeypadx+74,kKeypady+23,kKeypady+40,&DreamWebEngine::buttonSix },
|
||||
{ kKeypadx+9,kKeypadx+30,kKeypady+41,kKeypady+58,&DreamWebEngine::buttonSeven },
|
||||
{ kKeypadx+31,kKeypadx+52,kKeypady+41,kKeypady+58,&DreamWebEngine::buttonEight },
|
||||
{ kKeypadx+53,kKeypadx+74,kKeypady+41,kKeypady+58,&DreamWebEngine::buttonNine },
|
||||
{ kKeypadx+9,kKeypadx+30,kKeypady+59,kKeypady+73,&DreamWebEngine::buttonNought },
|
||||
{ kKeypadx+31,kKeypadx+74,kKeypady+59,kKeypady+73,&DreamWebEngine::buttonEnter },
|
||||
{ kKeypadx+72,kKeypadx+86,kKeypady+80,kKeypady+94,&DreamWebEngine::quitKey },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
|
||||
getRidOfReels();
|
||||
loadKeypad();
|
||||
createPanel();
|
||||
showIcon();
|
||||
showOuterPad();
|
||||
showKeypad();
|
||||
readMouse();
|
||||
showPointer();
|
||||
workToScreen();
|
||||
delPointer();
|
||||
_pressPointer = 0;
|
||||
_getBack = 0;
|
||||
while (true) {
|
||||
delPointer();
|
||||
readMouse();
|
||||
showKeypad();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
if (_pressCount == 0) {
|
||||
_pressed = 255;
|
||||
_graphicPress = 255;
|
||||
waitForVSync();
|
||||
} else
|
||||
--_pressCount;
|
||||
|
||||
dumpPointer();
|
||||
dumpKeypad();
|
||||
dumpTextLine();
|
||||
checkCoords(keypadList);
|
||||
if (_quitRequested || (_getBack == 1))
|
||||
break;
|
||||
if (_lightCount == 1) {
|
||||
if (_vars._lockStatus == 0)
|
||||
break;
|
||||
} else {
|
||||
if (_pressCount == 40) {
|
||||
addToPressList();
|
||||
if (_pressed == 11) {
|
||||
if (isItRight(digit0, digit1, digit2, digit3))
|
||||
_vars._lockStatus = 0;
|
||||
_sound->playChannel1(11);
|
||||
_lightCount = 120;
|
||||
_pressPointer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_manIsOffScreen = 0;
|
||||
_keypadGraphics.clear();
|
||||
restoreReels();
|
||||
redrawMainScrn();
|
||||
workToScreenM();
|
||||
}
|
||||
|
||||
// Note: isItRight comes from use.asm, but is only used by enterCode(),
|
||||
// so we place it here.
|
||||
bool DreamWebEngine::isItRight(uint8 digit0, uint8 digit1, uint8 digit2, uint8 digit3) {
|
||||
return digit0 == _pressList[0] && digit1 == _pressList[1]
|
||||
&& digit2 == _pressList[2] && digit3 == _pressList[3];
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadKeypad() {
|
||||
loadGraphicsFile(_keypadGraphics, "G02");
|
||||
}
|
||||
|
||||
void DreamWebEngine::quitKey() {
|
||||
commandOnlyCond(4, 222);
|
||||
|
||||
if (_mouseButton != _oldButton && (_mouseButton & 1))
|
||||
_getBack = 1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::addToPressList() {
|
||||
if (_pressPointer == 5)
|
||||
return;
|
||||
uint8 pressed = _pressed;
|
||||
if (pressed == 10)
|
||||
pressed = 0;
|
||||
|
||||
_pressList[_pressPointer] = pressed;
|
||||
++_pressPointer;
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonOne() {
|
||||
buttonPress(1);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonTwo() {
|
||||
buttonPress(2);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonThree() {
|
||||
buttonPress(3);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonFour() {
|
||||
buttonPress(4);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonFive() {
|
||||
buttonPress(5);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonSix() {
|
||||
buttonPress(6);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonSeven() {
|
||||
buttonPress(7);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonEight() {
|
||||
buttonPress(8);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonNine() {
|
||||
buttonPress(9);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonNought() {
|
||||
buttonPress(10);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonEnter() {
|
||||
buttonPress(11);
|
||||
}
|
||||
|
||||
void DreamWebEngine::buttonPress(uint8 buttonId) {
|
||||
commandOnlyCond(buttonId + 4, buttonId + 100);
|
||||
if ((_mouseButton & 1) && (_mouseButton != _oldButton)) {
|
||||
_pressed = buttonId;
|
||||
_graphicPress = buttonId + 21;
|
||||
_pressCount = 40;
|
||||
if (buttonId != 11)
|
||||
_sound->playChannel1(10);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::showOuterPad() {
|
||||
showFrame(_keypadGraphics, kKeypadx-3, kKeypady-4, 1, 0);
|
||||
showFrame(_keypadGraphics, kKeypadx+74, kKeypady+76, 37, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showKeypad() {
|
||||
singleKey(22, kKeypadx+9, kKeypady+5);
|
||||
singleKey(23, kKeypadx+31, kKeypady+5);
|
||||
singleKey(24, kKeypadx+53, kKeypady+5);
|
||||
singleKey(25, kKeypadx+9, kKeypady+23);
|
||||
singleKey(26, kKeypadx+31, kKeypady+23);
|
||||
singleKey(27, kKeypadx+53, kKeypady+23);
|
||||
singleKey(28, kKeypadx+9, kKeypady+41);
|
||||
singleKey(29, kKeypadx+31, kKeypady+41);
|
||||
singleKey(30, kKeypadx+53, kKeypady+41);
|
||||
singleKey(31, kKeypadx+9, kKeypady+59);
|
||||
singleKey(32, kKeypadx+31, kKeypady+59);
|
||||
if (_lightCount) {
|
||||
--_lightCount;
|
||||
uint8 frameIndex;
|
||||
uint16 y;
|
||||
if (_vars._lockStatus) {
|
||||
frameIndex = 36;
|
||||
y = kKeypady-1+63;
|
||||
} else {
|
||||
frameIndex = 41;
|
||||
y = kKeypady+4+63;
|
||||
}
|
||||
if ((_lightCount >= 60) && (_lightCount < 100))
|
||||
--frameIndex;
|
||||
showFrame(_keypadGraphics, kKeypadx+60, y, frameIndex, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::singleKey(uint8 key, uint16 x, uint16 y) {
|
||||
if (key == _graphicPress) {
|
||||
key += 11;
|
||||
if (_pressCount < 8)
|
||||
key -= 11;
|
||||
}
|
||||
key -= 20;
|
||||
showFrame(_keypadGraphics, x, y, key, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::dumpKeypad() {
|
||||
multiDump(kKeypadx - 3, kKeypady - 4, 120, 90);
|
||||
}
|
||||
|
||||
void DreamWebEngine::useMenu() {
|
||||
getRidOfReels();
|
||||
loadMenu();
|
||||
createPanel();
|
||||
showPanel();
|
||||
showIcon();
|
||||
_vars._newObs = 0;
|
||||
drawFloor();
|
||||
printSprites();
|
||||
showFrame(_menuGraphics2, kMenux-48, kMenuy-4, 4, 0);
|
||||
getUnderMenu();
|
||||
showFrame(_menuGraphics2, kMenux+54, kMenuy+72, 5, 0);
|
||||
workToScreenM();
|
||||
_getBack = 0;
|
||||
do {
|
||||
delPointer();
|
||||
putUnderMenu();
|
||||
showMenu();
|
||||
readMouse();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpMenu();
|
||||
dumpTextLine();
|
||||
RectWithCallback menuList[] = {
|
||||
{ kMenux+54,kMenux+68,kMenuy+72,kMenuy+88,&DreamWebEngine::quitKey },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
checkCoords(menuList);
|
||||
} while ((_getBack != 1) && !_quitRequested);
|
||||
_manIsOffScreen = 0;
|
||||
redrawMainScrn();
|
||||
_menuGraphics.clear();
|
||||
_menuGraphics2.clear();
|
||||
restoreReels();
|
||||
workToScreenM();
|
||||
}
|
||||
|
||||
void DreamWebEngine::dumpMenu() {
|
||||
multiDump(kMenux, kMenuy, 48, 48);
|
||||
}
|
||||
|
||||
void DreamWebEngine::getUnderMenu() {
|
||||
multiGet(_underTimedText, kMenux, kMenuy, 48, 48);
|
||||
}
|
||||
|
||||
void DreamWebEngine::putUnderMenu() {
|
||||
multiPut(_underTimedText, kMenux, kMenuy, 48, 48);
|
||||
}
|
||||
|
||||
// Note: showoutermenu from the asm version was unused and thus not placed here
|
||||
|
||||
void DreamWebEngine::showMenu() {
|
||||
++_menuCount;
|
||||
if (_menuCount == 37*2)
|
||||
_menuCount = 0;
|
||||
showFrame(_menuGraphics, kMenux, kMenuy, _menuCount / 2, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadMenu() {
|
||||
loadGraphicsFile(_menuGraphics, "S02"); // sprite name 3
|
||||
loadGraphicsFile(_menuGraphics2, "G07"); // mon. graphics 2
|
||||
}
|
||||
|
||||
void DreamWebEngine::viewFolder() {
|
||||
_manIsOffScreen = 1;
|
||||
getRidOfAll();
|
||||
loadFolder();
|
||||
_folderPage = 0;
|
||||
showFolder();
|
||||
workToScreenM();
|
||||
_getBack = 0;
|
||||
do {
|
||||
if (_quitRequested)
|
||||
break;
|
||||
delPointer();
|
||||
readMouse();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpTextLine();
|
||||
checkFolderCoords();
|
||||
} while (_getBack == 0);
|
||||
_manIsOffScreen = 0;
|
||||
_folderGraphics.clear();
|
||||
_folderGraphics2.clear();
|
||||
_folderGraphics3.clear();
|
||||
_folderCharset.clear();
|
||||
restoreAll();
|
||||
redrawMainScrn();
|
||||
workToScreenM();
|
||||
}
|
||||
|
||||
void DreamWebEngine::nextFolder() {
|
||||
if (_folderPage == 12) {
|
||||
blank();
|
||||
return;
|
||||
}
|
||||
commandOnlyCond(16, 201);
|
||||
if ((_mouseButton == 1) && (_mouseButton != _oldButton)) {
|
||||
++_folderPage;
|
||||
folderHints();
|
||||
delPointer();
|
||||
showFolder();
|
||||
_mouseButton = 0;
|
||||
checkFolderCoords();
|
||||
workToScreenM();
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::folderHints() {
|
||||
if (_folderPage == 5) {
|
||||
if ((_vars._aideDead != 1) && (getLocation(13) != 1)) {
|
||||
setLocation(13);
|
||||
showFolder();
|
||||
const uint8 *string = getTextInFile1(30);
|
||||
printDirect(string, 0, 86, 141, true);
|
||||
workToScreenM();
|
||||
hangOnP(200);
|
||||
}
|
||||
} else if (_folderPage == 9) {
|
||||
if (getLocation(7) != 1) {
|
||||
setLocation(7);
|
||||
showFolder();
|
||||
const uint8 *string = getTextInFile1(31);
|
||||
printDirect(string, 0, 86, 141, true);
|
||||
workToScreenM();
|
||||
hangOnP(200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::lastFolder() {
|
||||
if (_folderPage == 0) {
|
||||
blank();
|
||||
return;
|
||||
}
|
||||
commandOnlyCond(17, 202);
|
||||
|
||||
if ((_mouseButton == 1) && (_mouseButton != _oldButton)) {
|
||||
--_folderPage;
|
||||
delPointer();
|
||||
showFolder();
|
||||
_mouseButton = 0;
|
||||
checkFolderCoords();
|
||||
workToScreenM();
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::checkFolderCoords() {
|
||||
RectWithCallback folderList[] = {
|
||||
{ 280,320,160,200, &DreamWebEngine::quitKey },
|
||||
{ 143,300,6,194, &DreamWebEngine::nextFolder },
|
||||
{ 0,143,6,194, &DreamWebEngine::lastFolder },
|
||||
{ 0,320,0,200, &DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0, nullptr }
|
||||
};
|
||||
checkCoords(folderList);
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadFolder() {
|
||||
loadGraphicsFile(_folderGraphics, "G09"); // folder graphics 1
|
||||
loadGraphicsFile(_folderGraphics2, "G10"); // folder graphics 2
|
||||
loadGraphicsFile(_folderGraphics3, "G11"); // folder graphics 3
|
||||
loadGraphicsFile(_folderCharset, "C02"); // character set 3
|
||||
loadTempText("T50"); // folder text
|
||||
}
|
||||
|
||||
void DreamWebEngine::showFolder() {
|
||||
_commandType = 255;
|
||||
if (_folderPage) {
|
||||
useTempCharset(&_folderCharset);
|
||||
createPanel2();
|
||||
showFrame(_folderGraphics, 0, 0, 0, 0);
|
||||
showFrame(_folderGraphics, 143, 0, 1, 0);
|
||||
showFrame(_folderGraphics, 0, 92, 2, 0);
|
||||
showFrame(_folderGraphics, 143, 92, 3, 0);
|
||||
folderExit();
|
||||
if (_folderPage != 1)
|
||||
showLeftPage();
|
||||
if (_folderPage != 12)
|
||||
showRightPage();
|
||||
useCharset1();
|
||||
underTextLine();
|
||||
} else {
|
||||
createPanel2();
|
||||
showFrame(_folderGraphics3, 143-28, 0, 0, 0);
|
||||
showFrame(_folderGraphics3, 143-28, 92, 1, 0);
|
||||
folderExit();
|
||||
underTextLine();
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::folderExit() {
|
||||
showFrame(_folderGraphics2, 296, 178, 6, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showLeftPage() {
|
||||
showFrame(_folderGraphics2, 0, 12, 3, 0);
|
||||
uint16 y = 12+5;
|
||||
for (uint i = 0; i < 9; ++i) {
|
||||
showFrame(_folderGraphics2, 0, y, 4, 0);
|
||||
y += 16;
|
||||
}
|
||||
showFrame(_folderGraphics2, 0, y, 5, 0);
|
||||
_lineSpacing = 8;
|
||||
_charShift = 91;
|
||||
|
||||
if (getLanguage() == Common::RU_RUS)
|
||||
_charShift = 182;
|
||||
|
||||
uint8 pageIndex = _folderPage - 2;
|
||||
const uint8 *string = getTextInFile1(pageIndex * 2);
|
||||
y = 48;
|
||||
for (uint i = 0; i < 2; ++i) {
|
||||
uint8 lastChar;
|
||||
do {
|
||||
lastChar = printDirect(&string, 2, &y, 140, false, true);
|
||||
y += _lineSpacing;
|
||||
} while (lastChar != '\0');
|
||||
}
|
||||
_charShift = 0;
|
||||
_lineSpacing = 10;
|
||||
uint8 *bufferToSwap = workspace() + (48*kScreenwidth)+2;
|
||||
for (uint i = 0; i < 120; ++i) {
|
||||
for (uint j = 0; j < 65; ++j) {
|
||||
SWAP(bufferToSwap[j], bufferToSwap[130 - j]);
|
||||
}
|
||||
bufferToSwap += kScreenwidth;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::showRightPage() {
|
||||
showFrame(_folderGraphics2, 143, 12, 0, 0);
|
||||
uint16 y = 12+37;
|
||||
for (uint i = 0; i < 7; ++i) {
|
||||
showFrame(_folderGraphics2, 143, y, 1, 0);
|
||||
y += 16;
|
||||
}
|
||||
|
||||
showFrame(_folderGraphics2, 143, y, 2, 0);
|
||||
_lineSpacing = 8;
|
||||
uint8 pageIndex = _folderPage - 1;
|
||||
const uint8 *string = getTextInFile1(pageIndex * 2);
|
||||
y = 48;
|
||||
for (uint i = 0; i < 2; ++i) {
|
||||
uint8 lastChar;
|
||||
do {
|
||||
lastChar = printDirect(&string, 152, &y, 140, false, true);
|
||||
y += _lineSpacing;
|
||||
} while (lastChar != '\0');
|
||||
}
|
||||
_lineSpacing = 10;
|
||||
}
|
||||
|
||||
void DreamWebEngine::enterSymbol() {
|
||||
_manIsOffScreen = 1;
|
||||
getRidOfReels();
|
||||
loadGraphicsFile(_symbolGraphics, "G12"); // symbol graphics
|
||||
_symbolTopX = 24;
|
||||
_symbolTopDir = 0;
|
||||
_symbolBotX = 24;
|
||||
_symbolBotDir = 0;
|
||||
redrawMainScrn();
|
||||
showSymbol();
|
||||
underTextLine();
|
||||
workToScreenM();
|
||||
_getBack = 0;
|
||||
do {
|
||||
delPointer();
|
||||
updateSymbolTop();
|
||||
updateSymbolBot();
|
||||
showSymbol();
|
||||
readMouse();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpTextLine();
|
||||
dumpSymbol();
|
||||
RectWithCallback symbolList[] = {
|
||||
{ kSymbolx+40,kSymbolx+64,kSymboly+2,kSymboly+16,&DreamWebEngine::quitSymbol },
|
||||
{ kSymbolx,kSymbolx+52,kSymboly+20,kSymboly+50,&DreamWebEngine::setTopLeft },
|
||||
{ kSymbolx+52,kSymbolx+104,kSymboly+20,kSymboly+50,&DreamWebEngine::setTopRight },
|
||||
{ kSymbolx,kSymbolx+52,kSymboly+50,kSymboly+80,&DreamWebEngine::setBotLeft },
|
||||
{ kSymbolx+52,kSymbolx+104,kSymboly+50,kSymboly+80,&DreamWebEngine::setBotRight },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
checkCoords(symbolList);
|
||||
} while ((_getBack == 0) && !_quitRequested);
|
||||
if ((_symbolBotNum == 3) && (_symbolTopNum == 5)) {
|
||||
removeSetObject(43);
|
||||
placeSetObject(46);
|
||||
turnAnyPathOn(0, _roomNum + 12);
|
||||
_manIsOffScreen = 0;
|
||||
redrawMainScrn();
|
||||
_symbolGraphics.clear();
|
||||
restoreReels();
|
||||
workToScreenM();
|
||||
_sound->playChannel1(13);
|
||||
} else {
|
||||
removeSetObject(46);
|
||||
placeSetObject(43);
|
||||
turnAnyPathOff(0, _roomNum + 12);
|
||||
_manIsOffScreen = 0;
|
||||
redrawMainScrn();
|
||||
_symbolGraphics.clear();
|
||||
restoreReels();
|
||||
workToScreenM();
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::quitSymbol() {
|
||||
if (_symbolTopX != 24 || _symbolBotX != 24) {
|
||||
blank();
|
||||
return;
|
||||
};
|
||||
|
||||
commandOnlyCond(18, 222);
|
||||
|
||||
if (_mouseButton == _oldButton)
|
||||
return; // notqs
|
||||
|
||||
if (!(_mouseButton & 1))
|
||||
return;
|
||||
|
||||
_getBack = 1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::setTopLeft() {
|
||||
if (_symbolTopDir != 0) {
|
||||
blank();
|
||||
return;
|
||||
}
|
||||
|
||||
commandOnlyCond(19, 210);
|
||||
|
||||
if (_mouseButton != 0)
|
||||
_symbolTopDir = -1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::setTopRight() {
|
||||
if (_symbolTopDir != 0) {
|
||||
blank();
|
||||
return;
|
||||
}
|
||||
|
||||
commandOnlyCond(20, 211);
|
||||
|
||||
if (_mouseButton != 0)
|
||||
_symbolTopDir = +1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::setBotLeft() {
|
||||
if (_symbolBotDir != 0) {
|
||||
blank();
|
||||
return;
|
||||
}
|
||||
|
||||
commandOnlyCond(21, 212);
|
||||
|
||||
if (_mouseButton != 0)
|
||||
_symbolBotDir = -1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::setBotRight() {
|
||||
if (_symbolBotDir != 0) {
|
||||
blank();
|
||||
return;
|
||||
}
|
||||
|
||||
commandOnlyCond(22, 213);
|
||||
|
||||
if (_mouseButton != 0)
|
||||
_symbolBotDir = +1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::dumpSymbol() {
|
||||
_newTextLine = 0;
|
||||
multiDump(kSymbolx, kSymboly + 20, 104, 60);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showSymbol() {
|
||||
showFrame(_symbolGraphics, kSymbolx, kSymboly, 12, 0);
|
||||
|
||||
showFrame(_symbolGraphics, _symbolTopX + kSymbolx-44, kSymboly+20, _symbolTopNum, 32);
|
||||
uint8 nextTopSymbol = nextSymbol(_symbolTopNum);
|
||||
showFrame(_symbolGraphics, _symbolTopX + kSymbolx+5, kSymboly+20, nextTopSymbol, 32);
|
||||
uint8 nextNextTopSymbol = nextSymbol(nextTopSymbol);
|
||||
showFrame(_symbolGraphics, _symbolTopX + kSymbolx+54, kSymboly+20, nextNextTopSymbol, 32);
|
||||
|
||||
showFrame(_symbolGraphics, _symbolBotX + kSymbolx-44, kSymboly+49, 6 + _symbolBotNum, 32);
|
||||
uint8 nextBotSymbol = nextSymbol(_symbolBotNum);
|
||||
showFrame(_symbolGraphics, _symbolBotX + kSymbolx+5, kSymboly+49, 6 + nextBotSymbol, 32);
|
||||
uint8 nextNextBotSymbol = nextSymbol(nextBotSymbol);
|
||||
showFrame(_symbolGraphics, _symbolBotX + kSymbolx+54, kSymboly+49, 6 + nextNextBotSymbol, 32);
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::nextSymbol(uint8 symbol) {
|
||||
uint8 result = symbol + 1;
|
||||
if (result == 6)
|
||||
return 0;
|
||||
if (result == 12)
|
||||
return 6;
|
||||
return result;
|
||||
}
|
||||
|
||||
void DreamWebEngine::updateSymbolTop() {
|
||||
if (!_symbolTopDir)
|
||||
return; // topfinished
|
||||
|
||||
if (_symbolTopDir == -1) {
|
||||
// Backward
|
||||
_symbolTopX--;
|
||||
if (_symbolTopX != (byte)-1) {
|
||||
// Not wrapping
|
||||
if (_symbolTopX != 24)
|
||||
return; // topfinished
|
||||
_symbolTopDir = 0;
|
||||
} else {
|
||||
_symbolTopX = 48;
|
||||
_symbolTopNum++;
|
||||
if (_symbolTopNum != 6)
|
||||
return; // topfinished
|
||||
_symbolTopNum = 0;
|
||||
}
|
||||
} else {
|
||||
// Forward
|
||||
_symbolTopX++;
|
||||
if (_symbolTopX != 49) {
|
||||
// Not wrapping
|
||||
if (_symbolTopX != 24)
|
||||
return; // topfinished
|
||||
_symbolTopDir = 0;
|
||||
} else {
|
||||
_symbolTopX = 0;
|
||||
_symbolTopNum--;
|
||||
if (_symbolTopNum != (byte)-1)
|
||||
return; // topfinished
|
||||
_symbolTopNum = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::updateSymbolBot() {
|
||||
if (!_symbolBotDir)
|
||||
return; // botfinished
|
||||
|
||||
if (_symbolBotDir == -1) {
|
||||
// Backward
|
||||
_symbolBotX--;
|
||||
if (_symbolBotX != (byte)-1) {
|
||||
// Not wrapping
|
||||
if (_symbolBotX != 24)
|
||||
return; // botfinished
|
||||
_symbolBotDir = 0;
|
||||
} else {
|
||||
_symbolBotX = 48;
|
||||
_symbolBotNum++;
|
||||
if (_symbolBotNum != 6)
|
||||
return; // botfinished
|
||||
_symbolBotNum = 0;
|
||||
}
|
||||
} else {
|
||||
// Forward
|
||||
_symbolBotX++;
|
||||
if (_symbolBotX != 49) {
|
||||
// Not wrapping
|
||||
if (_symbolBotX != 24)
|
||||
return; // botfinished
|
||||
_symbolBotDir = 0;
|
||||
} else {
|
||||
_symbolBotX = 0;
|
||||
_symbolBotNum--;
|
||||
if (_symbolBotNum != (byte)-1)
|
||||
return; // botfinished
|
||||
_symbolBotNum = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::useDiary() {
|
||||
getRidOfReels();
|
||||
loadGraphicsFile(_diaryGraphics, "G14");
|
||||
loadTempText("T51");
|
||||
loadGraphicsFile(_diaryCharset, "C02");
|
||||
createPanel();
|
||||
showIcon();
|
||||
showDiary();
|
||||
underTextLine();
|
||||
showDiaryPage();
|
||||
readMouse();
|
||||
showPointer();
|
||||
workToScreen();
|
||||
delPointer();
|
||||
_getBack = 0;
|
||||
|
||||
RectWithCallback diaryList[] = {
|
||||
{ kDiaryx+94,kDiaryx+110,kDiaryy+97,kDiaryy+113,&DreamWebEngine::diaryKeyN },
|
||||
{ kDiaryx+151,kDiaryx+167,kDiaryy+71,kDiaryy+87,&DreamWebEngine::diaryKeyP },
|
||||
{ kDiaryx+176,kDiaryx+192,kDiaryy+108,kDiaryy+124,&DreamWebEngine::quitKey },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
|
||||
do {
|
||||
delPointer();
|
||||
readMouse();
|
||||
showDiaryKeys();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpDiaryKeys();
|
||||
dumpTextLine();
|
||||
checkCoords(diaryList);
|
||||
} while (!_getBack && !_quitRequested);
|
||||
|
||||
|
||||
_diaryGraphics.clear();
|
||||
getRidOfTempText();
|
||||
_diaryCharset.clear();
|
||||
restoreReels();
|
||||
_manIsOffScreen = 0;
|
||||
redrawMainScrn();
|
||||
workToScreenM();
|
||||
}
|
||||
|
||||
void DreamWebEngine::showDiary() {
|
||||
showFrame(_diaryGraphics, kDiaryx, kDiaryy + 37, 1, 0);
|
||||
showFrame(_diaryGraphics, kDiaryx + 176, kDiaryy + 108, 2, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showDiaryKeys() {
|
||||
if (!_pressCount)
|
||||
return; // nokeyatall
|
||||
|
||||
_pressCount--;
|
||||
|
||||
if (!_pressCount)
|
||||
return; // nokeyatall
|
||||
|
||||
if (_pressed == 'N') {
|
||||
byte frame = (_pressCount == 1) ? 3 : 4;
|
||||
showFrame(_diaryGraphics, kDiaryx + 94, kDiaryy + 97, frame, 0);
|
||||
} else {
|
||||
byte frame = (_pressCount == 1) ? 5 : 6;
|
||||
showFrame(_diaryGraphics, kDiaryx + 151, kDiaryy + 71, frame, 0);
|
||||
}
|
||||
|
||||
if (_pressCount == 1)
|
||||
showDiaryPage();
|
||||
}
|
||||
|
||||
void DreamWebEngine::dumpDiaryKeys() {
|
||||
if (_pressCount == 1) {
|
||||
if (_vars._sartainDead != 1 && _diaryPage == 5 && getLocation(6) != 1) {
|
||||
// Add Sartain Industries note
|
||||
setLocation(6);
|
||||
delPointer();
|
||||
const uint8 *string = getTextInFile1(12);
|
||||
printDirect(string, 70, 106, 241, 241 & 1);
|
||||
workToScreenM();
|
||||
hangOnP(200);
|
||||
createPanel();
|
||||
showIcon();
|
||||
showDiary();
|
||||
showDiaryPage();
|
||||
workToScreenM();
|
||||
showPointer();
|
||||
return;
|
||||
} else {
|
||||
multiDump(kDiaryx + 48, kDiaryy + 15, 200, 16);
|
||||
}
|
||||
}
|
||||
|
||||
multiDump(kDiaryx + 94, kDiaryy + 97, 16, 16);
|
||||
multiDump(kDiaryx + 151, kDiaryy + 71, 16, 16);
|
||||
}
|
||||
|
||||
void DreamWebEngine::diaryKeyP() {
|
||||
commandOnlyCond(23, 214);
|
||||
|
||||
if (!_mouseButton ||
|
||||
_oldButton == _mouseButton ||
|
||||
_pressCount)
|
||||
return; // notkeyp
|
||||
|
||||
_sound->playChannel1(16);
|
||||
_pressCount = 12;
|
||||
_pressed = 'P';
|
||||
_diaryPage--;
|
||||
|
||||
if (_diaryPage == 0xFF)
|
||||
_diaryPage = 11;
|
||||
}
|
||||
|
||||
void DreamWebEngine::diaryKeyN() {
|
||||
commandOnlyCond(23, 213);
|
||||
|
||||
if (!_mouseButton ||
|
||||
_oldButton == _mouseButton ||
|
||||
_pressCount)
|
||||
return; // notkeyn
|
||||
|
||||
_sound->playChannel1(16);
|
||||
_pressCount = 12;
|
||||
_pressed = 'N';
|
||||
_diaryPage++;
|
||||
|
||||
if (_diaryPage == 12)
|
||||
_diaryPage = 0;
|
||||
}
|
||||
|
||||
void DreamWebEngine::showDiaryPage() {
|
||||
showFrame(_diaryGraphics, kDiaryx, kDiaryy, 0, 0);
|
||||
useTempCharset(&_diaryCharset);
|
||||
|
||||
if (getLanguage() == Common::RU_RUS)
|
||||
useCharsetTempgraphics();
|
||||
|
||||
_charShift = 91+91;
|
||||
const uint8 *string = getTextInFile1(_diaryPage);
|
||||
uint16 y = kDiaryy + 16;
|
||||
printDirect(&string, kDiaryx + 48, &y, 240, 240 & 1, true);
|
||||
y = kDiaryy + 16;
|
||||
printDirect(&string, kDiaryx + 129, &y, 240, 240 & 1, true);
|
||||
y = kDiaryy + 23;
|
||||
printDirect(&string, kDiaryx + 48, &y, 240, 240 & 1, true);
|
||||
_charShift = 0;
|
||||
useCharset1();
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
274
engines/dreamweb/metaengine.cpp
Normal file
274
engines/dreamweb/metaengine.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
/* 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/savefile.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "graphics/thumbnail.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "dreamweb/dreamweb.h"
|
||||
#include "dreamweb/detection.h"
|
||||
|
||||
static const ADExtraGuiOptionsMap gameGuiOptions[] = {
|
||||
{
|
||||
GAMEOPTION_COPY_PROTECTION,
|
||||
{
|
||||
_s("Enable copy protection"),
|
||||
_s("Enable any copy protection that would otherwise be bypassed by default."),
|
||||
"copy_protection",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
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_BRIGHTPALETTE,
|
||||
{
|
||||
_s("Use bright palette mode"),
|
||||
_s("Display graphics using the game's bright palette"),
|
||||
"bright_palette",
|
||||
true,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
|
||||
#ifdef USE_TTS
|
||||
{
|
||||
GAMEOPTION_TTS_THINGS,
|
||||
{
|
||||
_s("Enable Text to Speech for Objects, Options, and the Bible Quote"),
|
||||
_s("Use TTS to read the descriptions (if TTS is available)"),
|
||||
"tts_enabled_objects",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
GAMEOPTION_TTS_SPEECH,
|
||||
{
|
||||
_s("Enable Text to Speech for Subtitles"),
|
||||
_s("Use TTS to read the subtitles (if TTS is available)"),
|
||||
"tts_enabled_speech",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
#endif
|
||||
|
||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||
};
|
||||
|
||||
class DreamWebMetaEngine : public AdvancedMetaEngine<DreamWeb::DreamWebGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "dreamweb";
|
||||
}
|
||||
|
||||
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
|
||||
return gameGuiOptions;
|
||||
}
|
||||
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const DreamWeb::DreamWebGameDescription *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;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
|
||||
Common::String getSavegameFile(int saveGameIdx, const char *target) const override {
|
||||
if (saveGameIdx == kSavegameFilePattern)
|
||||
return Common::String::format("DREAMWEB.D##");
|
||||
else
|
||||
return Common::String::format("DREAMWEB.D%02d", saveGameIdx);
|
||||
}
|
||||
};
|
||||
|
||||
bool DreamWebMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
switch(f) {
|
||||
case kSupportsListSaves:
|
||||
case kSupportsLoadingDuringStartup:
|
||||
case kSupportsDeleteSave:
|
||||
case kSavesSupportMetaInfo:
|
||||
case kSavesSupportThumbnail:
|
||||
case kSavesSupportCreationDate:
|
||||
case kSavesSupportPlayTime:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DreamWeb::DreamWebEngine::hasFeature(EngineFeature f) const {
|
||||
switch(f) {
|
||||
case kSupportsReturnToLauncher:
|
||||
return true;
|
||||
case kSupportsSubtitleOptions:
|
||||
return _gameDescription->desc.flags & ADGF_CD;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Common::Error DreamWebMetaEngine::createInstance(OSystem *syst, Engine **engine, const DreamWeb::DreamWebGameDescription *desc) const {
|
||||
*engine = new DreamWeb::DreamWebEngine(syst,desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
SaveStateList DreamWebMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Common::StringArray files = saveFileMan->listSavefiles("DREAMWEB.D##");
|
||||
|
||||
SaveStateList saveList;
|
||||
for (uint i = 0; i < files.size(); ++i) {
|
||||
const Common::String &file = files[i];
|
||||
Common::InSaveFile *stream = saveFileMan->openForLoading(file);
|
||||
if (!stream)
|
||||
error("cannot open save file %s", file.c_str());
|
||||
char name[17] = {};
|
||||
stream->seek(0x61); // The actual description string starts at desc[1]
|
||||
stream->read(name, sizeof(name) - 1);
|
||||
delete stream;
|
||||
|
||||
int slotNum = atoi(file.c_str() + file.size() - 2);
|
||||
SaveStateDescriptor sd(this, slotNum, name);
|
||||
saveList.push_back(sd);
|
||||
}
|
||||
|
||||
// Sort saves based on slot number.
|
||||
Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
|
||||
return saveList;
|
||||
}
|
||||
|
||||
int DreamWebMetaEngine::getMaximumSaveSlot() const { return 99; }
|
||||
|
||||
bool DreamWebMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
Common::String fileName = Common::String::format("DREAMWEB.D%02d", slot);
|
||||
return g_system->getSavefileManager()->removeSavefile(fileName);
|
||||
}
|
||||
|
||||
SaveStateDescriptor DreamWebMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
Common::String filename = Common::String::format("DREAMWEB.D%02d", slot);
|
||||
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
|
||||
|
||||
if (in) {
|
||||
DreamWeb::FileHeader header;
|
||||
in->read((uint8 *)&header, sizeof(DreamWeb::FileHeader));
|
||||
|
||||
char name[17] = {};
|
||||
in->skip(1); // The actual description string starts at desc[1]
|
||||
in->read(name, sizeof(name) - 1);
|
||||
|
||||
SaveStateDescriptor desc(this, slot, name);
|
||||
|
||||
// Check if there is a ScummVM data block
|
||||
if (header.len(6) == SCUMMVM_BLOCK_MAGIC_SIZE) {
|
||||
// Skip the game data
|
||||
for (byte i = 1; i <= 5; i++)
|
||||
in->skip(header.len(i));
|
||||
|
||||
uint32 tag = in->readUint32BE();
|
||||
if (tag != SCUMMVM_HEADER) {
|
||||
warning("ScummVM data block found, but the block header is incorrect - skipping");
|
||||
delete in;
|
||||
return desc;
|
||||
}
|
||||
|
||||
byte version = in->readByte();
|
||||
if (version > SAVEGAME_VERSION) {
|
||||
warning("ScummVM data block found, but it has been saved with a newer version of ScummVM - skipping");
|
||||
delete in;
|
||||
return desc;
|
||||
}
|
||||
|
||||
uint32 saveDate = in->readUint32LE();
|
||||
uint32 saveTime = in->readUint32LE();
|
||||
uint32 playTime = in->readUint32LE();
|
||||
Graphics::Surface *thumbnail;
|
||||
if (!Graphics::loadThumbnail(*in, thumbnail)) {
|
||||
warning("Missing or broken thumbnail - skipping");
|
||||
delete in;
|
||||
return desc;
|
||||
}
|
||||
|
||||
int day = (saveDate >> 24) & 0xFF;
|
||||
int month = (saveDate >> 16) & 0xFF;
|
||||
int year = saveDate & 0xFFFF;
|
||||
int hour = (saveTime >> 16) & 0xFF;
|
||||
int minutes = (saveTime >> 8) & 0xFF;
|
||||
|
||||
desc.setSaveDate(year, month, day);
|
||||
desc.setSaveTime(hour, minutes);
|
||||
desc.setPlayTime(playTime * 1000);
|
||||
desc.setThumbnail(thumbnail);
|
||||
}
|
||||
|
||||
delete in;
|
||||
return desc;
|
||||
}
|
||||
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(DREAMWEB)
|
||||
REGISTER_PLUGIN_DYNAMIC(DREAMWEB, PLUGIN_TYPE_ENGINE, DreamWebMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(DREAMWEB, PLUGIN_TYPE_ENGINE, DreamWebMetaEngine);
|
||||
#endif
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
Common::Error DreamWebEngine::loadGameState(int slot) {
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error DreamWebEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Language DreamWebEngine::getLanguage() const {
|
||||
return _gameDescription->desc.language;
|
||||
}
|
||||
|
||||
bool DreamWebEngine::isCD() {
|
||||
return _gameDescription->desc.flags & ADGF_CD;
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
37
engines/dreamweb/module.mk
Normal file
37
engines/dreamweb/module.mk
Normal file
@@ -0,0 +1,37 @@
|
||||
MODULE := engines/dreamweb
|
||||
|
||||
MODULE_OBJS := \
|
||||
backdrop.o \
|
||||
console.o \
|
||||
dreamweb.o \
|
||||
keypad.o \
|
||||
metaengine.o \
|
||||
monitor.o \
|
||||
mouse.o \
|
||||
newplace.o \
|
||||
object.o \
|
||||
pathfind.o \
|
||||
people.o \
|
||||
print.o \
|
||||
rain.o \
|
||||
rnca_archive.o \
|
||||
saveload.o \
|
||||
sound.o \
|
||||
sprite.o \
|
||||
stubs.o \
|
||||
talk.o \
|
||||
titles.o \
|
||||
use.o \
|
||||
vgafades.o \
|
||||
vgagrafx.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_DREAMWEB), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
783
engines/dreamweb/monitor.cpp
Normal file
783
engines/dreamweb/monitor.cpp
Normal file
@@ -0,0 +1,783 @@
|
||||
/* 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 "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
struct MonitorKeyEntry {
|
||||
uint8 keyAssigned;
|
||||
char username[12];
|
||||
char password[12];
|
||||
};
|
||||
|
||||
// New monitor key list
|
||||
static MonitorKeyEntry monitorKeyEntries[4] = {
|
||||
{ 1, "PUBLIC", "PUBLIC" },
|
||||
{ 0, "RYAN", "BLACKDRAGON" },
|
||||
{ 0, "LOUIS", "HENDRIX" },
|
||||
{ 0, "BECKETT", "SEPTIMUS" }
|
||||
};
|
||||
|
||||
void DreamWebEngine::useMon() {
|
||||
_vars._lastTrigger = 0;
|
||||
_currentFile[0] = 34;
|
||||
memset(_currentFile+1, ' ', 12);
|
||||
_currentFile[13] = 0;
|
||||
|
||||
monitorKeyEntries[0].keyAssigned = 1;
|
||||
monitorKeyEntries[1].keyAssigned = 0;
|
||||
monitorKeyEntries[2].keyAssigned = 0;
|
||||
monitorKeyEntries[3].keyAssigned = 0;
|
||||
|
||||
createPanel();
|
||||
showPanel();
|
||||
showIcon();
|
||||
drawFloor();
|
||||
getRidOfAll();
|
||||
loadGraphicsFile(_monitorGraphics, "G03"); // mon. graphic name
|
||||
loadPersonal();
|
||||
loadNews();
|
||||
loadCart();
|
||||
loadGraphicsFile(_monitorCharset, "C01"); // character set 2
|
||||
printOuterMon();
|
||||
initialMonCols();
|
||||
printLogo();
|
||||
workToScreen();
|
||||
turnOnPower();
|
||||
fadeUpYellows();
|
||||
fadeUpMonFirst();
|
||||
_monAdX = 76;
|
||||
_monAdY = 141;
|
||||
monMessage(1);
|
||||
hangOnCurs(120);
|
||||
monMessage(2);
|
||||
randomAccess(60);
|
||||
monMessage(3);
|
||||
hangOnCurs(100);
|
||||
printLogo();
|
||||
scrollMonitor();
|
||||
_bufferIn = 0;
|
||||
_bufferOut = 0;
|
||||
bool stop = false;
|
||||
do {
|
||||
uint16 oldMonadx = _monAdX;
|
||||
uint16 oldMonady = _monAdY;
|
||||
input();
|
||||
_monAdX = oldMonadx;
|
||||
_monAdY = oldMonady;
|
||||
stop = execCommand();
|
||||
if (_quitRequested) //TODO : Check why it crashes when put before the execcommand
|
||||
break;
|
||||
} while (!stop);
|
||||
_monitorGraphics.clear();
|
||||
_monitorCharset.clear();
|
||||
|
||||
_textFile1.clear();
|
||||
_textFile2.clear();
|
||||
_textFile3.clear();
|
||||
|
||||
_getBack = 1;
|
||||
_sound->playChannel1(26);
|
||||
_manIsOffScreen = 0;
|
||||
restoreAll();
|
||||
redrawMainScrn();
|
||||
workToScreenM();
|
||||
}
|
||||
|
||||
int DreamWebEngine::findCommand(const char *const cmdList[]) {
|
||||
// Loop over all commands in the list and see if we get a match
|
||||
int cmd = 0;
|
||||
while (cmdList[cmd] != nullptr) {
|
||||
const char *cmdStr = cmdList[cmd];
|
||||
const char *inputStr = _inputLine;
|
||||
// Compare the command, char by char, to see if we get a match.
|
||||
// We only care about the prefix matching, though.
|
||||
char inputChar, cmdChar;
|
||||
do {
|
||||
inputChar = *inputStr; inputStr += 2;
|
||||
cmdChar = *cmdStr++;
|
||||
if (cmdChar == 0)
|
||||
return cmd;
|
||||
} while (inputChar == cmdChar);
|
||||
++cmd;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool DreamWebEngine::execCommand() {
|
||||
static const char *const comlist[] = {
|
||||
"EXIT",
|
||||
"HELP",
|
||||
"LIST",
|
||||
"READ",
|
||||
"LOGON",
|
||||
"KEYS",
|
||||
nullptr
|
||||
};
|
||||
|
||||
static const char *const comlistFR[] = {
|
||||
"SORTIR",
|
||||
"AIDE",
|
||||
"LISTE",
|
||||
"LIRE",
|
||||
"CONNEXION",
|
||||
"TOUCHES", // should be CLES but it is translated as TOUCHES in the game...
|
||||
nullptr
|
||||
};
|
||||
|
||||
static const char *const comlistDE[] = {
|
||||
"ENDE",
|
||||
"HILF",
|
||||
"LISTE",
|
||||
"LIES",
|
||||
"ZUGRIFF",
|
||||
"DATEN",
|
||||
nullptr
|
||||
};
|
||||
|
||||
static const char *const comlistIT[] = {
|
||||
"ESCI",
|
||||
"AIUTO",
|
||||
"ELENCA",
|
||||
"LEGGI",
|
||||
"ACCEDI",
|
||||
"CHIAVI",
|
||||
nullptr
|
||||
};
|
||||
|
||||
static const char *const comlistES[] = {
|
||||
"SALIR",
|
||||
"AYUDA",
|
||||
"LISTA",
|
||||
"LEER",
|
||||
"ACCESO",
|
||||
"CLAVES",
|
||||
nullptr
|
||||
};
|
||||
|
||||
if (_inputLine[0] == 0) {
|
||||
// No input
|
||||
scrollMonitor();
|
||||
return false;
|
||||
}
|
||||
|
||||
int cmd = findCommand(comlist);
|
||||
if (cmd == -1) {
|
||||
// This did not match an english command. Try to find a localized one.
|
||||
switch (getLanguage()) {
|
||||
case Common::FR_FRA:
|
||||
cmd = findCommand(comlistFR);
|
||||
break;
|
||||
case Common::DE_DEU:
|
||||
cmd = findCommand(comlistDE);
|
||||
break;
|
||||
case Common::IT_ITA:
|
||||
cmd = findCommand(comlistIT);
|
||||
break;
|
||||
case Common::ES_ESP:
|
||||
cmd = findCommand(comlistES);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the selected command
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
return true;
|
||||
case 1:
|
||||
monMessage(6);
|
||||
// An extra addition in ScummVM: available commands.
|
||||
// Since the reference to the game manual is a form of copy protection,
|
||||
// this extra text is wrapped around the common copy protection check,
|
||||
// to keep it faithful to the original, if requested.
|
||||
if (!_copyProtection) {
|
||||
switch (getLanguage()) {
|
||||
case Common::FR_FRA:
|
||||
monPrint("LES COMMANDES VALIDES SONT SORTIR, AIDE, LISTE, LIRE, CONNEXION, TOUCHES");
|
||||
break;
|
||||
case Common::DE_DEU:
|
||||
monPrint("G\232LTIGE BEFEHLE SIND ENDE, HILFE, LISTE, LIES, ZUGRIFF, DATEN");
|
||||
break;
|
||||
case Common::IT_ITA:
|
||||
monPrint("I COMANDI VALIDI SONO ESCI, AIUTO, ELENCA, LEGGI, ACCEDI, CHIAVI");
|
||||
break;
|
||||
case Common::ES_ESP:
|
||||
default:
|
||||
monPrint("VALID COMMANDS ARE EXIT, HELP, LIST, READ, LOGON, KEYS");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
dirCom();
|
||||
break;
|
||||
case 3:
|
||||
read();
|
||||
break;
|
||||
case 4:
|
||||
signOn();
|
||||
break;
|
||||
case 5:
|
||||
showKeys();
|
||||
break;
|
||||
default:
|
||||
netError();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DreamWebEngine::monitorLogo() {
|
||||
if (_logoNum != _oldLogoNum) {
|
||||
_oldLogoNum = _logoNum;
|
||||
//fadeDownMon(); // FIXME: Commented out in ASM
|
||||
printLogo();
|
||||
printUnderMonitor();
|
||||
workToScreen();
|
||||
printLogo();
|
||||
//fadeUpMon(); // FIXME: Commented out in ASM
|
||||
printLogo();
|
||||
_sound->playChannel1(26);
|
||||
randomAccess(20);
|
||||
} else {
|
||||
printLogo();
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::printLogo() {
|
||||
showFrame(_monitorGraphics, 56, 32, 0, 0);
|
||||
showCurrentFile();
|
||||
}
|
||||
|
||||
void DreamWebEngine::input() {
|
||||
memset(_inputLine, 0, sizeof(_inputLine));
|
||||
_curPos = 0;
|
||||
printChar(_monitorCharset, _monAdX, _monAdY, '>', 0, nullptr, nullptr);
|
||||
multiDump(_monAdX, _monAdY, 6, 8);
|
||||
_monAdX += 6;
|
||||
_cursLocX = _monAdX;
|
||||
_cursLocY = _monAdY;
|
||||
while (true) {
|
||||
printCurs();
|
||||
waitForVSync();
|
||||
delCurs();
|
||||
readKey();
|
||||
if (_quitRequested)
|
||||
return;
|
||||
uint8 currentKey = _currentKey;
|
||||
if (currentKey == 0)
|
||||
continue;
|
||||
if (currentKey == 13)
|
||||
return;
|
||||
if (currentKey == 8) {
|
||||
if (_curPos > 0)
|
||||
delChar();
|
||||
continue;
|
||||
}
|
||||
if (_curPos == 28)
|
||||
continue;
|
||||
if ((currentKey == 32) && (_curPos == 0))
|
||||
continue;
|
||||
currentKey = makeCaps(currentKey);
|
||||
_inputLine[_curPos * 2 + 0] = currentKey;
|
||||
if (currentKey > 'Z')
|
||||
continue;
|
||||
multiGet(_mapStore + _curPos * 256, _monAdX, _monAdY, 8, 8);
|
||||
uint8 charWidth;
|
||||
printChar(_monitorCharset, _monAdX, _monAdY, currentKey, 0, &charWidth, nullptr);
|
||||
_inputLine[_curPos * 2 + 1] = charWidth;
|
||||
_monAdX += charWidth;
|
||||
++_curPos;
|
||||
_cursLocX += charWidth;
|
||||
}
|
||||
}
|
||||
|
||||
byte DreamWebEngine::makeCaps(byte c) {
|
||||
// TODO: Replace calls to this by toupper() ?
|
||||
if (c >= 'a')
|
||||
c -= 'a' - 'A'; // = 32
|
||||
return c;
|
||||
}
|
||||
|
||||
void DreamWebEngine::delChar() {
|
||||
--_curPos;
|
||||
_inputLine[_curPos * 2] = 0;
|
||||
uint8 width = _inputLine[_curPos * 2 + 1];
|
||||
_monAdX -= width;
|
||||
_cursLocX -= width;
|
||||
uint16 offset = _curPos;
|
||||
offset = ((offset & 0x00ff) << 8) | ((offset & 0xff00) >> 8);
|
||||
multiPut(_mapStore + offset, _monAdX, _monAdY, 8, 8);
|
||||
multiDump(_monAdX, _monAdY, 8, 8);
|
||||
}
|
||||
|
||||
void DreamWebEngine::printCurs() {
|
||||
uint16 x = _cursLocX;
|
||||
uint16 y = _cursLocY;
|
||||
uint16 height;
|
||||
if (_foreignRelease) {
|
||||
y -= 3;
|
||||
height = 11;
|
||||
} else
|
||||
height = 8;
|
||||
|
||||
multiGet(_textUnder, x, y, 6, height);
|
||||
++_mainTimer;
|
||||
if ((_mainTimer & 16) == 0)
|
||||
showFrame(_monitorCharset, x, y, '/' - 32, 0);
|
||||
multiDump(x - (getLanguage() == Common::RU_RUS ? 7 : 6), y, 12, height);
|
||||
}
|
||||
|
||||
void DreamWebEngine::delCurs() {
|
||||
uint16 x = _cursLocX;
|
||||
uint16 y = _cursLocY;
|
||||
uint16 width = 6;
|
||||
uint16 height;
|
||||
if (_foreignRelease) {
|
||||
y -= 3;
|
||||
height = 11;
|
||||
} else
|
||||
height = 8;
|
||||
multiPut(_textUnder, x, y, width, height);
|
||||
multiDump(x, y, width, height);
|
||||
}
|
||||
|
||||
void DreamWebEngine::scrollMonitor() {
|
||||
printLogo();
|
||||
printUnderMonitor();
|
||||
workToScreen();
|
||||
_sound->playChannel1(25);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showCurrentFile() {
|
||||
uint16 x;
|
||||
// Monitor Frame position differs between Floppy and CD version
|
||||
if (isCD())
|
||||
x = 178;
|
||||
else
|
||||
x = 199;
|
||||
const char *currentFile = _currentFile + 1;
|
||||
while (*currentFile) {
|
||||
char c = *currentFile++;
|
||||
c = modifyChar(c);
|
||||
printChar(_monitorCharset, &x, 37, c, 0, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::accessLightOn() {
|
||||
showFrame(_monitorGraphics, 74, 182, 8, 0);
|
||||
multiDump(74, 182, 12, 8);
|
||||
}
|
||||
|
||||
void DreamWebEngine::accessLightOff() {
|
||||
showFrame(_monitorGraphics, 74, 182, 7, 0);
|
||||
multiDump(74, 182, 12, 8);
|
||||
}
|
||||
|
||||
void DreamWebEngine::randomAccess(uint16 count) {
|
||||
for (uint16 i = 0; i < count; ++i) {
|
||||
waitForVSync();
|
||||
waitForVSync();
|
||||
uint16 v = _rnd.getRandomNumber(15);
|
||||
if (v < 10)
|
||||
accessLightOff();
|
||||
else
|
||||
accessLightOn();
|
||||
}
|
||||
accessLightOff();
|
||||
}
|
||||
|
||||
void DreamWebEngine::monMessage(uint8 index) {
|
||||
assert(index > 0);
|
||||
const char *string = _textFile1._text;
|
||||
for (uint8 i = 0; i < index; ++i) {
|
||||
while (*string++ != '+') {
|
||||
}
|
||||
}
|
||||
monPrint(string);
|
||||
}
|
||||
|
||||
void DreamWebEngine::netError() {
|
||||
monMessage(5);
|
||||
scrollMonitor();
|
||||
}
|
||||
|
||||
void DreamWebEngine::powerLightOn() {
|
||||
showFrame(_monitorGraphics, 257+4, 182, 6, 0);
|
||||
multiDump(257+4, 182, 12, 8);
|
||||
}
|
||||
|
||||
void DreamWebEngine::powerLightOff() {
|
||||
showFrame(_monitorGraphics, 257+4, 182, 5, 0);
|
||||
multiDump(257+4, 182, 12, 8);
|
||||
}
|
||||
|
||||
void DreamWebEngine::lockLightOn() {
|
||||
showFrame(_monitorGraphics, 56, 182, 10, 0);
|
||||
multiDump(58, 182, 12, 8);
|
||||
}
|
||||
|
||||
void DreamWebEngine::lockLightOff() {
|
||||
showFrame(_monitorGraphics, 56, 182, 9, 0);
|
||||
multiDump(58, 182, 12, 8);
|
||||
}
|
||||
|
||||
void DreamWebEngine::turnOnPower() {
|
||||
for (uint i = 0; i < 3; ++i) {
|
||||
powerLightOn();
|
||||
hangOn(30);
|
||||
powerLightOff();
|
||||
hangOn(30);
|
||||
}
|
||||
powerLightOn();
|
||||
}
|
||||
|
||||
void DreamWebEngine::printOuterMon() {
|
||||
showFrame(_monitorGraphics, 40, 32, 1, 0);
|
||||
showFrame(_monitorGraphics, 264, 32, 2, 0);
|
||||
showFrame(_monitorGraphics, 40, 12, 3, 0);
|
||||
showFrame(_monitorGraphics, 40, 164, 4, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadPersonal() {
|
||||
if (_vars._location == 0 || _vars._location == 42)
|
||||
loadTextFile(_textFile1, "T01"); // monitor file 1
|
||||
else
|
||||
loadTextFile(_textFile1, "T02"); // monitor file 2
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadNews() {
|
||||
// textfile2 holds information accessible by anyone
|
||||
if (_vars._newsItem == 0)
|
||||
loadTextFile(_textFile2, "T10"); // monitor file 10
|
||||
else if (_vars._newsItem == 1)
|
||||
loadTextFile(_textFile2, "T11"); // monitor file 11
|
||||
else if (_vars._newsItem == 2)
|
||||
loadTextFile(_textFile2, "T12"); // monitor file 12
|
||||
else
|
||||
loadTextFile(_textFile2, "T13"); // monitor file 13
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadCart() {
|
||||
byte cartridgeId = 0;
|
||||
uint16 objectIndex = findSetObject("INTF");
|
||||
uint16 cartridgeIndex = checkInside(objectIndex, 1);
|
||||
if (cartridgeIndex != kNumexobjects)
|
||||
cartridgeId = getExAd(cartridgeIndex)->objId[3] + 1;
|
||||
|
||||
if (cartridgeId == 0)
|
||||
loadTextFile(_textFile3, "T20"); // monitor file 20
|
||||
else if (cartridgeId == 1)
|
||||
loadTextFile(_textFile3, "T21"); // monitor file 21
|
||||
else if (cartridgeId == 2)
|
||||
loadTextFile(_textFile3, "T22"); // monitor file 22
|
||||
else if (cartridgeId == 3)
|
||||
loadTextFile(_textFile3, "T23"); // monitor file 23
|
||||
else
|
||||
loadTextFile(_textFile3, "T24"); // monitor file 24
|
||||
}
|
||||
|
||||
void DreamWebEngine::showKeys() {
|
||||
randomAccess(10);
|
||||
scrollMonitor();
|
||||
monMessage(18);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (monitorKeyEntries[i].keyAssigned)
|
||||
monPrint(monitorKeyEntries[i].username);
|
||||
}
|
||||
|
||||
scrollMonitor();
|
||||
}
|
||||
|
||||
const char *DreamWebEngine::getKeyAndLogo(const char *foundString) {
|
||||
byte newLogo = foundString[1] - 48;
|
||||
byte keyNum = foundString[3] - 48;
|
||||
|
||||
if (monitorKeyEntries[keyNum].keyAssigned == 1) {
|
||||
// Key OK
|
||||
_logoNum = newLogo;
|
||||
return foundString + 4;
|
||||
} else {
|
||||
monMessage(12); // "Access denied, key required -"
|
||||
monPrint(monitorKeyEntries[keyNum].username);
|
||||
scrollMonitor();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const char *DreamWebEngine::searchForString(const char *topic, const char *text) {
|
||||
char delim = *topic;
|
||||
|
||||
while (true) {
|
||||
const char *s = topic;
|
||||
int delimCount = 0;
|
||||
|
||||
char c;
|
||||
do {
|
||||
c = makeCaps(*text++);
|
||||
|
||||
if (c == '*' || (delim == '=' && c == 34))
|
||||
return nullptr;
|
||||
|
||||
if (c == delim) {
|
||||
delimCount++;
|
||||
if (delimCount == 2)
|
||||
return text;
|
||||
}
|
||||
|
||||
} while (c == *s++);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::dirCom() {
|
||||
randomAccess(30);
|
||||
|
||||
const char *dirname = parser();
|
||||
if (dirname[1]) {
|
||||
dirFile(dirname);
|
||||
return;
|
||||
}
|
||||
|
||||
_logoNum = 0;
|
||||
memcpy(_currentFile+1, "ROOT ", 12);
|
||||
monitorLogo();
|
||||
scrollMonitor();
|
||||
monMessage(9);
|
||||
searchForFiles(_textFile1._text);
|
||||
searchForFiles(_textFile2._text);
|
||||
searchForFiles(_textFile3._text);
|
||||
scrollMonitor();
|
||||
}
|
||||
|
||||
void DreamWebEngine::dirFile(const char *dirName) {
|
||||
char topic[14];
|
||||
|
||||
memcpy(topic, dirName, 14);
|
||||
topic[0] = 34;
|
||||
|
||||
const char *text = _textFile1._text;
|
||||
const char *found = searchForString(topic, text);
|
||||
if (!found) {
|
||||
text = _textFile2._text;
|
||||
found = searchForString(topic, text);
|
||||
if (!found) {
|
||||
text = _textFile3._text;
|
||||
found = searchForString(topic, text);
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
found = getKeyAndLogo(found);
|
||||
if (!found)
|
||||
return; // not logged in
|
||||
} else {
|
||||
monMessage(7);
|
||||
return;
|
||||
}
|
||||
|
||||
// "keyok2"
|
||||
memcpy(_currentFile+1, dirName+1, 12);
|
||||
monitorLogo();
|
||||
scrollMonitor();
|
||||
monMessage(10);
|
||||
|
||||
while (true) {
|
||||
byte curChar = *found++;
|
||||
if (curChar == 34 || curChar == '*') {
|
||||
// "endofdir2"
|
||||
scrollMonitor();
|
||||
return;
|
||||
}
|
||||
|
||||
if (curChar == '=')
|
||||
found = monPrint(found);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::read() {
|
||||
randomAccess(40);
|
||||
const char *name = parser();
|
||||
if (name[1] == 0) {
|
||||
netError();
|
||||
return;
|
||||
}
|
||||
|
||||
const char *topic = _currentFile;
|
||||
|
||||
const char *text = _textFile1._text;
|
||||
const char *found = searchForString(topic, text);
|
||||
if (!found) {
|
||||
text = _textFile2._text;
|
||||
found = searchForString(topic, text);
|
||||
if (!found) {
|
||||
text = _textFile3._text;
|
||||
found = searchForString(topic, text);
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (!getKeyAndLogo(found))
|
||||
return;
|
||||
} else {
|
||||
monMessage(7);
|
||||
return;
|
||||
}
|
||||
|
||||
// "keyok1"
|
||||
found = searchForString(name, found);
|
||||
if (!found) {
|
||||
_logoNum = _oldLogoNum;
|
||||
monMessage(11);
|
||||
return;
|
||||
}
|
||||
|
||||
// "findtopictext"
|
||||
monitorLogo();
|
||||
scrollMonitor();
|
||||
|
||||
found++;
|
||||
|
||||
while (true) {
|
||||
found = monPrint(found);
|
||||
if (found[0] == 34 || found[0] == '=' || found[0] == '*') {
|
||||
// "endoftopic"
|
||||
scrollMonitor();
|
||||
return;
|
||||
}
|
||||
|
||||
processTrigger();
|
||||
randomAccess(24);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::signOn() {
|
||||
const char *name = parser();
|
||||
|
||||
int8 foundIndex = -1;
|
||||
Common::String inputLine = name + 1;
|
||||
inputLine.trim();
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
if (inputLine.equalsIgnoreCase(monitorKeyEntries[i].username)) {
|
||||
// Check if the key has already been assigned
|
||||
if (monitorKeyEntries[i].keyAssigned) {
|
||||
monMessage(17);
|
||||
return;
|
||||
} else {
|
||||
foundIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundIndex == -1) {
|
||||
monMessage(13);
|
||||
return;
|
||||
}
|
||||
|
||||
monMessage(15);
|
||||
|
||||
uint16 prevX = _monAdX;
|
||||
uint16 prevY = _monAdY;
|
||||
input(); // password input
|
||||
_monAdX = prevX;
|
||||
_monAdY = prevY;
|
||||
|
||||
// The entered line has zeroes in-between each character
|
||||
uint32 len = strlen(monitorKeyEntries[foundIndex].password);
|
||||
bool found = true;
|
||||
|
||||
for (uint32 i = 0; i < len; i++) {
|
||||
if (monitorKeyEntries[foundIndex].password[i] != _inputLine[i * 2]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
scrollMonitor();
|
||||
monMessage(16);
|
||||
} else {
|
||||
monMessage(14);
|
||||
monPrint(monitorKeyEntries[foundIndex].username);
|
||||
scrollMonitor();
|
||||
monitorKeyEntries[foundIndex].keyAssigned = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::searchForFiles(const char *filesString) {
|
||||
byte curChar;
|
||||
|
||||
while (true) {
|
||||
curChar = filesString[0];
|
||||
filesString++;
|
||||
if (curChar == '*')
|
||||
return; // "endofdir"
|
||||
if (curChar == 34)
|
||||
filesString = monPrint(filesString);
|
||||
}
|
||||
}
|
||||
|
||||
const char *DreamWebEngine::parser() {
|
||||
char *output = _operand1;
|
||||
|
||||
memset(output, 0, sizeof(_operand1));
|
||||
|
||||
*output++ = '=';
|
||||
|
||||
const char *in = _inputLine;
|
||||
|
||||
uint8 c;
|
||||
|
||||
// skip command
|
||||
do {
|
||||
c = *in++;
|
||||
in++;
|
||||
|
||||
if (!c)
|
||||
return output;
|
||||
} while (c != 32);
|
||||
|
||||
// skip spaces between command and operand
|
||||
do {
|
||||
c = *in++;
|
||||
in++;
|
||||
} while (c == 32);
|
||||
|
||||
// copy first operand
|
||||
do {
|
||||
*output++ = c;
|
||||
c = *in++;
|
||||
in++;
|
||||
if (!c)
|
||||
return _operand1;
|
||||
} while (c != 32);
|
||||
|
||||
return _operand1;
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
170
engines/dreamweb/mouse.cpp
Normal file
170
engines/dreamweb/mouse.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/* 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/events.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
void DreamWebEngine::mouseCall(uint16 *x, uint16 *y, uint16 *state) {
|
||||
processEvents();
|
||||
Common::Point pos = _eventMan->getMousePos();
|
||||
*x = CLIP<int16>(pos.x, 15, 298);
|
||||
*y = CLIP<int16>(pos.y, 15, 184);
|
||||
|
||||
unsigned newState = _eventMan->getButtonState();
|
||||
*state = (newState == _oldMouseState ? 0 : newState);
|
||||
_oldMouseState = newState;
|
||||
}
|
||||
|
||||
void DreamWebEngine::readMouse() {
|
||||
_oldButton = _mouseButton;
|
||||
_mouseButton = readMouseState();
|
||||
}
|
||||
|
||||
uint16 DreamWebEngine::readMouseState() {
|
||||
_oldX = _mouseX;
|
||||
_oldY = _mouseY;
|
||||
uint16 x, y, state;
|
||||
mouseCall(&x, &y, &state);
|
||||
_mouseX = x;
|
||||
_mouseY = y;
|
||||
return state;
|
||||
}
|
||||
|
||||
void DreamWebEngine::dumpPointer() {
|
||||
dumpBlink();
|
||||
multiDump(_delHereX, _delHereY, _delXS, _delYS);
|
||||
if ((_oldPointerX != _delHereX) || (_oldPointerY != _delHereY))
|
||||
multiDump(_oldPointerX, _oldPointerY, _pointerXS, _pointerYS);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showPointer() {
|
||||
showBlink();
|
||||
uint16 x = _mouseX;
|
||||
_oldPointerX = _mouseX;
|
||||
uint16 y = _mouseY;
|
||||
_oldPointerY = _mouseY;
|
||||
if (_pickUp == 1) {
|
||||
const GraphicsFile *frames;
|
||||
if (_objectType != kExObjectType)
|
||||
frames = &_freeFrames;
|
||||
else
|
||||
frames = &_exFrames;
|
||||
const Frame *frame = &frames->_frames[(3 * _itemFrame + 1)];
|
||||
|
||||
uint8 width = MAX<uint8>(frame->width, 12);
|
||||
uint8 height = MAX<uint8>(frame->height, 12);
|
||||
_pointerXS = width;
|
||||
_pointerYS = height;
|
||||
uint16 xMin = (x >= width / 2) ? x - width / 2 : 0;
|
||||
uint16 yMin = (y >= height / 2) ? y - height / 2 : 0;
|
||||
_oldPointerX = xMin;
|
||||
_oldPointerY = yMin;
|
||||
multiGet(_pointerBack, xMin, yMin, width, height);
|
||||
showFrame(*frames, x, y, 3 * _itemFrame + 1, 128);
|
||||
showFrame(_icons1, x, y, 3, 128);
|
||||
} else {
|
||||
const Frame *frame = &_icons1._frames[_pointerFrame + 20];
|
||||
uint8 width = MAX<uint8>(frame->width, 12);
|
||||
uint8 height = MAX<uint8>(frame->height, 12);
|
||||
_pointerXS = width;
|
||||
_pointerYS = height;
|
||||
multiGet(_pointerBack, x, y, width, height);
|
||||
showFrame(_icons1, x, y, _pointerFrame + 20, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::delPointer() {
|
||||
if (_oldPointerX == 0xffff)
|
||||
return;
|
||||
_delHereX = _oldPointerX;
|
||||
_delHereY = _oldPointerY;
|
||||
_delXS = _pointerXS;
|
||||
_delYS = _pointerYS;
|
||||
multiPut(_pointerBack, _delHereX, _delHereY, _pointerXS, _pointerYS);
|
||||
}
|
||||
|
||||
void DreamWebEngine::animPointer() {
|
||||
if (_pointerMode == 2) {
|
||||
_pointerFrame = 0;
|
||||
if ((_realLocation == 14) && (_commandType == 211))
|
||||
_pointerFrame = 5;
|
||||
return;
|
||||
} else if (_pointerMode == 3) {
|
||||
if (_pointerSpeed != 0) {
|
||||
--_pointerSpeed;
|
||||
} else {
|
||||
_pointerSpeed = 5;
|
||||
++_pointerCount;
|
||||
if (_pointerCount == 16)
|
||||
_pointerCount = 0;
|
||||
}
|
||||
_pointerFrame = (_pointerCount <= 8) ? 1 : 2;
|
||||
return;
|
||||
}
|
||||
if (_vars._watchingTime != 0) {
|
||||
_pointerFrame = 11;
|
||||
return;
|
||||
}
|
||||
_pointerFrame = 0;
|
||||
if (_inMapArea == 0)
|
||||
return;
|
||||
if (_pointerFirstPath == 0)
|
||||
return;
|
||||
uint8 flag, flagEx;
|
||||
getFlagUnderP(&flag, &flagEx);
|
||||
if (flag < 2)
|
||||
return;
|
||||
if (flag >= 128)
|
||||
return;
|
||||
if (flag & 4) {
|
||||
_pointerFrame = 3;
|
||||
return;
|
||||
}
|
||||
if (flag & 16) {
|
||||
_pointerFrame = 4;
|
||||
return;
|
||||
}
|
||||
if (flag & 2) {
|
||||
_pointerFrame = 5;
|
||||
return;
|
||||
}
|
||||
if (flag & 8) {
|
||||
_pointerFrame = 6;
|
||||
return;
|
||||
}
|
||||
_pointerFrame = 8;
|
||||
}
|
||||
|
||||
void DreamWebEngine::checkCoords(const RectWithCallback *rectWithCallbacks) {
|
||||
if (_newLocation != 0xff)
|
||||
return;
|
||||
const RectWithCallback *r;
|
||||
for (r = rectWithCallbacks; r->_xMin != 0xffff; ++r) {
|
||||
if (r->contains(_mouseX, _mouseY)) {
|
||||
(this->*(r->_callback))();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
280
engines/dreamweb/newplace.cpp
Normal file
280
engines/dreamweb/newplace.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
/* 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 "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
|
||||
#include "common/text-to-speech.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
void DreamWebEngine::newPlace() {
|
||||
if (_vars._needToTravel == 1) {
|
||||
_vars._needToTravel = 0;
|
||||
selectLocation();
|
||||
} else if (_autoLocation != 0xFF) {
|
||||
_newLocation = _autoLocation;
|
||||
_autoLocation = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::selectLocation() {
|
||||
_inMapArea = 0;
|
||||
clearBeforeLoad();
|
||||
_getBack = 0;
|
||||
_pointerFrame = 22;
|
||||
readCityPic();
|
||||
showCity();
|
||||
_cityGraphics.clear();
|
||||
readDestIcon();
|
||||
loadTravelText();
|
||||
showPanel();
|
||||
showMan();
|
||||
showArrows();
|
||||
showExit();
|
||||
locationPic();
|
||||
underTextLine();
|
||||
_commandType = 255;
|
||||
readMouse();
|
||||
_pointerFrame = 0;
|
||||
showPointer();
|
||||
workToScreen();
|
||||
_sound->playChannel0(9, 255);
|
||||
_newLocation = 255;
|
||||
|
||||
while (_newLocation == 255) {
|
||||
if (_quitRequested)
|
||||
break;
|
||||
|
||||
delPointer();
|
||||
readMouse();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpTextLine();
|
||||
|
||||
if (_getBack == 1)
|
||||
break;
|
||||
|
||||
RectWithCallback destList[] = {
|
||||
{ 238,258,4,44,&DreamWebEngine::nextDest },
|
||||
{ 104,124,4,44,&DreamWebEngine::lastDest },
|
||||
{ 280,308,4,44,&DreamWebEngine::lookAtPlace },
|
||||
{ 104,216,138,192,&DreamWebEngine::destSelect },
|
||||
{ 273,320,157,198,&DreamWebEngine::getBack1 },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
checkCoords(destList);
|
||||
}
|
||||
|
||||
if (_quitRequested || _getBack == 1 || _newLocation == _vars._location) {
|
||||
_newLocation = _realLocation;
|
||||
_getBack = 0;
|
||||
}
|
||||
|
||||
_newplaceGraphics.clear();
|
||||
_newplaceGraphics2.clear();
|
||||
_newplaceGraphics3.clear();
|
||||
|
||||
_travelText.clear();
|
||||
}
|
||||
|
||||
void DreamWebEngine::showCity() {
|
||||
clearWork();
|
||||
showFrame(_cityGraphics, 57, 32, 0, 0);
|
||||
showFrame(_cityGraphics, 120+57, 32, 1, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::lookAtPlace() {
|
||||
commandOnlyCond(27, 224);
|
||||
|
||||
if (!(_mouseButton & 1) ||
|
||||
_mouseButton == _oldButton ||
|
||||
_destPos >= 15)
|
||||
return; // noinfo
|
||||
|
||||
delPointer();
|
||||
delTextLine();
|
||||
getUnderCenter();
|
||||
showFrame(_newplaceGraphics3, 60, 72, 0, 0);
|
||||
showFrame(_newplaceGraphics3, 60, 72 + 55, 4, 0);
|
||||
if (_foreignRelease)
|
||||
showFrame(_newplaceGraphics3, 60, 72+55+21, 4, 0);
|
||||
|
||||
const uint8 *string = (const uint8 *)_travelText.getString(_destPos);
|
||||
findNextColon(&string);
|
||||
|
||||
if (_ttsMan != nullptr && ConfMan.getBool("tts_enabled_objects"))
|
||||
_ttsMan->say((const char *)string, _textEncoding);
|
||||
|
||||
uint16 y = (_foreignRelease) ? 84 + 4 : 84;
|
||||
printDirect(&string, 63, &y, 191, 191 & 1);
|
||||
workToScreenM();
|
||||
hangOnP(500);
|
||||
_pointerMode = 0;
|
||||
_pointerFrame = 0;
|
||||
putUnderCenter();
|
||||
workToScreenM();
|
||||
}
|
||||
|
||||
void DreamWebEngine::getUnderCenter() {
|
||||
multiGet(_mapStore, 58, 72, 254, 110);
|
||||
}
|
||||
|
||||
void DreamWebEngine::putUnderCenter() {
|
||||
multiPut(_mapStore, 58, 72, 254, 110);
|
||||
}
|
||||
|
||||
void DreamWebEngine::locationPic() {
|
||||
const int roomPics[] = { 5, 0, 3, 2, 4, 1, 10, 9, 8, 6, 11, 4, 7, 7, 0, 0 };
|
||||
byte picture = roomPics[_destPos];
|
||||
|
||||
if (picture >= 6)
|
||||
showFrame(_newplaceGraphics2, 104, 138 + 14, picture - 6, 0); // Second slot
|
||||
else
|
||||
showFrame(_newplaceGraphics, 104, 138 + 14, picture + 4, 0);
|
||||
|
||||
if (_destPos == _realLocation)
|
||||
showFrame(_newplaceGraphics, 104, 140 + 14, 3, 0); // Currently in this location
|
||||
|
||||
const uint8 *string = (const uint8 *)_travelText.getString(_destPos);
|
||||
printDirect(string, 50, 20, 241, 241 & 1);
|
||||
|
||||
speakObject((const char *)string);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showArrows() {
|
||||
showFrame(_newplaceGraphics, 116 - 12, 16, 0, 0);
|
||||
showFrame(_newplaceGraphics, 226 + 12, 16, 1, 0);
|
||||
showFrame(_newplaceGraphics, 280, 14, 2, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::nextDest() {
|
||||
commandOnlyCond(28, 218);
|
||||
|
||||
if (!(_mouseButton & 1) || _oldButton == 1)
|
||||
return; // nodu
|
||||
|
||||
do {
|
||||
_destPos++;
|
||||
if (_destPos == 15)
|
||||
_destPos = 0; // last destination
|
||||
} while (!getLocation(_destPos));
|
||||
|
||||
_newTextLine = 1;
|
||||
delTextLine();
|
||||
delPointer();
|
||||
showPanel();
|
||||
showMan();
|
||||
showArrows();
|
||||
locationPic();
|
||||
underTextLine();
|
||||
readMouse();
|
||||
showPointer();
|
||||
workToScreen();
|
||||
delPointer();
|
||||
}
|
||||
|
||||
void DreamWebEngine::lastDest() {
|
||||
commandOnlyCond(29, 219);
|
||||
|
||||
if (!(_mouseButton & 1) || _oldButton == 1)
|
||||
return; // nodd
|
||||
|
||||
do {
|
||||
_destPos--;
|
||||
if (_destPos == 0xFF)
|
||||
_destPos = 15; // first destination
|
||||
} while (!getLocation(_destPos));
|
||||
|
||||
_newTextLine = 1;
|
||||
delTextLine();
|
||||
delPointer();
|
||||
showPanel();
|
||||
showMan();
|
||||
showArrows();
|
||||
locationPic();
|
||||
underTextLine();
|
||||
readMouse();
|
||||
showPointer();
|
||||
workToScreen();
|
||||
delPointer();
|
||||
}
|
||||
|
||||
void DreamWebEngine::destSelect() {
|
||||
commandOnlyCond(30, 222);
|
||||
|
||||
if (!(_mouseButton & 1) || _oldButton == 1)
|
||||
return; // notrav
|
||||
|
||||
_newLocation = _destPos;
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::getLocation(uint8 index) {
|
||||
return _roomsCanGo[index];
|
||||
}
|
||||
|
||||
void DreamWebEngine::setLocation(uint8 index) {
|
||||
_roomsCanGo[index] = 1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::clearLocation(uint8 index) {
|
||||
_roomsCanGo[index] = 0;
|
||||
}
|
||||
|
||||
void DreamWebEngine::resetLocation(uint8 index) {
|
||||
if (index == 5) {
|
||||
// delete hotel
|
||||
purgeALocation(5);
|
||||
purgeALocation(21);
|
||||
purgeALocation(22);
|
||||
purgeALocation(27);
|
||||
} else if (index == 8) {
|
||||
// delete TV studio
|
||||
purgeALocation(8);
|
||||
purgeALocation(28);
|
||||
} else if (index == 6) {
|
||||
// delete sarters
|
||||
purgeALocation(6);
|
||||
purgeALocation(20);
|
||||
purgeALocation(25);
|
||||
} else if (index == 13) {
|
||||
// delete boathouse
|
||||
purgeALocation(13);
|
||||
purgeALocation(29);
|
||||
}
|
||||
|
||||
clearLocation(index);
|
||||
}
|
||||
|
||||
void DreamWebEngine::readDestIcon() {
|
||||
loadGraphicsFile(_newplaceGraphics, "G05");
|
||||
loadGraphicsFile(_newplaceGraphics2, "G06");
|
||||
loadGraphicsFile(_newplaceGraphics3, "G08");
|
||||
}
|
||||
|
||||
void DreamWebEngine::readCityPic() {
|
||||
loadGraphicsFile(_cityGraphics, "G04");
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
1260
engines/dreamweb/object.cpp
Normal file
1260
engines/dreamweb/object.cpp
Normal file
File diff suppressed because it is too large
Load Diff
349
engines/dreamweb/pathfind.cpp
Normal file
349
engines/dreamweb/pathfind.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
/* 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 "dreamweb/dreamweb.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
void DreamWebEngine::turnPathOn(uint8 param) {
|
||||
findOrMake(param, 0xff, _roomNum + 100);
|
||||
PathNode *roomsPaths = getRoomsPaths()->nodes;
|
||||
if (param == 0xff)
|
||||
return;
|
||||
roomsPaths[param].on = 0xff;
|
||||
}
|
||||
|
||||
void DreamWebEngine::turnPathOff(uint8 param) {
|
||||
findOrMake(param, 0x00, _roomNum + 100);
|
||||
PathNode *roomsPaths = getRoomsPaths()->nodes;
|
||||
if (param == 0xff)
|
||||
return;
|
||||
roomsPaths[param].on = 0x00;
|
||||
}
|
||||
|
||||
void DreamWebEngine::turnAnyPathOn(uint8 param, uint8 room) {
|
||||
findOrMake(param, 0xff, room + 100);
|
||||
_pathData[room].nodes[param].on = 0xff;
|
||||
}
|
||||
|
||||
void DreamWebEngine::turnAnyPathOff(uint8 param, uint8 room) {
|
||||
findOrMake(param, 0x00, room + 100);
|
||||
_pathData[room].nodes[param].on = 0x00;
|
||||
}
|
||||
|
||||
RoomPaths *DreamWebEngine::getRoomsPaths() {
|
||||
return &_pathData[_roomNum];
|
||||
}
|
||||
|
||||
void DreamWebEngine::faceRightWay() {
|
||||
PathNode *paths = getRoomsPaths()->nodes;
|
||||
uint8 dir = paths[_mansPath].dir;
|
||||
_turnToFace = dir;
|
||||
_leaveDirection = dir;
|
||||
}
|
||||
|
||||
void DreamWebEngine::setWalk() {
|
||||
if (_linePointer != 254) {
|
||||
// Already walking
|
||||
_finalDest = _pointersPath;
|
||||
} else if (_pointersPath == _mansPath) {
|
||||
// Can't walk
|
||||
faceRightWay();
|
||||
} else if (_vars._watchMode == 1) {
|
||||
// Holding reel
|
||||
_vars._destAfterHold = _pointersPath;
|
||||
_vars._watchMode = 2;
|
||||
} else if (_vars._watchMode == 2) {
|
||||
// Can't walk
|
||||
} else {
|
||||
_destination = _pointersPath;
|
||||
_finalDest = _pointersPath;
|
||||
if (_mouseButton != 2 || _commandType == 3) {
|
||||
autoSetWalk();
|
||||
} else {
|
||||
_walkAndExam = 1;
|
||||
_walkExamType = _commandType;
|
||||
_walkExamNum = _command;
|
||||
autoSetWalk();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::autoSetWalk() {
|
||||
if (_finalDest == _mansPath)
|
||||
return;
|
||||
const RoomPaths *roomsPaths = getRoomsPaths();
|
||||
checkDest(roomsPaths);
|
||||
_lineStartX = roomsPaths->nodes[_mansPath].x - 12;
|
||||
_lineStartY = roomsPaths->nodes[_mansPath].y - 12;
|
||||
_lineEndX = roomsPaths->nodes[_destination].x - 12;
|
||||
_lineEndY = roomsPaths->nodes[_destination].y - 12;
|
||||
bresenhams();
|
||||
if (_lineDirection != 0) {
|
||||
_linePointer = _lineLength - 1;
|
||||
_lineDirection = 1;
|
||||
return;
|
||||
}
|
||||
_linePointer = 0;
|
||||
}
|
||||
|
||||
void DreamWebEngine::checkDest(const RoomPaths *roomsPaths) {
|
||||
const PathSegment *segments = roomsPaths->segments;
|
||||
const uint8 tmp = _mansPath << 4;
|
||||
uint8 destination = _destination;
|
||||
for (uint i = 0; i < 24; ++i) {
|
||||
if ((segments[i].b0 & 0xf0) == tmp &&
|
||||
(segments[i].b0 & 0x0f) == _destination) {
|
||||
_destination = segments[i].b1 & 0x0f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (((segments[i].b0 & 0x0f) << 4) == tmp &&
|
||||
((segments[i].b0 & 0xf0) >> 4) == _destination) {
|
||||
destination = segments[i].b1 & 0x0f;
|
||||
}
|
||||
}
|
||||
_destination = destination;
|
||||
}
|
||||
|
||||
void DreamWebEngine::findXYFromPath() {
|
||||
const PathNode *roomsPaths = getRoomsPaths()->nodes;
|
||||
_ryanX = roomsPaths[_mansPath].x - 12;
|
||||
_ryanY = roomsPaths[_mansPath].y - 12;
|
||||
}
|
||||
|
||||
bool DreamWebEngine::checkIfPathIsOn(uint8 index) {
|
||||
RoomPaths *roomsPaths = getRoomsPaths();
|
||||
uint8 pathOn = roomsPaths->nodes[index].on;
|
||||
return pathOn == 0xff;
|
||||
}
|
||||
|
||||
void DreamWebEngine::bresenhams() {
|
||||
workoutFrames();
|
||||
Common::Point *lineData = &_lineData[0];
|
||||
int16 startX = (int16)_lineStartX;
|
||||
int16 startY = (int16)_lineStartY;
|
||||
int16 endX = (int16)_lineEndX;
|
||||
int16 endY = (int16)_lineEndY;
|
||||
|
||||
if (endX == startX) {
|
||||
uint16 deltaY;
|
||||
int8 y;
|
||||
if (endY < startY) {
|
||||
deltaY = startY - endY;
|
||||
y = (int8)endY;
|
||||
_lineDirection = 1;
|
||||
} else {
|
||||
deltaY = endY - startY;
|
||||
y = (int8)startY;
|
||||
_lineDirection = 0;
|
||||
}
|
||||
++deltaY;
|
||||
int8 x = (int8)startX;
|
||||
_lineLength = deltaY;
|
||||
for (; deltaY; --deltaY) {
|
||||
lineData->x = x;
|
||||
lineData->y = y;
|
||||
++lineData;
|
||||
++y;
|
||||
}
|
||||
return;
|
||||
}
|
||||
uint16 deltaX;
|
||||
if (endX < startX) {
|
||||
deltaX = startX - endX;
|
||||
SWAP(startX, endX);
|
||||
SWAP(startY, endY);
|
||||
_lineStartX = (uint16)startX;
|
||||
_lineStartY = (uint16)startY;
|
||||
_lineEndX = (uint16)endX;
|
||||
_lineEndY = (uint16)endY;
|
||||
_lineDirection = 1;
|
||||
} else {
|
||||
deltaX = endX - startX;
|
||||
_lineDirection = 0;
|
||||
}
|
||||
|
||||
int16 increment;
|
||||
if (endY == startY) {
|
||||
int8 x = (int8)startX;
|
||||
int8 y = (int8)startY;
|
||||
++deltaX;
|
||||
_lineLength = deltaX;
|
||||
for (; deltaX; --deltaX) {
|
||||
lineData->x = x;
|
||||
lineData->y = y;
|
||||
++lineData;
|
||||
++x;
|
||||
}
|
||||
return;
|
||||
}
|
||||
uint16 deltaY;
|
||||
if (startY > endY) {
|
||||
deltaY = startY - endY;
|
||||
increment = -1;
|
||||
} else {
|
||||
deltaY = endY - startY;
|
||||
increment = 1;
|
||||
}
|
||||
|
||||
uint16 delta1, delta2;
|
||||
byte lineRoutine;
|
||||
|
||||
if (deltaY > deltaX) {
|
||||
lineRoutine = 1;
|
||||
delta1 = deltaY;
|
||||
delta2 = deltaX;
|
||||
} else {
|
||||
lineRoutine = 0;
|
||||
delta1 = deltaX;
|
||||
delta2 = deltaY;
|
||||
}
|
||||
|
||||
uint16 increment1 = delta2 * 2;
|
||||
uint16 increment2 = delta2 * 2 - delta1 * 2;
|
||||
int16 remainder = delta2 * 2 - delta1;
|
||||
++delta1;
|
||||
int8 x = (int8)startX;
|
||||
int8 y = (int8)startY;
|
||||
_lineLength = delta1;
|
||||
if (lineRoutine != 1) {
|
||||
for (; delta1; --delta1) {
|
||||
lineData->x = x;
|
||||
lineData->y = y;
|
||||
++lineData;
|
||||
++x;
|
||||
if (remainder < 0) {
|
||||
remainder += increment1;
|
||||
} else {
|
||||
remainder += increment2;
|
||||
y += increment;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (; delta1; --delta1) {
|
||||
lineData->x = x;
|
||||
lineData->y = y;
|
||||
++lineData;
|
||||
y += increment;
|
||||
if (remainder < 0) {
|
||||
remainder += increment1;
|
||||
} else {
|
||||
remainder += increment2;
|
||||
++x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::workoutFrames() {
|
||||
byte tmp;
|
||||
int diffx, diffy;
|
||||
|
||||
// We have to use signed arithmetic here because these values can
|
||||
// be slightly negative when walking off-screen
|
||||
int lineStartX = (int16)_lineStartX;
|
||||
int lineStartY = (int16)_lineStartY;
|
||||
int lineEndX = (int16)_lineEndX;
|
||||
int lineEndY = (int16)_lineEndY;
|
||||
|
||||
|
||||
diffx = ABS(lineStartX - lineEndX);
|
||||
diffy = ABS(lineStartY - lineEndY);
|
||||
|
||||
if (diffx < diffy) {
|
||||
tmp = 2;
|
||||
if (diffx >= (diffy >> 1))
|
||||
tmp = 1;
|
||||
} else {
|
||||
// tendstohoriz
|
||||
tmp = 0;
|
||||
if (diffy >= (diffx >> 1))
|
||||
tmp = 1;
|
||||
}
|
||||
|
||||
if (lineStartX >= lineEndX) {
|
||||
// isinleft
|
||||
if (lineStartY < lineEndY) {
|
||||
if (tmp != 1)
|
||||
tmp ^= 2;
|
||||
tmp += 4;
|
||||
} else {
|
||||
// topleft
|
||||
tmp += 6;
|
||||
}
|
||||
} else {
|
||||
// isinright
|
||||
if (lineStartY < lineEndY) {
|
||||
tmp += 2;
|
||||
} else {
|
||||
// botright
|
||||
if (tmp != 1)
|
||||
tmp ^= 2;
|
||||
}
|
||||
}
|
||||
|
||||
_turnToFace = tmp & 7;
|
||||
_turnDirection = 0;
|
||||
}
|
||||
|
||||
byte DreamWebEngine::findFirstPath(byte x, byte y) {
|
||||
PathNode *paths = _pathData[_roomNum].nodes;
|
||||
|
||||
for (uint8 index = 0; index < 12; index++) {
|
||||
if (paths[index].x1 == 0xff && paths[index].y1 == 0xff)
|
||||
continue; // "nofirst"
|
||||
|
||||
if (x < paths[index].x1 || y < paths[index].y1)
|
||||
continue; // "nofirst"
|
||||
|
||||
if (x >= paths[index].x2 || y >= paths[index].y2)
|
||||
continue; // "nofirst"
|
||||
|
||||
return paths[index].on; // "gotfirst"
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte DreamWebEngine::findPathOfPoint(byte x, byte y) {
|
||||
PathNode *paths = _pathData[_roomNum].nodes;
|
||||
|
||||
for (uint8 index = 0; index < 12; index++) {
|
||||
if (paths[index].on != 0xff)
|
||||
continue; // "flunkedit"
|
||||
|
||||
if (paths[index].x1 == 0xff && paths[index].y1 == 0xff)
|
||||
continue; // "flunkedit"
|
||||
|
||||
if (x < paths[index].x1 || y < paths[index].y1)
|
||||
continue; // "flunkedit"
|
||||
|
||||
if (x >= paths[index].x2 || y >= paths[index].y2)
|
||||
continue; // "flunkedit"
|
||||
|
||||
return index; // "gotvalidpath"
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
1123
engines/dreamweb/people.cpp
Normal file
1123
engines/dreamweb/people.cpp
Normal file
File diff suppressed because it is too large
Load Diff
348
engines/dreamweb/print.cpp
Normal file
348
engines/dreamweb/print.cpp
Normal file
@@ -0,0 +1,348 @@
|
||||
/* 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 "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
void DreamWebEngine::printBoth(const GraphicsFile &charSet, uint16 *x, uint16 y, uint8 c, uint8 nextChar) {
|
||||
uint16 newX = *x;
|
||||
uint8 width, height;
|
||||
printChar(charSet, &newX, y, c, nextChar, &width, &height);
|
||||
multiDump(*x, y, width, height);
|
||||
*x = newX;
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::getNextWord(const GraphicsFile &charSet, const uint8 *string, uint8 *totalWidth, uint8 *charCount) {
|
||||
*totalWidth = 0;
|
||||
*charCount = 0;
|
||||
while (true) {
|
||||
uint8 firstChar = *string;
|
||||
++string;
|
||||
++*charCount;
|
||||
if ((firstChar == ':') || (firstChar == 0)) { //endall
|
||||
*totalWidth += 6;
|
||||
return 1;
|
||||
}
|
||||
if (firstChar == 32) { //endword
|
||||
*totalWidth += 6;
|
||||
return 0;
|
||||
}
|
||||
firstChar = modifyChar(firstChar);
|
||||
// WORKAROUND: Also filter out invalid characters here (refer to the
|
||||
// workaround in printChar() below for more info).
|
||||
if (firstChar >= 32 && firstChar != 255) {
|
||||
uint8 secondChar = *string;
|
||||
uint8 width = charSet._frames[firstChar - 32 + _charShift].width;
|
||||
width = kernChars(firstChar, secondChar, width);
|
||||
*totalWidth += width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::printChar(const GraphicsFile &charSet, uint16* x, uint16 y, uint8 c, uint8 nextChar, uint8 *width, uint8 *height, bool kerning) {
|
||||
// WORKAROUND: Some texts contain leftover tab characters, which will cause
|
||||
// OOB memory access when showing a character, as all the printable ones are
|
||||
// from 32 onwards. We compensate for that here by ignoring all the invalid
|
||||
// characters (0 - 31).
|
||||
if (c < 32 || c == 255)
|
||||
return;
|
||||
|
||||
uint8 dummyWidth, dummyHeight;
|
||||
if (width == nullptr)
|
||||
width = &dummyWidth;
|
||||
if (height == nullptr)
|
||||
height = &dummyHeight;
|
||||
if (_foreignRelease)
|
||||
y -= 3;
|
||||
uint16 tmp = c - 32 + _charShift;
|
||||
showFrame(charSet, *x, y, tmp & 0x1ff, (tmp >> 8) & 0xfe, width, height);
|
||||
if (!kerning)
|
||||
*width = kernChars(c, nextChar, *width);
|
||||
(*x) += *width;
|
||||
}
|
||||
|
||||
void DreamWebEngine::printChar(const GraphicsFile &charSet, uint16 x, uint16 y, uint8 c, uint8 nextChar, uint8 *width, uint8 *height) {
|
||||
printChar(charSet, &x, y, c, nextChar, width, height);
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::printSlow(const uint8 *string, uint16 x, uint16 y, uint8 maxWidth, bool centered) {
|
||||
_pointerFrame = 1;
|
||||
_pointerMode = 3;
|
||||
do {
|
||||
uint16 offset = x;
|
||||
uint16 charCount = getNumber(_charset1, string, maxWidth, centered, &offset);
|
||||
do {
|
||||
uint8 c0 = string[0];
|
||||
uint8 c1 = string[1];
|
||||
uint8 c2 = string[2];
|
||||
c0 = modifyChar(c0);
|
||||
printBoth(_charset1, &offset, y, c0, c1);
|
||||
if ((c1 == 0) || (c1 == ':')) {
|
||||
return 0;
|
||||
}
|
||||
if (charCount != 1) {
|
||||
c1 = modifyChar(c1);
|
||||
_charShift = getLanguage() == Common::RU_RUS ? 182 : 91;
|
||||
uint16 offset2 = offset;
|
||||
printBoth(_charset1, &offset2, y, c1, c2);
|
||||
_charShift = 0;
|
||||
for (int i=0; i<2; ++i) {
|
||||
uint16 mouseState = waitFrames();
|
||||
if (_quitRequested)
|
||||
return 0;
|
||||
if (mouseState == 0)
|
||||
continue;
|
||||
if (mouseState != _oldButton) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++string;
|
||||
--charCount;
|
||||
} while (charCount);
|
||||
y += 10;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::printDirect(const uint8* string, uint16 x, uint16 y, uint8 maxWidth, bool centered) {
|
||||
return printDirect(&string, x, &y, maxWidth, centered);
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::printDirect(const uint8** string, uint16 x, uint16 *y, uint8 maxWidth, bool centered, bool kerning) {
|
||||
_lastXPos = x;
|
||||
const GraphicsFile &charSet = *_currentCharset;
|
||||
while (true) {
|
||||
uint16 offset = x;
|
||||
uint8 charCount = getNumber(charSet, *string, maxWidth, centered, &offset);
|
||||
uint16 i = offset;
|
||||
do {
|
||||
uint8 c = (*string)[0];
|
||||
++(*string);
|
||||
if ((c == 0) || (c == ':')) {
|
||||
return c;
|
||||
}
|
||||
uint8 nextChar = (*string)[0];
|
||||
c = modifyChar(c);
|
||||
uint8 width, height;
|
||||
printChar(charSet, &i, *y, c, nextChar, &width, &height);
|
||||
_lastXPos = i;
|
||||
--charCount;
|
||||
} while (charCount);
|
||||
*y += _lineSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::getNumber(const GraphicsFile &charSet, const uint8 *string, uint16 maxWidth, bool centered, uint16* offset) {
|
||||
uint8 totalWidth = 0;
|
||||
uint8 charCount = 0;
|
||||
while (true) {
|
||||
uint8 wordTotalWidth, wordCharCount;
|
||||
uint8 done = getNextWord(charSet, string, &wordTotalWidth, &wordCharCount);
|
||||
string += wordCharCount;
|
||||
|
||||
uint16 tmp = totalWidth + wordTotalWidth - 10;
|
||||
if (done == 1) { //endoftext
|
||||
if (tmp < maxWidth) {
|
||||
totalWidth += wordTotalWidth;
|
||||
charCount += wordCharCount;
|
||||
}
|
||||
|
||||
if (centered) {
|
||||
tmp = (maxWidth & 0xfe) + 2 + 20 - totalWidth;
|
||||
tmp /= 2;
|
||||
} else {
|
||||
tmp = 0;
|
||||
}
|
||||
*offset += tmp;
|
||||
return charCount;
|
||||
}
|
||||
if (tmp >= maxWidth) { //gotoverend
|
||||
if (centered) {
|
||||
tmp = (maxWidth & 0xfe) - totalWidth + 20;
|
||||
tmp /= 2;
|
||||
} else {
|
||||
tmp = 0;
|
||||
}
|
||||
*offset += tmp;
|
||||
return charCount;
|
||||
}
|
||||
totalWidth += wordTotalWidth;
|
||||
charCount += wordCharCount;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::kernChars(uint8 firstChar, uint8 secondChar, uint8 width) {
|
||||
if (getLanguage() == Common::RU_RUS) {
|
||||
if ((firstChar == 'a') || (firstChar == 'u') || (firstChar == 0xa0)
|
||||
|| (firstChar == 0xa8) || (firstChar == 0xa9) || (firstChar == 0xe9)) {
|
||||
if ((secondChar == 0xe2) || (secondChar == 'n') || (secondChar == 't') || (secondChar == 'r') || (secondChar == 'i') || (secondChar == 'l'))
|
||||
return width-1;
|
||||
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
if ((firstChar == 'a') || (firstChar == 'u')) {
|
||||
if ((secondChar == 'n') || (secondChar == 't') || (secondChar == 'r') || (secondChar == 'i') || (secondChar == 'l'))
|
||||
return width-1;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
uint16 DreamWebEngine::waitFrames() {
|
||||
readMouse();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
delPointer();
|
||||
return _mouseButton;
|
||||
}
|
||||
|
||||
const char *DreamWebEngine::monPrint(const char *string) {
|
||||
uint16 x = _monAdX;
|
||||
const char *iterator = string;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
|
||||
uint16 count = getNumber(_monitorCharset, (const uint8 *)iterator, 166, false, &x);
|
||||
do {
|
||||
char c = *iterator++;
|
||||
if (c == ':')
|
||||
break;
|
||||
if ((c == 0) || (c == '"') || (c == '=')) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if (c == '%') {
|
||||
_vars._lastTrigger = *iterator;
|
||||
iterator += 2;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
c = modifyChar(c);
|
||||
printChar(_monitorCharset, &x, _monAdY, c, 0, nullptr, nullptr, true);
|
||||
_cursLocX = x;
|
||||
_cursLocY = _monAdY;
|
||||
_mainTimer = 1;
|
||||
printCurs();
|
||||
waitForVSync();
|
||||
lockMon();
|
||||
delCurs();
|
||||
} while (--count);
|
||||
|
||||
x = _monAdX;
|
||||
scrollMonitor();
|
||||
_cursLocX = _monAdX;
|
||||
}
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
void DreamWebEngine::rollEndCreditsGameWon() {
|
||||
_sound->playChannel0(16, 255);
|
||||
_sound->volumeSet(7);
|
||||
_sound->volumeChange(0, -1);
|
||||
|
||||
multiGet(_mapStore, 75, 20, 160, 160);
|
||||
|
||||
const uint8 *string = getTextInFile1(3);
|
||||
const int linespacing = _lineSpacing;
|
||||
|
||||
for (int i = 0; i < 254; ++i) {
|
||||
// Output the text, initially with an offset of 10 pixels,
|
||||
// then move it up one pixel until we shifted it by a complete
|
||||
// line of text.
|
||||
for (int j = 0; j < linespacing; ++j) {
|
||||
waitForVSync();
|
||||
multiPut(_mapStore, 75, 20, 160, 160);
|
||||
waitForVSync();
|
||||
|
||||
// Output up to 18 lines of text
|
||||
uint16 y = 10 - j;
|
||||
const uint8 *tmp_str = string;
|
||||
for (int k = 0; k < 18; ++k) {
|
||||
printDirect(&tmp_str, 75, &y, 160 + 1, true);
|
||||
y += linespacing;
|
||||
}
|
||||
|
||||
waitForVSync();
|
||||
multiDump(75, 20, 160, 160);
|
||||
}
|
||||
|
||||
// Skip to the next text line
|
||||
byte c;
|
||||
do {
|
||||
c = *string++;
|
||||
} while (c != ':' && c != 0);
|
||||
}
|
||||
|
||||
hangOn(100);
|
||||
panelToMap();
|
||||
fadeScreenUpHalf();
|
||||
}
|
||||
|
||||
void DreamWebEngine::rollEndCreditsGameLost() {
|
||||
multiGet(_mapStore, 25, 20, 160, 160);
|
||||
|
||||
const uint8 *string = getTextInFile1(49);
|
||||
const int linespacing = _lineSpacing;
|
||||
|
||||
for (int i = 0; i < 80; ++i) {
|
||||
// Output the text, initially with an offset of 10 pixels,
|
||||
// then move it up one pixel until we shifted it by a complete
|
||||
// line of text.
|
||||
for (int j = 0; j < linespacing; ++j) {
|
||||
waitForVSync();
|
||||
multiPut(_mapStore, 25, 20, 160, 160);
|
||||
waitForVSync();
|
||||
|
||||
// Output up to 18 lines of text
|
||||
uint16 y = 10 - j;
|
||||
const uint8 *tmp_str = string;
|
||||
for (int k = 0; k < 18; ++k) {
|
||||
printDirect(&tmp_str, 25, &y, 160 + 1, true);
|
||||
y += linespacing;
|
||||
}
|
||||
|
||||
waitForVSync();
|
||||
multiDump(25, 20, 160, 160);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE)
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip to the next text line
|
||||
byte c;
|
||||
do {
|
||||
c = *string++;
|
||||
} while (c != ':' && c != 0);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE)
|
||||
return;
|
||||
}
|
||||
|
||||
hangOne(120);
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
191
engines/dreamweb/rain.cpp
Normal file
191
engines/dreamweb/rain.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/* 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 "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
void DreamWebEngine::showRain() {
|
||||
// Do nothing if there's no rain at all
|
||||
if (_rainList.empty())
|
||||
return;
|
||||
|
||||
const uint8 *frameData = _mainSprites.getFrameData(58);
|
||||
|
||||
for (auto &rain : _rainList) {
|
||||
uint16 y = rain.y + _mapAdY + _mapYStart;
|
||||
uint16 x = rain.x + _mapAdX + _mapXStart;
|
||||
uint16 size = rain.size;
|
||||
uint16 offset = (rain.w3 - rain.b5) & 511;
|
||||
rain.w3 = offset;
|
||||
const uint8 *src = frameData + offset;
|
||||
uint8 *dst = workspace() + y * kScreenwidth + x;
|
||||
for (uint16 j = 0; j < size; ++j) {
|
||||
uint8 v = src[j];
|
||||
if (v != 0)
|
||||
*dst = v;
|
||||
dst += kScreenwidth-1; // advance diagonally
|
||||
}
|
||||
}
|
||||
|
||||
if (_sound->isChannel1Playing())
|
||||
return;
|
||||
if (_realLocation == 2 && _vars._beenMugged != 1)
|
||||
return;
|
||||
if (_realLocation == 55)
|
||||
return;
|
||||
|
||||
if (randomNumber() >= 1) // play thunder with 1 in 256 chance
|
||||
return;
|
||||
|
||||
uint8 soundIndex;
|
||||
if (_sound->getChannel0Playing() != 6)
|
||||
soundIndex = 4;
|
||||
else
|
||||
soundIndex = 7;
|
||||
_sound->playChannel1(soundIndex);
|
||||
}
|
||||
|
||||
uint8 DreamWebEngine::getBlockOfPixel(uint8 x, uint8 y) {
|
||||
uint8 flag, flagEx, type, flagX, flagY;
|
||||
checkOne(x + _mapXStart, y + _mapYStart, &flag, &flagEx, &type, &flagX, &flagY);
|
||||
if (flag & 1)
|
||||
return 0;
|
||||
else
|
||||
return type;
|
||||
}
|
||||
|
||||
void DreamWebEngine::splitIntoLines(uint8 x, uint8 y) {
|
||||
do {
|
||||
Rain rain;
|
||||
|
||||
// Look for line start
|
||||
while (!getBlockOfPixel(x, y)) {
|
||||
--x;
|
||||
++y;
|
||||
if (x == 0 || y >= _mapYSize)
|
||||
return;
|
||||
}
|
||||
|
||||
rain.x = x;
|
||||
rain.y = y;
|
||||
|
||||
uint8 length = 1;
|
||||
|
||||
// Look for line end
|
||||
while (getBlockOfPixel(x, y)) {
|
||||
--x;
|
||||
++y;
|
||||
if (x == 0 || y >= _mapYSize)
|
||||
break;
|
||||
++length;
|
||||
}
|
||||
|
||||
rain.size = length;
|
||||
rain.w3 = _rnd.getRandomNumber(65535);
|
||||
rain.b5 = _rnd.getRandomNumberRng(4, 7);
|
||||
_rainList.push_back(rain);
|
||||
} while (x > 0 && y < _mapYSize);
|
||||
}
|
||||
|
||||
struct RainLocation {
|
||||
uint8 location;
|
||||
uint8 x, y;
|
||||
uint8 rainSpacing;
|
||||
};
|
||||
|
||||
static const RainLocation rainLocationList[] = {
|
||||
{ 1,44,10,16 },
|
||||
{ 4,11,30,14 },
|
||||
{ 4,22,30,14 },
|
||||
{ 3,33,10,14 },
|
||||
{ 10,33,30,14 },
|
||||
{ 10,22,30,24 },
|
||||
{ 9,22,10,14 },
|
||||
{ 2,33,0,14 },
|
||||
{ 2,22,0,14 },
|
||||
{ 6,11,30,14 },
|
||||
{ 7,11,20,18 },
|
||||
{ 7,0,20,18 },
|
||||
{ 7,0,30,18 },
|
||||
{ 55,44,0,14 },
|
||||
{ 5,22,30,14 },
|
||||
|
||||
{ 8,0,10,18 },
|
||||
{ 8,11,10,18 },
|
||||
{ 8,22,10,18 },
|
||||
{ 8,33,10,18 },
|
||||
{ 8,33,20,18 },
|
||||
{ 8,33,30,18 },
|
||||
{ 8,33,40,18 },
|
||||
{ 8,22,40,18 },
|
||||
{ 8,11,40,18 },
|
||||
|
||||
{ 21,44,20,18 },
|
||||
{ 255,0,0,0 }
|
||||
};
|
||||
|
||||
void DreamWebEngine::initRain() {
|
||||
const RainLocation *r = rainLocationList;
|
||||
_rainList.clear();
|
||||
|
||||
uint8 rainSpacing = 0;
|
||||
|
||||
// look up location in rainLocationList to determine rainSpacing
|
||||
for (r = rainLocationList; r->location != 0xff; ++r) {
|
||||
if (r->location == _realLocation &&
|
||||
r->x == _mapX && r->y == _mapY) {
|
||||
rainSpacing = r->rainSpacing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rainSpacing == 0) {
|
||||
// location not found in rainLocationList: no rain
|
||||
return;
|
||||
}
|
||||
|
||||
// start lines of rain from top of screen
|
||||
uint8 x = 4;
|
||||
do {
|
||||
uint8 delta = _rnd.getRandomNumberRng(3, rainSpacing - 1);
|
||||
x += delta;
|
||||
if (x >= _mapXSize)
|
||||
break;
|
||||
|
||||
splitIntoLines(x, 0);
|
||||
} while (true);
|
||||
|
||||
// start lines of rain from side of screen
|
||||
uint8 y = 0;
|
||||
do {
|
||||
uint8 delta = _rnd.getRandomNumberRng(3, rainSpacing - 1);
|
||||
y += delta;
|
||||
if (y >= _mapYSize)
|
||||
break;
|
||||
|
||||
splitIntoLines(_mapXSize - 1, y);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
|
||||
136
engines/dreamweb/rnca_archive.cpp
Normal file
136
engines/dreamweb/rnca_archive.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/* 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/array.h"
|
||||
#include "common/compression/deflate.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/ptr.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/compression/rnc_deco.h"
|
||||
#include "common/file.h"
|
||||
|
||||
#include "dreamweb/rnca_archive.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
RNCAArchive* RNCAArchive::open(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose) {
|
||||
FileMap files;
|
||||
|
||||
if (stream->readUint32BE() != 0x524e4341)
|
||||
return nullptr;
|
||||
|
||||
uint16 metadataSize1 = stream->readUint16BE();
|
||||
stream->readUint16BE(); // No idea
|
||||
uint16 metadataSize2 = stream->readUint16BE();
|
||||
stream->readByte(); // Always zero
|
||||
|
||||
if (metadataSize1 != metadataSize2 || metadataSize1 < 15)
|
||||
return nullptr;
|
||||
|
||||
int headerlessMetadataSize = metadataSize1 - 11;
|
||||
byte *metadata = new byte[headerlessMetadataSize];
|
||||
stream->read(metadata, headerlessMetadataSize);
|
||||
const byte *eptr = metadata;
|
||||
|
||||
while (eptr < metadata + headerlessMetadataSize - 5) {
|
||||
const byte *ptr = eptr;
|
||||
while (*ptr)
|
||||
ptr++;
|
||||
Common::String fileName((const char *) eptr, ptr - eptr);
|
||||
ptr++;
|
||||
uint32 off = READ_BE_UINT32(ptr);
|
||||
eptr = ptr + 4;
|
||||
files[Common::Path(fileName, Common::Path::kNoSeparator)] = RNCAFileDescriptor(fileName, off);
|
||||
}
|
||||
|
||||
delete[] metadata;
|
||||
|
||||
return new RNCAArchive(files, stream, dispose);
|
||||
}
|
||||
|
||||
bool RNCAArchive::hasFile(const Common::Path &path) const {
|
||||
return _files.contains(translatePath(path));
|
||||
}
|
||||
|
||||
int RNCAArchive::listMembers(Common::ArchiveMemberList &list) const {
|
||||
for (const auto &file : _files) {
|
||||
list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(file._key, *this)));
|
||||
}
|
||||
|
||||
return _files.size();
|
||||
}
|
||||
|
||||
const Common::ArchiveMemberPtr RNCAArchive::getMember(const Common::Path &path) const {
|
||||
Common::Path translated = translatePath(path);
|
||||
if (!_files.contains(translated))
|
||||
return nullptr;
|
||||
|
||||
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_files.getVal(translated)._fileName, *this));
|
||||
}
|
||||
|
||||
Common::SharedArchiveContents RNCAArchive::readContentsForPath(const Common::Path &translated) const {
|
||||
if (!_files.contains(translated))
|
||||
return Common::SharedArchiveContents();
|
||||
const RNCAFileDescriptor& desc = _files.getVal(translated);
|
||||
_stream->seek(desc._fileDataOffset);
|
||||
|
||||
if (_stream->readUint32BE() != Common::RncDecoder::kRnc1Signature) {
|
||||
return Common::SharedArchiveContents();
|
||||
}
|
||||
|
||||
// Read unpacked/packed file length
|
||||
uint32 unpackLen = _stream->readUint32BE();
|
||||
uint32 packLen = _stream->readUint32BE();
|
||||
|
||||
if (unpackLen > 0x7ffff000 || packLen > 0x7ffff000) {
|
||||
debug("Header error for %s", desc._fileName.c_str());
|
||||
return Common::SharedArchiveContents();
|
||||
}
|
||||
|
||||
// Rewind back the header
|
||||
_stream->seek(desc._fileDataOffset);
|
||||
packLen += 0x12;
|
||||
|
||||
byte *compressedBuffer = new byte[packLen];
|
||||
if (_stream->read(compressedBuffer, packLen) != packLen) {
|
||||
debug("Read error for %s", desc._fileName.c_str());
|
||||
return Common::SharedArchiveContents();
|
||||
}
|
||||
byte *uncompressedBuffer = new byte[unpackLen];
|
||||
|
||||
Common::RncDecoder rnc;
|
||||
|
||||
if (rnc.unpackM1(compressedBuffer, packLen, uncompressedBuffer) != (int32) unpackLen) {
|
||||
debug("Unpacking error for %s", desc._fileName.c_str());
|
||||
return Common::SharedArchiveContents();
|
||||
}
|
||||
|
||||
byte b = 0;
|
||||
for (byte *ptr = uncompressedBuffer; ptr < uncompressedBuffer + unpackLen; ptr++) {
|
||||
b += *ptr;
|
||||
*ptr = b;
|
||||
}
|
||||
|
||||
return Common::SharedArchiveContents(uncompressedBuffer, unpackLen);
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
66
engines/dreamweb/rnca_archive.h
Normal file
66
engines/dreamweb/rnca_archive.h
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DREAMWEB_RNCA_ARCHIVE_H
|
||||
#define DREAMWEB_RNCA_ARCHIVE_H
|
||||
|
||||
#include "common/archive.h"
|
||||
#include "common/ptr.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/hashmap.h"
|
||||
#include "common/hash-str.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
class RNCAArchive : public Common::MemcachingCaseInsensitiveArchive {
|
||||
public:
|
||||
bool hasFile(const Common::Path &path) const override;
|
||||
int listMembers(Common::ArchiveMemberList&) const override;
|
||||
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
|
||||
Common::SharedArchiveContents readContentsForPath(const Common::Path &translated) const override;
|
||||
|
||||
static RNCAArchive* open(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose = DisposeAfterUse::NO);
|
||||
|
||||
private:
|
||||
class RNCAFileDescriptor {
|
||||
private:
|
||||
Common::String _fileName;
|
||||
|
||||
// Offset of the file contents relative to the beginning of RNCA stream
|
||||
uint32 _fileDataOffset;
|
||||
|
||||
RNCAFileDescriptor(const Common::String& filename, uint32 off) : _fileName(filename), _fileDataOffset(off) {}
|
||||
friend class RNCAArchive;
|
||||
public:
|
||||
// It's public for hashmap
|
||||
RNCAFileDescriptor() : _fileDataOffset(0) {}
|
||||
};
|
||||
|
||||
typedef Common::HashMap<Common::Path, RNCAFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
|
||||
|
||||
RNCAArchive(FileMap files, Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose)
|
||||
: _files(files), _stream(stream, dispose) {
|
||||
}
|
||||
|
||||
FileMap _files;
|
||||
Common::DisposablePtr<Common::SeekableReadStream> _stream;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
925
engines/dreamweb/saveload.cpp
Normal file
925
engines/dreamweb/saveload.cpp
Normal file
@@ -0,0 +1,925 @@
|
||||
/* 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 "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
|
||||
#include "engines/metaengine.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
#include "gui/saveload.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/translation.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
// Temporary storage for loading the room from a savegame
|
||||
Room g_madeUpRoomDat;
|
||||
|
||||
|
||||
void syncReelRoutine(Common::Serializer &s, ReelRoutine *reel) {
|
||||
s.syncAsByte(reel->reallocation);
|
||||
s.syncAsByte(reel->mapX);
|
||||
s.syncAsByte(reel->mapY);
|
||||
s.syncAsUint16LE(reel->_reelPointer);
|
||||
s.syncAsByte(reel->period);
|
||||
s.syncAsByte(reel->counter);
|
||||
s.syncAsByte(reel->b7);
|
||||
}
|
||||
|
||||
void syncGameVars(Common::Serializer &s, GameVars &vars) {
|
||||
s.syncAsByte(vars._startVars);
|
||||
s.syncAsByte(vars._progressPoints);
|
||||
s.syncAsByte(vars._watchOn);
|
||||
s.syncAsByte(vars._shadesOn);
|
||||
s.syncAsByte(vars._secondCount);
|
||||
s.syncAsByte(vars._minuteCount);
|
||||
s.syncAsByte(vars._hourCount);
|
||||
s.syncAsByte(vars._zoomOn);
|
||||
s.syncAsByte(vars._location);
|
||||
s.syncAsByte(vars._exPos);
|
||||
s.syncAsUint16LE(vars._exFramePos);
|
||||
s.syncAsUint16LE(vars._exTextPos);
|
||||
s.syncAsUint16LE(vars._card1Money);
|
||||
s.syncAsUint16LE(vars._listPos);
|
||||
s.syncAsByte(vars._ryanPage);
|
||||
s.syncAsUint16LE(vars._watchingTime);
|
||||
s.syncAsUint16LE(vars._reelToWatch);
|
||||
s.syncAsUint16LE(vars._endWatchReel);
|
||||
s.syncAsByte(vars._speedCount);
|
||||
s.syncAsByte(vars._watchSpeed);
|
||||
s.syncAsUint16LE(vars._reelToHold);
|
||||
s.syncAsUint16LE(vars._endOfHoldReel);
|
||||
s.syncAsByte(vars._watchMode);
|
||||
s.syncAsByte(vars._destAfterHold);
|
||||
s.syncAsByte(vars._newsItem);
|
||||
s.syncAsByte(vars._liftFlag);
|
||||
s.syncAsByte(vars._liftPath);
|
||||
s.syncAsByte(vars._lockStatus);
|
||||
s.syncAsByte(vars._doorPath);
|
||||
s.syncAsByte(vars._countToOpen);
|
||||
s.syncAsByte(vars._countToClose);
|
||||
s.syncAsByte(vars._rockstarDead);
|
||||
s.syncAsByte(vars._generalDead);
|
||||
s.syncAsByte(vars._sartainDead);
|
||||
s.syncAsByte(vars._aideDead);
|
||||
s.syncAsByte(vars._beenMugged);
|
||||
s.syncAsByte(vars._gunPassFlag);
|
||||
s.syncAsByte(vars._canMoveAltar);
|
||||
s.syncAsByte(vars._talkedToAttendant);
|
||||
s.syncAsByte(vars._talkedToSparky);
|
||||
s.syncAsByte(vars._talkedToBoss);
|
||||
s.syncAsByte(vars._talkedToRecep);
|
||||
s.syncAsByte(vars._cardPassFlag);
|
||||
s.syncAsByte(vars._madmanFlag);
|
||||
s.syncAsByte(vars._keeperFlag);
|
||||
s.syncAsByte(vars._lastTrigger);
|
||||
s.syncAsByte(vars._manDead);
|
||||
s.syncAsByte(vars._seed1);
|
||||
s.syncAsByte(vars._seed2);
|
||||
s.syncAsByte(vars._seed3);
|
||||
s.syncAsByte(vars._needToTravel);
|
||||
s.syncAsByte(vars._throughDoor);
|
||||
s.syncAsByte(vars._newObs);
|
||||
s.syncAsByte(vars._ryanOn);
|
||||
s.syncAsByte(vars._combatCount);
|
||||
s.syncAsByte(vars._lastWeapon);
|
||||
s.syncAsByte(vars._dreamNumber);
|
||||
s.syncAsByte(vars._roomAfterDream);
|
||||
s.syncAsByte(vars._shakeCounter);
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadGame() {
|
||||
commandOnlyCond(41, 246);
|
||||
if (_mouseButton == _oldButton)
|
||||
return; // "noload"
|
||||
if (_mouseButton == 1)
|
||||
doLoad(-1);
|
||||
}
|
||||
|
||||
// if -1, open menu to ask for slot to load
|
||||
// if >= 0, directly load from that slot
|
||||
void DreamWebEngine::doLoad(int savegameId) {
|
||||
_loadingOrSave = 1;
|
||||
|
||||
if (ConfMan.getBool("originalsaveload") && savegameId == -1) {
|
||||
showOpBox();
|
||||
showLoadOps();
|
||||
_currentSlot = 0;
|
||||
showSlots();
|
||||
showNames();
|
||||
_pointerFrame = 0;
|
||||
workToScreenM();
|
||||
namesToOld();
|
||||
_getBack = 0;
|
||||
|
||||
while (_getBack == 0) {
|
||||
if (_quitRequested)
|
||||
return;
|
||||
delPointer();
|
||||
readMouse();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpTextLine();
|
||||
RectWithCallback loadlist[] = {
|
||||
{ kOpsx+176,kOpsx+192,kOpsy+60,kOpsy+76,&DreamWebEngine::getBackToOps },
|
||||
{ kOpsx+128,kOpsx+190,kOpsy+12,kOpsy+100,&DreamWebEngine::actualLoad },
|
||||
{ kOpsx+2,kOpsx+92,kOpsy+4,kOpsy+81,&DreamWebEngine::selectSlot },
|
||||
{ kOpsx+158,kOpsx+158+(18*3),kOpsy-17,kOpsy-1,&DreamWebEngine::selectSaveLoadPage },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
checkCoords(loadlist);
|
||||
if (_getBack == 2)
|
||||
return; // "quitloaded"
|
||||
}
|
||||
} else {
|
||||
|
||||
if (savegameId == -1) {
|
||||
// Wait till both mouse buttons are up. We should wait till the user
|
||||
// releases the mouse button, otherwise the follow-up mouseup event
|
||||
// will trigger a load of the save slot under the mouse cursor. Fixes
|
||||
// bug #6175.
|
||||
while (_oldMouseState > 0) {
|
||||
readMouse();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
|
||||
// Open dialog to get savegameId
|
||||
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
|
||||
savegameId = dialog->runModalWithCurrentTarget();
|
||||
delete dialog;
|
||||
}
|
||||
|
||||
if (savegameId < 0) {
|
||||
_getBack = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
loadPosition(savegameId);
|
||||
|
||||
_getBack = 1;
|
||||
}
|
||||
|
||||
// If we reach this point, loadPosition() has just been called.
|
||||
// Among other things, it will have filled g_MadeUpRoomDat.
|
||||
|
||||
_saveGraphics.clear();
|
||||
|
||||
startLoading(g_madeUpRoomDat);
|
||||
_sound->loadRoomsSample(_roomsSample);
|
||||
_roomLoaded = 1;
|
||||
_newLocation = 255;
|
||||
clearSprites();
|
||||
initMan();
|
||||
initRain();
|
||||
_textAddressX = 13;
|
||||
_textAddressY = 182;
|
||||
_textLen = 240;
|
||||
startup();
|
||||
workToScreen();
|
||||
_getBack = 4;
|
||||
}
|
||||
|
||||
|
||||
void DreamWebEngine::saveGame() {
|
||||
if (_vars._manDead == 2) {
|
||||
blank();
|
||||
return;
|
||||
}
|
||||
|
||||
commandOnlyCond(44, 247);
|
||||
if (_mouseButton != 1)
|
||||
return;
|
||||
|
||||
_loadingOrSave = 2;
|
||||
|
||||
if (ConfMan.getBool("originalsaveload")) {
|
||||
showOpBox();
|
||||
showSaveOps();
|
||||
_currentSlot = 0;
|
||||
showSlots();
|
||||
showNames();
|
||||
workToScreenM();
|
||||
namesToOld();
|
||||
_bufferIn = 0;
|
||||
_bufferOut = 0;
|
||||
_getBack = 0;
|
||||
|
||||
while (_getBack == 0) {
|
||||
if (_quitRequested)
|
||||
return;
|
||||
delPointer();
|
||||
checkInput();
|
||||
readMouse();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpTextLine();
|
||||
|
||||
RectWithCallback savelist[] = {
|
||||
{ kOpsx+176,kOpsx+192,kOpsy+60,kOpsy+76,&DreamWebEngine::getBackToOps },
|
||||
{ kOpsx+128,kOpsx+190,kOpsy+12,kOpsy+100,&DreamWebEngine::actualSave },
|
||||
{ kOpsx+2,kOpsx+92,kOpsy+4,kOpsy+81,&DreamWebEngine::selectSlot },
|
||||
{ kOpsx+158,kOpsx+158+(18*3),kOpsy-17,kOpsy-1,&DreamWebEngine::selectSaveLoadPage },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
checkCoords(savelist);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// Wait till both mouse buttons are up. We should wait till the user
|
||||
// releases the mouse button, otherwise the follow-up mouseup event
|
||||
// will trigger a save into the save slot under the mouse cursor. Fixes
|
||||
// bug #6175.
|
||||
while (_oldMouseState > 0) {
|
||||
readMouse();
|
||||
g_system->delayMillis(10);
|
||||
}
|
||||
|
||||
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
|
||||
int savegameId = dialog->runModalWithCurrentTarget();
|
||||
Common::String game_description = dialog->getResultString();
|
||||
if (game_description.empty())
|
||||
game_description = "Untitled";
|
||||
delete dialog;
|
||||
|
||||
if (savegameId < 0) {
|
||||
_getBack = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
char descbuf[17] = { 2, 0 };
|
||||
Common::strlcpy((char *)descbuf + 1, game_description.c_str(), 16);
|
||||
unsigned int desclen = game_description.size();
|
||||
if (desclen > 15)
|
||||
desclen = 15;
|
||||
// zero terminate, and pad with ones
|
||||
descbuf[++desclen] = 0;
|
||||
while (desclen < 16)
|
||||
descbuf[++desclen] = 1;
|
||||
|
||||
// TODO: The below is copied from actualsave
|
||||
_saveGraphics.clear();
|
||||
restoreAll(); // reels
|
||||
_textAddressX = 13;
|
||||
_textAddressY = 182;
|
||||
_textLen = 240;
|
||||
redrawMainScrn();
|
||||
workToScreen(); // show the main screen without the mouse pointer
|
||||
|
||||
// We need to save after the scene has been redrawn, to capture the
|
||||
// correct screen thumbnail
|
||||
savePosition(savegameId, descbuf);
|
||||
|
||||
workToScreenM();
|
||||
_getBack = 4;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::namesToOld() {
|
||||
memcpy(_saveNamesOld, _saveNames, 17*21);
|
||||
}
|
||||
|
||||
void DreamWebEngine::oldToNames() {
|
||||
memcpy(_saveNames, _saveNamesOld, 17*21);
|
||||
}
|
||||
|
||||
void DreamWebEngine::saveLoad() {
|
||||
if (ConfMan.getBool("originalsaveload"))
|
||||
createThumbnail(_thumbnail);
|
||||
if (_vars._watchingTime || (_pointerMode == 2)) {
|
||||
blank();
|
||||
return;
|
||||
}
|
||||
commandOnlyCond(43, 253);
|
||||
if ((_mouseButton != _oldButton) && (_mouseButton & 1))
|
||||
doSaveLoad();
|
||||
}
|
||||
|
||||
void DreamWebEngine::doSaveLoad() {
|
||||
_pointerFrame = 0;
|
||||
_textAddressX = 70;
|
||||
_textAddressY = 182-8;
|
||||
_textLen = 181;
|
||||
_manIsOffScreen = 1;
|
||||
clearWork();
|
||||
createPanel2();
|
||||
underTextLine();
|
||||
getRidOfAll();
|
||||
loadSaveBox();
|
||||
showOpBox();
|
||||
showMainOps();
|
||||
workToScreen();
|
||||
|
||||
RectWithCallback opsList[] = {
|
||||
{ kOpsx+59,kOpsx+114,kOpsy+30,kOpsy+76,&DreamWebEngine::getBackFromOps },
|
||||
{ kOpsx+10,kOpsx+77,kOpsy+10,kOpsy+59,&DreamWebEngine::DOSReturn },
|
||||
{ kOpsx+128,kOpsx+190,kOpsy+16,kOpsy+100,&DreamWebEngine::discOps },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
|
||||
bool firstOps = true;
|
||||
|
||||
do { // restart ops
|
||||
if (firstOps) {
|
||||
firstOps = false;
|
||||
} else {
|
||||
showOpBox();
|
||||
showMainOps();
|
||||
workToScreenM();
|
||||
}
|
||||
_getBack = 0;
|
||||
|
||||
do { // wait ops
|
||||
if (_quitRequested) {
|
||||
_manIsOffScreen = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
readMouse();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpTextLine();
|
||||
delPointer();
|
||||
checkCoords(opsList);
|
||||
} while (!_getBack);
|
||||
} while (_getBack == 2);
|
||||
|
||||
_textAddressX = 13;
|
||||
_textAddressY = 182;
|
||||
_textLen = 240;
|
||||
if (_getBack != 4) {
|
||||
_saveGraphics.clear();
|
||||
restoreAll();
|
||||
redrawMainScrn();
|
||||
workToScreenM();
|
||||
_commandType = 200;
|
||||
}
|
||||
_manIsOffScreen = 0;
|
||||
}
|
||||
|
||||
void DreamWebEngine::getBackFromOps() {
|
||||
if (_vars._manDead == 2)
|
||||
blank();
|
||||
else
|
||||
getBack1();
|
||||
}
|
||||
|
||||
void DreamWebEngine::getBackToOps() {
|
||||
commandOnlyCond(42, 201);
|
||||
|
||||
if (_mouseButton != _oldButton) {
|
||||
if (_mouseButton & 1) {
|
||||
oldToNames();
|
||||
_getBack = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::showMainOps() {
|
||||
showFrame(_saveGraphics, kOpsx+10, kOpsy+10, 8, 0);
|
||||
showFrame(_saveGraphics, kOpsx+59, kOpsy+30, 7, 0);
|
||||
showFrame(_saveGraphics, kOpsx+128+4, kOpsy+12, 1, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showDiscOps() {
|
||||
showFrame(_saveGraphics, kOpsx+128+4, kOpsy+12, 1, 0);
|
||||
showFrame(_saveGraphics, kOpsx+10, kOpsy+10, 9, 0);
|
||||
showFrame(_saveGraphics, kOpsx+59, kOpsy+30, 10, 0);
|
||||
showFrame(_saveGraphics, kOpsx+176+2, kOpsy+60-4, 5, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::discOps() {
|
||||
commandOnlyCond(43, 249);
|
||||
|
||||
if (_mouseButton == _oldButton || !(_mouseButton & 1))
|
||||
return;
|
||||
|
||||
scanForNames();
|
||||
_loadingOrSave = 2;
|
||||
showOpBox();
|
||||
showDiscOps();
|
||||
_currentSlot = 0;
|
||||
workToScreenM();
|
||||
_getBack = 0;
|
||||
|
||||
RectWithCallback discOpsList[] = {
|
||||
{ kOpsx+59,kOpsx+114,kOpsy+30,kOpsy+76,&DreamWebEngine::loadGame },
|
||||
{ kOpsx+10,kOpsx+79,kOpsy+10,kOpsy+59,&DreamWebEngine::saveGame },
|
||||
{ kOpsx+176,kOpsx+192,kOpsy+60,kOpsy+76,&DreamWebEngine::getBackToOps },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
|
||||
do {
|
||||
if (_quitRequested)
|
||||
return; // quitdiscops
|
||||
|
||||
delPointer();
|
||||
readMouse();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpTextLine();
|
||||
checkCoords(discOpsList);
|
||||
} while (!_getBack);
|
||||
}
|
||||
|
||||
void DreamWebEngine::actualSave() {
|
||||
commandOnlyCond(44, 222);
|
||||
|
||||
if (!(_mouseButton & 1))
|
||||
return;
|
||||
|
||||
unsigned int slot = _currentSlot + 7 * _saveLoadPage;
|
||||
|
||||
const char *desc = &_saveNames[17*slot];
|
||||
if (desc[1] == 0) // The actual description string starts at desc[1]
|
||||
return;
|
||||
|
||||
savePosition(slot, desc);
|
||||
|
||||
_saveGraphics.clear();
|
||||
restoreAll(); // reels
|
||||
_textAddressX = 13;
|
||||
_textAddressY = 182;
|
||||
_textLen = 240;
|
||||
redrawMainScrn();
|
||||
workToScreenM();
|
||||
_getBack = 4;
|
||||
}
|
||||
|
||||
void DreamWebEngine::actualLoad() {
|
||||
commandOnlyCond(41, 221);
|
||||
|
||||
if (_mouseButton == _oldButton || _mouseButton != 1)
|
||||
return;
|
||||
|
||||
unsigned int slot = _currentSlot + 7 * _saveLoadPage;
|
||||
|
||||
const char *desc = &_saveNames[17*slot];
|
||||
if (desc[1] == 0) // The actual description string starts at desc[1]
|
||||
return;
|
||||
|
||||
loadPosition(slot);
|
||||
_getBack = 1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::savePosition(unsigned int slot, const char *descbuf) {
|
||||
|
||||
const Room ¤tRoom = g_roomData[_vars._location];
|
||||
|
||||
Room madeUpRoom = currentRoom;
|
||||
madeUpRoom.roomsSample = _roomsSample;
|
||||
madeUpRoom.mapX = _mapX;
|
||||
madeUpRoom.mapY = _mapY;
|
||||
madeUpRoom.liftFlag = _vars._liftFlag;
|
||||
madeUpRoom.b21 = _mansPath;
|
||||
madeUpRoom.facing = _facing;
|
||||
madeUpRoom.b27 = 255;
|
||||
|
||||
Common::String filename = getSavegameFilename(slot);
|
||||
debug(1, "savePosition: slot %d filename %s", slot, filename.c_str());
|
||||
Common::OutSaveFile *outSaveFile = getSaveFileManager()->openForSaving(filename);
|
||||
if (!outSaveFile) // TODO: Do proper error handling!
|
||||
error("save could not be opened for writing");
|
||||
|
||||
// Initialize new header
|
||||
FileHeader header;
|
||||
|
||||
// Note: _desc is not zero-terminated
|
||||
const char *desc = "DREAMWEB DATA FILE COPYRIGHT 1992 CREATIVE REALITY";
|
||||
assert(strlen(desc) == sizeof(header._desc));
|
||||
memcpy(header._desc, desc, sizeof(header._desc));
|
||||
memset(&header._len[0], 0, sizeof(header._len));
|
||||
memset(&header._padding[0], 0, sizeof(header._padding));
|
||||
|
||||
// fill length fields in savegame file header
|
||||
uint16 len[6] = { 17, kLengthofvars, kLengthofextra,
|
||||
4*kNumChanges, 48, kNumReelRoutines*8+1 };
|
||||
for (int i = 0; i < 6; ++i)
|
||||
header.setLen(i, len[i]);
|
||||
|
||||
// Write a new section with data that we need for ScummVM (version,
|
||||
// thumbnail, played time etc). We don't really care for its size,
|
||||
// so we just set it to a magic number.
|
||||
header.setLen(6, SCUMMVM_BLOCK_MAGIC_SIZE);
|
||||
|
||||
outSaveFile->write((const uint8 *)&header, sizeof(FileHeader));
|
||||
outSaveFile->write(descbuf, len[0]);
|
||||
// TODO: Convert more to serializer?
|
||||
Common::Serializer s(nullptr, outSaveFile);
|
||||
syncGameVars(s, _vars);
|
||||
|
||||
// the Extras segment:
|
||||
outSaveFile->write((const uint8 *)_exFrames._frames, kFrameBlocksize);
|
||||
outSaveFile->write((const uint8 *)_exFrames._data, kExframeslen);
|
||||
outSaveFile->write((const uint8 *)_exData, sizeof(DynObject)*kNumexobjects);
|
||||
outSaveFile->write((const uint8 *)_exText._offsetsLE, 2*(kNumExObjects+2));
|
||||
outSaveFile->write((const uint8 *)_exText._text, kExtextlen);
|
||||
|
||||
outSaveFile->write(_listOfChanges, len[3]);
|
||||
|
||||
// len[4] == 48, which is sizeof(Room) plus 16 for 'Roomscango'
|
||||
outSaveFile->write((const uint8 *)&madeUpRoom, sizeof(Room));
|
||||
outSaveFile->write(_roomsCanGo, 16);
|
||||
|
||||
for (unsigned int i = 0; i < kNumReelRoutines; ++i) {
|
||||
syncReelRoutine(s, &_reelRoutines[i]);
|
||||
}
|
||||
// Terminator
|
||||
s.syncAsByte(_reelRoutines[kNumReelRoutines].reallocation);
|
||||
|
||||
// ScummVM data block
|
||||
outSaveFile->writeUint32BE(SCUMMVM_HEADER);
|
||||
outSaveFile->writeByte(SAVEGAME_VERSION);
|
||||
TimeDate curTime;
|
||||
g_system->getTimeAndDate(curTime);
|
||||
uint32 saveDate = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF);
|
||||
uint32 saveTime = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF);
|
||||
uint32 playTime = g_engine->getTotalPlayTime() / 1000;
|
||||
outSaveFile->writeUint32LE(saveDate);
|
||||
outSaveFile->writeUint32LE(saveTime);
|
||||
outSaveFile->writeUint32LE(playTime);
|
||||
|
||||
if (ConfMan.getBool("originalsaveload"))
|
||||
Graphics::saveThumbnail(*outSaveFile, _thumbnail);
|
||||
else
|
||||
Graphics::saveThumbnail(*outSaveFile);
|
||||
|
||||
outSaveFile->finalize();
|
||||
if (outSaveFile->err()) {
|
||||
// TODO: Do proper error handling
|
||||
warning("an error occurred while writing the savegame");
|
||||
}
|
||||
|
||||
delete outSaveFile;
|
||||
}
|
||||
|
||||
|
||||
// Utility struct for a savegame sanity check in loadPosition
|
||||
struct FrameExtent {
|
||||
uint16 start;
|
||||
uint16 length;
|
||||
bool operator<(const struct FrameExtent& other) const { return start<other.start; }
|
||||
};
|
||||
|
||||
void DreamWebEngine::loadPosition(unsigned int slot) {
|
||||
_timeCount = 0;
|
||||
clearChanges();
|
||||
|
||||
Common::String filename = getSavegameFilename(slot);
|
||||
debug(1, "loadPosition: slot %d filename %s", slot, filename.c_str());
|
||||
Common::InSaveFile *inSaveFile = getSaveFileManager()->openForLoading(filename);
|
||||
if (!inSaveFile) // TODO: Do proper error handling!
|
||||
error("save could not be opened for reading");
|
||||
|
||||
FileHeader header;
|
||||
|
||||
inSaveFile->read((uint8 *)&header, sizeof(FileHeader));
|
||||
|
||||
// read segment lengths from savegame file header
|
||||
int len[6];
|
||||
for (int i = 0; i < 6; ++i)
|
||||
len[i] = header.len(i);
|
||||
if (len[0] != 17)
|
||||
::error("Error loading save: description buffer isn't 17 bytes");
|
||||
|
||||
if (slot < 21) {
|
||||
inSaveFile->read(&_saveNames[17*slot], len[0]);
|
||||
} else {
|
||||
// The savenames buffer only has room for 21 descriptions
|
||||
uint8 namebuf[17];
|
||||
inSaveFile->read(namebuf, 17);
|
||||
}
|
||||
|
||||
// TODO: Use serializer for more?
|
||||
Common::Serializer s(inSaveFile, nullptr);
|
||||
syncGameVars(s, _vars);
|
||||
|
||||
// the Extras segment:
|
||||
inSaveFile->read((uint8 *)_exFrames._frames, kFrameBlocksize);
|
||||
inSaveFile->read((uint8 *)_exFrames._data, kExframeslen);
|
||||
inSaveFile->read((uint8 *)_exData, sizeof(DynObject)*kNumexobjects);
|
||||
inSaveFile->read((uint8 *)_exText._offsetsLE, 2*(kNumExObjects+2));
|
||||
inSaveFile->read((uint8 *)_exText._text, kExtextlen);
|
||||
|
||||
inSaveFile->read(_listOfChanges, len[3]);
|
||||
|
||||
// len[4] == 48, which is sizeof(Room) plus 16 for 'Roomscango'
|
||||
// Note: the values read into g_madeUpRoomDat are only used in actualLoad,
|
||||
// which is (almost) immediately called after this function
|
||||
inSaveFile->read((uint8 *)&g_madeUpRoomDat, sizeof(Room));
|
||||
inSaveFile->read(_roomsCanGo, 16);
|
||||
|
||||
for (unsigned int i = 0; i < kNumReelRoutines; ++i) {
|
||||
syncReelRoutine(s, &_reelRoutines[i]);
|
||||
}
|
||||
// Terminator
|
||||
s.syncAsByte(_reelRoutines[kNumReelRoutines].reallocation);
|
||||
|
||||
// Check if there's a ScummVM data block
|
||||
if (header.len(6) == SCUMMVM_BLOCK_MAGIC_SIZE) {
|
||||
uint32 tag = inSaveFile->readUint32BE();
|
||||
if (tag != SCUMMVM_HEADER) {
|
||||
warning("ScummVM data block found, but the block header is incorrect - skipping");
|
||||
delete inSaveFile;
|
||||
return;
|
||||
}
|
||||
|
||||
byte version = inSaveFile->readByte();
|
||||
if (version > SAVEGAME_VERSION) {
|
||||
warning("ScummVM data block found, but it has been saved with a newer version of ScummVM - skipping");
|
||||
delete inSaveFile;
|
||||
return;
|
||||
}
|
||||
|
||||
inSaveFile->skip(4); // saveDate
|
||||
inSaveFile->skip(4); // saveTime
|
||||
uint32 playTime = inSaveFile->readUint32LE();
|
||||
g_engine->setTotalPlayTime(playTime * 1000);
|
||||
|
||||
// The thumbnail data follows, but we don't need it here
|
||||
}
|
||||
|
||||
delete inSaveFile;
|
||||
|
||||
|
||||
// Do a sanity check on exFrames data to detect exFrames corruption
|
||||
// caused by a (now fixed) bug in emergencyPurge. See bug #6196.
|
||||
// Gather the location of frame data of all used ex object frames.
|
||||
Common::List<FrameExtent> flist;
|
||||
for (unsigned int i = 0; i < kNumexobjects; ++i) {
|
||||
if (_exData[i].mapad[0] != 0xff) {
|
||||
FrameExtent fe;
|
||||
Frame *frame = &_exFrames._frames[3*i+0];
|
||||
fe.start = frame->ptr();
|
||||
fe.length = frame->width * frame->height;
|
||||
flist.push_back(fe);
|
||||
|
||||
frame = &_exFrames._frames[3*i+1];
|
||||
fe.start = frame->ptr();
|
||||
fe.length = frame->width * frame->height;
|
||||
flist.push_back(fe);
|
||||
}
|
||||
}
|
||||
// ...and check if the frames overlap.
|
||||
Common::sort(flist.begin(), flist.end(), Common::Less<FrameExtent>());
|
||||
uint16 curEnd = 0;
|
||||
|
||||
for (auto &frame : flist) {
|
||||
if (frame.start < curEnd)
|
||||
error("exFrames data corruption in savegame");
|
||||
curEnd = frame.start + frame.length;
|
||||
}
|
||||
if (curEnd > _vars._exFramePos) {
|
||||
if (curEnd > kExframeslen)
|
||||
error("exFrames data corruption in savegame");
|
||||
warning("Fixing up exFramePos");
|
||||
_vars._exFramePos = curEnd;
|
||||
}
|
||||
// (end of sanity check)
|
||||
}
|
||||
|
||||
// Count number of save files, and load their descriptions into _saveNames
|
||||
uint DreamWebEngine::scanForNames() {
|
||||
// There are 21 save slots, each of which are 17 bytes. The first byte
|
||||
// doesn't seem to be used. The name starts at the second byte. All the
|
||||
// slots are initialized to be empty.
|
||||
for (unsigned int slot = 0; slot < 21; ++slot) {
|
||||
_saveNames[17 * slot + 0] = 2;
|
||||
_saveNames[17 * slot + 1] = 0;
|
||||
for (int i = 2; i < 17; ++i)
|
||||
_saveNames[17 * slot + i] = 1; // initialize with 1'sdrea
|
||||
}
|
||||
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Common::StringArray files = saveFileMan->listSavefiles("DREAMWEB.D??");
|
||||
Common::sort(files.begin(), files.end());
|
||||
|
||||
SaveStateList saveList;
|
||||
for (uint i = 0; i < files.size(); ++i) {
|
||||
const Common::String &file = files[i];
|
||||
Common::InSaveFile *stream = saveFileMan->openForLoading(file);
|
||||
if (!stream)
|
||||
error("cannot open save file %s", file.c_str());
|
||||
char name[17] = {};
|
||||
stream->seek(0x61);
|
||||
stream->read(name, sizeof(name) - 1);
|
||||
delete stream;
|
||||
|
||||
int slotNum = atoi(file.c_str() + file.size() - 2);
|
||||
SaveStateDescriptor sd(getMetaEngine(), slotNum, name);
|
||||
saveList.push_back(sd);
|
||||
if (slotNum < 21)
|
||||
Common::strlcpy(&_saveNames[17 * slotNum + 1], name, 16); // the first character is unused
|
||||
}
|
||||
|
||||
// FIXME: Can the following be safely removed?
|
||||
// al = saveList.size() <= 7 ? (uint8)saveList.size() : 7;
|
||||
|
||||
return saveList.size();
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadOld() {
|
||||
commandOnlyCond(48, 252);
|
||||
|
||||
if (!(_mouseButton & 1))
|
||||
return;
|
||||
|
||||
doLoad(-1);
|
||||
|
||||
if (_getBack == 4 || _quitRequested)
|
||||
return;
|
||||
|
||||
showDecisions();
|
||||
workToScreenM();
|
||||
_getBack = 0;
|
||||
}
|
||||
|
||||
void DreamWebEngine::showDecisions() {
|
||||
createPanel2();
|
||||
showOpBox();
|
||||
showFrame(_saveGraphics, kOpsx + 17, kOpsy + 13, 6, 0);
|
||||
underTextLine();
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadSaveBox() {
|
||||
loadGraphicsFile(_saveGraphics, "G08");
|
||||
}
|
||||
|
||||
// show savegame names (original interface), and set kCursorpos
|
||||
void DreamWebEngine::showNames() {
|
||||
unsigned int offset = 7 * _saveLoadPage;
|
||||
for (int slot = 0; slot < 7; ++slot) {
|
||||
// The first character of the savegame name is unused
|
||||
Common::String name(&_saveNames[17 * (slot + offset) + 1]);
|
||||
|
||||
if (slot != _currentSlot) {
|
||||
printDirect((const uint8 *)name.c_str(), kOpsx + 21, kOpsy + 10*slot + 10, 200, false);
|
||||
continue;
|
||||
}
|
||||
if (_loadingOrSave != 2) {
|
||||
_charShift = 91;
|
||||
|
||||
if (getLanguage() == Common::RU_RUS)
|
||||
_charShift = 182;
|
||||
|
||||
printDirect((const uint8 *)name.c_str(), kOpsx + 21, kOpsy + 10*slot + 10, 200, false);
|
||||
_charShift = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
int pos = name.size();
|
||||
_cursorPos = pos;
|
||||
name += '/'; // cursor character
|
||||
printDirect((const uint8 *)name.c_str(), kOpsx + 21, kOpsy + 10*slot + 10, 200, false);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::checkInput() {
|
||||
if (_loadingOrSave == 3)
|
||||
return;
|
||||
|
||||
readKey();
|
||||
|
||||
unsigned int slot = _currentSlot + 7 * _saveLoadPage;
|
||||
|
||||
// The first character of the savegame name is unused
|
||||
char *name = &_saveNames[17*slot + 1];
|
||||
|
||||
if (_currentKey == 0) {
|
||||
return;
|
||||
} else if (_currentKey == 13) {
|
||||
_loadingOrSave = 3;
|
||||
} else if (_currentKey == 8) {
|
||||
if (_cursorPos == 0)
|
||||
return;
|
||||
|
||||
--_cursorPos;
|
||||
name[_cursorPos] = 0;
|
||||
name[_cursorPos+1] = 1;
|
||||
} else {
|
||||
if (_cursorPos == 14)
|
||||
return;
|
||||
|
||||
name[_cursorPos] = _currentKey;
|
||||
name[_cursorPos+1] = 0;
|
||||
name[_cursorPos+2] = 1;
|
||||
++_cursorPos;
|
||||
}
|
||||
|
||||
showOpBox();
|
||||
showNames();
|
||||
showSlots();
|
||||
showSaveOps();
|
||||
workToScreenM();
|
||||
}
|
||||
|
||||
void DreamWebEngine::selectSaveLoadPage() {
|
||||
commandOnlyCond(31, 254);
|
||||
|
||||
if (_mouseButton != 1 || _mouseButton == _oldButton)
|
||||
return;
|
||||
uint saveLoadPage = (_mouseX - (kOpsx + 158)) / 18;
|
||||
if (saveLoadPage != _saveLoadPage) {
|
||||
_saveLoadPage = saveLoadPage;
|
||||
// This will also make the first slot the selected one, based
|
||||
// on the mouse Y position. I can't decide if this is a feature
|
||||
// or not.
|
||||
selectSlot();
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::selectSlot() {
|
||||
commandOnlyCond(45, 244);
|
||||
|
||||
if (_mouseButton != 1 || _mouseButton == _oldButton)
|
||||
return; // noselslot
|
||||
if (_loadingOrSave == 3)
|
||||
_loadingOrSave--;
|
||||
|
||||
oldToNames();
|
||||
int y = _mouseY - (kOpsy + 4);
|
||||
if (y < 11)
|
||||
_currentSlot = 0;
|
||||
else
|
||||
_currentSlot = y / 11;
|
||||
|
||||
delPointer();
|
||||
showOpBox();
|
||||
showSlots();
|
||||
showNames();
|
||||
if (_loadingOrSave == 1)
|
||||
showLoadOps();
|
||||
else
|
||||
showSaveOps();
|
||||
readMouse();
|
||||
showPointer();
|
||||
workToScreen();
|
||||
delPointer();
|
||||
}
|
||||
|
||||
void DreamWebEngine::showSlots() {
|
||||
showFrame(_icons1, kOpsx + 158, kOpsy - 11, 12, 0);
|
||||
showFrame(_icons1, kOpsx + 158 + 18 * _saveLoadPage, kOpsy - 11, 13 + _saveLoadPage, 0);
|
||||
showFrame(_saveGraphics, kOpsx + 7, kOpsy + 8, 2, 0);
|
||||
|
||||
uint16 y = kOpsy + 11;
|
||||
|
||||
for (int slot = 0; slot < 7; slot++) {
|
||||
if (slot == _currentSlot)
|
||||
showFrame(_saveGraphics, kOpsx + 10, y, 3, 0);
|
||||
|
||||
y += 10;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::showOpBox() {
|
||||
showFrame(_saveGraphics, kOpsx, kOpsy, 0, 0);
|
||||
|
||||
// This call displays half of the ops dialog in the CD version. It's not
|
||||
// in the floppy version, and if it's called, a stray red dot is shown in
|
||||
// the game dialogs. It is included in the early UK CD release, which had
|
||||
// similar data files as the floppy release (bug #6039).
|
||||
if (isCD() && getLanguage() != Common::EN_GRB)
|
||||
showFrame(_saveGraphics, kOpsx, kOpsy + 55, 4, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showLoadOps() {
|
||||
showFrame(_saveGraphics, kOpsx + 128 + 4, kOpsy + 12, 1, 0);
|
||||
showFrame(_saveGraphics, kOpsx + 176 + 2, kOpsy + 60 - 4, 5, 0);
|
||||
printMessage(kOpsx + 104, kOpsy + 14, 55, 101, (101 & 1));
|
||||
}
|
||||
|
||||
void DreamWebEngine::showSaveOps() {
|
||||
showFrame(_saveGraphics, kOpsx + 128 + 4, kOpsy + 12, 1, 0);
|
||||
showFrame(_saveGraphics, kOpsx + 176 + 2, kOpsy + 60 - 4, 5, 0);
|
||||
printMessage(kOpsx + 104, kOpsy + 14, 54, 101, (101 & 1));
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
276
engines/dreamweb/sound.cpp
Normal file
276
engines/dreamweb/sound.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "audio/decoders/raw.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
|
||||
#include "dreamweb/dreamweb.h"
|
||||
#include "dreamweb/sound.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
DreamWebSound::DreamWebSound(DreamWebEngine *vm) : _vm(vm) {
|
||||
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
|
||||
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
|
||||
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
|
||||
|
||||
_currentSample = 0xff;
|
||||
_channel0Playing = 255;
|
||||
_channel0Repeat = 0;
|
||||
_channel0NewSound = false;
|
||||
_channel1Playing = 255;
|
||||
_channel1NewSound = false;
|
||||
|
||||
_volume = 0;
|
||||
_volumeTo = 0;
|
||||
_volumeDirection = 0;
|
||||
_volumeCount = 0;
|
||||
}
|
||||
|
||||
DreamWebSound::~DreamWebSound() {
|
||||
}
|
||||
|
||||
bool DreamWebSound::loadSpeech(byte type1, int idx1, byte type2, int idx2) {
|
||||
cancelCh1();
|
||||
|
||||
Common::String name = Common::String::format("%c%02d%c%04d.RAW", type1, idx1, type2, idx2);
|
||||
debug(2, "loadSpeech() name:%s", name.c_str());
|
||||
return loadSpeech(name);
|
||||
}
|
||||
|
||||
void DreamWebSound::volumeChange(uint8 value, int8 direction) {
|
||||
_volumeTo = value;
|
||||
_volumeDirection = direction;
|
||||
}
|
||||
|
||||
void DreamWebSound::volumeAdjust() {
|
||||
if (_volumeDirection == 0)
|
||||
return;
|
||||
if (_volume != _volumeTo) {
|
||||
_volumeCount += 64;
|
||||
// Only modify the volume every 256/64 = 4th time around
|
||||
if (_volumeCount == 0)
|
||||
_volume += _volumeDirection;
|
||||
} else {
|
||||
_volumeDirection = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebSound::playChannel0(uint8 index, uint8 repeat) {
|
||||
debug(1, "playChannel0(index:%d, repeat:%d)", index, repeat);
|
||||
|
||||
_channel0Playing = index;
|
||||
_channel0Repeat = repeat;
|
||||
_channel0NewSound = true;
|
||||
}
|
||||
|
||||
void DreamWebSound::playChannel1(uint8 index) {
|
||||
debug(1, "playChannel1(index:%d)", index);
|
||||
if (_channel1Playing == 7)
|
||||
return;
|
||||
|
||||
_channel1Playing = index;
|
||||
_channel1NewSound = true;
|
||||
}
|
||||
|
||||
void DreamWebSound::cancelCh0() {
|
||||
debug(1, "cancelCh0()");
|
||||
_channel0Playing = 255;
|
||||
_channel0Repeat = 0;
|
||||
stopSound(0);
|
||||
}
|
||||
|
||||
void DreamWebSound::cancelCh1() {
|
||||
debug(1, "cancelCh1()");
|
||||
_channel1Playing = 255;
|
||||
stopSound(1);
|
||||
}
|
||||
|
||||
void DreamWebSound::loadRoomsSample(uint8 sample) {
|
||||
debug(1, "loadRoomsSample(sample:%d)", sample);
|
||||
|
||||
if (sample == 255 || _currentSample == sample)
|
||||
return; // loaded already
|
||||
|
||||
assert(sample < 100);
|
||||
Common::String sampleSuffix = Common::String::format("V%02d", sample);
|
||||
_currentSample = sample;
|
||||
|
||||
uint8 ch0 = _channel0Playing;
|
||||
if (ch0 >= 12 && ch0 != 255)
|
||||
cancelCh0();
|
||||
uint8 ch1 = _channel1Playing;
|
||||
if (ch1 >= 12)
|
||||
cancelCh1();
|
||||
loadSounds(1, sampleSuffix.c_str());
|
||||
}
|
||||
|
||||
void DreamWebSound::playSound(uint8 channel, uint8 id, uint8 loops) {
|
||||
debug(1, "playSound(channel:%u, id:%u, loops:%u)", channel, id, loops);
|
||||
|
||||
int bank = 0;
|
||||
bool speech = false;
|
||||
Audio::Mixer::SoundType type = channel == 0?
|
||||
Audio::Mixer::kMusicSoundType: Audio::Mixer::kSFXSoundType;
|
||||
|
||||
if (id >= 12) {
|
||||
id -= 12;
|
||||
bank = 1;
|
||||
if (id == 50) {
|
||||
speech = true;
|
||||
type = Audio::Mixer::kSpeechSoundType;
|
||||
}
|
||||
}
|
||||
const SoundData &data = _soundData[bank];
|
||||
|
||||
Audio::SeekableAudioStream *raw;
|
||||
if (!speech) {
|
||||
if (id >= data.samples.size() || data.samples[id].size == 0) {
|
||||
warning("invalid sample #%u played", id);
|
||||
return;
|
||||
}
|
||||
|
||||
const Sample &sample = data.samples[id];
|
||||
uint8 *buffer = (uint8 *)malloc(sample.size);
|
||||
if (!buffer)
|
||||
error("out of memory: cannot allocate memory for sound(%u bytes)", sample.size);
|
||||
memcpy(buffer, data.data.begin() + sample.offset, sample.size);
|
||||
|
||||
raw = Audio::makeRawStream(buffer, sample.size, 22050, Audio::FLAG_UNSIGNED);
|
||||
} else {
|
||||
uint8 *buffer = (uint8 *)malloc(_speechData.size());
|
||||
if (!buffer)
|
||||
error("out of memory: cannot allocate memory for sound(%u bytes)", _speechData.size());
|
||||
memcpy(buffer, _speechData.begin(), _speechData.size());
|
||||
raw = Audio::makeRawStream(buffer, _speechData.size(), 22050, Audio::FLAG_UNSIGNED);
|
||||
}
|
||||
|
||||
Audio::AudioStream *stream;
|
||||
if (loops > 1) {
|
||||
stream = new Audio::LoopingAudioStream(raw, (loops < 255) ? loops : 0);
|
||||
} else
|
||||
stream = raw;
|
||||
|
||||
if (_vm->_mixer->isSoundHandleActive(_channelHandle[channel]))
|
||||
_vm->_mixer->stopHandle(_channelHandle[channel]);
|
||||
_vm->_mixer->playStream(type, &_channelHandle[channel], stream);
|
||||
}
|
||||
|
||||
void DreamWebSound::stopSound(uint8 channel) {
|
||||
debug(1, "stopSound(%u)", channel);
|
||||
assert(channel == 0 || channel == 1);
|
||||
_vm->_mixer->stopHandle(_channelHandle[channel]);
|
||||
}
|
||||
|
||||
bool DreamWebSound::loadSpeech(const Common::String &filename) {
|
||||
if (ConfMan.getBool("tts_enabled_speech") || !_vm->hasSpeech())
|
||||
return false;
|
||||
|
||||
Common::File file;
|
||||
if (!file.open(_vm->getSpeechDirName().appendComponent(filename)))
|
||||
return false;
|
||||
|
||||
debug(1, "loadSpeech(%s)", filename.c_str());
|
||||
|
||||
uint size = file.size();
|
||||
_speechData.resize(size);
|
||||
file.read(_speechData.begin(), size);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DreamWebSound::soundHandler() {
|
||||
_vm->_subtitles = ConfMan.getBool("subtitles");
|
||||
volumeAdjust();
|
||||
|
||||
uint volume = _volume;
|
||||
//.vol file loaded into soundbuf:0x4000
|
||||
//volume table at (volume * 0x100 + 0x3f00)
|
||||
//volume value could be from 1 to 7
|
||||
//1 - 0x10-0xff
|
||||
//2 - 0x1f-0xdf
|
||||
//3 - 0x2f-0xd0
|
||||
//4 - 0x3e-0xc1
|
||||
//5 - 0x4d-0xb2
|
||||
//6 - 0x5d-0xa2
|
||||
//7 - 0x6f-0x91
|
||||
if (volume >= 8)
|
||||
volume = 7;
|
||||
volume = (8 - volume) * Audio::Mixer::kMaxChannelVolume / 8;
|
||||
_vm->_mixer->setChannelVolume(_channelHandle[0], volume);
|
||||
|
||||
if (_channel0NewSound) {
|
||||
_channel0NewSound = false;
|
||||
if (_channel0Playing != 255) {
|
||||
playSound(0, _channel0Playing, _channel0Repeat);
|
||||
}
|
||||
}
|
||||
if (_channel1NewSound) {
|
||||
_channel1NewSound = false;
|
||||
if (_channel1Playing != 255) {
|
||||
playSound(1, _channel1Playing, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_vm->_mixer->isSoundHandleActive(_channelHandle[0])) {
|
||||
_channel0Playing = 255;
|
||||
}
|
||||
if (!_vm->_mixer->isSoundHandleActive(_channelHandle[1])) {
|
||||
_channel1Playing = 255;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebSound::loadSounds(uint bank, const Common::String &suffix) {
|
||||
Common::Path filename(_vm->getDatafilePrefix() + suffix);
|
||||
debug(1, "loadSounds(%u, %s)", bank, filename.toString(Common::Path::kNativeSeparator).c_str());
|
||||
Common::File file;
|
||||
if (!file.open(filename)) {
|
||||
warning("cannot open %s", filename.toString(Common::Path::kNativeSeparator).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 header[96];
|
||||
file.read(header, sizeof(header));
|
||||
uint tablesize = READ_LE_UINT16(header + 50);
|
||||
debug(1, "table size = %u", tablesize);
|
||||
|
||||
SoundData &soundData = _soundData[bank];
|
||||
soundData.samples.resize(tablesize / 6);
|
||||
uint total = 0;
|
||||
for (uint i = 0; i < tablesize / 6; ++i) {
|
||||
uint8 entry[6];
|
||||
Sample &sample = soundData.samples[i];
|
||||
file.read(entry, sizeof(entry));
|
||||
sample.offset = entry[0] * 16384 + READ_LE_UINT16(entry + 1);
|
||||
sample.size = READ_LE_UINT16(entry + 3) * 2048;
|
||||
total += sample.size;
|
||||
debug(1, "offset: %08x, size: %u", sample.offset, sample.size);
|
||||
}
|
||||
soundData.data.resize(total);
|
||||
file.read(soundData.data.begin(), total);
|
||||
file.close();
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
90
engines/dreamweb/sound.h
Normal file
90
engines/dreamweb/sound.h
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DREAMWEB_SOUND_H
|
||||
#define DREAMWEB_SOUND_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/str.h"
|
||||
#include "audio/mixer.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
class DreamWebEngine;
|
||||
|
||||
class DreamWebSound {
|
||||
public:
|
||||
DreamWebSound(DreamWebEngine *vm);
|
||||
~DreamWebSound();
|
||||
|
||||
bool loadSpeech(byte type1, int idx1, byte type2, int idx2);
|
||||
void volumeSet(uint8 value) { _volume = value; }
|
||||
void volumeChange(uint8 value, int8 direction);
|
||||
void playChannel0(uint8 index, uint8 repeat);
|
||||
void playChannel1(uint8 index);
|
||||
uint8 getChannel0Playing() { return _channel0Playing; }
|
||||
bool isChannel1Playing() { return _channel1Playing != 255; }
|
||||
void cancelCh0();
|
||||
void cancelCh1();
|
||||
void loadRoomsSample(uint8 sample);
|
||||
void soundHandler();
|
||||
void loadSounds(uint bank, const Common::String &suffix);
|
||||
|
||||
private:
|
||||
DreamWebEngine *_vm;
|
||||
|
||||
struct Sample {
|
||||
uint offset;
|
||||
uint size;
|
||||
Sample(): offset(), size() {}
|
||||
};
|
||||
|
||||
struct SoundData {
|
||||
Common::Array<Sample> samples;
|
||||
Common::Array<uint8> data;
|
||||
};
|
||||
|
||||
SoundData _soundData[2];
|
||||
Common::Array<uint8> _speechData;
|
||||
|
||||
Audio::SoundHandle _channelHandle[2];
|
||||
|
||||
uint8 _currentSample;
|
||||
uint8 _channel0Playing;
|
||||
uint8 _channel0Repeat;
|
||||
bool _channel0NewSound;
|
||||
uint8 _channel1Playing;
|
||||
bool _channel1NewSound;
|
||||
|
||||
uint8 _volume;
|
||||
uint8 _volumeTo;
|
||||
int8 _volumeDirection;
|
||||
uint8 _volumeCount;
|
||||
|
||||
void volumeAdjust();
|
||||
void playSound(uint8 channel, uint8 id, uint8 loops);
|
||||
void stopSound(uint8 channel);
|
||||
bool loadSpeech(const Common::String &filename);
|
||||
};
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
|
||||
#endif
|
||||
1087
engines/dreamweb/sprite.cpp
Normal file
1087
engines/dreamweb/sprite.cpp
Normal file
File diff suppressed because it is too large
Load Diff
409
engines/dreamweb/structs.h
Normal file
409
engines/dreamweb/structs.h
Normal file
@@ -0,0 +1,409 @@
|
||||
/* 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 DREAMWEB_STRUCTS_H
|
||||
#define DREAMWEB_STRUCTS_H
|
||||
|
||||
#include "common/endian.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
struct GraphicsFile;
|
||||
struct SetObject;
|
||||
|
||||
struct Sprite {
|
||||
bool _mainManCallback;
|
||||
const GraphicsFile *_frameData;
|
||||
uint8 x;
|
||||
uint8 y;
|
||||
uint8 frameNumber;
|
||||
uint8 delay;
|
||||
uint8 animFrame; // index into SetObject::frames
|
||||
SetObject *_objData;
|
||||
uint8 speed;
|
||||
uint8 priority;
|
||||
uint8 walkFrame;
|
||||
uint8 type;
|
||||
uint8 hidden;
|
||||
};
|
||||
|
||||
struct RectWithCallback {
|
||||
uint16 _xMin, _xMax;
|
||||
uint16 _yMin, _yMax;
|
||||
void (DreamWebEngine::*_callback)();
|
||||
|
||||
bool contains(uint16 x, uint16 y) const {
|
||||
return (x >= _xMin) && (x < _xMax) && (y >= _yMin) && (y < _yMax);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
struct SetObject {
|
||||
uint8 b0;
|
||||
uint8 b1;
|
||||
uint8 b2;
|
||||
uint8 slotSize;
|
||||
uint8 slotCount;
|
||||
uint8 priority;
|
||||
uint8 b6;
|
||||
uint8 delay;
|
||||
uint8 type;
|
||||
uint8 b9;
|
||||
uint8 b10;
|
||||
uint8 b11;
|
||||
uint8 objId[4];
|
||||
uint8 b16;
|
||||
uint8 index;
|
||||
uint8 frames[40]; // Table mapping animFrame to sprite frame number
|
||||
uint8 mapad[5];
|
||||
uint8 b63;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct DynObject {
|
||||
uint8 currentLocation;
|
||||
uint8 index;
|
||||
uint8 mapad[5];
|
||||
uint8 slotSize; // the size of an object's slots
|
||||
uint8 slotCount; // the number of slots of an object
|
||||
uint8 objectSize; // the size of an object
|
||||
uint8 turnedOn;
|
||||
uint8 initialLocation;
|
||||
uint8 objId[4];
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ObjPos {
|
||||
uint8 xMin;
|
||||
uint8 yMin;
|
||||
uint8 xMax;
|
||||
uint8 yMax;
|
||||
uint8 index;
|
||||
bool contains(uint8 x, uint8 y) const {
|
||||
return (x >= xMin) && (x < xMax) && (y >= yMin) && (y < yMax);
|
||||
}
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct Frame {
|
||||
uint8 width;
|
||||
uint8 height;
|
||||
uint16 _ptr;
|
||||
uint16 ptr() const { return READ_LE_UINT16(&_ptr); }
|
||||
void setPtr(uint16 v) { WRITE_LE_UINT16(&_ptr, v); }
|
||||
uint8 x;
|
||||
uint8 y;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct Reel {
|
||||
uint8 frame_lo;
|
||||
uint8 frame_hi;
|
||||
uint16 frame() const { return READ_LE_UINT16(&frame_lo); }
|
||||
void setFrame(uint16 v) { WRITE_LE_UINT16(&frame_lo, v); }
|
||||
uint8 x;
|
||||
uint8 y;
|
||||
uint8 b4;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
|
||||
|
||||
struct ReelRoutine {
|
||||
uint8 reallocation;
|
||||
uint8 mapX;
|
||||
uint8 mapY;
|
||||
uint16 _reelPointer;
|
||||
uint16 reelPointer() const { return _reelPointer; }
|
||||
void setReelPointer(uint16 v) { _reelPointer = v; }
|
||||
void incReelPointer() { _reelPointer++; }
|
||||
uint8 period;
|
||||
uint8 counter;
|
||||
uint8 b7;
|
||||
};
|
||||
|
||||
struct People {
|
||||
uint16 _reelPointer;
|
||||
ReelRoutine *_routinePointer;
|
||||
uint8 b4;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
struct Room {
|
||||
char name[13];
|
||||
uint8 roomsSample;
|
||||
uint8 b14;
|
||||
uint8 mapX;
|
||||
uint8 mapY;
|
||||
uint8 b17;
|
||||
uint8 b18;
|
||||
uint8 b19;
|
||||
uint8 liftFlag;
|
||||
uint8 b21;
|
||||
uint8 facing;
|
||||
uint8 countToOpen;
|
||||
uint8 liftPath;
|
||||
uint8 doorPath;
|
||||
uint8 b26;
|
||||
uint8 b27;
|
||||
uint8 b28;
|
||||
uint8 b29;
|
||||
uint8 b30;
|
||||
uint8 realLocation;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
extern const Room g_roomData[];
|
||||
|
||||
struct Rain {
|
||||
uint8 x;
|
||||
uint8 y;
|
||||
uint8 size;
|
||||
uint16 w3;
|
||||
uint8 b5;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct Change {
|
||||
uint8 index;
|
||||
uint8 location;
|
||||
uint8 value;
|
||||
uint8 type;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct PathNode {
|
||||
uint8 x;
|
||||
uint8 y;
|
||||
uint8 x1;
|
||||
uint8 y1;
|
||||
uint8 x2;
|
||||
uint8 y2;
|
||||
uint8 on;
|
||||
uint8 dir;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct PathSegment {
|
||||
uint8 b0;
|
||||
uint8 b1;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct RoomPaths {
|
||||
PathNode nodes[12];
|
||||
PathSegment segments[24];
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct FileHeader {
|
||||
char _desc[50];
|
||||
uint16 _len[20];
|
||||
uint8 _padding[6];
|
||||
|
||||
uint16 len(unsigned int i) const {
|
||||
assert(i < 20);
|
||||
return READ_LE_UINT16(&_len[i]);
|
||||
}
|
||||
void setLen(unsigned int i, uint16 length) {
|
||||
assert(i < 20);
|
||||
WRITE_LE_UINT16(&_len[i], length);
|
||||
}
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct Atmosphere {
|
||||
uint8 _location;
|
||||
uint8 _mapX;
|
||||
uint8 _mapY;
|
||||
uint8 _sound;
|
||||
uint8 _repeat;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
|
||||
|
||||
enum ObjectTypes {
|
||||
kSetObjectType1 = 1,
|
||||
kFreeObjectType = 2,
|
||||
kSetObjectType3 = 3,
|
||||
kExObjectType = 4
|
||||
};
|
||||
|
||||
struct ObjectRef {
|
||||
uint8 _index;
|
||||
uint8 _type; // enum ObjectTypes
|
||||
|
||||
bool operator==(const ObjectRef &r) const {
|
||||
return _index == r._index && _type == r._type;
|
||||
}
|
||||
bool operator!=(const ObjectRef &r) const {
|
||||
return _index != r._index || _type != r._type;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
struct BackdropMapFlag {
|
||||
uint8 _flag;
|
||||
uint8 _flagEx;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct MapFlag {
|
||||
uint8 _flag;
|
||||
uint8 _flagEx;
|
||||
uint8 _type;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct TextFile {
|
||||
TextFile(unsigned int size = 66) : _size(size), _text(0) { _offsetsLE = new uint16[_size]; }
|
||||
|
||||
~TextFile() {
|
||||
delete[] _offsetsLE;
|
||||
_offsetsLE = 0;
|
||||
_size = 0;
|
||||
clear();
|
||||
}
|
||||
|
||||
uint16 *_offsetsLE;
|
||||
unsigned int _size;
|
||||
char *_text;
|
||||
|
||||
const char *getString(unsigned int i) const {
|
||||
assert(i < _size);
|
||||
return _text + getOffset(i);
|
||||
}
|
||||
void setOffset(unsigned int i, uint16 offset) {
|
||||
WRITE_LE_UINT16(&_offsetsLE[i], offset);
|
||||
}
|
||||
uint16 getOffset(unsigned int i) const {
|
||||
return READ_LE_UINT16(&_offsetsLE[i]);
|
||||
}
|
||||
void clear() {
|
||||
delete[] _text;
|
||||
_text = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct GraphicsFile {
|
||||
GraphicsFile() : _data(0), _frames(0) { }
|
||||
|
||||
Frame *_frames;
|
||||
uint8 *_data;
|
||||
|
||||
const uint8 *getFrameData(unsigned int i) const {
|
||||
// There is 2080 bytes of Frame data, but that is between 346 and 347
|
||||
// frames
|
||||
assert(i < 346);
|
||||
return _data + _frames[i].ptr();
|
||||
}
|
||||
void clear() {
|
||||
delete[] _frames;
|
||||
_frames = 0;
|
||||
delete[] _data;
|
||||
_data = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct GameVars {
|
||||
uint8 _startVars;
|
||||
uint8 _progressPoints;
|
||||
uint8 _watchOn;
|
||||
uint8 _shadesOn;
|
||||
uint8 _secondCount;
|
||||
uint8 _minuteCount;
|
||||
uint8 _hourCount;
|
||||
uint8 _zoomOn;
|
||||
uint8 _location;
|
||||
uint8 _exPos;
|
||||
uint16 _exFramePos;
|
||||
uint16 _exTextPos;
|
||||
uint16 _card1Money;
|
||||
uint16 _listPos;
|
||||
uint8 _ryanPage;
|
||||
uint16 _watchingTime;
|
||||
uint16 _reelToWatch; // reel plays from here in mode 0
|
||||
uint16 _endWatchReel; // and stops here. Mode set to 1
|
||||
uint8 _speedCount;
|
||||
uint8 _watchSpeed;
|
||||
uint16 _reelToHold; // if mode is 1 hold on this reel
|
||||
uint16 _endOfHoldReel; // if mode is 2 then play to endOfHoldReel and reset mode to -1
|
||||
uint8 _watchMode;
|
||||
uint8 _destAfterHold; // set walking destination
|
||||
uint8 _newsItem;
|
||||
uint8 _liftFlag;
|
||||
uint8 _liftPath;
|
||||
uint8 _lockStatus;
|
||||
uint8 _doorPath;
|
||||
uint8 _countToOpen;
|
||||
uint8 _countToClose;
|
||||
uint8 _rockstarDead;
|
||||
uint8 _generalDead;
|
||||
uint8 _sartainDead;
|
||||
uint8 _aideDead;
|
||||
uint8 _beenMugged;
|
||||
uint8 _gunPassFlag;
|
||||
uint8 _canMoveAltar;
|
||||
uint8 _talkedToAttendant;
|
||||
uint8 _talkedToSparky;
|
||||
uint8 _talkedToBoss;
|
||||
uint8 _talkedToRecep;
|
||||
uint8 _cardPassFlag;
|
||||
uint8 _madmanFlag;
|
||||
uint8 _keeperFlag;
|
||||
uint8 _lastTrigger;
|
||||
uint8 _manDead;
|
||||
uint8 _seed1;
|
||||
uint8 _seed2;
|
||||
uint8 _seed3;
|
||||
uint8 _needToTravel;
|
||||
uint8 _throughDoor;
|
||||
uint8 _newObs;
|
||||
uint8 _ryanOn;
|
||||
uint8 _combatCount;
|
||||
uint8 _lastWeapon;
|
||||
uint8 _dreamNumber;
|
||||
uint8 _roomAfterDream;
|
||||
uint8 _shakeCounter;
|
||||
};
|
||||
|
||||
struct TimedTemp {
|
||||
TimedTemp() : _timeCount(0), _string(0) { }
|
||||
|
||||
uint8 _x;
|
||||
uint8 _y;
|
||||
|
||||
uint16 _timeCount;
|
||||
uint16 _countToTimed;
|
||||
|
||||
const char *_string;
|
||||
};
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
|
||||
#endif
|
||||
|
||||
3012
engines/dreamweb/stubs.cpp
Normal file
3012
engines/dreamweb/stubs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
278
engines/dreamweb/talk.cpp
Normal file
278
engines/dreamweb/talk.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
/* 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 "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
#include "common/text-to-speech.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
void DreamWebEngine::talk() {
|
||||
_talkPos = 0;
|
||||
_inMapArea = 0;
|
||||
_character = _command;
|
||||
createPanel();
|
||||
showPanel();
|
||||
showMan();
|
||||
showExit();
|
||||
underTextLine();
|
||||
convIcons();
|
||||
startTalk();
|
||||
_commandType = 255;
|
||||
readMouse();
|
||||
showPointer();
|
||||
workToScreen();
|
||||
|
||||
RectWithCallback talkList[] = {
|
||||
{ 273,320,157,198,&DreamWebEngine::getBack1 },
|
||||
{ 240,290,2,44,&DreamWebEngine::moreTalk },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
|
||||
do {
|
||||
delPointer();
|
||||
readMouse();
|
||||
animPointer();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpTextLine();
|
||||
_getBack = 0;
|
||||
checkCoords(talkList);
|
||||
if (_quitRequested)
|
||||
break;
|
||||
} while (!_getBack);
|
||||
|
||||
if (_talkPos >= 4)
|
||||
_personData->b7 |= 128;
|
||||
|
||||
redrawMainScrn();
|
||||
workToScreenM();
|
||||
if (_speechLoaded) {
|
||||
_sound->cancelCh1();
|
||||
_sound->volumeChange(0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::convIcons() {
|
||||
uint8 index = _character & 127;
|
||||
uint16 frame = getPersFrame(index);
|
||||
const GraphicsFile *base = findSource(frame);
|
||||
showFrame(*base, 234, 2, frame, 0);
|
||||
}
|
||||
|
||||
uint16 DreamWebEngine::getPersFrame(uint8 index) {
|
||||
return READ_LE_UINT16(&_personFramesLE[index]);
|
||||
}
|
||||
|
||||
void DreamWebEngine::startTalk() {
|
||||
_talkMode = 0;
|
||||
|
||||
const uint8 *str = getPersonText(_character & 0x7F, 0);
|
||||
uint16 y;
|
||||
|
||||
_charShift = 91+91;
|
||||
|
||||
if (_ttsMan != nullptr && ConfMan.getBool("tts_enabled_speech")) {
|
||||
const char *text = (const char *)str;
|
||||
const char *goodText = strchr(text, ':') + 1;
|
||||
_ttsMan->say(goodText, _textEncoding);
|
||||
}
|
||||
|
||||
if (getLanguage() == Common::RU_RUS)
|
||||
useCharsetIcons1();
|
||||
|
||||
y = 64;
|
||||
printDirect(&str, 66, &y, 241, true);
|
||||
|
||||
if (getLanguage() == Common::RU_RUS)
|
||||
resetCharset();
|
||||
|
||||
_charShift = 0;
|
||||
y = 80;
|
||||
printDirect(&str, 66, &y, 241, true);
|
||||
|
||||
if (hasSpeech()) {
|
||||
_speechLoaded = _sound->loadSpeech('R', _realLocation, 'C', 64*(_character & 0x7F));
|
||||
if (_speechLoaded) {
|
||||
_sound->volumeChange(6, 1);
|
||||
_sound->playChannel1(62);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint8 *DreamWebEngine::getPersonText(uint8 index, uint8 talkPos) {
|
||||
const uint8 *text = (const uint8 *)_personText.getString(index*64 + talkPos);
|
||||
if (_ttsMan != nullptr && ConfMan.getBool("tts_enabled_speech"))
|
||||
_ttsMan->say((const char *)text, Common::TextToSpeechManager::INTERRUPT, _textEncoding);
|
||||
return text;
|
||||
}
|
||||
|
||||
void DreamWebEngine::moreTalk() {
|
||||
if (_talkMode != 0) {
|
||||
redes();
|
||||
return;
|
||||
}
|
||||
|
||||
commandOnlyCond(49, 215);
|
||||
|
||||
if (_mouseButton == _oldButton)
|
||||
return; // nomore
|
||||
|
||||
if (!(_mouseButton & 1))
|
||||
return;
|
||||
|
||||
_talkMode = 2;
|
||||
_talkPos = 4;
|
||||
|
||||
if (_character >= 100)
|
||||
_talkPos = 48; // second part
|
||||
doSomeTalk();
|
||||
}
|
||||
|
||||
void DreamWebEngine::doSomeTalk() {
|
||||
// FIXME: This is for the CD version only
|
||||
|
||||
while (true) {
|
||||
const uint8 *str = getPersonText(_character & 0x7F, _talkPos);
|
||||
|
||||
if (*str == 0) {
|
||||
// endheartalk
|
||||
_pointerMode = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
createPanel();
|
||||
showPanel();
|
||||
showMan();
|
||||
showExit();
|
||||
convIcons();
|
||||
|
||||
printDirect(str, 164, 64, 144, false);
|
||||
|
||||
_speechLoaded = _sound->loadSpeech('R', _realLocation, 'C', (64 * (_character & 0x7F)) + _talkPos);
|
||||
if (_speechLoaded)
|
||||
_sound->playChannel1(62);
|
||||
|
||||
_pointerMode = 3;
|
||||
workToScreenM();
|
||||
if (hangOnPQ())
|
||||
return;
|
||||
|
||||
_talkPos++;
|
||||
|
||||
str = getPersonText(_character & 0x7F, _talkPos);
|
||||
if (*str == 0) {
|
||||
// endheartalk
|
||||
_pointerMode = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (*str != ':' && *str != 32) {
|
||||
createPanel();
|
||||
showPanel();
|
||||
showMan();
|
||||
showExit();
|
||||
convIcons();
|
||||
printDirect(str, 48, 128, 144, false);
|
||||
|
||||
_speechLoaded = _sound->loadSpeech('R', _realLocation, 'C', (64 * (_character & 0x7F)) + _talkPos);
|
||||
if (_speechLoaded)
|
||||
_sound->playChannel1(62);
|
||||
|
||||
_pointerMode = 3;
|
||||
workToScreenM();
|
||||
if (hangOnPQ())
|
||||
return;
|
||||
}
|
||||
|
||||
_talkPos++;
|
||||
}
|
||||
}
|
||||
|
||||
bool DreamWebEngine::hangOnPQ() {
|
||||
_getBack = 0;
|
||||
|
||||
RectWithCallback quitList[] = {
|
||||
{ 273,320,157,198,&DreamWebEngine::getBack1 },
|
||||
{ 0,320,0,200,&DreamWebEngine::blank },
|
||||
{ 0xFFFF,0,0,0,nullptr }
|
||||
};
|
||||
|
||||
uint16 speechFlag = 0;
|
||||
|
||||
do {
|
||||
delPointer();
|
||||
readMouse();
|
||||
animPointer();
|
||||
showPointer();
|
||||
waitForVSync();
|
||||
dumpPointer();
|
||||
dumpTextLine();
|
||||
checkCoords(quitList);
|
||||
|
||||
if (_getBack == 1 || _quitRequested) {
|
||||
// Quit conversation
|
||||
delPointer();
|
||||
_pointerMode = 0;
|
||||
_sound->cancelCh1();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_speechLoaded && !_sound->isChannel1Playing()) {
|
||||
speechFlag++;
|
||||
if (speechFlag == 40)
|
||||
break;
|
||||
}
|
||||
} while (!_mouseButton || _oldButton);
|
||||
|
||||
delPointer();
|
||||
_pointerMode = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void DreamWebEngine::redes() {
|
||||
if (_sound->isChannel1Playing() || _talkMode != 2) {
|
||||
blank();
|
||||
return;
|
||||
}
|
||||
|
||||
commandOnlyCond(50, 217);
|
||||
|
||||
if (!(_mouseButton & 1))
|
||||
return;
|
||||
|
||||
delPointer();
|
||||
createPanel();
|
||||
showPanel();
|
||||
showMan();
|
||||
showExit();
|
||||
convIcons();
|
||||
startTalk();
|
||||
readMouse();
|
||||
showPointer();
|
||||
workToScreen();
|
||||
delPointer();
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
510
engines/dreamweb/titles.cpp
Normal file
510
engines/dreamweb/titles.cpp
Normal file
@@ -0,0 +1,510 @@
|
||||
/* 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 "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
#include "engines/util.h"
|
||||
#include "common/text-to-speech.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
namespace {
|
||||
void initTitlesGfx() {
|
||||
Graphics::ModeWithFormatList modes = {
|
||||
// First try for a 640x480 mode
|
||||
Graphics::ModeWithFormat(640, 480, Graphics::PixelFormat::createFormatCLUT8()),
|
||||
// System doesn't support it, so fall back on 320x240 mode
|
||||
Graphics::ModeWithFormat(320, 240, Graphics::PixelFormat::createFormatCLUT8()),
|
||||
};
|
||||
|
||||
initGraphicsAny(modes);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::endGame() {
|
||||
loadTempText("T83");
|
||||
monkSpeaking();
|
||||
if (_quitRequested)
|
||||
return;
|
||||
gettingShot();
|
||||
getRidOfTempText();
|
||||
_sound->volumeChange(7, 1);
|
||||
hangOn(200);
|
||||
}
|
||||
|
||||
void DreamWebEngine::monkSpeaking() {
|
||||
_roomsSample = 35;
|
||||
_sound->loadRoomsSample(_roomsSample);
|
||||
GraphicsFile graphics;
|
||||
loadGraphicsFile(graphics, "G15");
|
||||
clearWork();
|
||||
showFrame(graphics, 160, 72, 0, 128); // show monk
|
||||
workToScreen();
|
||||
_sound->volumeSet(7);
|
||||
_sound->volumeChange(hasSpeech() ? 5 : 0, -1);
|
||||
_sound->playChannel0(12, 255);
|
||||
fadeScreenUps();
|
||||
hangOn(300);
|
||||
|
||||
// TODO: Subtitles+speech mode
|
||||
if (hasSpeech()) {
|
||||
for (int i = 40; i < 48; i++) {
|
||||
_speechLoaded = _sound->loadSpeech('T', 83, 'T', i);
|
||||
|
||||
_sound->playChannel1(62);
|
||||
|
||||
do {
|
||||
waitForVSync();
|
||||
if (_quitRequested)
|
||||
return;
|
||||
} while (_sound->isChannel1Playing());
|
||||
}
|
||||
} else {
|
||||
for (int i = 40; i <= 44; i++) {
|
||||
uint8 printResult = 0;
|
||||
const uint8 *string = getTextInFile1(i);
|
||||
|
||||
do {
|
||||
uint16 y = 140;
|
||||
printResult = printDirect(&string, 36, &y, 239, 239 & 1);
|
||||
workToScreen();
|
||||
clearWork();
|
||||
showFrame(graphics, 160, 72, 0, 128); // show monk
|
||||
hangOnP(240);
|
||||
if (_quitRequested)
|
||||
return;
|
||||
} while (printResult != 0);
|
||||
}
|
||||
}
|
||||
|
||||
_sound->volumeChange(7, 1);
|
||||
fadeScreenDowns();
|
||||
hangOn(300);
|
||||
graphics.clear();
|
||||
}
|
||||
|
||||
void DreamWebEngine::gettingShot() {
|
||||
_newLocation = 55;
|
||||
clearPalette();
|
||||
loadIntroRoom();
|
||||
fadeScreenUps();
|
||||
_sound->volumeChange(0, -1);
|
||||
runEndSeq();
|
||||
clearBeforeLoad();
|
||||
}
|
||||
|
||||
void DreamWebEngine::bibleQuote() {
|
||||
const char *enStory = "And I heard a great voice out of the temple saying to the seven angels, "
|
||||
"Go your ways and pour out the vails of the wrath of god upon the earth. "
|
||||
"Book of revelation Chapter 16 verse 1.";
|
||||
const char *frStory = "Puis j'entendis une voix forte qui venait du temple et disait aux sept anges: "
|
||||
"Allez verser sur la terre les sept coupes de la col\xC3\xA8re de Dieu. "
|
||||
"L'Apocalypse, chapitre 16, verset 1";
|
||||
const char *esStory = "O\xC3\xAD una gran voz que dec\xC3\xAD""a"" desde el templo a los siete \xC3\xA1ngeles: "
|
||||
"Id y derramad sobre la tierra las siete copas de la ira de Dios. "
|
||||
"Apocalipsis, cap\xC3\xADtulo 16, vers\xC3\xAD""culo"" primero.";
|
||||
const char *deStory = "Dann h\xC3\xB6rte ich, wie eine laute Stimme aus dem Tempel den sieben Engeln zurief: "
|
||||
"Geht und gie\xC3\x9Ft die sieben Schalen mit dem Zorn Gottes \xC3\xBC""ber"" die Erde. "
|
||||
"Offenbarung des Johannes. Kapitel 16 Vers 1";
|
||||
const char *itStory = "Udii poi una gran voce dal tempio che diceva ai sette angeli: "
|
||||
"Andate e versate sulla terra le sette coppe dell'ira di Dio. "
|
||||
"Dal libro dell'Apocalisse, capitolo uno, primo versetto";
|
||||
const char *ruStory = "\xD1\x83\xD1\x81\xD0\xBB\xD1\x8B\xD1\x88\xD0\xB0\xD0\xBB \xD1\x8F \xD0\xB8\xD0\xB7 \xD1\x85\xD1\x80\xD0\xB0\xD0\xBC\xD0\xB0 \xD1\x80\xD1\x8F\xD1\x89\xD0\xB8\xD0\xB9 \xD1\x81\xD0\xB5\xD0\xBC\xD0\xB8 \xD0\x90\xD0\xBD\xD0\xB3\xD0\xB5\xD0\xBB\xD0\xB0\xD0\xBC\x3A: "
|
||||
"\xD0\xB8\xD0\xB4\xD0\xB8\xD1\x82\xD0\xB5 \xD0\xB8 \xD0\xB2\xD1\x8B\xD0\xBB\xD0\xB5\xD0\xB9\xD1\x82\xD0\xB5 \xD1\x81\xD0\xB5\xD0\xBC\xD1\x8C \xD1\x87\xD0\xB0\xD1\x88 \xD0\xB3\xD0\xBD\xD0\xB5\xD0\xB2\xD0\xB0 \xD0\x91\xD0\xBE\xD0\xB6\xD0\xB8\xD1\x8F \xD0\xBD\xD0\xB0 \xD0\xB7\xD0\xB5\xD0\xBC\xD0\xBB\xD1\x8E\x2E. "
|
||||
"\xD0\x9E\xD0\xA2\xD0\x9A\xD0\xA0\xD0\x9E\xD0\x92\xD0\x95\xD0\x9D\xD0\x98\xD0\x95 \xD0\x98\xD0\x9E\xD0\x90\xD0\x9D\xD0\x9D\xD0\x90 \xD0\x91\xD0\x9E\xD0\x93\xD0\x9E\xD0\xA1\xD0\x9B\xD0\x9E\xD0\x92\xD0\x90 16:1";
|
||||
const char *csStory = "Tu jsem usly\xC5\xA1""el"" mocn\xC3\xBD hlas ze svatyn\xC4\x9B, kter\xC3\xBD t\xC4\x9Bm sedmi and\xC4\x9Bl\xC5\xAFm \xC5\x99\xC3\xADkal: "
|
||||
"Jd\xC4\x9Bte a vylejte t\xC4\x9B""ch"" sedm misek Bo\xC5\xBE\xC3\xADho hn\xC4\x9Bvu na zem. "
|
||||
"Zjeven\xC3\xAD 16 ver\xC5\xA1 1";
|
||||
|
||||
|
||||
const char *theStory;
|
||||
switch(getLanguage()) {
|
||||
case Common::ES_ESP:
|
||||
theStory = esStory;
|
||||
break;
|
||||
case Common::FR_FRA:
|
||||
theStory = frStory;
|
||||
break;
|
||||
case Common::IT_ITA:
|
||||
theStory = itStory;
|
||||
break;
|
||||
case Common::DE_DEU:
|
||||
theStory = deStory;
|
||||
break;
|
||||
case Common::RU_RUS:
|
||||
theStory = ruStory;
|
||||
break;
|
||||
case Common::CS_CZE:
|
||||
theStory = csStory;
|
||||
break;
|
||||
default:
|
||||
theStory = enStory;
|
||||
break;
|
||||
}
|
||||
|
||||
initTitlesGfx();
|
||||
|
||||
showPCX("I00");
|
||||
fadeScreenUps();
|
||||
|
||||
hangOne(80);
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "biblequotearly"
|
||||
}
|
||||
|
||||
if (_ttsMan != nullptr && ConfMan.getBool("tts_enabled_objects")) {
|
||||
_ttsMan->say(theStory);
|
||||
while (_ttsMan->isSpeaking() && _lastHardKey != Common::KEYCODE_ESCAPE)
|
||||
hangOne(1);
|
||||
_ttsMan->stop();
|
||||
|
||||
} else
|
||||
hangOne(560);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "biblequotearly"
|
||||
}
|
||||
|
||||
fadeScreenDowns();
|
||||
|
||||
hangOne(200);
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "biblequotearly"
|
||||
}
|
||||
|
||||
_sound->cancelCh0();
|
||||
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
}
|
||||
|
||||
void DreamWebEngine::hangOne(uint16 delay) {
|
||||
do {
|
||||
waitForVSync();
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE)
|
||||
return; // "hangonearly"
|
||||
} while (--delay);
|
||||
}
|
||||
|
||||
void DreamWebEngine::intro() {
|
||||
loadTempText("T82");
|
||||
loadPalFromIFF();
|
||||
setMode();
|
||||
_newLocation = 50;
|
||||
clearPalette();
|
||||
loadIntroRoom();
|
||||
_sound->volumeSet(7);
|
||||
_sound->volumeChange(hasSpeech() ? 4 : 0, -1);
|
||||
_sound->playChannel0(12, 255);
|
||||
fadeScreenUps();
|
||||
runIntroSeq();
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "introearly"
|
||||
}
|
||||
|
||||
clearBeforeLoad();
|
||||
_newLocation = 52;
|
||||
loadIntroRoom();
|
||||
runIntroSeq();
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "introearly"
|
||||
}
|
||||
|
||||
clearBeforeLoad();
|
||||
_newLocation = 53;
|
||||
loadIntroRoom();
|
||||
runIntroSeq();
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "introearly"
|
||||
}
|
||||
|
||||
clearBeforeLoad();
|
||||
allPalette();
|
||||
_newLocation = 54;
|
||||
loadIntroRoom();
|
||||
runIntroSeq();
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "introearly"
|
||||
}
|
||||
|
||||
getRidOfTempText();
|
||||
clearBeforeLoad();
|
||||
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
}
|
||||
|
||||
void DreamWebEngine::runIntroSeq() {
|
||||
_getBack = 0;
|
||||
|
||||
do {
|
||||
waitForVSync();
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE)
|
||||
break;
|
||||
|
||||
spriteUpdate();
|
||||
waitForVSync();
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE)
|
||||
break;
|
||||
|
||||
delEverything();
|
||||
printSprites();
|
||||
reelsOnScreen();
|
||||
afterIntroRoom();
|
||||
useTimedText();
|
||||
waitForVSync();
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE)
|
||||
break;
|
||||
|
||||
dumpMap();
|
||||
dumpTimedText();
|
||||
waitForVSync();
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE)
|
||||
break;
|
||||
|
||||
} while (_getBack != 1);
|
||||
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
getRidOfTempText();
|
||||
clearBeforeLoad();
|
||||
}
|
||||
|
||||
// These were not called in this program arc
|
||||
// in the original code.. Bug?
|
||||
//getRidOfTempText();
|
||||
//clearBeforeLoad();
|
||||
}
|
||||
|
||||
void DreamWebEngine::runEndSeq() {
|
||||
atmospheres();
|
||||
_getBack = 0;
|
||||
|
||||
do {
|
||||
waitForVSync();
|
||||
spriteUpdate();
|
||||
waitForVSync();
|
||||
delEverything();
|
||||
printSprites();
|
||||
reelsOnScreen();
|
||||
afterIntroRoom();
|
||||
useTimedText();
|
||||
waitForVSync();
|
||||
dumpMap();
|
||||
dumpTimedText();
|
||||
waitForVSync();
|
||||
} while (_getBack != 1 && !_quitRequested);
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadIntroRoom() {
|
||||
_introCount = 0;
|
||||
_vars._location = 255;
|
||||
loadRoom();
|
||||
_mapOffsetX = 72;
|
||||
_mapOffsetY = 16;
|
||||
clearSprites();
|
||||
_vars._throughDoor = 0;
|
||||
_currentKey = 0;
|
||||
_mainMode = 0;
|
||||
clearWork();
|
||||
_vars._newObs = 1;
|
||||
drawFloor();
|
||||
reelsOnScreen();
|
||||
spriteUpdate();
|
||||
printSprites();
|
||||
workToScreen();
|
||||
}
|
||||
|
||||
void DreamWebEngine::set16ColPalette() {
|
||||
}
|
||||
|
||||
void DreamWebEngine::realCredits() {
|
||||
_roomsSample = 33;
|
||||
_sound->loadRoomsSample(_roomsSample);
|
||||
_sound->volumeSet(0);
|
||||
|
||||
initTitlesGfx();
|
||||
hangOn(35);
|
||||
|
||||
showPCX("I01");
|
||||
_sound->playChannel0(12, 0);
|
||||
|
||||
hangOne(2);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
allPalette();
|
||||
hangOne(80);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
fadeScreenDowns();
|
||||
hangOne(256);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
showPCX("I02");
|
||||
_sound->playChannel0(12, 0);
|
||||
hangOne(2);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
allPalette();
|
||||
hangOne(80);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
fadeScreenDowns();
|
||||
hangOne(256);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
showPCX("I03");
|
||||
_sound->playChannel0(12, 0);
|
||||
hangOne(2);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
allPalette();
|
||||
hangOne(80);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
fadeScreenDowns();
|
||||
hangOne(256);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
showPCX("I04");
|
||||
_sound->playChannel0(12, 0);
|
||||
hangOne(2);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
allPalette();
|
||||
hangOne(80);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
fadeScreenDowns();
|
||||
hangOne(256);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
showPCX("I05");
|
||||
_sound->playChannel0(12, 0);
|
||||
hangOne(2);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
allPalette();
|
||||
hangOne(80);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
fadeScreenDowns();
|
||||
hangOne(256);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
showPCX("I06");
|
||||
fadeScreenUps();
|
||||
hangOne(60);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
_sound->playChannel0(13, 0);
|
||||
hangOne(350);
|
||||
|
||||
if (_lastHardKey == Common::KEYCODE_ESCAPE) {
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
return; // "realcreditsearly"
|
||||
}
|
||||
|
||||
fadeScreenDowns();
|
||||
hangOne(256);
|
||||
|
||||
_lastHardKey = Common::KEYCODE_INVALID;
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
1611
engines/dreamweb/use.cpp
Normal file
1611
engines/dreamweb/use.cpp
Normal file
File diff suppressed because it is too large
Load Diff
284
engines/dreamweb/vgafades.cpp
Normal file
284
engines/dreamweb/vgafades.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
/* 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 "dreamweb/sound.h"
|
||||
#include "dreamweb/dreamweb.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
void DreamWebEngine::clearStartPal() {
|
||||
memset(_startPal, 0, 256 * 3);
|
||||
}
|
||||
|
||||
void DreamWebEngine::clearEndPal() {
|
||||
memset(_endPal, 0, 256 * 3);
|
||||
}
|
||||
|
||||
void DreamWebEngine::palToStartPal() {
|
||||
memcpy(_startPal, _mainPal, 256 * 3);
|
||||
}
|
||||
|
||||
void DreamWebEngine::endPalToStart() {
|
||||
memcpy(_startPal, _endPal, 256 * 3);
|
||||
}
|
||||
|
||||
void DreamWebEngine::startPalToEnd() {
|
||||
memcpy(_endPal, _startPal, 256 * 3);
|
||||
}
|
||||
|
||||
void DreamWebEngine::palToEndPal() {
|
||||
memcpy(_endPal, _mainPal, 256 * 3);
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeDOS() {
|
||||
return; // FIXME later
|
||||
|
||||
waitForVSync();
|
||||
//processEvents will be called from waitForVSync
|
||||
uint8 *dst = _startPal;
|
||||
getPalette(dst, 0, 64);
|
||||
for (uint fade = 0; fade < 64; ++fade) {
|
||||
for (uint c = 0; c < 768; ++c) { //original sources decrement 768 values -> 256 colors
|
||||
if (dst[c]) {
|
||||
--dst[c];
|
||||
}
|
||||
}
|
||||
setPalette(dst, 0, 64);
|
||||
waitForVSync();
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::doFade() {
|
||||
if (_fadeDirection == 0)
|
||||
return;
|
||||
|
||||
processEvents();
|
||||
uint8 *src = _startPal + 3 * _colorPos;
|
||||
setPalette(src, _colorPos, _numToFade);
|
||||
|
||||
_colorPos += _numToFade;
|
||||
if (_colorPos == 0)
|
||||
fadeCalculation();
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeCalculation() {
|
||||
if (_fadeCount == 0) {
|
||||
_fadeDirection = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 *startPal = _startPal;
|
||||
const uint8 *endPal = _endPal;
|
||||
for (uint i = 0; i < 256 * 3; ++i) {
|
||||
uint8 s = startPal[i];
|
||||
uint8 e = endPal[i];
|
||||
if (s == e)
|
||||
continue;
|
||||
else if (s > e)
|
||||
--startPal[i];
|
||||
else {
|
||||
if (_fadeCount <= e)
|
||||
++startPal[i];
|
||||
}
|
||||
}
|
||||
--_fadeCount;
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeUpYellows() {
|
||||
palToEndPal();
|
||||
memset(_endPal + 231 * 3, 0, 8 * 3);
|
||||
memset(_endPal + 246 * 3, 0, 1 * 3);
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 63;
|
||||
_colorPos = 0;
|
||||
_numToFade = 128;
|
||||
hangOn(128);
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeUpMonFirst() {
|
||||
palToStartPal();
|
||||
palToEndPal();
|
||||
memset(_startPal + 231 * 3, 0, 8 * 3);
|
||||
memset(_startPal + 246 * 3, 0, 1 * 3);
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 63;
|
||||
_colorPos = 0;
|
||||
_numToFade = 128;
|
||||
hangOn(64);
|
||||
_sound->playChannel1(26);
|
||||
hangOn(64);
|
||||
}
|
||||
|
||||
|
||||
void DreamWebEngine::fadeDownMon() {
|
||||
palToStartPal();
|
||||
palToEndPal();
|
||||
memset(_endPal + 231 * 3, 0, 8 * 3);
|
||||
memset(_endPal + 246 * 3, 0, 1 * 3);
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 63;
|
||||
_colorPos = 0;
|
||||
_numToFade = 128;
|
||||
hangOn(64);
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeUpMon() {
|
||||
palToStartPal();
|
||||
palToEndPal();
|
||||
memset(_startPal + 231 * 3, 0, 8 * 3);
|
||||
memset(_startPal + 246 * 3, 0, 1 * 3);
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 63;
|
||||
_colorPos = 0;
|
||||
_numToFade = 128;
|
||||
hangOn(128);
|
||||
}
|
||||
|
||||
void DreamWebEngine::initialMonCols() {
|
||||
palToStartPal();
|
||||
memset(_startPal + 230 * 3, 0, 9 * 3);
|
||||
memset(_startPal + 246 * 3, 0, 1 * 3);
|
||||
processEvents();
|
||||
setPalette(_startPal + 230 * 3, 230, 18);
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeScreenUp() {
|
||||
clearStartPal();
|
||||
palToEndPal();
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 63;
|
||||
_colorPos = 0;
|
||||
_numToFade = 128;
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeScreenUps() {
|
||||
clearStartPal();
|
||||
palToEndPal();
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 63;
|
||||
_colorPos = 0;
|
||||
_numToFade = 64;
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeScreenUpHalf() {
|
||||
endPalToStart();
|
||||
palToEndPal();
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 31;
|
||||
_colorPos = 0;
|
||||
_numToFade = 32;
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeScreenDown() {
|
||||
palToStartPal();
|
||||
clearEndPal();
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 63;
|
||||
_colorPos = 0;
|
||||
_numToFade = 128;
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeScreenDowns() {
|
||||
palToStartPal();
|
||||
clearEndPal();
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 63;
|
||||
_colorPos = 0;
|
||||
_numToFade = 64;
|
||||
}
|
||||
|
||||
void DreamWebEngine::fadeScreenDownHalf() {
|
||||
palToStartPal();
|
||||
palToEndPal();
|
||||
|
||||
const uint8 *startPal = _startPal;
|
||||
uint8 *endPal = _endPal;
|
||||
for (uint i = 0; i < 256 * 3; ++i) {
|
||||
*endPal >>= 1;
|
||||
endPal++;
|
||||
}
|
||||
|
||||
memcpy(endPal + (56*3), startPal + (56*3), 3*5);
|
||||
memcpy(endPal + (77*3), startPal + (77*3), 3*2);
|
||||
|
||||
_fadeDirection = 1;
|
||||
_fadeCount = 31;
|
||||
_colorPos = 0;
|
||||
_numToFade = 32;
|
||||
}
|
||||
|
||||
|
||||
void DreamWebEngine::clearPalette() {
|
||||
_fadeDirection = 0;
|
||||
clearStartPal();
|
||||
dumpCurrent();
|
||||
}
|
||||
|
||||
// Converts palette to grey scale, summed using formula
|
||||
// .20xred + .59xGreen + .11xBlue
|
||||
void DreamWebEngine::greyscaleSum() {
|
||||
byte *src = _mainPal;
|
||||
byte *dst = _endPal;
|
||||
|
||||
for (uint i = 0; i < 256; ++i) {
|
||||
const unsigned int r = 20 * *src++;
|
||||
const unsigned int g = 59 * *src++;
|
||||
const unsigned int b = 11 * *src++;
|
||||
const byte grey = (r + b + g) / 100;
|
||||
byte tmp;
|
||||
|
||||
tmp = grey;
|
||||
//if (tmp != 0) // FIXME: The assembler code has this check commented out. Bug or feature?
|
||||
tmp += _addToRed;
|
||||
*dst++ = tmp;
|
||||
|
||||
tmp = grey;
|
||||
if (tmp != 0)
|
||||
tmp += _addToGreen;
|
||||
*dst++ = tmp;
|
||||
|
||||
tmp = grey;
|
||||
if (tmp != 0)
|
||||
tmp += _addToBlue;
|
||||
*dst++ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::allPalette() {
|
||||
memcpy(_startPal, _mainPal, 3 * 256);
|
||||
dumpCurrent();
|
||||
}
|
||||
|
||||
void DreamWebEngine::dumpCurrent() {
|
||||
uint8 *pal = _startPal;
|
||||
|
||||
waitForVSync();
|
||||
processEvents();
|
||||
setPalette(pal, 0, 128);
|
||||
|
||||
pal += 128 * 3;
|
||||
|
||||
waitForVSync();
|
||||
processEvents();
|
||||
setPalette(pal, 128, 128);
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
440
engines/dreamweb/vgagrafx.cpp
Normal file
440
engines/dreamweb/vgagrafx.cpp
Normal file
@@ -0,0 +1,440 @@
|
||||
/* 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 "dreamweb/dreamweb.h"
|
||||
#include "common/file.h"
|
||||
#include "engines/util.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/scaler/downscaler.h"
|
||||
#include "image/pcx.h"
|
||||
|
||||
namespace DreamWeb {
|
||||
|
||||
const uint16 kZoomx = 8;
|
||||
const uint16 kZoomy = 132;
|
||||
|
||||
void DreamWebEngine::multiGet(uint8 *dst, uint16 x, uint16 y, uint8 w, uint8 h) {
|
||||
assert(x < kScreenwidth);
|
||||
assert(y < kScreenheight);
|
||||
|
||||
const uint8 *src = workspace() + x + y * kScreenwidth;
|
||||
|
||||
if (y + h > kScreenheight)
|
||||
h = kScreenheight - y;
|
||||
if (x + w > kScreenwidth)
|
||||
w = kScreenwidth - x;
|
||||
|
||||
for (unsigned l = 0; l < h; ++l) {
|
||||
const uint8 *src_p = src + kScreenwidth * l;
|
||||
uint8 *dst_p = dst + w * l;
|
||||
memcpy(dst_p, src_p, w);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::multiPut(const uint8 *src, uint16 x, uint16 y, uint8 w, uint8 h) {
|
||||
assert(x < kScreenwidth);
|
||||
assert(y < kScreenheight);
|
||||
|
||||
uint8 *dst = workspace() + x + y * kScreenwidth;
|
||||
|
||||
if (y + h > kScreenheight)
|
||||
h = kScreenheight - y;
|
||||
if (x + w > kScreenwidth)
|
||||
w = kScreenwidth - x;
|
||||
|
||||
for (unsigned l = 0; l < h; ++l) {
|
||||
const uint8 *src_p = src + w * l;
|
||||
uint8 *dst_p = dst + kScreenwidth * l;
|
||||
memcpy(dst_p, src_p, w);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::multiDump(uint16 x, uint16 y, uint8 width, uint8 height) {
|
||||
unsigned offset = x + y * kScreenwidth;
|
||||
blit(workspace() + offset, kScreenwidth, x, y, width, height);
|
||||
}
|
||||
|
||||
void DreamWebEngine::workToScreen() {
|
||||
blit(workspace(), kScreenwidth, 0, 0, kScreenwidth, kScreenheight);
|
||||
}
|
||||
|
||||
void DreamWebEngine::frameOutNm(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
|
||||
dst += pitch * y + x;
|
||||
|
||||
for (uint16 j = 0; j < height; ++j) {
|
||||
memcpy(dst, src, width);
|
||||
dst += pitch;
|
||||
src += width;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::frameOutBh(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
|
||||
uint16 stride = pitch - width;
|
||||
dst += y * pitch + x;
|
||||
|
||||
for (uint16 i = 0; i < height; ++i) {
|
||||
for (uint16 j = 0; j < width; ++j) {
|
||||
if (*dst == 0xff) {
|
||||
*dst = *src;
|
||||
}
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::frameOutFx(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
|
||||
uint16 stride = pitch - width;
|
||||
dst += y * pitch + x;
|
||||
dst -= width;
|
||||
|
||||
for (uint16 j = 0; j < height; ++j) {
|
||||
for (uint16 i = 0; i < width; ++i) {
|
||||
uint8 pixel = src[width - i - 1];
|
||||
if (pixel)
|
||||
*dst = pixel;
|
||||
++dst;
|
||||
}
|
||||
src += width;
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::doShake() {
|
||||
uint8 &counter = _vars._shakeCounter;
|
||||
if (counter == 48)
|
||||
return;
|
||||
|
||||
++counter;
|
||||
static const int shakeTable[] = {
|
||||
0, -2, 3, -2, 0, 2, 4, -1,
|
||||
1, -3, 3, 2, 0, -2, 3, -2,
|
||||
0, 2, 4, -1, 1, -3, 3, 2,
|
||||
0, -2, 3, -2, 0, 2, 4, -1,
|
||||
|
||||
1, -3, 3, 2, 0, -2, 3, -2,
|
||||
0, 2, 4, -1, 1, -3, 3, 2,
|
||||
0, -2, 3, -2, 0, 2, 4, -1,
|
||||
1, -3, 3, 2, 0, -2, 3, -2,
|
||||
|
||||
0, 2, 4, -1, 1, -3, 3, 2,
|
||||
0, -2, 3, -2, 0, 2, 4, -1,
|
||||
1, -3, 3, 2, 0, -2, 3, -2,
|
||||
0, 2, 4, -1, 1, -3, 3, 2,
|
||||
|
||||
0, -2, 3, -2, 0, 2, 4, -1,
|
||||
1, -3, 3, 0,
|
||||
};
|
||||
assert(counter < ARRAYSIZE(shakeTable));
|
||||
int offset = shakeTable[counter];
|
||||
setShakePos(offset >= 0 ? offset : -offset);
|
||||
}
|
||||
|
||||
void DreamWebEngine::setMode() {
|
||||
waitForVSync();
|
||||
initGraphics(kScreenwidth, kScreenheight);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showPCX(const Common::String &suffix) {
|
||||
Common::Path name(getDatafilePrefix() + suffix);
|
||||
Common::File pcxFile;
|
||||
if (!pcxFile.open(name)) {
|
||||
warning("showpcx: Could not open '%s'", name.toString(Common::Path::kNativeSeparator).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
Image::PCXDecoder pcx;
|
||||
if (!pcx.loadStream(pcxFile)) {
|
||||
warning("showpcx: Could not process '%s'", name.toString(Common::Path::kNativeSeparator).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the 16-color palette into the 'maingamepal' buffer. Note that
|
||||
// the color components have to be adjusted from 8 to 6 bits.
|
||||
memset(_mainPal, 0xff, 256 * 3);
|
||||
memcpy(_mainPal, pcx.getPalette().data(), 48);
|
||||
for (int i = 0; i < 48; i++) {
|
||||
_mainPal[i] >>= 2;
|
||||
}
|
||||
|
||||
const Graphics::Surface *pcxSurface = pcx.getSurface();
|
||||
if (pcxSurface->format.bytesPerPixel != 1)
|
||||
error("Invalid bytes per pixel in PCX surface (%d)", pcxSurface->format.bytesPerPixel);
|
||||
|
||||
g_system->fillScreen(0);
|
||||
if (pcxSurface->w >= g_system->getWidth() * 2) {
|
||||
Graphics::Surface *s = g_system->lockScreen();
|
||||
Graphics::downscaleSurfaceByHalf(s, pcxSurface, _mainPal);
|
||||
g_system->unlockScreen();
|
||||
} else {
|
||||
g_system->copyRectToScreen(pcxSurface->getPixels(), pcxSurface->pitch,
|
||||
0, 0, pcxSurface->w, pcxSurface->h);
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::frameOutV(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, int16 x, int16 y) {
|
||||
// NB : These resilience checks were not in the original engine, but did they result in undefined behaviour
|
||||
// or was something broken during porting to C++?
|
||||
assert(pitch == kScreenwidth);
|
||||
|
||||
if (x < 0) {
|
||||
assert(width >= -x);
|
||||
width -= -x;
|
||||
src += -x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
assert(height >= -y);
|
||||
height -= -y;
|
||||
src += (-y) * width;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if ((uint16)x >= kScreenwidth)
|
||||
return;
|
||||
if ((uint16)y >= kScreenheight)
|
||||
return;
|
||||
if ((uint16)x + width > kScreenwidth) {
|
||||
width = kScreenwidth - x;
|
||||
}
|
||||
if ((uint16)y + height > kScreenheight) {
|
||||
height = kScreenheight - y;
|
||||
}
|
||||
|
||||
uint16 stride = pitch - width;
|
||||
dst += pitch * y + x;
|
||||
|
||||
for (uint16 j = 0; j < height; ++j) {
|
||||
for (uint16 i = 0; i < width; ++i) {
|
||||
uint8 pixel = *src++;
|
||||
if (pixel)
|
||||
*dst = pixel;
|
||||
++dst;
|
||||
}
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void DreamWebEngine::showFrame(const GraphicsFile &frameData, uint16 x, uint16 y, uint16 frameNumber, uint8 effectsFlag) {
|
||||
uint8 width, height;
|
||||
showFrame(frameData, x, y, frameNumber, effectsFlag, &width, &height);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showFrameInternal(const uint8 *pSrc, uint16 x, uint16 y, uint8 effectsFlag, uint8 width, uint8 height) {
|
||||
if (effectsFlag) {
|
||||
if (effectsFlag & 128) { //centered
|
||||
x -= width / 2;
|
||||
y -= height / 2;
|
||||
}
|
||||
if (effectsFlag & 64) { // diffDest
|
||||
error("Unsupported DreamWebEngine::showFrame effectsFlag %d", effectsFlag);
|
||||
/*
|
||||
frameOutFx(es.ptr(0, dx * *height), pSrc, dx, *width, *height, x, y);
|
||||
return;
|
||||
*/
|
||||
}
|
||||
if (effectsFlag & 8) { // printList
|
||||
//addToPrintList(x - _mapAdX, y - _mapAdY); // NB: Commented in the original asm
|
||||
}
|
||||
if (effectsFlag & 4) { // flippedX
|
||||
frameOutFx(workspace(), pSrc, kScreenwidth, width, height, x, y);
|
||||
return;
|
||||
}
|
||||
if (effectsFlag & 2) { // noMask
|
||||
frameOutNm(workspace(), pSrc, kScreenwidth, width, height, x, y);
|
||||
return;
|
||||
}
|
||||
if (effectsFlag & 32) {
|
||||
frameOutBh(workspace(), pSrc, kScreenwidth, width, height, x, y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// "noEffects"
|
||||
frameOutV(workspace(), pSrc, kScreenwidth, width, height, x, y);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showFrame(const GraphicsFile &frameData, uint16 x, uint16 y, uint16 frameNumber, uint8 effectsFlag, uint8 *width, uint8 *height) {
|
||||
const Frame *frame = &frameData._frames[frameNumber];
|
||||
if ((frame->width == 0) && (frame->height == 0)) {
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// "notBlankShow"
|
||||
if ((effectsFlag & 128) == 0) {
|
||||
x += frame->x;
|
||||
y += frame->y;
|
||||
}
|
||||
|
||||
// "skipOffsets"
|
||||
*width = frame->width;
|
||||
*height = frame->height;
|
||||
const uint8 *pSrc = frameData.getFrameData(frameNumber);
|
||||
|
||||
showFrameInternal(pSrc, x, y, effectsFlag, *width, *height);
|
||||
}
|
||||
|
||||
void DreamWebEngine::clearWork() {
|
||||
memset(workspace(), 0, kScreenwidth*kScreenheight);
|
||||
}
|
||||
|
||||
void DreamWebEngine::dumpZoom() {
|
||||
if (_vars._zoomOn == 1)
|
||||
multiDump(kZoomx + 5, kZoomy + 4, 46, 40);
|
||||
}
|
||||
|
||||
void DreamWebEngine::crosshair() {
|
||||
uint16 frame;
|
||||
if ((_commandType != 3) && (_commandType < 10)) {
|
||||
frame = 9;
|
||||
} else {
|
||||
frame = 29;
|
||||
}
|
||||
showFrame(_icons1, kZoomx + 24, kZoomy + 19, frame, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::getUnderZoom() {
|
||||
multiGet(_zoomSpace, kZoomx + 5, kZoomy + 4, 46, 40);
|
||||
}
|
||||
|
||||
void DreamWebEngine::putUnderZoom() {
|
||||
multiPut(_zoomSpace, kZoomx + 5, kZoomy + 4, 46, 40);
|
||||
}
|
||||
|
||||
void DreamWebEngine::zoomIcon() {
|
||||
if (_vars._zoomOn == 0)
|
||||
return;
|
||||
showFrame(_icons1, kZoomx, kZoomy-1, 8, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::zoom() {
|
||||
if (_vars._watchingTime != 0)
|
||||
return;
|
||||
if (_vars._zoomOn != 1)
|
||||
return;
|
||||
if (_commandType >= 199) {
|
||||
putUnderZoom();
|
||||
return;
|
||||
}
|
||||
uint16 srcOffset = (_oldPointerY - 9) * kScreenwidth + (_oldPointerX - 11);
|
||||
uint16 dstOffset = (kZoomy + 4) * kScreenwidth + (kZoomx + 5);
|
||||
const uint8 *src = workspace() + srcOffset;
|
||||
uint8 *dst = workspace() + dstOffset;
|
||||
for (uint i = 0; i < 20; ++i) {
|
||||
for (uint j = 0; j < 23; ++j) {
|
||||
uint8 v = src[j];
|
||||
dst[2*j+0] = v;
|
||||
dst[2*j+1] = v;
|
||||
dst[2*j+kScreenwidth] = v;
|
||||
dst[2*j+kScreenwidth+1] = v;
|
||||
}
|
||||
src += kScreenwidth;
|
||||
dst += kScreenwidth*2;
|
||||
}
|
||||
crosshair();
|
||||
_didZoom = 1;
|
||||
}
|
||||
|
||||
void DreamWebEngine::panelToMap() {
|
||||
multiGet(_mapStore, _mapXStart + _mapAdX, _mapYStart + _mapAdY, _mapXSize, _mapYSize);
|
||||
}
|
||||
|
||||
void DreamWebEngine::mapToPanel() {
|
||||
multiPut(_mapStore, _mapXStart + _mapAdX, _mapYStart + _mapAdY, _mapXSize, _mapYSize);
|
||||
}
|
||||
|
||||
void DreamWebEngine::dumpMap() {
|
||||
multiDump(_mapXStart + _mapAdX, _mapYStart + _mapAdY, _mapXSize, _mapYSize);
|
||||
}
|
||||
|
||||
bool DreamWebEngine::pixelCheckSet(const ObjPos *pos, uint8 x, uint8 y) {
|
||||
x -= pos->xMin;
|
||||
y -= pos->yMin;
|
||||
SetObject *setObject = getSetAd(pos->index);
|
||||
const Frame &frame = _setFrames._frames[setObject->index];
|
||||
const uint8 *ptr = _setFrames.getFrameData(setObject->index) + y * frame.width + x;
|
||||
return *ptr != 0;
|
||||
}
|
||||
|
||||
void DreamWebEngine::loadPalFromIFF() {
|
||||
Common::File palFile;
|
||||
uint8* buf = new uint8[2000];
|
||||
palFile.open(Common::Path(getDatafilePrefix() + "PAL"));
|
||||
palFile.read(buf, 2000);
|
||||
palFile.close();
|
||||
|
||||
const uint8 *src = buf + 0x30;
|
||||
uint8 *dst = _mainPal;
|
||||
for (uint i = 0; i < 256*3; ++i) {
|
||||
uint8 c = src[i] / 4;
|
||||
if (_brightPalette) {
|
||||
if (c) {
|
||||
c = c + c / 2 + c / 4;
|
||||
if (c > 63)
|
||||
c = 63;
|
||||
}
|
||||
}
|
||||
dst[i] = c;
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
void DreamWebEngine::createPanel() {
|
||||
showFrame(_icons2, 0, 8, 0, 2);
|
||||
showFrame(_icons2, 160, 8, 0, 2);
|
||||
showFrame(_icons2, 0, 104, 0, 2);
|
||||
showFrame(_icons2, 160, 104, 0, 2);
|
||||
}
|
||||
|
||||
void DreamWebEngine::createPanel2() {
|
||||
createPanel();
|
||||
showFrame(_icons2, 0, 0, 5, 2);
|
||||
showFrame(_icons2, 160, 0, 5, 2);
|
||||
}
|
||||
|
||||
void DreamWebEngine::showPanel() {
|
||||
showFrame(_icons1, 72, 0, 19, 0);
|
||||
showFrame(_icons1, 192, 0, 19, 0);
|
||||
}
|
||||
|
||||
void DreamWebEngine::transferFrame(uint8 from, uint8 to, uint8 offset) {
|
||||
const Frame &freeFrame = _freeFrames._frames[3*from + offset];
|
||||
Frame &exFrame = _exFrames._frames[3*to + offset];
|
||||
|
||||
exFrame.width = freeFrame.width;
|
||||
exFrame.height = freeFrame.height;
|
||||
exFrame.x = freeFrame.x;
|
||||
exFrame.y = freeFrame.y;
|
||||
uint16 byteCount = freeFrame.width * freeFrame.height;
|
||||
|
||||
const uint8 *src = _freeFrames.getFrameData(3*from + offset);
|
||||
uint8 *dst = _exFrames._data + _vars._exFramePos;
|
||||
assert(_vars._exFramePos + byteCount <= kExframeslen);
|
||||
memcpy(dst, src, byteCount);
|
||||
|
||||
exFrame.setPtr(_vars._exFramePos);
|
||||
_vars._exFramePos += byteCount;
|
||||
}
|
||||
|
||||
} // End of namespace DreamWeb
|
||||
Reference in New Issue
Block a user