TOLTECS: Initial checkin
This commit is contained in:
parent
528c1173d7
commit
7c2835313e
18 changed files with 5077 additions and 0 deletions
139
engines/toltecs/animation.cpp
Normal file
139
engines/toltecs/animation.cpp
Normal file
|
@ -0,0 +1,139 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "base/version.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
#include "toltecs/animation.h"
|
||||
#include "toltecs/screen.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
AnimationPlayer::AnimationPlayer(ToltecsEngine *vm) : _vm(vm) {
|
||||
_animBuffer = new byte[262144];
|
||||
}
|
||||
|
||||
AnimationPlayer::~AnimationPlayer() {
|
||||
delete[] _animBuffer;
|
||||
}
|
||||
|
||||
void AnimationPlayer::start(uint resIndex) {
|
||||
debug(1, "AnimationPlayer::start(%d)", resIndex);
|
||||
|
||||
_resIndex = resIndex;
|
||||
|
||||
_vm->_arc->openResource(_resIndex);
|
||||
_height = _vm->_arc->readUint16LE();
|
||||
_width = _vm->_arc->readUint16LE();
|
||||
_frameCount = _vm->_arc->readUint16LE();
|
||||
_vm->_arc->read(_palette, 768);
|
||||
_curFrameSize = _vm->_arc->readUint32LE();
|
||||
_nextFrameOffset = _curFrameSize + 782;
|
||||
_vm->_arc->read(_animBuffer, _curFrameSize);
|
||||
_nextFrameSize = _vm->_arc->readUint32LE();
|
||||
_vm->_arc->closeResource();
|
||||
|
||||
debug(1, "AnimationPlayer::start() width = %d; height = %d; frameCount = %d", _width, _height, _frameCount);
|
||||
|
||||
unpackFrame();
|
||||
|
||||
_keepFrameCounter = 0;
|
||||
_frameNumber = 0;
|
||||
// TODO mov screenFlag01, 0FFFFh
|
||||
// TODO mov animDrawFrameFlag, 0FFFFh
|
||||
|
||||
_firstNextFrameOffset = _nextFrameOffset;
|
||||
_firstCurFrameSize = _curFrameSize;
|
||||
_firstNextFrameSize = _nextFrameSize;
|
||||
|
||||
}
|
||||
|
||||
void AnimationPlayer::nextFrame() {
|
||||
debug(1, "AnimationPlayer::nextFrame()");
|
||||
|
||||
if (_frameNumber == _frameCount) {
|
||||
_nextFrameOffset = _firstNextFrameOffset;
|
||||
_curFrameSize = _firstCurFrameSize;
|
||||
_nextFrameSize = _firstNextFrameSize;
|
||||
_frameNumber = 1;
|
||||
} else {
|
||||
_frameNumber++;
|
||||
}
|
||||
|
||||
debug(1, "AnimationPlayer::nextFrame() frameNumber = %d", _frameNumber);
|
||||
|
||||
if (_keepFrameCounter > 0) {
|
||||
_keepFrameCounter--;
|
||||
return;
|
||||
}
|
||||
|
||||
_vm->_arc->openResource(_resIndex);
|
||||
_vm->_arc->seek(_nextFrameOffset, SEEK_CUR);
|
||||
_curFrameSize = _nextFrameSize;
|
||||
|
||||
if (_curFrameSize == 0)
|
||||
_curFrameSize = 1;
|
||||
|
||||
_vm->_arc->read(_animBuffer, _curFrameSize);
|
||||
_nextFrameSize = _vm->_arc->readUint32LE();
|
||||
_nextFrameOffset += _curFrameSize + 4;
|
||||
|
||||
if (_curFrameSize > 1) {
|
||||
unpackFrame();
|
||||
// TODO mov animDrawFrameFlag, 0FFFFh
|
||||
} else {
|
||||
_keepFrameCounter = _animBuffer[0] - 1;
|
||||
// TODO mov animDrawFrameFlag, 0
|
||||
}
|
||||
|
||||
_vm->_arc->closeResource();
|
||||
|
||||
|
||||
}
|
||||
|
||||
int16 AnimationPlayer::getStatus() {
|
||||
debug(1, "AnimationPlayer::getStatus()");
|
||||
int16 status = -1;
|
||||
if (_frameNumber == _frameCount)
|
||||
status = 0;
|
||||
else if (_frameNumber == _frameCount - 1)
|
||||
status = 1;
|
||||
debug(1, "AnimationPlayer::getStatus() status = %d", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
void AnimationPlayer::unpackFrame() {
|
||||
_vm->_screen->unpackRle(_animBuffer, _vm->_screen->_frontScreen, _width, _height);
|
||||
_vm->_screen->unpackRle(_animBuffer, _vm->_screen->_backScreen, _width, _height);
|
||||
}
|
||||
|
||||
} // End of namespace Toltecs
|
85
engines/toltecs/animation.h
Normal file
85
engines/toltecs/animation.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOLTECS_ANIMATION_H
|
||||
#define TOLTECS_ANIMATION_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/array.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/voc.h"
|
||||
#include "sound/audiocd.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
#include "toltecs/resource.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
class AnimationPlayer {
|
||||
public:
|
||||
AnimationPlayer(ToltecsEngine *vm);
|
||||
~AnimationPlayer();
|
||||
|
||||
void start(uint resIndex);
|
||||
void nextFrame();
|
||||
int16 getStatus();
|
||||
uint16 getFrameNumber() const { return _frameNumber; }
|
||||
|
||||
//protected:
|
||||
public:
|
||||
ToltecsEngine *_vm;
|
||||
|
||||
// 262144
|
||||
byte *_animBuffer;
|
||||
|
||||
uint _resIndex;
|
||||
byte _palette[768];
|
||||
|
||||
uint16 _width, _height;
|
||||
uint16 _frameNumber, _frameCount;
|
||||
uint32 _keepFrameCounter;
|
||||
|
||||
uint32 _curFrameSize;
|
||||
uint32 _nextFrameSize, _nextFrameOffset;
|
||||
|
||||
uint32 _firstNextFrameOffset, _firstCurFrameSize, _firstNextFrameSize;
|
||||
|
||||
void unpackFrame();
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
||||
#endif /* TOLTECS_ANIMATION_H */
|
121
engines/toltecs/detection.cpp
Normal file
121
engines/toltecs/detection.cpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "base/plugins.h"
|
||||
|
||||
#include "common/advancedDetector.h"
|
||||
#include "common/file.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
struct ToltecsGameDescription {
|
||||
Common::ADGameDescription desc;
|
||||
};
|
||||
|
||||
uint32 ToltecsEngine::getFeatures() const {
|
||||
return _gameDescription->desc.flags;
|
||||
}
|
||||
|
||||
Common::Language ToltecsEngine::getLanguage() const {
|
||||
return _gameDescription->desc.language;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const PlainGameDescriptor toltecsGames[] = {
|
||||
{"toltecs", "3 Skulls of the Toltecs"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
static const ToltecsGameDescription gameDescriptions[] = {
|
||||
|
||||
{
|
||||
// Toltecs English version
|
||||
{
|
||||
"toltecs",
|
||||
0,
|
||||
AD_ENTRY1s("WESTERN", "05472037e9cfde146e953c434e74f0f4", 337643527),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformPC,
|
||||
Common::ADGF_NO_FLAGS
|
||||
},
|
||||
},
|
||||
|
||||
{ AD_TABLE_END_MARKER }
|
||||
};
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
||||
static const Common::ADParams detectionParams = {
|
||||
// Pointer to ADGameDescription or its superset structure
|
||||
(const byte *)Toltecs::gameDescriptions,
|
||||
// Size of that superset structure
|
||||
sizeof(Toltecs::ToltecsGameDescription),
|
||||
// Number of bytes to compute MD5 sum for
|
||||
5000,
|
||||
// List of all engine targets
|
||||
toltecsGames,
|
||||
// Structure for autoupgrading obsolete targets
|
||||
0,
|
||||
// Name of single gameid (optional)
|
||||
"toltecs",
|
||||
// List of files for file-based fallback detection (optional)
|
||||
0,
|
||||
// Flags
|
||||
0
|
||||
};
|
||||
|
||||
class ToltecsMetaEngine : public Common::AdvancedMetaEngine {
|
||||
public:
|
||||
ToltecsMetaEngine() : Common::AdvancedMetaEngine(detectionParams) {}
|
||||
|
||||
virtual const char *getName() const {
|
||||
return "Toltecs Engine";
|
||||
}
|
||||
|
||||
virtual const char *getCopyright() const {
|
||||
return "Toltecs Engine (C) 1996";
|
||||
}
|
||||
|
||||
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
|
||||
};
|
||||
|
||||
bool ToltecsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
|
||||
const Toltecs::ToltecsGameDescription *gd = (const Toltecs::ToltecsGameDescription *)desc;
|
||||
if (gd) {
|
||||
*engine = new Toltecs::ToltecsEngine(syst, gd);
|
||||
}
|
||||
return gd != 0;
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(TOLTECS)
|
||||
REGISTER_PLUGIN_DYNAMIC(TOLTECS, PLUGIN_TYPE_ENGINE, ToltecsMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(TOLTECS, PLUGIN_TYPE_ENGINE, ToltecsMetaEngine);
|
||||
#endif
|
133
engines/toltecs/input.cpp
Normal file
133
engines/toltecs/input.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "base/version.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
#include "toltecs/input.h"
|
||||
#include "toltecs/palette.h"
|
||||
#include "toltecs/resource.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
Input::Input(ToltecsEngine *vm) : _vm(vm) {
|
||||
|
||||
_mouseX = 0;
|
||||
_mouseY = 0;
|
||||
_mousePosDelta = 0;
|
||||
_mouseCounter = 0;
|
||||
_mouseButtonPressedFlag = false;
|
||||
_mouseButton = 0;
|
||||
_mouseDisabled = 0;
|
||||
|
||||
_leftButtonDown = false;
|
||||
_rightButtonDown = false;
|
||||
|
||||
}
|
||||
|
||||
Input::~Input() {
|
||||
}
|
||||
|
||||
void Input::update() {
|
||||
|
||||
Common::Event event;
|
||||
Common::EventManager *eventMan = _vm->_system->getEventManager();
|
||||
while (eventMan->pollEvent(event)) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_KEYDOWN:
|
||||
case Common::EVENT_QUIT:
|
||||
break;
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
_mouseX = event.mouse.x;
|
||||
_mouseY = event.mouse.y;
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
_mouseX = event.mouse.x;
|
||||
_mouseY = event.mouse.y;
|
||||
_leftButtonDown = true;
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
_mouseX = event.mouse.x;
|
||||
_mouseY = event.mouse.y;
|
||||
_leftButtonDown = false;
|
||||
break;
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
_mouseX = event.mouse.x;
|
||||
_mouseY = event.mouse.y;
|
||||
_rightButtonDown = true;
|
||||
break;
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
_mouseX = event.mouse.x;
|
||||
_mouseY = event.mouse.y;
|
||||
_rightButtonDown = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_mouseDisabled == 0) {
|
||||
_mousePosDelta = _mousePosDelta + _mouseY - _mouseX;
|
||||
|
||||
if (_mouseCounter > 0)
|
||||
_mouseCounter--;
|
||||
|
||||
byte mouseButtons = 0;
|
||||
if (_leftButtonDown)
|
||||
mouseButtons |= 1;
|
||||
if (_rightButtonDown)
|
||||
mouseButtons |= 2;
|
||||
|
||||
if (mouseButtons != 0) {
|
||||
if (!_mouseButtonPressedFlag) {
|
||||
_mouseButton = mouseButtons;
|
||||
if (_mouseCounter != 0)
|
||||
_mouseButton |= 0x80;
|
||||
_mouseCounter = 30; // maybe TODO
|
||||
_mouseButtonPressedFlag = true;
|
||||
} else {
|
||||
_mouseButton = 0;
|
||||
}
|
||||
} else {
|
||||
_mouseButtonPressedFlag = false;
|
||||
_mouseButton = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int16 Input::getMouseDeltaStuff(int16 divisor) {
|
||||
return ABS(_mousePosDelta % divisor);
|
||||
}
|
||||
|
||||
} // End of namespace Toltecs
|
76
engines/toltecs/input.h
Normal file
76
engines/toltecs/input.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOLTECS_INPUT_H
|
||||
#define TOLTECS_INPUT_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/array.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/voc.h"
|
||||
#include "sound/audiocd.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
class Input {
|
||||
public:
|
||||
Input(ToltecsEngine *vm);
|
||||
~Input();
|
||||
|
||||
void update();
|
||||
|
||||
void enableMouse();
|
||||
void disableMouse();
|
||||
|
||||
int16 getMouseDeltaStuff(int16 divisor);
|
||||
|
||||
//protected:
|
||||
public:
|
||||
ToltecsEngine *_vm;
|
||||
|
||||
int16 _mouseX, _mouseY;
|
||||
int16 _mousePosDelta;
|
||||
int16 _mouseCounter;
|
||||
bool _mouseButtonPressedFlag;
|
||||
byte _mouseButton;
|
||||
int16 _mouseDisabled;
|
||||
|
||||
bool _leftButtonDown, _rightButtonDown;
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
||||
#endif /* TOLTECS_INPUT_H */
|
21
engines/toltecs/module.mk
Normal file
21
engines/toltecs/module.mk
Normal file
|
@ -0,0 +1,21 @@
|
|||
MODULE := engines/toltecs
|
||||
|
||||
MODULE_OBJS = \
|
||||
animation.o \
|
||||
detection.o \
|
||||
input.o \
|
||||
palette.o \
|
||||
toltecs.o \
|
||||
resource.o \
|
||||
screen.o \
|
||||
script.o \
|
||||
segmap.o
|
||||
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_TOLTECS), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
157
engines/toltecs/palette.cpp
Normal file
157
engines/toltecs/palette.cpp
Normal file
|
@ -0,0 +1,157 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "base/version.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
#include "toltecs/palette.h"
|
||||
#include "toltecs/resource.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
Palette::Palette(ToltecsEngine *vm) : _vm(vm) {
|
||||
|
||||
clearFragments();
|
||||
|
||||
}
|
||||
|
||||
Palette::~Palette() {
|
||||
}
|
||||
|
||||
void Palette::setFullPalette(byte *palette) {
|
||||
byte colors[1024];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
colors[i * 4 + 0] = palette[i * 3 + 0] << 2;
|
||||
colors[i * 4 + 1] = palette[i * 3 + 1] << 2;
|
||||
colors[i * 4 + 2] = palette[i * 3 + 2] << 2;
|
||||
colors[i * 4 + 3] = 255;
|
||||
}
|
||||
_vm->_system->setPalette((const byte *)colors, 0, 256);
|
||||
_vm->_system->updateScreen();
|
||||
}
|
||||
|
||||
void Palette::setDeltaPalette(byte *palette, byte mask, char deltaValue, int16 count, int16 startIndex) {
|
||||
|
||||
byte colors[1024];
|
||||
|
||||
byte *palPtr = palette + startIndex * 3;
|
||||
int16 index = startIndex, colorCount = count;
|
||||
byte rgb;
|
||||
|
||||
count++;
|
||||
|
||||
mask &= 7;
|
||||
|
||||
_vm->_system->grabPalette(colors, 0, 256);
|
||||
|
||||
if (deltaValue < 0) {
|
||||
deltaValue = -deltaValue;
|
||||
while (count--) {
|
||||
rgb = *palPtr++;
|
||||
if (mask & 1) colors[index * 4 + 0] = CLIP<int>(rgb + deltaValue, 0, 63) << 2;
|
||||
rgb = *palPtr++;
|
||||
if (mask & 2) colors[index * 4 + 1] = CLIP<int>(rgb + deltaValue, 0, 63) << 2;
|
||||
rgb = *palPtr++;
|
||||
if (mask & 4) colors[index * 4 + 2] = CLIP<int>(rgb + deltaValue, 0, 63) << 2;
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
while (count--) {
|
||||
rgb = *palPtr++;
|
||||
if (mask & 1) colors[index * 4 + 0] = CLIP<int>(rgb - deltaValue, deltaValue, 255) << 2;
|
||||
rgb = *palPtr++;
|
||||
if (mask & 2) colors[index * 4 + 1] = CLIP<int>(rgb - deltaValue, deltaValue, 255) << 2;
|
||||
rgb = *palPtr++;
|
||||
if (mask & 4) colors[index * 4 + 2] = CLIP<int>(rgb - deltaValue, deltaValue, 255) << 2;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
debug(0, "startIndex = %d; colorCount = %d", startIndex, colorCount);
|
||||
|
||||
_vm->_system->setPalette((const byte *)colors, 0, 256);
|
||||
|
||||
}
|
||||
|
||||
void Palette::loadAddPalette(uint resIndex, byte startIndex) {
|
||||
byte *data = _vm->_res->load(resIndex);
|
||||
memcpy(&_mainPalette[startIndex * 3], data, _vm->_res->getCurItemSize());
|
||||
}
|
||||
|
||||
void Palette::loadAddPaletteFrom(byte *source, byte startIndex, byte count) {
|
||||
memcpy(&_mainPalette[startIndex * 3], source, count * 3);
|
||||
}
|
||||
|
||||
void Palette::addFragment(uint resIndex, int16 id) {
|
||||
debug(0, "Palette::addFragment(%d, %d)", resIndex, id);
|
||||
|
||||
byte *fragmentData = _vm->_res->load(resIndex);
|
||||
byte count = _vm->_res->getCurItemSize() / 3;
|
||||
|
||||
memcpy(&_mainPalette[_fragmentIndex * 3], fragmentData, count * 3);
|
||||
|
||||
PaletteFragment fragment;
|
||||
fragment.id = id;
|
||||
fragment.index = _fragmentIndex;
|
||||
fragment.count = count;
|
||||
_fragments.push_back(fragment);
|
||||
|
||||
debug(0, "Palette::addFragment() index = %02X; count = %02X", fragment.index, fragment.count);
|
||||
|
||||
_fragmentIndex += count;
|
||||
|
||||
}
|
||||
|
||||
uint16 Palette::findFragment(int16 id) {
|
||||
debug(0, "Palette::findFragment(%d)", id);
|
||||
|
||||
uint16 result = 0;
|
||||
for (PaletteFragmentArray::iterator iter = _fragments.begin(); iter != _fragments.end(); iter++) {
|
||||
PaletteFragment fragment = *iter;
|
||||
if (fragment.id == id) {
|
||||
result = (fragment.count << 8) | fragment.index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
debug(0, "Palette::findFragment() result = %04X", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Palette::clearFragments() {
|
||||
debug(0, "Palette::clearFragments()");
|
||||
_fragmentIndex = 128;
|
||||
_fragments.clear();
|
||||
}
|
||||
|
||||
} // End of namespace Toltecs
|
87
engines/toltecs/palette.h
Normal file
87
engines/toltecs/palette.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOLTECS_PALETTE_H
|
||||
#define TOLTECS_PALETTE_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/array.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/voc.h"
|
||||
#include "sound/audiocd.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
//#define ROT(index) (((index << 4) & 0xF0) | ((index >> 4) & 0x0F))
|
||||
//#define ROT(index) (index)
|
||||
|
||||
class Palette {
|
||||
public:
|
||||
Palette(ToltecsEngine *vm);
|
||||
~Palette();
|
||||
|
||||
void setFullPalette(byte *palette);
|
||||
void setDeltaPalette(byte *palette, byte mask, char deltaValue, int16 count, int16 startIndex);
|
||||
|
||||
void loadAddPalette(uint resIndex, byte startIndex);
|
||||
void loadAddPaletteFrom(byte *source, byte startIndex, byte count);
|
||||
|
||||
void addFragment(uint resIndex, int16 id);
|
||||
uint16 findFragment(int16 id);
|
||||
void clearFragments();
|
||||
|
||||
byte *getMainPalette() { return _mainPalette; }
|
||||
|
||||
protected:
|
||||
|
||||
struct PaletteFragment {
|
||||
int16 id;
|
||||
byte index, count;
|
||||
};
|
||||
|
||||
typedef Common::Array<PaletteFragment> PaletteFragmentArray;
|
||||
|
||||
ToltecsEngine *_vm;
|
||||
|
||||
byte _mainPalette[768];
|
||||
|
||||
PaletteFragmentArray _fragments;
|
||||
byte _fragmentIndex;
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
||||
#endif /* TOLTECS_PALETTE_H */
|
161
engines/toltecs/resource.cpp
Normal file
161
engines/toltecs/resource.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "base/version.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
#include "toltecs/resource.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
|
||||
/* ArchiveReader */
|
||||
|
||||
ArchiveReader::ArchiveReader() {
|
||||
}
|
||||
|
||||
ArchiveReader::~ArchiveReader() {
|
||||
}
|
||||
|
||||
void ArchiveReader::openArchive(const char *filename) {
|
||||
open(filename);
|
||||
for (uint i = 0; i < 10000; i++)
|
||||
_offsets[i] = readUint32LE();
|
||||
}
|
||||
|
||||
uint32 ArchiveReader::openResource(uint resIndex) {
|
||||
uint32 resourceSize = getResourceSize(resIndex);
|
||||
seek(_offsets[resIndex]);
|
||||
return resourceSize;
|
||||
}
|
||||
|
||||
void ArchiveReader::closeResource() {
|
||||
}
|
||||
|
||||
|
||||
uint32 ArchiveReader::getResourceSize(uint resIndex) {
|
||||
return _offsets[resIndex + 1] - _offsets[resIndex];
|
||||
}
|
||||
|
||||
void ArchiveReader::dump(uint resIndex, const char *prefix) {
|
||||
int32 resourceSize = getResourceSize(resIndex);
|
||||
byte *data = new byte[resourceSize];
|
||||
|
||||
char fn[256];
|
||||
|
||||
if (prefix)
|
||||
snprintf(fn, 256, "%s_%04X.0", prefix, resIndex);
|
||||
else
|
||||
snprintf(fn, 256, "%04X.0", resIndex);
|
||||
|
||||
openResource(resIndex);
|
||||
read(data, resourceSize);
|
||||
closeResource();
|
||||
|
||||
FILE *o = fopen(fn, "wb");
|
||||
fwrite(data, resourceSize, 1, o);
|
||||
fclose(o);
|
||||
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
/* ResourceCache */
|
||||
|
||||
ResourceCache::ResourceCache(ToltecsEngine *vm) : _vm(vm) {
|
||||
|
||||
_base = new byte[kMaxCacheSize];
|
||||
_bytesUsed = 0;
|
||||
|
||||
memset(_cache, 0, sizeof(_cache));
|
||||
_cacheCount = 0;
|
||||
|
||||
_curItemOffset = 0;
|
||||
_curItemSize = 0;
|
||||
|
||||
}
|
||||
|
||||
ResourceCache::~ResourceCache() {
|
||||
delete[] _base;
|
||||
}
|
||||
|
||||
byte *ResourceCache::load(uint resIndex) {
|
||||
byte *data = NULL;
|
||||
if (existsItem(resIndex)) {
|
||||
debug(1, "ResourceCache::load(%d) From cache", resIndex);
|
||||
data = _base + _curItemOffset;
|
||||
} else {
|
||||
debug(1, "ResourceCache::load(%d) From disk", resIndex);
|
||||
uint32 size = _vm->_arc->openResource(resIndex);
|
||||
data = addItem(resIndex, size);
|
||||
_vm->_arc->read(data, size);
|
||||
_vm->_arc->closeResource();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
bool ResourceCache::existsItem(uint resIndex) {
|
||||
for (uint i = 0; i < _cacheCount; i++) {
|
||||
if (_cache[i].resIndex == resIndex) {
|
||||
_curItemOffset = _cache[i].offset;
|
||||
_curItemSize = _cache[i].size;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
byte *ResourceCache::addItem(uint resIndex, uint32 size) {
|
||||
|
||||
checkCapacity(size);
|
||||
|
||||
_curItemOffset = _bytesUsed;
|
||||
_curItemSize = size;
|
||||
|
||||
_cache[_cacheCount].resIndex = resIndex;
|
||||
_cache[_cacheCount].offset = _curItemOffset;
|
||||
_cache[_cacheCount].size = _curItemSize;
|
||||
_cacheCount++;
|
||||
|
||||
_bytesUsed += size;
|
||||
|
||||
return _base + _curItemOffset;
|
||||
|
||||
}
|
||||
|
||||
void ResourceCache::checkCapacity(uint32 size) {
|
||||
if (_cacheCount > kMaxCacheItems || _bytesUsed + size > kMaxCacheSize) {
|
||||
_cacheCount = 0;
|
||||
_bytesUsed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Toltecs
|
115
engines/toltecs/resource.h
Normal file
115
engines/toltecs/resource.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOLTECS_RESOURCE_H
|
||||
#define TOLTECS_RESOURCE_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/array.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/voc.h"
|
||||
#include "sound/audiocd.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
/*
|
||||
TODO:
|
||||
|
||||
ArchiveReader:
|
||||
- Add support for external resources; and check if they're used
|
||||
|
||||
*/
|
||||
|
||||
const uint kMaxCacheItems = 1024;
|
||||
const uint kMaxCacheSize = 8 * 1024 * 1024; // 8 MB
|
||||
|
||||
|
||||
class ArchiveReader : public Common::File {
|
||||
public:
|
||||
ArchiveReader();
|
||||
~ArchiveReader();
|
||||
|
||||
void openArchive(const char *filename);
|
||||
|
||||
// Returns the size of the opened resource
|
||||
uint32 openResource(uint resIndex);
|
||||
// Closes the resource
|
||||
void closeResource();
|
||||
// Returns the size of the resource
|
||||
uint32 getResourceSize(uint resIndex);
|
||||
|
||||
void dump(uint resIndex, const char *prefix = NULL);
|
||||
|
||||
protected:
|
||||
uint32 _offsets[10000];
|
||||
|
||||
};
|
||||
|
||||
class ResourceCache {
|
||||
public:
|
||||
ResourceCache(ToltecsEngine *vm);
|
||||
~ResourceCache();
|
||||
|
||||
byte *load(uint resIndex);
|
||||
uint32 getCurItemSize() const { return _curItemSize; }
|
||||
|
||||
protected:
|
||||
|
||||
struct CacheItem {
|
||||
uint resIndex;
|
||||
//int value; // what is this?
|
||||
int32 offset; // offset into _base
|
||||
uint32 size; // size of the item
|
||||
};
|
||||
|
||||
ToltecsEngine *_vm;
|
||||
|
||||
byte *_base;
|
||||
uint32 _bytesUsed;
|
||||
uint32 _curItemOffset, _curItemSize;
|
||||
|
||||
CacheItem _cache[kMaxCacheItems];
|
||||
uint _cacheCount;
|
||||
|
||||
bool existsItem(uint resIndex);
|
||||
byte *addItem(uint resIndex, uint32 size);
|
||||
void checkCapacity(uint32 size);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
||||
#endif /* TOLTECS_H */
|
971
engines/toltecs/screen.cpp
Normal file
971
engines/toltecs/screen.cpp
Normal file
|
@ -0,0 +1,971 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "base/version.h"
|
||||
|
||||
#include "graphics/cursorman.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
#include "toltecs/palette.h"
|
||||
#include "toltecs/resource.h"
|
||||
#include "toltecs/screen.h"
|
||||
#include "toltecs/script.h"
|
||||
#include "toltecs/segmap.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
Screen::Screen(ToltecsEngine *vm) : _vm(vm) {
|
||||
|
||||
_frontScreen = new byte[268800];
|
||||
_backScreen = new byte[870400];
|
||||
|
||||
memset(_fontResIndexArray, 0, sizeof(_fontResIndexArray));
|
||||
_fontColor1 = 0;
|
||||
_fontColor2 = 0;
|
||||
|
||||
// Screen shaking
|
||||
_shakeActive = false;
|
||||
_shakeCounterInit = 0;
|
||||
_shakeCounter = 0;
|
||||
_shakePos = 0;
|
||||
|
||||
// Verb line
|
||||
_verbLineNum = 0;
|
||||
memset(_verbLineItems, 0, sizeof(_verbLineItems));
|
||||
_verbLineX = 160;
|
||||
_verbLineY = 2;
|
||||
_verbLineWidth = 20;
|
||||
_verbLineCount = 0;
|
||||
|
||||
// Talk text
|
||||
_talkTextItemNum = 0;
|
||||
memset(_talkTextItems, 0, sizeof(_talkTextItems));
|
||||
_talkTextX = 0;//TODO correct init values
|
||||
_talkTextY = 0;
|
||||
_talkTextFontColor = 0;
|
||||
_talkTextMaxWidth = 520;
|
||||
|
||||
}
|
||||
|
||||
Screen::~Screen() {
|
||||
|
||||
delete[] _frontScreen;
|
||||
delete[] _backScreen;
|
||||
|
||||
}
|
||||
|
||||
void Screen::unpackRle(byte *source, byte *dest, uint16 width, uint16 height) {
|
||||
int32 size = width * height;
|
||||
while (size > 0) {
|
||||
byte a = *source++;
|
||||
byte b = *source++;
|
||||
if (a == 0) {
|
||||
dest += b;
|
||||
size -= b;
|
||||
} else {
|
||||
b = ((b << 4) & 0xF0) | ((b >> 4) & 0x0F);
|
||||
memset(dest, b, a);
|
||||
dest += a;
|
||||
size -= a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::loadMouseCursor(uint resIndex) {
|
||||
byte mouseCursor[16 * 16], *mouseCursorP = mouseCursor;
|
||||
byte *cursorData = _vm->_res->load(resIndex);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
byte pixel;
|
||||
byte mask1 = *cursorData++;
|
||||
byte mask2 = *cursorData++;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
pixel = 0xE5;
|
||||
if ((mask2 & 0x80) == 0)
|
||||
pixel = 0xE0;
|
||||
mask2 <<= 1;
|
||||
if ((mask1 & 0x80) == 0)
|
||||
pixel = 0;
|
||||
mask1 <<= 1;
|
||||
*mouseCursorP++ = pixel;
|
||||
}
|
||||
}
|
||||
//CursorMan.replaceCursor((const byte*)mouseCursor, 16, 16, 0, 0, 0);
|
||||
// FIXME: Where's the cursor hotspot? Using 8, 8 seems good enough for now.
|
||||
CursorMan.replaceCursor((const byte*)mouseCursor, 16, 16, 8, 8, 0);
|
||||
}
|
||||
|
||||
void Screen::drawGuiImage(int16 x, int16 y, uint resIndex) {
|
||||
|
||||
byte *imageData = _vm->_res->load(resIndex);
|
||||
int16 headerSize = READ_LE_UINT16(imageData);
|
||||
int16 width = imageData[2];
|
||||
int16 height = imageData[3];
|
||||
int16 workWidth = width, workHeight = height;
|
||||
imageData += headerSize;
|
||||
|
||||
byte *dest = _frontScreen + x + (y + _vm->_cameraHeight) * 640;
|
||||
|
||||
debug(0, "Screen::drawGuiImage() x = %d; y = %d; w = %d; h = %d; resIndex = %d", x, y, width, height, resIndex);
|
||||
|
||||
//_vm->_arc->dump(resIndex, "gui");
|
||||
|
||||
while (workHeight > 0) {
|
||||
int count = 1;
|
||||
byte pixel = *imageData++;
|
||||
if (pixel & 0x80) {
|
||||
pixel &= 0x7F;
|
||||
count = *imageData++;
|
||||
count += 2;
|
||||
}
|
||||
pixel = pixel + 0xE0;
|
||||
while (count-- && workHeight > 0) {
|
||||
*dest++ = pixel;
|
||||
workWidth--;
|
||||
if (workWidth == 0) {
|
||||
workHeight--;
|
||||
dest += 640 - width;
|
||||
workWidth = width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Screen::startShakeScreen(int16 shakeCounter) {
|
||||
_shakeActive = true;
|
||||
_shakeCounterInit = shakeCounter;
|
||||
_shakeCounter = shakeCounter;
|
||||
_shakePos = 0;
|
||||
}
|
||||
|
||||
void Screen::stopShakeScreen() {
|
||||
_shakeActive = false;
|
||||
_vm->_system->setShakePos(0);
|
||||
}
|
||||
|
||||
void Screen::updateShakeScreen() {
|
||||
if (_shakeActive) {
|
||||
_shakeCounter--;
|
||||
if (_shakeCounter == 0) {
|
||||
_shakeCounter = _shakeCounterInit;
|
||||
_shakePos ^= 8;
|
||||
_vm->_system->setShakePos(_shakePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::addStaticSprite(byte *spriteItem) {
|
||||
|
||||
DrawRequest drawRequest;
|
||||
memset(&drawRequest, 0, sizeof(drawRequest));
|
||||
|
||||
drawRequest.y = READ_LE_UINT16(spriteItem + 0);
|
||||
drawRequest.x = READ_LE_UINT16(spriteItem + 2);
|
||||
int16 fragmentId = READ_LE_UINT16(spriteItem + 4);
|
||||
drawRequest.baseColor = _vm->_palette->findFragment(fragmentId) & 0xFF;
|
||||
drawRequest.resIndex = READ_LE_UINT16(spriteItem + 6);
|
||||
drawRequest.flags = READ_LE_UINT16(spriteItem + 8);
|
||||
drawRequest.scaling = 0;
|
||||
|
||||
debug(0, "Screen::addStaticSprite() x = %d; y = %d; baseColor = %d; resIndex = %d; flags = %04X", drawRequest.x, drawRequest.y, drawRequest.baseColor, drawRequest.resIndex, drawRequest.flags);
|
||||
|
||||
addDrawRequest(drawRequest);
|
||||
|
||||
}
|
||||
|
||||
void Screen::addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, int16 *spriteArray, bool loop, int mode) {
|
||||
|
||||
debug(0, "Screen::addAnimatedSprite(%d, %d, %d)", x, y, fragmentId);
|
||||
|
||||
DrawRequest drawRequest;
|
||||
memset(&drawRequest, 0, sizeof(drawRequest));
|
||||
|
||||
drawRequest.x = x;
|
||||
drawRequest.y = y;
|
||||
drawRequest.baseColor = _vm->_palette->findFragment(fragmentId) & 0xFF;
|
||||
|
||||
if (mode == 1) {
|
||||
drawRequest.scaling = _vm->_segmap->getScalingAtPoint(drawRequest.x, drawRequest.y);
|
||||
} else if (mode == 2) {
|
||||
drawRequest.scaling = 0;
|
||||
}
|
||||
|
||||
int16 count = spriteArray[0];
|
||||
|
||||
debug(0, "count = %d", count);
|
||||
|
||||
for (int16 index = 1; index <= count; index++) {
|
||||
|
||||
byte *spriteItem = data + spriteArray[index];
|
||||
|
||||
uint16 loopNum = READ_LE_UINT16(spriteItem + 0) & 0x7FFF;
|
||||
uint16 loopCount = READ_LE_UINT16(spriteItem + 2);
|
||||
uint16 frameNum = READ_LE_UINT16(spriteItem + 4);
|
||||
uint16 frameCount = READ_LE_UINT16(spriteItem + 6);
|
||||
drawRequest.resIndex = READ_LE_UINT16(spriteItem + 8);
|
||||
drawRequest.flags = READ_LE_UINT16(spriteItem + 10 + loopNum * 2);
|
||||
|
||||
debug(0, "Screen::addAnimatedSprite(%d of %d) loopNum = %d; loopCount = %d; frameNum = %d; frameCount = %d; resIndex = %d; flags = %04X, mode = %d",
|
||||
index, count, loopNum, loopCount, frameNum, frameCount, drawRequest.resIndex, drawRequest.flags, mode);
|
||||
|
||||
addDrawRequest(drawRequest);
|
||||
|
||||
frameNum++;
|
||||
if (frameNum == frameCount) {
|
||||
frameNum = 0;
|
||||
loopNum++;
|
||||
if (loopNum == loopCount) {
|
||||
if (loop) {
|
||||
loopNum = 0;
|
||||
} else {
|
||||
loopNum--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loopNum |= 0x8000;
|
||||
}
|
||||
|
||||
WRITE_LE_UINT16(spriteItem + 0, loopNum);
|
||||
WRITE_LE_UINT16(spriteItem + 4, frameNum);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Screen::clearSprites() {
|
||||
|
||||
_spriteDrawList.clear();
|
||||
// TODO
|
||||
|
||||
}
|
||||
|
||||
void Screen::addDrawRequest(const DrawRequest &drawRequest) {
|
||||
|
||||
int16 scaleValueX, scaleValueY;
|
||||
int16 spriteDraw_X, spriteDraw_Y;
|
||||
byte *spriteData;
|
||||
int16 frameNum;
|
||||
|
||||
SpriteDrawItem sprite;
|
||||
memset(&sprite, 0, sizeof(SpriteDrawItem));
|
||||
|
||||
if (drawRequest.flags == 0xFFFF)
|
||||
return;
|
||||
|
||||
sprite.flags = 0;
|
||||
sprite.baseColor = drawRequest.baseColor;
|
||||
sprite.x = drawRequest.x;
|
||||
sprite.y = drawRequest.y;
|
||||
sprite.ybottom = drawRequest.y;
|
||||
sprite.resIndex = drawRequest.resIndex;
|
||||
|
||||
spriteData = _vm->_res->load(drawRequest.resIndex);
|
||||
|
||||
if (drawRequest.flags & 0x2000) {
|
||||
sprite.flags |= 0x10;
|
||||
}
|
||||
|
||||
if (drawRequest.flags & 0x4000) {
|
||||
sprite.flags |= 0x40;
|
||||
}
|
||||
|
||||
frameNum = drawRequest.flags & 0x0FFF;
|
||||
|
||||
// First initialize the sprite item with the values from the sprite resource
|
||||
|
||||
SpriteFrameEntry spriteFrameEntry(spriteData + frameNum * 12);
|
||||
|
||||
if (spriteFrameEntry.w == 0 || spriteFrameEntry.h == 0)
|
||||
return;
|
||||
|
||||
sprite.offset = spriteFrameEntry.offset;
|
||||
|
||||
sprite.width = spriteFrameEntry.w;
|
||||
sprite.height = spriteFrameEntry.h;
|
||||
|
||||
sprite.origWidth = spriteFrameEntry.w;
|
||||
sprite.origHeight = spriteFrameEntry.h;
|
||||
|
||||
if (drawRequest.flags & 0x1000) {
|
||||
spriteDraw_X = spriteFrameEntry.w - spriteFrameEntry.x;
|
||||
} else {
|
||||
spriteDraw_X = spriteFrameEntry.x;
|
||||
}
|
||||
|
||||
spriteDraw_Y = spriteFrameEntry.y;
|
||||
|
||||
// If the sprite should be scaled we need to initialize some values now
|
||||
|
||||
if (drawRequest.scaling != 0) {
|
||||
|
||||
byte scaleValue = ABS(drawRequest.scaling);
|
||||
|
||||
scaleValueX = scaleValue * sprite.origWidth;
|
||||
sprite.xdelta = (10000 * sprite.origWidth) / scaleValueX;
|
||||
scaleValueX /= 100;
|
||||
|
||||
scaleValueY = scaleValue * sprite.origHeight;
|
||||
sprite.ydelta = (10000 * sprite.origHeight) / scaleValueY;
|
||||
scaleValueY /= 100;
|
||||
|
||||
if (drawRequest.scaling > 0) {
|
||||
sprite.flags |= 2;
|
||||
sprite.width = sprite.origWidth + scaleValueX;
|
||||
sprite.height = sprite.origHeight + scaleValueY;
|
||||
spriteDraw_X += (spriteDraw_X * scaleValue) / 100;
|
||||
spriteDraw_Y += (spriteDraw_Y * scaleValue) / 100;
|
||||
} else {
|
||||
sprite.flags |= 1;
|
||||
sprite.width = sprite.origWidth - scaleValueX;
|
||||
sprite.height = sprite.origHeight - 1 - scaleValueY;
|
||||
if (sprite.width <= 0 || sprite.height <= 0)
|
||||
return;
|
||||
spriteDraw_X -= (spriteDraw_X * scaleValue) / 100;
|
||||
spriteDraw_Y -= (spriteDraw_Y * scaleValue) / 100;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sprite.x -= spriteDraw_X;
|
||||
sprite.y -= spriteDraw_Y;
|
||||
|
||||
sprite.yerror = sprite.ydelta;
|
||||
|
||||
// Now we check if the sprite needs to be clipped
|
||||
|
||||
// Clip Y
|
||||
if (sprite.y - _vm->_cameraY < 0) {
|
||||
|
||||
int16 clipHeight = ABS(sprite.y - _vm->_cameraY);
|
||||
int16 chopHeight, skipHeight, lineWidth;
|
||||
byte *spriteFrameData;
|
||||
|
||||
sprite.height -= clipHeight;
|
||||
if (sprite.height <= 0)
|
||||
return;
|
||||
|
||||
sprite.y = _vm->_cameraY;
|
||||
|
||||
// If the sprite is scaled
|
||||
if (sprite.flags & 3) {
|
||||
chopHeight = sprite.ydelta;
|
||||
skipHeight = clipHeight;
|
||||
if ((sprite.flags & 2) == 0) {
|
||||
do {
|
||||
chopHeight -= 100;
|
||||
if (chopHeight <= 0) {
|
||||
skipHeight++;
|
||||
chopHeight += sprite.ydelta;
|
||||
} else {
|
||||
clipHeight--;
|
||||
}
|
||||
} while (clipHeight > 0);
|
||||
} else {
|
||||
do {
|
||||
chopHeight -= 100;
|
||||
if (chopHeight < 0) {
|
||||
skipHeight--;
|
||||
chopHeight += sprite.ydelta + 100;
|
||||
}
|
||||
clipHeight--;
|
||||
} while (clipHeight > 0);
|
||||
}
|
||||
sprite.yerror = chopHeight;
|
||||
}
|
||||
|
||||
spriteFrameData = spriteData + sprite.offset;
|
||||
|
||||
// Now the sprite's offset is adjusted to point to the starting line
|
||||
if ((sprite.flags & 0x10) == 0) {
|
||||
while (clipHeight--) {
|
||||
lineWidth = 0;
|
||||
while (lineWidth </*CHECKME was != */ sprite.origWidth) {
|
||||
sprite.offset++;
|
||||
lineWidth += (*spriteFrameData++) & 0x0F;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lineWidth = 0;
|
||||
while (clipHeight--) {
|
||||
while (lineWidth < sprite.origWidth) {
|
||||
sprite.offset += 2;
|
||||
spriteFrameData++;
|
||||
lineWidth += *spriteFrameData++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (sprite.y + sprite.height - _vm->_cameraY - _vm->_cameraHeight > 0)
|
||||
sprite.height -= sprite.y + sprite.height - _vm->_cameraY - _vm->_cameraHeight;
|
||||
if (sprite.height <= 0)
|
||||
return;
|
||||
|
||||
sprite.value1 = 0;
|
||||
|
||||
if (drawRequest.flags & 0x1000) {
|
||||
// Left border
|
||||
sprite.flags |= 4;
|
||||
if (sprite.x - _vm->_cameraX < 0) {
|
||||
sprite.width -= ABS(sprite.x - _vm->_cameraX);
|
||||
if (sprite.width <= 0)
|
||||
return;
|
||||
sprite.x = _vm->_cameraX;
|
||||
}
|
||||
// Right border
|
||||
if (sprite.x + sprite.width - _vm->_cameraX - 640 > 0) {
|
||||
sprite.flags |= 8;
|
||||
sprite.width -= sprite.x + sprite.width - _vm->_cameraX - 640;
|
||||
if (sprite.width <= 0)
|
||||
return;
|
||||
sprite.value1 = sprite.x + sprite.width - _vm->_cameraX - 640;
|
||||
}
|
||||
} else {
|
||||
// Left border
|
||||
if (sprite.x - _vm->_cameraX < 0) {
|
||||
sprite.flags |= 8;
|
||||
sprite.width -= ABS(sprite.x - _vm->_cameraX);
|
||||
if (sprite.width <= 0)
|
||||
return;
|
||||
sprite.value1 = ABS(sprite.x - _vm->_cameraX);
|
||||
sprite.x = _vm->_cameraX;
|
||||
}
|
||||
// Right border
|
||||
if (sprite.x + sprite.width - _vm->_cameraX - 640 > 0) {
|
||||
sprite.flags |= 8;
|
||||
sprite.width -= sprite.x + sprite.width - _vm->_cameraX - 640;
|
||||
if (sprite.width <= 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add sprite sorted by priority
|
||||
Common::List<SpriteDrawItem>::iterator iter = _spriteDrawList.begin();
|
||||
while (iter != _spriteDrawList.end() && (*iter).ybottom <= sprite.ybottom) {
|
||||
iter++;
|
||||
}
|
||||
_spriteDrawList.insert(iter, sprite);
|
||||
|
||||
}
|
||||
|
||||
void Screen::drawSprite(SpriteDrawItem *sprite) {
|
||||
|
||||
debug(0, "Screen::drawSprite() x = %d; y = %d; flags = %04X; resIndex = %d; offset = %08X; drawX = %d; drawY = %d",
|
||||
sprite->x, sprite->y, sprite->flags, sprite->resIndex, sprite->offset,
|
||||
sprite->x - _vm->_cameraX, sprite->y - _vm->_cameraY);
|
||||
debug(0, "Screen::drawSprite() width = %d; height = %d; origWidth = %d; origHeight = %d",
|
||||
sprite->width, sprite->height, sprite->origWidth, sprite->origHeight);
|
||||
|
||||
byte *source = _vm->_res->load(sprite->resIndex) + sprite->offset;
|
||||
byte *dest = _frontScreen + (sprite->x - _vm->_cameraX) + (sprite->y - _vm->_cameraY) * 640;
|
||||
|
||||
// FIXME: Temporary hack until proper clipping is implemented
|
||||
/*
|
||||
int16 dx = sprite->x - _vm->_cameraX, dy = sprite->y - _vm->_cameraY;
|
||||
if (dx < 0 || dy < 0 || dx + sprite->width >= 640 || dy + sprite->height >= 400)
|
||||
return;
|
||||
*/
|
||||
|
||||
SpriteReader spriteReader(source, sprite);
|
||||
|
||||
if (sprite->flags & 0x40) {
|
||||
// TODO: Shadow sprites
|
||||
} else if (sprite->flags & 0x10) {
|
||||
// 256 color sprite
|
||||
drawSpriteCore(dest, spriteReader, sprite);
|
||||
} else {
|
||||
// 16 color sprite
|
||||
if (sprite->flags & 1) {
|
||||
SpriteFilterScaleDown spriteScaler(sprite, &spriteReader);
|
||||
drawSpriteCore(dest, spriteScaler, sprite);
|
||||
} else if (sprite->flags & 2) {
|
||||
SpriteFilterScaleUp spriteScaler(sprite, &spriteReader);
|
||||
drawSpriteCore(dest, spriteScaler, sprite);
|
||||
} else {
|
||||
drawSpriteCore(dest, spriteReader, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
debug(0, "Screen::drawSprite() ok");
|
||||
|
||||
}
|
||||
|
||||
void Screen::drawSpriteCore(byte *dest, SpriteFilter &reader, SpriteDrawItem *sprite) {
|
||||
|
||||
int16 destInc;
|
||||
|
||||
/*
|
||||
if ((sprite->flags & 8))
|
||||
return;
|
||||
*/
|
||||
|
||||
if (sprite->flags & 4) {
|
||||
destInc = -1;
|
||||
dest += sprite->width;
|
||||
} else {
|
||||
destInc = 1;
|
||||
}
|
||||
|
||||
SpriteReaderStatus status;
|
||||
PixelPacket packet;
|
||||
|
||||
byte *destp = dest;
|
||||
int16 skipX = sprite->value1;
|
||||
|
||||
do {
|
||||
status = reader.readPacket(packet);
|
||||
|
||||
if (skipX > 0) {
|
||||
while (skipX > 0) {
|
||||
skipX -= packet.count;
|
||||
if (skipX < 0) {
|
||||
packet.count = ABS(skipX);
|
||||
break;
|
||||
}
|
||||
status = reader.readPacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
if (((sprite->flags & 0x10) && (packet.pixel != 0xFF)) || !(sprite->flags & 0x10) && (packet.pixel != 0)) {
|
||||
if (sprite->flags & 0x40) {
|
||||
} else if (sprite->flags & 0x10) {
|
||||
packet.pixel = ((packet.pixel << 4) & 0xF0) | ((packet.pixel >> 4) & 0x0F);
|
||||
} else {
|
||||
packet.pixel += sprite->baseColor - 1;
|
||||
}
|
||||
while (packet.count--) {
|
||||
*dest = packet.pixel;
|
||||
dest += destInc;
|
||||
}
|
||||
} else {
|
||||
dest += packet.count * destInc;
|
||||
}
|
||||
|
||||
if (status == kSrsEndOfLine) {
|
||||
dest = destp + 640;
|
||||
destp = dest;
|
||||
skipX = sprite->value1;
|
||||
}
|
||||
|
||||
} while (status != kSrsEndOfSprite);
|
||||
|
||||
}
|
||||
|
||||
void Screen::drawSprites() {
|
||||
for (Common::List<SpriteDrawItem>::iterator iter = _spriteDrawList.begin(); iter != _spriteDrawList.end(); iter++) {
|
||||
SpriteDrawItem *sprite = &(*iter);
|
||||
drawSprite(sprite);
|
||||
_vm->_segmap->restoreMasksBySprite(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) {
|
||||
|
||||
debug(0, "Screen::updateVerbLine() _verbLineNum = %d; _verbLineX = %d; _verbLineY = %d; _verbLineWidth = %d; _verbLineCount = %d",
|
||||
_verbLineNum, _verbLineX, _verbLineY, _verbLineWidth, _verbLineCount);
|
||||
|
||||
Font font(_vm->_res->load(_fontResIndexArray[0]));
|
||||
|
||||
_verbLineItems[_verbLineNum].slotIndex = slotIndex;
|
||||
_verbLineItems[_verbLineNum].slotOffset = slotOffset;
|
||||
|
||||
// First clear the line
|
||||
int16 y = _verbLineY;
|
||||
for (int16 i = 0; i < _verbLineCount; i++) {
|
||||
byte *dest = _frontScreen + _verbLineX - _verbLineWidth / 2 + (y - 1 + _vm->_cameraHeight) * 640;
|
||||
for (int16 j = 0; j < 20; j++) {
|
||||
memset(dest, 0xE0, _verbLineWidth);
|
||||
dest += 640;
|
||||
}
|
||||
y += 18;
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
byte *sourceString;
|
||||
byte *destString;
|
||||
byte len;
|
||||
|
||||
_tempStringLen1 = 0;
|
||||
destString = _tempString;
|
||||
y = _verbLineY;
|
||||
|
||||
memset(_tempString, 0, sizeof(_tempString));
|
||||
|
||||
for (int16 i = 0; i <= _verbLineNum; i++) {
|
||||
sourceString = _vm->_script->getSlotData(_verbLineItems[i].slotIndex) + _verbLineItems[i].slotOffset;
|
||||
preprocessText(_fontResIndexArray[0], _verbLineWidth, width, sourceString, destString, len);
|
||||
_tempStringLen1 += len;
|
||||
}
|
||||
|
||||
if (_verbLineCount != 1) {
|
||||
int16 charWidth;
|
||||
if (*sourceString < 0xF0) {
|
||||
while (*sourceString > 0x20 && *sourceString < 0xF0 && len > 0/*CHECKME, len check added*/) {
|
||||
byte ch = *sourceString--;
|
||||
_tempStringLen1--;
|
||||
len--;
|
||||
charWidth = font.getCharWidth(ch) + font.getSpacing() - 1;
|
||||
width -= charWidth;
|
||||
}
|
||||
width += charWidth;
|
||||
sourceString++;
|
||||
_tempStringLen1 -= len;
|
||||
_tempStringLen2 = len + 1;
|
||||
|
||||
drawString(_verbLineX - 1 - (width / 2), y, 0xF9, 0xFF, _fontResIndexArray[0]);
|
||||
|
||||
destString = _tempString;
|
||||
width = 0;
|
||||
preprocessText(_fontResIndexArray[0], _verbLineWidth, width, sourceString, destString, len);
|
||||
|
||||
_tempStringLen1 += len;
|
||||
y += 9;
|
||||
}
|
||||
y += 9;
|
||||
}
|
||||
|
||||
_tempStringLen1 -= len;
|
||||
_tempStringLen2 = len;
|
||||
|
||||
drawString(_verbLineX - 1 - (width / 2), y, 0xF9, 0xFF, _fontResIndexArray[0]);
|
||||
|
||||
}
|
||||
|
||||
void Screen::updateTalkText(int16 slotIndex, int16 slotOffset) {
|
||||
|
||||
int16 x, y, maxWidth, width, length;
|
||||
byte durationModifier = 1;
|
||||
byte *textData = _vm->_script->getSlotData(slotIndex) + slotOffset;
|
||||
|
||||
TalkTextItem *item = &_talkTextItems[_talkTextItemNum];
|
||||
|
||||
item->fontNum = 0;
|
||||
item->color = _talkTextFontColor;
|
||||
|
||||
//debug(0, "## _talkTextMaxWidth = %d", _talkTextMaxWidth);
|
||||
|
||||
x = CLIP<int16>(_talkTextX - _vm->_cameraX, 120, _talkTextMaxWidth);
|
||||
y = CLIP<int16>(_talkTextY - _vm->_cameraY, 4, _vm->_cameraHeight - 16);
|
||||
|
||||
maxWidth = 624 - ABS(x - 320) * 2;
|
||||
|
||||
while (1) {
|
||||
if (*textData == 0x0A) {
|
||||
x = CLIP<int16>(textData[3], 120, _talkTextMaxWidth);
|
||||
y = CLIP<int16>(READ_LE_UINT16(&textData[1]), 4, _vm->_cameraHeight - 16);
|
||||
maxWidth = 624 - ABS(x - 320) * 2;
|
||||
textData += 4;
|
||||
} else if (*textData == 0x14) {
|
||||
item->color = textData[1];
|
||||
textData += 2;
|
||||
} else if (*textData == 0x19) {
|
||||
durationModifier = textData[1];
|
||||
textData += 2;
|
||||
} else if (*textData < 0x0A) {
|
||||
item->fontNum = textData[1];
|
||||
textData += 2;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
item->slotIndex = slotIndex;
|
||||
item->slotOffset = textData - _vm->_script->getSlotData(slotIndex);
|
||||
|
||||
width = 0;
|
||||
length = 0;
|
||||
|
||||
item->rectCount = 0;
|
||||
|
||||
Font font(_vm->_res->load(_fontResIndexArray[item->fontNum]));
|
||||
int16 wordLength, wordWidth;
|
||||
|
||||
while (*textData < 0xF0) {
|
||||
if (*textData == 0x1E) {
|
||||
textData++;
|
||||
addTalkTextRect(font, x, y, length, width, item);
|
||||
// CHECKME?
|
||||
width = 0;
|
||||
length = 0;
|
||||
} else {
|
||||
wordLength = 0;
|
||||
wordWidth = 0;
|
||||
while (*textData >= 0x20 && *textData < 0xF0) {
|
||||
byte ch = *textData++;
|
||||
wordLength++;
|
||||
if (ch == 0x20) {
|
||||
wordWidth += font.getWidth();
|
||||
break;
|
||||
} else {
|
||||
wordWidth += font.getCharWidth(ch) + font.getSpacing() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
debug(0, "## width = %d; wordWidth = %d; width + wordWidth = %d; maxWidth + font.getWidth() = %d",
|
||||
width, wordWidth, width + wordWidth, maxWidth + font.getWidth());
|
||||
|
||||
if (width + wordWidth > maxWidth + font.getWidth()) {
|
||||
addTalkTextRect(font, x, y, length, width, item);
|
||||
width = wordWidth;
|
||||
length = wordLength;
|
||||
} else {
|
||||
width += wordWidth;
|
||||
length += wordLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addTalkTextRect(font, x, y, length, width, item);
|
||||
|
||||
debug(0, "## item->rectCount = %d", item->rectCount);
|
||||
|
||||
int16 textDurationMultiplier = item->duration + 8;
|
||||
// TODO: Check sound/text flags
|
||||
if (*textData == 0xFE) {
|
||||
//textDurationMultiplier += 100;
|
||||
}
|
||||
item->duration = 4 * textDurationMultiplier * durationModifier;
|
||||
|
||||
}
|
||||
|
||||
void Screen::addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 width, TalkTextItem *item) {
|
||||
|
||||
if (width > 0) {
|
||||
TextRect *textRect = &item->rects[item->rectCount];
|
||||
width = width + 1 - font.getSpacing();
|
||||
textRect->width = width;
|
||||
item->duration += length;
|
||||
textRect->length = length;
|
||||
textRect->y = y;
|
||||
textRect->x = CLIP<int16>(x - width / 2, 0, 640);
|
||||
item->rectCount++;
|
||||
}
|
||||
|
||||
y += font.getHeight() - 1;
|
||||
|
||||
}
|
||||
|
||||
void Screen::drawTalkTextItems() {
|
||||
|
||||
//debug(0, "## _talkTextItemNum = %d", _talkTextItemNum);
|
||||
|
||||
for (int16 i = 0; i <= _talkTextItemNum; i++) {
|
||||
TalkTextItem *item = &_talkTextItems[i];
|
||||
byte *text = _vm->_script->getSlotData(item->slotIndex) + item->slotOffset;
|
||||
|
||||
if (item->fontNum == -1 || item->duration == 0)
|
||||
continue;
|
||||
|
||||
item->duration -= _vm->_counter01;
|
||||
if (item->duration < 0)
|
||||
item->duration = 0;
|
||||
|
||||
Font font(_vm->_res->load(_fontResIndexArray[item->fontNum]));
|
||||
for (byte j = 0; j < item->rectCount; j++) {
|
||||
int16 x = item->rects[j].x;
|
||||
for (byte pos = 0; pos < item->rects[j].length; pos++) {
|
||||
byte ch = *text++;
|
||||
if (ch < 0x20)
|
||||
continue;
|
||||
if (ch == 0x20) {
|
||||
x += font.getWidth();
|
||||
} else {
|
||||
drawChar2(font, _frontScreen, x, item->rects[j].y, ch, item->color);
|
||||
x += font.getCharWidth(ch) + font.getSpacing() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int16 Screen::getTalkTextDuration() {
|
||||
return _talkTextItems[_talkTextItemNum].duration;
|
||||
}
|
||||
|
||||
void Screen::registerFont(uint fontIndex, uint resIndex) {
|
||||
_fontResIndexArray[fontIndex] = resIndex;
|
||||
}
|
||||
|
||||
void Screen::printText(byte *textData) {
|
||||
|
||||
int16 x = 0, y = 0;
|
||||
|
||||
// Really strange stuff.
|
||||
for (int i = 30; i >= 0; i--) {
|
||||
if (textData[i] >= 0xF0)
|
||||
break;
|
||||
if (i == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
if (*textData == 0x0A) {
|
||||
// Set text position
|
||||
y = textData[1];
|
||||
x = READ_LE_UINT32(textData + 2);
|
||||
textData += 4;
|
||||
} else if (*textData == 0x0B) {
|
||||
// Inc text position
|
||||
y += textData[1]; // CHECKME: Maybe these are signed?
|
||||
x += textData[2];
|
||||
textData += 3;
|
||||
} else {
|
||||
byte *destString = _tempString;
|
||||
int width = 0;
|
||||
_tempStringLen1 = 0;
|
||||
preprocessText(_fontResIndexArray[1], 640, width, textData, destString, _tempStringLen2);
|
||||
drawString(x - width / 2, y, _fontColor1, _fontColor2, _fontResIndexArray[1]);
|
||||
}
|
||||
|
||||
} while (*textData != 0xFF);
|
||||
|
||||
}
|
||||
|
||||
void Screen::preprocessText(uint fontResIndex, int maxWidth, int &width, byte *&sourceString, byte *&destString, byte &len) {
|
||||
|
||||
Font font(_vm->_res->load(fontResIndex));
|
||||
|
||||
len = 0;
|
||||
while (*sourceString >= 0x20 && *sourceString < 0xF0) {
|
||||
byte ch = *sourceString;
|
||||
byte charWidth;
|
||||
if (ch <= 0x20)
|
||||
charWidth = font.getWidth();
|
||||
else
|
||||
charWidth = font.getCharWidth(ch) + font.getSpacing() - 1;
|
||||
if (width + charWidth >= maxWidth)
|
||||
break;
|
||||
len++;
|
||||
width += charWidth;
|
||||
*destString++ = *sourceString++;
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::drawString(int16 x, int16 y, byte fontColor1, byte fontColor2, uint fontResIndex) {
|
||||
|
||||
debug(0, "Screen::drawString(%d, %d, %d, %d, %d) _tempStringLen1 = %d; _tempStringLen2 = %d", x, y, fontColor1, fontColor2, fontResIndex, _tempStringLen1, _tempStringLen2);
|
||||
|
||||
Font font(_vm->_res->load(fontResIndex));
|
||||
|
||||
byte color = fontColor1;
|
||||
byte *text = _tempString;
|
||||
byte len = _tempStringLen1 + _tempStringLen2;
|
||||
int16 yadd = 1;
|
||||
|
||||
for (byte pos = 0; pos < len; pos++) {
|
||||
if (pos == _tempStringLen1) {
|
||||
color = fontColor2;
|
||||
}
|
||||
byte ch = *text++;
|
||||
if (ch <= 0x20) {
|
||||
x += font.getWidth();
|
||||
} else {
|
||||
drawChar(font, _frontScreen, x + 1, y + _vm->_cameraHeight - yadd, ch, color);
|
||||
x += font.getCharWidth(ch) + font.getSpacing() - 1;
|
||||
yadd = -yadd;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Merge drawChar and drawChar2
|
||||
|
||||
void Screen::drawChar(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color) {
|
||||
|
||||
int16 charWidth, charHeight;
|
||||
byte *charData;
|
||||
|
||||
dest += x + (y * 640);
|
||||
|
||||
charWidth = font.getCharWidth(ch);
|
||||
charHeight = font.getHeight() - 2;
|
||||
charData = font.getCharData(ch);
|
||||
|
||||
while (charHeight--) {
|
||||
byte lineWidth = charWidth;
|
||||
while (lineWidth > 0) {
|
||||
byte count = charData[0] & 0x0F;
|
||||
byte flags = charData[0] & 0xF0;
|
||||
charData++;
|
||||
lineWidth -= count;
|
||||
if (!(flags & 0x80) && (flags & 0x10)) {
|
||||
memset(dest, color, count);
|
||||
}
|
||||
dest += count;
|
||||
}
|
||||
dest += 640 - charWidth;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Screen::drawChar2(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color) {
|
||||
|
||||
int16 charWidth, charHeight;
|
||||
byte *charData;
|
||||
|
||||
dest += x + (y * 640);
|
||||
|
||||
charWidth = font.getCharWidth(ch);
|
||||
charHeight = font.getHeight() - 2;
|
||||
charData = font.getCharData(ch);
|
||||
|
||||
while (charHeight--) {
|
||||
byte lineWidth = charWidth;
|
||||
while (lineWidth > 0) {
|
||||
byte count = charData[0] & 0x0F;
|
||||
byte flags = charData[0] & 0xF0;
|
||||
charData++;
|
||||
lineWidth -= count;
|
||||
|
||||
if ((flags & 0x80) == 0) {
|
||||
if ((flags & 0x10) == 0) {
|
||||
memset(dest, 0, count);
|
||||
} else {
|
||||
memset(dest, color, count);
|
||||
}
|
||||
}
|
||||
|
||||
dest += count;
|
||||
}
|
||||
dest += 640 - charWidth;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
void Screen::update() {
|
||||
}
|
||||
*/
|
||||
|
||||
} // End of namespace Toltecs
|
378
engines/toltecs/screen.h
Normal file
378
engines/toltecs/screen.h
Normal file
|
@ -0,0 +1,378 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOLTECS_SCREEN_H
|
||||
#define TOLTECS_SCREEN_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/list.h"
|
||||
#include "common/array.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/voc.h"
|
||||
#include "sound/audiocd.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
struct DrawRequest {
|
||||
int16 x, y;
|
||||
int16 resIndex;
|
||||
uint16 flags;
|
||||
int16 baseColor;
|
||||
int8 scaling;
|
||||
};
|
||||
|
||||
struct SpriteDrawItem {
|
||||
int16 x, y;
|
||||
int16 width, height;
|
||||
int16 origWidth, origHeight;
|
||||
int16 resIndex;
|
||||
uint32 offset;
|
||||
int16 xdelta, ydelta;
|
||||
uint16 flags;
|
||||
int16 value1, yerror;
|
||||
int16 ybottom;
|
||||
int16 baseColor;
|
||||
};
|
||||
|
||||
struct SpriteFrameEntry {
|
||||
int16 y, x, h, w;
|
||||
uint32 offset;
|
||||
SpriteFrameEntry() {
|
||||
}
|
||||
SpriteFrameEntry(byte *data) {
|
||||
y = READ_LE_UINT16(data + 0);
|
||||
x = READ_LE_UINT16(data + 2);
|
||||
h = READ_LE_UINT16(data + 4);
|
||||
w = READ_LE_UINT16(data + 6);
|
||||
offset = READ_LE_UINT32(data + 8);
|
||||
}
|
||||
};
|
||||
|
||||
class Font {
|
||||
public:
|
||||
Font(byte *fontData) : _fontData(fontData) {
|
||||
}
|
||||
~Font() {
|
||||
}
|
||||
int16 getSpacing() const {
|
||||
return _fontData[1];
|
||||
}
|
||||
int16 getHeight() const {
|
||||
return _fontData[2];
|
||||
}
|
||||
int16 getWidth() const {
|
||||
return _fontData[3];
|
||||
}
|
||||
int16 getCharWidth(byte ch) const {
|
||||
return _fontData[4 + (ch - 0x21)];
|
||||
}
|
||||
byte *getCharData(byte ch) const {
|
||||
return _fontData + 0x298 + READ_LE_UINT16(&_fontData[0xE0 + (ch - 0x21) * 2]);
|
||||
}
|
||||
protected:
|
||||
byte *_fontData;
|
||||
};
|
||||
|
||||
//*BEGIN*TEST*CODE********************************************************************************************
|
||||
|
||||
struct PixelPacket {
|
||||
byte count;
|
||||
byte pixel;
|
||||
};
|
||||
|
||||
enum SpriteReaderStatus {
|
||||
kSrsPixelsLeft,
|
||||
kSrsEndOfLine,
|
||||
kSrsEndOfSprite
|
||||
};
|
||||
|
||||
class SpriteFilter {
|
||||
public:
|
||||
SpriteFilter(SpriteDrawItem *sprite) : _sprite(sprite) {
|
||||
}
|
||||
virtual SpriteReaderStatus readPacket(PixelPacket &packet) = 0;
|
||||
protected:
|
||||
SpriteDrawItem *_sprite;
|
||||
};
|
||||
|
||||
class SpriteReader : public SpriteFilter {
|
||||
public:
|
||||
SpriteReader(byte *source, SpriteDrawItem *sprite) : SpriteFilter(sprite), _source(source) {
|
||||
_curWidth = _sprite->origWidth;
|
||||
_curHeight = _sprite->origHeight;
|
||||
}
|
||||
SpriteReaderStatus readPacket(PixelPacket &packet) {
|
||||
if ((_sprite->flags & 0x40) || (_sprite->flags & 0x10)) {
|
||||
packet.pixel = *_source++;
|
||||
packet.count = *_source++;
|
||||
} else {
|
||||
packet.count = _source[0] & 0x0F;
|
||||
packet.pixel = (_source[0] & 0xF0) >> 4;
|
||||
_source++;
|
||||
}
|
||||
_curWidth -= packet.count;
|
||||
if (_curWidth <= 0) {
|
||||
_curHeight--;
|
||||
if (_curHeight == 0) {
|
||||
return kSrsEndOfSprite;
|
||||
} else {
|
||||
_curWidth = _sprite->origWidth;
|
||||
return kSrsEndOfLine;
|
||||
}
|
||||
} else {
|
||||
return kSrsPixelsLeft;
|
||||
}
|
||||
}
|
||||
byte *getSource() {
|
||||
return _source;
|
||||
}
|
||||
void setSource(byte *source) {
|
||||
_source = source;
|
||||
_curHeight++;
|
||||
}
|
||||
protected:
|
||||
byte *_source;
|
||||
int16 _curWidth, _curHeight;
|
||||
};
|
||||
|
||||
class SpriteFilterScaleDown : public SpriteFilter {
|
||||
public:
|
||||
SpriteFilterScaleDown(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
|
||||
_height = _sprite->height;
|
||||
_yerror = _sprite->yerror;
|
||||
_origHeight = _sprite->origHeight;
|
||||
_scalerStatus = 0;
|
||||
}
|
||||
SpriteReaderStatus readPacket(PixelPacket &packet) {
|
||||
SpriteReaderStatus status;
|
||||
if (_scalerStatus == 0) {
|
||||
_xerror = _sprite->xdelta;
|
||||
_yerror -= 100;
|
||||
while (_yerror <= 0) {
|
||||
do {
|
||||
status = _reader->readPacket(packet);
|
||||
} while (status == kSrsPixelsLeft);
|
||||
_yerror += _sprite->ydelta - 100;
|
||||
}
|
||||
if (status == kSrsEndOfSprite)
|
||||
return kSrsEndOfSprite;
|
||||
_scalerStatus = 1;
|
||||
}
|
||||
if (_scalerStatus == 1) {
|
||||
status = _reader->readPacket(packet);
|
||||
byte updcount = packet.count;
|
||||
while (updcount--) {
|
||||
_xerror -= 100;
|
||||
if (_xerror <= 0) {
|
||||
if (packet.count > 0)
|
||||
packet.count--;
|
||||
_xerror += _sprite->xdelta;
|
||||
}
|
||||
}
|
||||
if (status == kSrsEndOfLine) {
|
||||
if (--_height == 0)
|
||||
return kSrsEndOfSprite;
|
||||
_scalerStatus = 0;
|
||||
return kSrsEndOfLine;
|
||||
}
|
||||
}
|
||||
return kSrsPixelsLeft;
|
||||
}
|
||||
protected:
|
||||
SpriteReader *_reader;
|
||||
int16 _xerror, _yerror;
|
||||
int16 _height;
|
||||
int16 _origHeight;
|
||||
int _scalerStatus;
|
||||
};
|
||||
|
||||
class SpriteFilterScaleUp : public SpriteFilter {
|
||||
public:
|
||||
SpriteFilterScaleUp(SpriteDrawItem *sprite, SpriteReader *reader) : SpriteFilter(sprite), _reader(reader) {
|
||||
_height = _sprite->height;
|
||||
_yerror = _sprite->yerror;
|
||||
_origHeight = _sprite->origHeight;
|
||||
_scalerStatus = 0;
|
||||
}
|
||||
SpriteReaderStatus readPacket(PixelPacket &packet) {
|
||||
SpriteReaderStatus status;
|
||||
if (_scalerStatus == 0) {
|
||||
_xerror = _sprite->xdelta;
|
||||
_sourcep = _reader->getSource();
|
||||
_scalerStatus = 1;
|
||||
}
|
||||
if (_scalerStatus == 1) {
|
||||
status = _reader->readPacket(packet);
|
||||
byte updcount = packet.count;
|
||||
while (updcount--) {
|
||||
_xerror -= 100;
|
||||
if (_xerror <= 0) {
|
||||
packet.count++;
|
||||
_xerror += _sprite->xdelta;
|
||||
}
|
||||
}
|
||||
if (status == kSrsEndOfLine) {
|
||||
if (--_height == 0)
|
||||
return kSrsEndOfSprite;
|
||||
_yerror -= 100;
|
||||
if (_yerror <= 0) {
|
||||
_reader->setSource(_sourcep);
|
||||
_yerror += _sprite->ydelta + 100;
|
||||
}
|
||||
_scalerStatus = 0;
|
||||
return kSrsEndOfLine;
|
||||
}
|
||||
}
|
||||
return kSrsPixelsLeft;
|
||||
}
|
||||
protected:
|
||||
SpriteReader *_reader;
|
||||
byte *_sourcep;
|
||||
int16 _xerror, _yerror;
|
||||
int16 _height;
|
||||
int16 _origHeight;
|
||||
int _scalerStatus;
|
||||
};
|
||||
|
||||
//*END*TEST*CODE**********************************************************************************************
|
||||
|
||||
struct TextRect {
|
||||
int16 x, y;
|
||||
int16 width, length;
|
||||
};
|
||||
|
||||
struct TalkTextItem {
|
||||
int16 duration;
|
||||
int16 slotIndex;
|
||||
int16 slotOffset;
|
||||
int16 fontNum;
|
||||
byte color;
|
||||
byte rectCount;
|
||||
TextRect rects[15];
|
||||
};
|
||||
|
||||
class Screen {
|
||||
public:
|
||||
Screen(ToltecsEngine *vm);
|
||||
~Screen();
|
||||
|
||||
void unpackRle(byte *source, byte *dest, uint16 width, uint16 height);
|
||||
|
||||
void loadMouseCursor(uint resIndex);
|
||||
|
||||
void drawGuiImage(int16 x, int16 y, uint resIndex);
|
||||
|
||||
void startShakeScreen(int16 shakeCounter);
|
||||
void stopShakeScreen();
|
||||
void updateShakeScreen();
|
||||
|
||||
// Sprite list
|
||||
void addStaticSprite(byte *spriteItem);
|
||||
void addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, int16 *spriteArray, bool loop, int mode);
|
||||
void clearSprites();
|
||||
|
||||
// Sprite drawing
|
||||
void drawSprite(SpriteDrawItem *sprite);
|
||||
void drawSpriteCore(byte *dest, SpriteFilter &reader, SpriteDrawItem *sprite);
|
||||
void drawSprites();
|
||||
|
||||
// Verb line
|
||||
void updateVerbLine(int16 slotIndex, int16 slotOffset);
|
||||
|
||||
// Talk text
|
||||
void updateTalkText(int16 slotIndex, int16 slotOffset);
|
||||
void addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 width, TalkTextItem *item);
|
||||
void drawTalkTextItems();
|
||||
int16 getTalkTextDuration();
|
||||
|
||||
// Font/text
|
||||
void registerFont(uint fontIndex, uint resIndex);
|
||||
void printText(byte *textData);
|
||||
void preprocessText(uint fontResIndex, int maxWidth, int &width, byte *&sourceString, byte *&destString, byte &len);
|
||||
void drawString(int16 x, int16 y, byte fontColor1, byte fontColor2, uint fontResIndex);
|
||||
void drawChar(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color);
|
||||
void drawChar2(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color);
|
||||
|
||||
//protected:
|
||||
public:
|
||||
|
||||
struct VerbLineItem {
|
||||
int16 slotIndex;
|
||||
int16 slotOffset;
|
||||
};
|
||||
|
||||
struct Rect {
|
||||
int16 x, y, width, height;
|
||||
};
|
||||
|
||||
ToltecsEngine *_vm;
|
||||
|
||||
byte *_frontScreen, *_backScreen;
|
||||
|
||||
Common::List<SpriteDrawItem> _spriteDrawList;
|
||||
|
||||
uint _fontResIndexArray[10];
|
||||
byte _fontColor1, _fontColor2;
|
||||
|
||||
byte _tempString[100];
|
||||
byte _tempStringLen1, _tempStringLen2;
|
||||
|
||||
// Screen shaking
|
||||
bool _shakeActive;
|
||||
int16 _shakeCounterInit, _shakeCounter;
|
||||
int _shakePos;
|
||||
|
||||
// Verb line
|
||||
int16 _verbLineNum;
|
||||
VerbLineItem _verbLineItems[8];
|
||||
int16 _verbLineX, _verbLineY, _verbLineWidth;
|
||||
int16 _verbLineCount;
|
||||
|
||||
// Talk text
|
||||
int16 _talkTextX, _talkTextY;
|
||||
int16 _talkTextMaxWidth;
|
||||
byte _talkTextFontColor;
|
||||
int16 _talkTextItemNum;
|
||||
TalkTextItem _talkTextItems[5];
|
||||
|
||||
void addDrawRequest(const DrawRequest &drawRequest);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
||||
#endif /* TOLTECS_SCREEN_H */
|
1219
engines/toltecs/script.cpp
Normal file
1219
engines/toltecs/script.cpp
Normal file
File diff suppressed because it is too large
Load diff
132
engines/toltecs/script.h
Normal file
132
engines/toltecs/script.h
Normal file
|
@ -0,0 +1,132 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOLTECS_SCRIPT_H
|
||||
#define TOLTECS_SCRIPT_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/array.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/voc.h"
|
||||
#include "sound/audiocd.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
const int kMaxScriptSlots = 50;
|
||||
|
||||
class ScriptInterpreter {
|
||||
public:
|
||||
ScriptInterpreter(ToltecsEngine *vm);
|
||||
~ScriptInterpreter();
|
||||
|
||||
void loadScript(uint resIndex, uint slotIndex);
|
||||
void runScript(uint slotIndex);
|
||||
|
||||
byte *getSlotData(int slotIndex) const { return _slots[slotIndex].data; }
|
||||
|
||||
protected:
|
||||
|
||||
enum VarType {
|
||||
vtByte,
|
||||
vtWord
|
||||
};
|
||||
|
||||
struct ScriptRegs {
|
||||
int16 reg0;
|
||||
int16 reg1;
|
||||
int16 reg2;
|
||||
int16 reg3;
|
||||
int16 reg4;
|
||||
int16 reg5;
|
||||
int16 reg6;
|
||||
int16 sp;
|
||||
int16 reg8;
|
||||
};
|
||||
|
||||
struct ScriptSlot {
|
||||
byte *data;
|
||||
int32 size;
|
||||
uint resIndex;
|
||||
};
|
||||
|
||||
ToltecsEngine *_vm;
|
||||
|
||||
byte *_stack;
|
||||
|
||||
byte *_code, *_subCode;
|
||||
byte *_localData;
|
||||
bool _switchStack1, _switchStack2, _switchStack3;
|
||||
bool _scriptFlag01;
|
||||
|
||||
ScriptSlot _slots[kMaxScriptSlots];
|
||||
|
||||
ScriptRegs _regs;
|
||||
int16 _savedSp;
|
||||
|
||||
byte readByte();
|
||||
int16 readInt16();
|
||||
|
||||
void execOpcode(byte opcode);
|
||||
void execKernelOpcode(uint16 kernelOpcode);
|
||||
|
||||
VarType getGameVarType(uint variable);
|
||||
int16 getGameVar(uint variable);
|
||||
void setGameVar(uint variable, int16 value);
|
||||
|
||||
byte arg8(int16 offset);
|
||||
int16 arg16(int16 offset);
|
||||
int32 arg32(int16 offset);
|
||||
|
||||
void push8(byte value);
|
||||
byte pop8();
|
||||
void push16(int16 value);
|
||||
int16 pop16();
|
||||
void push32(int32 value);
|
||||
int32 pop32();
|
||||
|
||||
void localWrite8(int16 offset, byte value);
|
||||
byte localRead8(int16 offset);
|
||||
void localWrite16(int16 offset, int16 value);
|
||||
int16 localRead16(int16 offset);
|
||||
void localWrite32(int16 offset, int32 value);
|
||||
int32 localRead32(int16 offset);
|
||||
byte *localPtr(int16 offset);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
||||
#endif /* TOLTECS_H */
|
535
engines/toltecs/segmap.cpp
Normal file
535
engines/toltecs/segmap.cpp
Normal file
|
@ -0,0 +1,535 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "graphics/primitives.h"
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "base/version.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
#include "toltecs/resource.h"
|
||||
#include "toltecs/screen.h"
|
||||
#include "toltecs/segmap.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
SegmentMap::SegmentMap(ToltecsEngine *vm) : _vm(vm) {
|
||||
_maskRectData = new byte[32768];
|
||||
}
|
||||
|
||||
SegmentMap::~SegmentMap() {
|
||||
delete[] _maskRectData;
|
||||
}
|
||||
|
||||
void SegmentMap::load(byte *source) {
|
||||
|
||||
// TODO: Use MemoryReadStream
|
||||
|
||||
_maskRects.clear();
|
||||
_pathRects.clear();
|
||||
_infoRects.clear();
|
||||
|
||||
// Load mask rects
|
||||
uint16 maskSize = READ_LE_UINT16(source);
|
||||
source += 2;
|
||||
uint16 maskRectCount = READ_LE_UINT16(source);
|
||||
source += 2;
|
||||
uint16 maskRectDataSize = maskRectCount * 12 + 2;
|
||||
|
||||
debug(0, "SegmentMap::load() maskRectCount = %d", maskRectCount);
|
||||
|
||||
for (uint16 i = 0; i < maskRectCount; i++) {
|
||||
SegmapMaskRect maskRect;
|
||||
maskRect.y = READ_LE_UINT16(source);
|
||||
maskRect.x = READ_LE_UINT16(source + 2);
|
||||
maskRect.height = READ_LE_UINT16(source + 4);
|
||||
maskRect.width = READ_LE_UINT16(source + 6);
|
||||
maskRect.maskOffset = READ_LE_UINT16(source + 8);
|
||||
maskRect.maskOffset -= maskRectDataSize;
|
||||
maskRect.ybottom = READ_LE_UINT16(source + 10);
|
||||
|
||||
debug(0, "SegmentMap::load() (%d, %d, %d, %d, %04X, %d)",
|
||||
maskRect.x, maskRect.y, maskRect.width, maskRect.height, maskRect.maskOffset, maskRect.ybottom);
|
||||
|
||||
source += 12;
|
||||
_maskRects.push_back(maskRect);
|
||||
}
|
||||
|
||||
memcpy(_maskRectData, source, maskSize - maskRectDataSize);
|
||||
source += maskSize - maskRectDataSize;
|
||||
|
||||
// Load path rects
|
||||
|
||||
source += 2; // skip rects array size
|
||||
|
||||
uint16 pathRectCount = READ_LE_UINT16(source);
|
||||
source += 2;
|
||||
|
||||
debug(0, "SegmentMap::load() pathRectCount = %d", pathRectCount);
|
||||
|
||||
for (uint16 i = 0; i < pathRectCount; i++) {
|
||||
SegmapPathRect pathRect;
|
||||
pathRect.y = READ_LE_UINT16(source);
|
||||
pathRect.x = READ_LE_UINT16(source + 2);
|
||||
pathRect.height = READ_LE_UINT16(source + 4);
|
||||
pathRect.width = READ_LE_UINT16(source + 6);
|
||||
|
||||
debug(0, "SegmentMap::load() (%d, %d, %d, %d)", pathRect.x, pathRect.y, pathRect.width, pathRect.height);
|
||||
|
||||
source += 8;
|
||||
_pathRects.push_back(pathRect);
|
||||
}
|
||||
|
||||
// Load info rects
|
||||
|
||||
source += 2; // skip rects array size
|
||||
|
||||
uint16 infoRectCount = READ_LE_UINT16(source);
|
||||
source += 2;
|
||||
debug(0, "SegmentMap::load() infoRectCount = %d", infoRectCount);
|
||||
for (uint16 i = 0; i < infoRectCount; i++) {
|
||||
SegmapInfoRect infoRect;
|
||||
infoRect.y = READ_LE_UINT16(source);
|
||||
infoRect.x = READ_LE_UINT16(source + 2);
|
||||
infoRect.height = READ_LE_UINT16(source + 4);
|
||||
infoRect.width = READ_LE_UINT16(source + 6);
|
||||
infoRect.id = source[8];
|
||||
infoRect.a = source[9];
|
||||
infoRect.b = source[10];
|
||||
infoRect.c = source[11];
|
||||
|
||||
debug(0, "SegmentMap::load() (%d, %d, %d, %d) (%d, %d, %d, %d)",
|
||||
infoRect.x, infoRect.y, infoRect.width, infoRect.height,
|
||||
infoRect.id, (int8)infoRect.a, (int8)infoRect.b, (int8)infoRect.c);
|
||||
|
||||
source += 12;
|
||||
_infoRects.push_back(infoRect);
|
||||
}
|
||||
|
||||
// TODO Other stuff
|
||||
|
||||
|
||||
}
|
||||
|
||||
int SegmentMap::findPathRectAtPoint(int x, int y) {
|
||||
for (uint rectIndex = 0; rectIndex < _pathRects.size(); rectIndex++) {
|
||||
if (y >= _pathRects[rectIndex].y && y <= _pathRects[rectIndex].y + _pathRects[rectIndex].height &&
|
||||
x >= _pathRects[rectIndex].x && x <= _pathRects[rectIndex].x + _pathRects[rectIndex].width) {
|
||||
return rectIndex;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SegmentMap::adjustPathPoint(int x, int y) {
|
||||
|
||||
if (findPathRectAtPoint(x, y) != -1)
|
||||
return;
|
||||
|
||||
uint32 minDistance = 0xFFFFFFFF, distance;
|
||||
int x2, y2;
|
||||
|
||||
for (uint rectIndex = 0; rectIndex < _pathRects.size(); rectIndex++) {
|
||||
|
||||
if (ABS(x - _pathRects[rectIndex].x) >= ABS((x - (_pathRects[rectIndex].x + _pathRects[rectIndex].width)))) {
|
||||
x2 = _pathRects[rectIndex].x + _pathRects[rectIndex].width;
|
||||
} else {
|
||||
x2 = _pathRects[rectIndex].x;
|
||||
}
|
||||
|
||||
if (ABS(y - _pathRects[rectIndex].y) >= ABS((y - (_pathRects[rectIndex].y + _pathRects[rectIndex].height)))) {
|
||||
y2 = _pathRects[rectIndex].y + _pathRects[rectIndex].height;
|
||||
} else {
|
||||
y2 = _pathRects[rectIndex].y;
|
||||
}
|
||||
|
||||
if (x >= _pathRects[rectIndex].x && x < _pathRects[rectIndex].x + _pathRects[rectIndex].width) {
|
||||
x2 = x;
|
||||
}
|
||||
|
||||
distance = ABS(y - y2) + ABS(x - x2);
|
||||
if (distance < minDistance) {
|
||||
if (y >= _pathRects[rectIndex].y && y <= _pathRects[rectIndex].y + _pathRects[rectIndex].height)
|
||||
_y = y;
|
||||
else
|
||||
_y = y2;
|
||||
if (x >= _pathRects[rectIndex].x && x <= _pathRects[rectIndex].x + _pathRects[rectIndex].width)
|
||||
_x = x;
|
||||
else
|
||||
_x = x2;
|
||||
minDistance = distance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int SegmentMap::findNextPathRect(int srcRectIndex) {
|
||||
|
||||
uint v28;
|
||||
int result;
|
||||
int minDistance, distance;
|
||||
int x1, y1, x2, y2;
|
||||
int nx1, nx2, nx3;
|
||||
int ny, ny2, ny3;
|
||||
|
||||
result = -1;
|
||||
minDistance = 65535;
|
||||
|
||||
x1 = _pathRects[srcRectIndex].x;
|
||||
y1 = _pathRects[srcRectIndex].y;
|
||||
|
||||
x2 = x1 + _pathRects[srcRectIndex].width;
|
||||
y2 = y1 + _pathRects[srcRectIndex].height;
|
||||
|
||||
for (uint rectIndex = 0; rectIndex < _pathRects.size(); ++rectIndex) {
|
||||
|
||||
if ( y1 == _pathRects[rectIndex].height + _pathRects[rectIndex].y && x1 < _pathRects[rectIndex].x + _pathRects[rectIndex].width && x2 > _pathRects[rectIndex].x ) {
|
||||
ny = y1;
|
||||
|
||||
LABEL_28:
|
||||
if ( x1 >= _pathRects[rectIndex].x ) {
|
||||
nx1 = x1;
|
||||
} else {
|
||||
nx1 = _pathRects[rectIndex].x;
|
||||
}
|
||||
if ( x2 <= _pathRects[rectIndex].x + _pathRects[rectIndex].width ) {
|
||||
nx2 = x2 - 1;
|
||||
} else {
|
||||
nx2 = _pathRects[rectIndex].x + _pathRects[rectIndex].width - 1;
|
||||
}
|
||||
if ( ABS(_x - nx1) >= ABS(_x - nx2) ) {
|
||||
nx3 = nx2 - 1;
|
||||
} else {
|
||||
nx3 = nx1;
|
||||
}
|
||||
if ( _x > nx1 && _x < nx2 ) {
|
||||
nx3 = _x;
|
||||
}
|
||||
goto LABEL_55;
|
||||
}
|
||||
if ( y2 == _pathRects[rectIndex].y && x1 < _pathRects[rectIndex].x + _pathRects[rectIndex].width && x2 > _pathRects[rectIndex].x ) {
|
||||
ny = y2 - 1;
|
||||
goto LABEL_28;
|
||||
}
|
||||
if ( x1 == _pathRects[rectIndex].x + _pathRects[rectIndex].width && y1 < _pathRects[rectIndex].y + _pathRects[rectIndex].height && y2 > _pathRects[rectIndex].y ) {
|
||||
nx3 = x1;
|
||||
} else {
|
||||
if ( x2 != _pathRects[rectIndex].x || y1 >= _pathRects[rectIndex].y + _pathRects[rectIndex].height || y2 <= _pathRects[rectIndex].y )
|
||||
continue;
|
||||
nx3 = x2 - 1;
|
||||
}
|
||||
if ( y1 >= _pathRects[rectIndex].y ) {
|
||||
ny3 = y1;
|
||||
} else {
|
||||
ny3 = _pathRects[rectIndex].y;
|
||||
}
|
||||
if ( y2 <= _pathRects[rectIndex].y + _pathRects[rectIndex].height ) {
|
||||
ny2 = y2 - 1;
|
||||
} else {
|
||||
ny2 = _pathRects[rectIndex].y + _pathRects[rectIndex].height - 1;
|
||||
}
|
||||
if ( ABS(_y - ny3) >= ABS(_y - ny2) ) {
|
||||
ny = ny2 - 1;
|
||||
} else {
|
||||
ny = ny3;
|
||||
}
|
||||
if ( _y > ny3 && _y < ny2 ) {
|
||||
ny = _y;
|
||||
}
|
||||
|
||||
LABEL_55:
|
||||
distance = ABS(_x - nx3) + ABS(_y - ny);
|
||||
v28 = 0;
|
||||
while ( v28 < _rectIndexArray2Count ) {
|
||||
if ( rectIndex == _rectIndexArray2[v28] ) {
|
||||
distance = minDistance;
|
||||
break;
|
||||
}
|
||||
++v28;
|
||||
}
|
||||
|
||||
v28 = 0;
|
||||
while ( v28 < _rectIndexArray1Count ) {
|
||||
if ( rectIndex == _rectIndexArray1[v28] ) {
|
||||
distance = minDistance;
|
||||
break;
|
||||
}
|
||||
++v28;
|
||||
}
|
||||
|
||||
if ( distance < minDistance ) {
|
||||
result = rectIndex;
|
||||
minDistance = distance;
|
||||
_pointsArray[_pointsCount].y = ny;
|
||||
_pointsArray[_pointsCount].x = nx3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct LineData {
|
||||
int pitch;
|
||||
byte *surf;
|
||||
};
|
||||
|
||||
void plotProc(int x, int y, int color, void *data) {
|
||||
LineData *ld = (LineData*)data;
|
||||
ld->surf[x + y * ld->pitch] = color;
|
||||
}
|
||||
|
||||
void SegmentMap::findPath(int16 *pointsArray, int destX, int destY, int x, int y) {
|
||||
|
||||
int index;
|
||||
int sourceRectIndex, destRectIndex;
|
||||
int pointsCount;
|
||||
|
||||
pointsCount = 2;
|
||||
index = 0;
|
||||
|
||||
debug(0, "SegmentMap::findPath(fromX: %d; fromY: %d; toX: %d; toY: %d)", x, y, destX, destY);
|
||||
|
||||
sourceRectIndex = findPathRectAtPoint(x, y);
|
||||
if ( sourceRectIndex == -1 ) {
|
||||
adjustPathPoint(x, y);
|
||||
x = _x;
|
||||
y = _y;
|
||||
}
|
||||
|
||||
_rectIndexArray1Count = 0;
|
||||
_rectIndexArray2Count = 0;
|
||||
_pointsCount = 0;
|
||||
|
||||
_x = destX;
|
||||
_y = destY;
|
||||
|
||||
adjustPathPoint(_x, _y);
|
||||
destRectIndex = findPathRectAtPoint(_x, _y);
|
||||
sourceRectIndex = findPathRectAtPoint(x, y);
|
||||
if ( sourceRectIndex != -1 ) {
|
||||
if ( destRectIndex != sourceRectIndex ) {
|
||||
while ( 1 ) {
|
||||
do {
|
||||
_rectIndexArray2[_rectIndexArray2Count++] = sourceRectIndex;
|
||||
sourceRectIndex = findNextPathRect(sourceRectIndex);
|
||||
_pointsCount++;
|
||||
} while ( sourceRectIndex != -1 && sourceRectIndex != destRectIndex );
|
||||
if ( sourceRectIndex != -1 && sourceRectIndex == destRectIndex )
|
||||
break;
|
||||
_rectIndexArray1[_rectIndexArray1Count++] = _rectIndexArray2[--_rectIndexArray2Count];
|
||||
_pointsCount -= 2;
|
||||
sourceRectIndex = _rectIndexArray2[--_rectIndexArray2Count];
|
||||
}
|
||||
sourceRectIndex = 0;
|
||||
while ( sourceRectIndex < _pointsCount ) {
|
||||
pointsArray[pointsCount++] = _pointsArray[sourceRectIndex].y;
|
||||
pointsArray[pointsCount++] = _pointsArray[sourceRectIndex].x;
|
||||
index++;
|
||||
sourceRectIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
pointsArray[pointsCount++] = _y;
|
||||
pointsArray[pointsCount++] = _x;
|
||||
|
||||
pointsArray[0] = 0;
|
||||
pointsArray[1] = index + 1;
|
||||
}
|
||||
|
||||
debug(0, "SegmentMap::findPath() count = %d", pointsArray[1]);
|
||||
|
||||
/*
|
||||
int sx = x, sy = y;
|
||||
LineData ld;
|
||||
ld.pitch = _vm->_sceneWidth;
|
||||
ld.surf = _vm->_screen->_backScreen;
|
||||
for (int16 i = 0; i < pointsArray[1] * 2; i+=2) {
|
||||
debug(0, "x = %d; y = %d", pointsArray[3+i], pointsArray[2+i]);
|
||||
Graphics::drawLine(sx, sy, pointsArray[3+i], pointsArray[2+i], 0xFF, plotProc, &ld);
|
||||
sx = pointsArray[3+i];
|
||||
sy = pointsArray[2+i];
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
int8 SegmentMap::getScalingAtPoint(int16 x, int16 y) {
|
||||
int8 scaling = 0;
|
||||
for (uint i = 0; i < _infoRects.size(); i++) {
|
||||
if (_infoRects[i].id == 0 &&
|
||||
y >= _infoRects[i].y && y <= _infoRects[i].y + _infoRects[i].height &&
|
||||
x >= _infoRects[i].x && x <= _infoRects[i].x + _infoRects[i].width) {
|
||||
char topScaling = (char)_infoRects[i].b;
|
||||
char bottomScaling = (char)_infoRects[i].c;
|
||||
if (y - _infoRects[i].y > 0) {
|
||||
scaling = (ABS(y - _infoRects[i].y) * (bottomScaling - topScaling) / _infoRects[i].height) + topScaling;
|
||||
}
|
||||
}
|
||||
}
|
||||
return scaling;
|
||||
}
|
||||
|
||||
void SegmentMap::getRgbModifiertAtPoint(int16 x, int16 y, int16 id, byte &r, byte &g, byte &b) {
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
for (uint i = 0; i < _infoRects.size(); i++) {
|
||||
if (_infoRects[i].id == id &&
|
||||
y >= _infoRects[i].y && y <= _infoRects[i].y + _infoRects[i].height &&
|
||||
x >= _infoRects[i].x && x <= _infoRects[i].x + _infoRects[i].width) {
|
||||
|
||||
r = _infoRects[i].a;
|
||||
g = _infoRects[i].b;
|
||||
b = _infoRects[i].c;
|
||||
}
|
||||
}
|
||||
debug(0, "SegmentMap::getRgbModifiertAtPoint() r: %d; g: %d; b: %d", r, g, b);
|
||||
}
|
||||
|
||||
void SegmentMap::restoreMasksBySprite(SpriteDrawItem *sprite) {
|
||||
// TODO: This needs more optimization
|
||||
for (uint i = 0; i < _maskRects.size(); i++) {
|
||||
|
||||
#if 0
|
||||
if ( *(__int16 *)((char *)&spriteDrawList[0].y2 + v5) <= (unsigned __int16)v3->ybottom )
|
||||
{
|
||||
if ( (unsigned __int16)(*(__int16 *)((char *)&spriteDrawList[0].height + v5)
|
||||
+ *(__int16 *)((char *)&spriteDrawList[0].y + v5)) > v3->y )
|
||||
{
|
||||
if ( (unsigned __int16)(v3->height + v3->y) > *(__int16 *)((char *)&spriteDrawList[0].y + v5) )
|
||||
{
|
||||
if ( (unsigned __int16)(*(__int16 *)((char *)&spriteDrawList[0].width + v5)
|
||||
+ *(__int16 *)((char *)&spriteDrawList[0].x + v5)) > v3->x )
|
||||
{
|
||||
if ( (unsigned __int16)(v3->width + v3->x) > *(__int16 *)((char *)&spriteDrawList[0].x + v5) )
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
if (sprite->ybottom <= _maskRects[i].ybottom) {
|
||||
restoreMask(i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SegmentMap::restoreMask(int16 index) {
|
||||
// TODO: This needs more optimization
|
||||
SegmapMaskRect *maskRect = &_maskRects[index];
|
||||
|
||||
int16 maskX = maskRect->x, maskY = maskRect->y;
|
||||
int16 skipX = 0;
|
||||
int16 x = maskRect->x - _vm->_cameraX;
|
||||
int16 y = maskRect->y - _vm->_cameraY;
|
||||
int16 width = maskRect->width;
|
||||
int16 height = maskRect->height;
|
||||
byte *mask = _maskRectData + maskRect->maskOffset;
|
||||
|
||||
debug(0, "SegmentMap::restoreMask() screenX = %d; screenY = %d; maskX = %d; maskY = %d",
|
||||
x, y, maskRect->x, maskRect->y);
|
||||
|
||||
// Not on screen, skip
|
||||
if (x + width < 0 || y + height < 0 || x >= 640 || y >= _vm->_cameraHeight)
|
||||
return;
|
||||
|
||||
if (x < 0) {
|
||||
skipX = -x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
int16 skipY = -y;
|
||||
for (int16 h = 0; h < skipY; h++) {
|
||||
int16 w = width;
|
||||
while (w > 0) {
|
||||
w -= (*mask++) & 0x7F;
|
||||
}
|
||||
}
|
||||
y = 0;
|
||||
height -= skipY;
|
||||
maskY += skipY;
|
||||
}
|
||||
|
||||
if (x + width >= 640) {
|
||||
width -= x + width - 640;
|
||||
}
|
||||
|
||||
if (y + height >= _vm->_cameraHeight) {
|
||||
height -= y + height - _vm->_cameraHeight;
|
||||
}
|
||||
|
||||
byte *backScreen = _vm->_screen->_backScreen + maskX + (maskY * _vm->_sceneWidth);
|
||||
byte *frontScreen = _vm->_screen->_frontScreen + x + (y * 640);
|
||||
|
||||
for (int16 h = 0; h < height; h++) {
|
||||
byte *src = backScreen;
|
||||
byte *dst = frontScreen;
|
||||
byte maskLine[640], *maskLineP = maskLine;
|
||||
|
||||
int16 w = width;
|
||||
while (w > 0) {
|
||||
byte m = *mask++;
|
||||
byte count = m & 0x7F;
|
||||
if (m & 0x80)
|
||||
memset(maskLineP, 1, count);
|
||||
else
|
||||
memset(maskLineP, 0, count);
|
||||
maskLineP += count;
|
||||
w -= count;
|
||||
}
|
||||
|
||||
src += skipX;
|
||||
for (int16 c = skipX; c < width; c++) {
|
||||
if (maskLine[c] == 1)
|
||||
*dst = *src;
|
||||
dst++;
|
||||
src++;
|
||||
}
|
||||
|
||||
backScreen += _vm->_sceneWidth;
|
||||
frontScreen += 640;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SegmentMap::debugDrawRects(Graphics::Surface *surf) {
|
||||
for (uint16 i = 0; i < _pathRects.size(); i++) {
|
||||
SegmapPathRect pathRect = _pathRects[i];
|
||||
surf->frameRect(
|
||||
Common::Rect(pathRect.x, pathRect.y, pathRect.x + pathRect.width, pathRect.y + pathRect.height),
|
||||
255);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Toltecs
|
134
engines/toltecs/segmap.h
Normal file
134
engines/toltecs/segmap.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOLTECS_SEGMAP_H
|
||||
#define TOLTECS_SEGMAP_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/array.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/voc.h"
|
||||
#include "sound/audiocd.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
#include "toltecs/screen.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
struct ScriptWalk {
|
||||
int16 y, x;
|
||||
int16 y1, x1, y2, x2;
|
||||
int16 yerror, xerror;
|
||||
int16 mulValue;
|
||||
int16 scaling;
|
||||
};
|
||||
|
||||
class SegmentMap {
|
||||
public:
|
||||
SegmentMap(ToltecsEngine *vm);
|
||||
~SegmentMap();
|
||||
|
||||
void load(byte *source);
|
||||
|
||||
int findPathRectAtPoint(int x, int y);
|
||||
void adjustPathPoint(int x, int y);
|
||||
|
||||
void findPath(int16 *pointsArray, int destX, int destY, int x, int y);
|
||||
|
||||
int8 getScalingAtPoint(int16 x, int16 y);
|
||||
void getRgbModifiertAtPoint(int16 x, int16 y, int16 id, byte &r, byte &g, byte &b);
|
||||
|
||||
void restoreMasksBySprite(SpriteDrawItem *sprite);
|
||||
void restoreMask(int16 index);
|
||||
|
||||
void debugDrawRects(Graphics::Surface *surf);
|
||||
|
||||
//protected:
|
||||
public: // for debugging purposes
|
||||
|
||||
struct SegmapMaskRect {
|
||||
int16 y, x;
|
||||
int16 height, width;
|
||||
int16 maskOffset;
|
||||
int16 ybottom;
|
||||
};
|
||||
|
||||
struct SegmapPathRect {
|
||||
int16 y, x;
|
||||
int16 height, width;
|
||||
};
|
||||
|
||||
struct SegmapInfoRect {
|
||||
int16 y, x;
|
||||
int16 height, width;
|
||||
byte id;
|
||||
byte a, b, c;
|
||||
};
|
||||
|
||||
struct PathPoint {
|
||||
int16 y, x;
|
||||
};
|
||||
|
||||
typedef Common::Array<SegmapMaskRect> SegmapMaskRectArray;
|
||||
typedef Common::Array<SegmapPathRect> SegmapPathRectArray;
|
||||
typedef Common::Array<SegmapInfoRect> SegmapInfoRectArray;
|
||||
|
||||
ToltecsEngine *_vm;
|
||||
|
||||
SegmapMaskRectArray _maskRects;
|
||||
byte *_maskRectData;
|
||||
|
||||
SegmapPathRectArray _pathRects;
|
||||
SegmapInfoRectArray _infoRects;
|
||||
|
||||
int _rectIndexArray1[1000];
|
||||
uint _rectIndexArray1Count;
|
||||
|
||||
int _rectIndexArray2[1000];
|
||||
uint _rectIndexArray2Count;
|
||||
|
||||
PathPoint _pointsArray[1000];
|
||||
int16 _pointsCount;
|
||||
|
||||
int _x, _y;
|
||||
|
||||
int findNextPathRect(int srcRectIndex);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
||||
#endif /* TOLTECS_SEGMAP_H */
|
483
engines/toltecs/toltecs.cpp
Normal file
483
engines/toltecs/toltecs.cpp
Normal file
|
@ -0,0 +1,483 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "base/version.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "graphics/primitives.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
#include "toltecs/animation.h"
|
||||
#include "toltecs/input.h"
|
||||
#include "toltecs/palette.h"
|
||||
#include "toltecs/resource.h"
|
||||
#include "toltecs/script.h"
|
||||
#include "toltecs/screen.h"
|
||||
#include "toltecs/segmap.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
struct GameSettings {
|
||||
const char *gameid;
|
||||
const char *description;
|
||||
byte id;
|
||||
uint32 features;
|
||||
const char *detectname;
|
||||
};
|
||||
|
||||
ToltecsEngine::ToltecsEngine(OSystem *syst, const ToltecsGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
|
||||
|
||||
// Setup mixer
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
|
||||
|
||||
_rnd = new Common::RandomSource();
|
||||
syst->getEventManager()->registerRandomSource(*_rnd, "toltecs");
|
||||
|
||||
int cd_num = ConfMan.getInt("cdrom");
|
||||
if (cd_num >= 0)
|
||||
_system->openCD(cd_num);
|
||||
|
||||
}
|
||||
|
||||
ToltecsEngine::~ToltecsEngine() {
|
||||
delete _rnd;
|
||||
}
|
||||
|
||||
int ToltecsEngine::init() {
|
||||
// Initialize backend
|
||||
_system->beginGFXTransaction();
|
||||
initCommonGFX(false);
|
||||
_system->initSize(640, 400);
|
||||
_system->endGFXTransaction();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ToltecsEngine::go() {
|
||||
|
||||
_system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true);
|
||||
|
||||
_quitGame = false;
|
||||
_counter01 = 0;
|
||||
_counter02 = 0;
|
||||
_movieSceneFlag = false;
|
||||
_flag01 = 0;
|
||||
|
||||
_cameraX = 0;
|
||||
_cameraY = 0;
|
||||
_newCameraX = 0;
|
||||
_newCameraY = 0;
|
||||
_cameraTop = 26;
|
||||
_cameraHeight = 0;
|
||||
_yetAnotherX = 0;
|
||||
|
||||
_sceneWidth = 0;
|
||||
_sceneHeight = 0;
|
||||
|
||||
_doSpeech = true;
|
||||
_doText = true;
|
||||
|
||||
_walkSpeedY = 5;
|
||||
_walkSpeedX = 1;
|
||||
|
||||
_arc = new ArchiveReader();
|
||||
_arc->openArchive("WESTERN");
|
||||
|
||||
_res = new ResourceCache(this);
|
||||
|
||||
_screen = new Screen(this);
|
||||
|
||||
_script = new ScriptInterpreter(this);
|
||||
_anim = new AnimationPlayer(this);
|
||||
_palette = new Palette(this);
|
||||
_segmap = new SegmentMap(this);
|
||||
_input = new Input(this);
|
||||
|
||||
_system->showMouse(true);
|
||||
|
||||
#if 1
|
||||
|
||||
_script->loadScript(0, 0);
|
||||
_script->runScript(0);
|
||||
|
||||
#endif
|
||||
|
||||
delete _arc;
|
||||
delete _res;
|
||||
delete _screen;
|
||||
delete _script;
|
||||
delete _anim;
|
||||
delete _palette;
|
||||
delete _segmap;
|
||||
delete _input;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ToltecsEngine::loadScene(uint resIndex) {
|
||||
// TODO
|
||||
|
||||
byte *scene = _res->load(resIndex);
|
||||
|
||||
uint32 imageSize = READ_LE_UINT32(scene);
|
||||
_sceneResIndex = resIndex;
|
||||
_sceneHeight = READ_LE_UINT16(scene + 4);
|
||||
_sceneWidth = READ_LE_UINT16(scene + 6);
|
||||
|
||||
// Load scene palette
|
||||
_palette->loadAddPaletteFrom(scene + 8, 0, 128);
|
||||
|
||||
// Load scene background
|
||||
byte *source = scene + 392;
|
||||
byte *destp = _screen->_backScreen;
|
||||
byte *destEnd = destp + _sceneWidth * _sceneHeight;
|
||||
while (destp < destEnd) {
|
||||
int count = 1;
|
||||
byte pixel = *source++;
|
||||
if (pixel & 0x80) {
|
||||
pixel &= 0x7F;
|
||||
count = *source++;
|
||||
count += 2;
|
||||
}
|
||||
memset(destp, pixel, count);
|
||||
destp += count;
|
||||
}
|
||||
|
||||
debug(0, "_sceneWidth = %d; _sceneHeight = %d", _sceneWidth, _sceneHeight);
|
||||
|
||||
// Load scene segmap
|
||||
_segmap->load(scene + imageSize + 4);
|
||||
|
||||
}
|
||||
|
||||
void ToltecsEngine::updateScreen() {
|
||||
// TODO
|
||||
|
||||
byte *destp = _screen->_frontScreen;
|
||||
byte *srcp = _screen->_backScreen + _cameraX + _cameraY * _sceneWidth;
|
||||
for (uint y = 0; y < MIN<uint>(_cameraHeight, 400); y++) {
|
||||
memcpy(destp, srcp, MIN<uint>(_sceneWidth, 640));
|
||||
destp += 640;
|
||||
srcp += _sceneWidth;
|
||||
}
|
||||
|
||||
_screen->drawSprites();
|
||||
_screen->clearSprites();
|
||||
|
||||
_screen->drawTalkTextItems();
|
||||
|
||||
_system->copyRectToScreen((const byte *)_screen->_frontScreen, 640, 0, 0, 640, 400);
|
||||
_system->updateScreen();
|
||||
|
||||
updateCamera();
|
||||
}
|
||||
|
||||
void ToltecsEngine::setCamera(int16 x, int16 y) {
|
||||
|
||||
// TODO font_sub_4B5BB()
|
||||
|
||||
if (x > _sceneWidth)
|
||||
x = _sceneWidth;
|
||||
|
||||
if (y > _sceneHeight - _cameraHeight)
|
||||
y = _sceneHeight - _cameraHeight;
|
||||
|
||||
// TODO DirtyRect clearing stuff
|
||||
|
||||
_screen->clearSprites();
|
||||
|
||||
_cameraX = x;
|
||||
_newCameraX = x;
|
||||
|
||||
_cameraY = y;
|
||||
_newCameraY = y;
|
||||
|
||||
// TODO More DirtyRect clearing stuff
|
||||
|
||||
}
|
||||
|
||||
void ToltecsEngine::setCameraTop(int16 top) {
|
||||
if (top != _cameraTop) {
|
||||
_cameraTop = top;
|
||||
_cameraHeight = 400 - _cameraTop;
|
||||
debug(0, "ToltecsEngine::setCameraTop() _cameraTop = %d; _cameraHeight = %d", _cameraTop, _cameraHeight);
|
||||
// TODO: clearScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void ToltecsEngine::scrollCameraUp(int16 delta) {
|
||||
if (_newCameraY > 0) {
|
||||
if (_newCameraY < delta)
|
||||
_newCameraY = 0;
|
||||
else
|
||||
_newCameraY -= delta;
|
||||
// TODO: font_sub_4B5BB();
|
||||
}
|
||||
}
|
||||
|
||||
void ToltecsEngine::scrollCameraDown(int16 delta) {
|
||||
debug(0, "ToltecsEngine::scrollCameraDown(%d)", delta);
|
||||
if (_newCameraY != _sceneHeight - _cameraHeight) {
|
||||
if (_sceneHeight - _cameraHeight < _newCameraY + delta)
|
||||
delta += (_sceneHeight - _cameraHeight) - (delta + _newCameraY);
|
||||
_newCameraY += delta;
|
||||
debug(0, "ToltecsEngine::scrollCameraDown() _newCameraY = %d; delta = %d", _newCameraY, delta);
|
||||
// TODO: font_sub_4B5BB();
|
||||
}
|
||||
}
|
||||
|
||||
void ToltecsEngine::scrollCameraLeft(int16 delta) {
|
||||
if (_newCameraX > 0) {
|
||||
if (_newCameraX < delta)
|
||||
_newCameraX = 0;
|
||||
else
|
||||
_newCameraX -= delta;
|
||||
// TODO: font_sub_4B5BB();
|
||||
}
|
||||
}
|
||||
|
||||
void ToltecsEngine::scrollCameraRight(int16 delta) {
|
||||
debug(0, "ToltecsEngine::scrollCameraRight(%d)", delta);
|
||||
if (_newCameraX != _sceneWidth - 640) {
|
||||
if (_sceneWidth - 640 < delta + _newCameraX)
|
||||
delta += (_sceneWidth - 640) - (delta + _newCameraX);
|
||||
_newCameraX += delta;
|
||||
debug(0, "ToltecsEngine::scrollCameraRight() _newCameraX = %d; delta = %d", _newCameraY, delta);
|
||||
// TODO: font_sub_4B5BB();
|
||||
}
|
||||
}
|
||||
|
||||
void ToltecsEngine::updateCamera() {
|
||||
|
||||
_yetAnotherX = _newCameraX;
|
||||
if (_cameraX != _yetAnotherX) {
|
||||
//dirtyFullRefresh = -1;
|
||||
}
|
||||
_cameraX = _yetAnotherX;
|
||||
|
||||
if (_cameraY != _newCameraY) {
|
||||
if (_cameraY < _newCameraY) {
|
||||
/*
|
||||
drawRequest.resIndex = -(cameraY - anotherY);
|
||||
drawRequest.y = cameraHeight + cameraY;
|
||||
drawRequest.x = cameraX;
|
||||
drawRequest.flags = 640;
|
||||
*/
|
||||
debug(0, "ToltecsEngine::updateCamera() a: (%d, %d, %d, %d)",
|
||||
-(_cameraY - _newCameraY), _cameraHeight + _cameraY, _cameraX, 640);
|
||||
//dirtyFullRefresh = -1;
|
||||
} else {
|
||||
/*
|
||||
drawRequest.resIndex = cameraY - anotherY;
|
||||
drawRequest.y = anotherY;
|
||||
drawRequest.x = cameraX;
|
||||
drawRequest.flags = 640;
|
||||
*/
|
||||
debug(0, "ToltecsEngine::updateCamera() b: (%d, %d, %d, %d)",
|
||||
_cameraY - _newCameraY, _newCameraY, _cameraX, 640);
|
||||
//dirtyFullRefresh = -1;
|
||||
}
|
||||
}
|
||||
_cameraY = _newCameraY;
|
||||
|
||||
debug(0, "ToltecsEngine::checkCamera() _cameraX = %d; _cameraY = %d", _cameraX, _cameraY);
|
||||
|
||||
}
|
||||
|
||||
void ToltecsEngine::talk(int16 slotIndex, int16 slotOffset) {
|
||||
|
||||
byte *scanData = _script->getSlotData(slotIndex) + slotOffset;
|
||||
|
||||
while (*scanData < 0xF0) {
|
||||
|
||||
if (*scanData == 0x19) {
|
||||
scanData++;
|
||||
} else if (*scanData == 0x14) {
|
||||
scanData++;
|
||||
} else if (*scanData == 0x0A) {
|
||||
scanData += 4;
|
||||
} else if (*scanData < 0x0A) {
|
||||
scanData++;
|
||||
}
|
||||
|
||||
scanData++;
|
||||
}
|
||||
|
||||
if (*scanData == 0xFE) {
|
||||
if (_doSpeech) {
|
||||
int16 resIndex = READ_LE_UINT16(scanData + 1);
|
||||
debug(0, "ToltecsEngine::talk() playSound(resIndex: %d)", resIndex);
|
||||
}
|
||||
if (_doText) {
|
||||
_screen->updateTalkText(slotIndex, slotOffset);
|
||||
} else {
|
||||
// TODO: font_sub_4B3E2
|
||||
}
|
||||
} else {
|
||||
_screen->updateTalkText(slotIndex, slotOffset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ToltecsEngine::playText(int16 slotIndex, int16 slotOffset) {
|
||||
|
||||
byte *textData = _script->getSlotData(slotIndex) + slotOffset;
|
||||
|
||||
debug(0, "ToltecsEngine::playText() [textData = %s]", (char*)textData);
|
||||
|
||||
Common::String str;
|
||||
while (*textData < 0xF0) {
|
||||
if (*textData >= 32)
|
||||
str += (char)*textData;
|
||||
textData++;
|
||||
}
|
||||
|
||||
debug(0, "ToltecsEngine::playText() [%s]", str.c_str());
|
||||
|
||||
}
|
||||
|
||||
void ToltecsEngine::walk(byte *walkData) {
|
||||
|
||||
int16 xdelta, ydelta, v8, v10, v11;
|
||||
int16 xstep, ystep;
|
||||
ScriptWalk walkInfo;
|
||||
|
||||
walkInfo.y = READ_LE_UINT16(walkData + 0);
|
||||
walkInfo.x = READ_LE_UINT16(walkData + 2);
|
||||
walkInfo.y1 = READ_LE_UINT16(walkData + 4);
|
||||
walkInfo.x1 = READ_LE_UINT16(walkData + 6);
|
||||
walkInfo.y2 = READ_LE_UINT16(walkData + 8);
|
||||
walkInfo.x2 = READ_LE_UINT16(walkData + 10);
|
||||
walkInfo.yerror = READ_LE_UINT16(walkData + 12);
|
||||
walkInfo.xerror = READ_LE_UINT16(walkData + 14);
|
||||
walkInfo.mulValue = READ_LE_UINT16(walkData + 16);
|
||||
walkInfo.scaling = READ_LE_UINT16(walkData + 18);
|
||||
|
||||
walkInfo.scaling = -_segmap->getScalingAtPoint(walkInfo.x, walkInfo.y);
|
||||
|
||||
if (walkInfo.y1 < walkInfo.y2)
|
||||
ystep = -1;
|
||||
else
|
||||
ystep = 1;
|
||||
ydelta = ABS(walkInfo.y1 - walkInfo.y2) * _walkSpeedY;
|
||||
|
||||
if (walkInfo.x1 < walkInfo.x2)
|
||||
xstep = -1;
|
||||
else
|
||||
xstep = 1;
|
||||
xdelta = ABS(walkInfo.x1 - walkInfo.x2) * _walkSpeedX;
|
||||
|
||||
debug(0, "ToltecsEngine::walk() xdelta = %d; ydelta = %d", xdelta, ydelta);
|
||||
|
||||
if (xdelta > ydelta)
|
||||
SWAP(xdelta, ydelta);
|
||||
|
||||
v8 = 100 * xdelta;
|
||||
if (v8 != 0) {
|
||||
if (walkInfo.scaling > 0)
|
||||
v8 -= v8 * ABS(walkInfo.scaling) / 100;
|
||||
else
|
||||
v8 += v8 * ABS(walkInfo.scaling) / 100;
|
||||
if (ydelta != 0)
|
||||
v8 /= ydelta;
|
||||
}
|
||||
|
||||
if (ydelta > ABS(walkInfo.x1 - walkInfo.x2) * _walkSpeedX) {
|
||||
v10 = 100 - walkInfo.scaling;
|
||||
v11 = v8;
|
||||
} else {
|
||||
v10 = v8;
|
||||
v11 = 100 - walkInfo.scaling;
|
||||
}
|
||||
|
||||
walkInfo.yerror += walkInfo.mulValue * v10;
|
||||
while (walkInfo.yerror >= 100 * _walkSpeedY) {
|
||||
walkInfo.yerror -= 100 * _walkSpeedY;
|
||||
if (walkInfo.y == walkInfo.y1) {
|
||||
walkInfo.x = walkInfo.x1;
|
||||
break;
|
||||
}
|
||||
walkInfo.y += ystep;
|
||||
}
|
||||
|
||||
walkInfo.xerror += walkInfo.mulValue * v11;
|
||||
while (walkInfo.xerror >= 100 * _walkSpeedX) {
|
||||
walkInfo.xerror -= 100 * _walkSpeedX;
|
||||
if (walkInfo.x == walkInfo.x1) {
|
||||
walkInfo.y = walkInfo.y1;
|
||||
break;
|
||||
}
|
||||
walkInfo.x += xstep;
|
||||
}
|
||||
|
||||
WRITE_LE_UINT16(walkData + 0, walkInfo.y);
|
||||
WRITE_LE_UINT16(walkData + 2, walkInfo.x);
|
||||
WRITE_LE_UINT16(walkData + 4, walkInfo.y1);
|
||||
WRITE_LE_UINT16(walkData + 6, walkInfo.x1);
|
||||
WRITE_LE_UINT16(walkData + 8, walkInfo.y2);
|
||||
WRITE_LE_UINT16(walkData + 10, walkInfo.x2);
|
||||
WRITE_LE_UINT16(walkData + 12, walkInfo.yerror);
|
||||
WRITE_LE_UINT16(walkData + 14, walkInfo.xerror);
|
||||
WRITE_LE_UINT16(walkData + 16, walkInfo.mulValue);
|
||||
WRITE_LE_UINT16(walkData + 18, walkInfo.scaling);
|
||||
|
||||
}
|
||||
|
||||
int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize) {
|
||||
|
||||
rectData += index * itemSize;
|
||||
|
||||
while (1) {
|
||||
int16 rectY = READ_LE_UINT16(rectData);
|
||||
if (rectY == -10)
|
||||
break;
|
||||
int16 rectX = READ_LE_UINT16(rectData + 2);
|
||||
int16 rectH = READ_LE_UINT16(rectData + 4);
|
||||
int16 rectW = READ_LE_UINT16(rectData + 6);
|
||||
|
||||
debug(0, "x = %d; y = %d; x1 = %d; y2 = %d; w = %d; h = %d",
|
||||
x, y, rectX, rectY, rectW, rectH);
|
||||
|
||||
if (x >= rectX && x <= rectX + rectW && y >= rectY && y <= rectY + rectH) {
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
rectData += itemSize;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
} // End of namespace Toltecs
|
130
engines/toltecs/toltecs.h
Normal file
130
engines/toltecs/toltecs.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOLTECS_H
|
||||
#define TOLTECS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/voc.h"
|
||||
#include "sound/audiocd.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
enum ToltecsGameFeatures {
|
||||
GF_PACKED = (1 << 0)
|
||||
};
|
||||
|
||||
struct ToltecsGameDescription;
|
||||
|
||||
class AnimationPlayer;
|
||||
class ArchiveReader;
|
||||
class Input;
|
||||
class Palette;
|
||||
class ResourceCache;
|
||||
class ScriptInterpreter;
|
||||
class Screen;
|
||||
class SegmentMap;
|
||||
|
||||
class ToltecsEngine : public ::Engine {
|
||||
Common::KeyState _keyPressed;
|
||||
|
||||
protected:
|
||||
int init();
|
||||
int go();
|
||||
// void shutdown();
|
||||
|
||||
public:
|
||||
ToltecsEngine(OSystem *syst, const ToltecsGameDescription *gameDesc);
|
||||
virtual ~ToltecsEngine();
|
||||
|
||||
Common::RandomSource *_rnd;
|
||||
const ToltecsGameDescription *_gameDescription;
|
||||
uint32 getFeatures() const;
|
||||
Common::Language getLanguage() const;
|
||||
|
||||
void loadScene(uint resIndex);
|
||||
|
||||
void updateScreen();
|
||||
|
||||
void setCamera(int16 x, int16 y);
|
||||
void setCameraTop(int16 top);
|
||||
void scrollCameraUp(int16 delta);
|
||||
void scrollCameraDown(int16 delta);
|
||||
void scrollCameraLeft(int16 delta);
|
||||
void scrollCameraRight(int16 delta);
|
||||
void updateCamera();
|
||||
|
||||
void talk(int16 slotIndex, int16 slotOffset);
|
||||
void playText(int16 slotIndex, int16 slotOffset);
|
||||
|
||||
void walk(byte *walkData);
|
||||
|
||||
int16 findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize);
|
||||
|
||||
public:
|
||||
AnimationPlayer *_anim;
|
||||
ArchiveReader *_arc;
|
||||
Input *_input;
|
||||
Palette *_palette;
|
||||
ResourceCache *_res;
|
||||
ScriptInterpreter *_script;
|
||||
Screen *_screen;
|
||||
SegmentMap *_segmap;
|
||||
|
||||
uint _sceneResIndex;
|
||||
int16 _sceneWidth, _sceneHeight;
|
||||
//byte _scenePalette[768];
|
||||
|
||||
bool _quitGame;
|
||||
int _counter01, _counter02;
|
||||
bool _movieSceneFlag;
|
||||
byte _flag01;
|
||||
|
||||
// TODO: Move camera stuff into own Scene class
|
||||
int16 _cameraX, _cameraY;
|
||||
int16 _newCameraX, _newCameraY;
|
||||
int16 _cameraTop, _cameraHeight;
|
||||
int16 _yetAnotherX;
|
||||
|
||||
bool _doSpeech, _doText;
|
||||
|
||||
int16 _walkSpeedY, _walkSpeedX;
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
||||
#endif /* TOLTECS_H */
|
Loading…
Add table
Add a link
Reference in a new issue