Initial commit
This commit is contained in:
2
engines/sludge/POTFILES
Normal file
2
engines/sludge/POTFILES
Normal file
@@ -0,0 +1,2 @@
|
||||
engines/sludge/event.cpp
|
||||
engines/sludge/keymapper_tables.h
|
||||
536
engines/sludge/backdrop.cpp
Normal file
536
engines/sludge/backdrop.cpp
Normal file
@@ -0,0 +1,536 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "image/png.h"
|
||||
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/imgloader.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/speech.h"
|
||||
#include "sludge/statusba.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
#include "sludge/variable.h"
|
||||
#include "sludge/version.h"
|
||||
#include "sludge/zbuffer.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
void GraphicsManager::killParallax() {
|
||||
if (!_parallaxLayers)
|
||||
return;
|
||||
|
||||
for (ParallaxLayers::iterator it = _parallaxLayers->begin(); it != _parallaxLayers->end(); ++it) {
|
||||
(*it)->surface.free();
|
||||
delete (*it);
|
||||
(*it) = nullptr;
|
||||
}
|
||||
_parallaxLayers->clear();
|
||||
|
||||
delete _parallaxLayers;
|
||||
_parallaxLayers = nullptr;
|
||||
}
|
||||
|
||||
bool GraphicsManager::loadParallax(uint16 v, uint16 fracX, uint16 fracY) {
|
||||
if (!_parallaxLayers)
|
||||
_parallaxLayers = new ParallaxLayers;
|
||||
|
||||
setResourceForFatal(v);
|
||||
if (!g_sludge->_resMan->openFileFromNum(v))
|
||||
return fatal("Can't open parallax image");
|
||||
|
||||
ParallaxLayer *nP = new ParallaxLayer;
|
||||
if (!checkNew(nP))
|
||||
return false;
|
||||
|
||||
_parallaxLayers->push_back(nP);
|
||||
|
||||
if (!ImgLoader::loadImage(v, "parallax", g_sludge->_resMan->getData(), &nP->surface, 0))
|
||||
return false;
|
||||
|
||||
nP->fileNum = v;
|
||||
nP->fractionX = fracX;
|
||||
nP->fractionY = fracY;
|
||||
|
||||
// 65535 is the value of AUTOFIT constant in Sludge
|
||||
if (fracX == 65535) {
|
||||
nP->wrapS = false;
|
||||
if (nP->surface.w < (int16)_winWidth) {
|
||||
fatal("For AUTOFIT parallax backgrounds, the image must be at least as wide as the game window/screen.");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
nP->wrapS = true;
|
||||
}
|
||||
|
||||
if (fracY == 65535) {
|
||||
nP->wrapT = false;
|
||||
if (nP->surface.h < (int16)_winHeight) {
|
||||
fatal("For AUTOFIT parallax backgrounds, the image must be at least as tall as the game window/screen.");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
nP->wrapT = true;
|
||||
}
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsManager::drawParallax() {
|
||||
if (!_parallaxLayers || _parallaxLayers->empty())
|
||||
return;
|
||||
|
||||
// display parallax from bottom to top
|
||||
for (ParallaxLayers::iterator it = _parallaxLayers->begin(); it != _parallaxLayers->end(); ++it) {
|
||||
ParallaxLayer *p = *it;
|
||||
p->cameraX = sortOutPCamera(_cameraX, p->fractionX, (int)(_sceneWidth - (float)_winWidth / _cameraZoom), (int)(p->surface.w - (float)_winWidth / _cameraZoom));
|
||||
p->cameraY = sortOutPCamera(_cameraY, p->fractionY, (int)(_sceneHeight - (float)_winHeight / _cameraZoom), (int)(p->surface.h - (float)_winHeight / _cameraZoom));
|
||||
|
||||
uint w = p->wrapS ? _sceneWidth : p->surface.w;
|
||||
uint h = p->wrapT ? _sceneHeight : p->surface.h;
|
||||
|
||||
debugC(1, kSludgeDebugGraphics, "drawParallax(): camX: %d camY: %d dims: %d x %d sceneDims: %d x %d winDims: %d x %d surf: %d x %d", p->cameraX, p->cameraY, w, h, _sceneWidth, _sceneHeight, _winWidth, _winHeight, p->surface.w, p->surface.h);
|
||||
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(p->surface);
|
||||
|
||||
for (uint y = 0; y < _sceneHeight; y += p->surface.h) {
|
||||
for (uint x = 0; x < _sceneWidth; x += p->surface.w) {
|
||||
tmp.blendBlitTo(_renderSurface, x - p->cameraX, y - p->cameraY);
|
||||
debugC(3, kSludgeDebugGraphics, "drawParallax(): blit to: %d, %d", x - p->cameraX, y - p->cameraY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsManager::saveParallax(Common::WriteStream *stream) {
|
||||
if (!_parallaxLayers)
|
||||
return;
|
||||
|
||||
ParallaxLayers::iterator it;
|
||||
for (it = _parallaxLayers->begin(); it != _parallaxLayers->end(); ++it) {
|
||||
stream->writeByte(1);
|
||||
stream->writeUint16BE((*it)->fileNum);
|
||||
stream->writeUint16BE((*it)->fractionX);
|
||||
stream->writeUint16BE((*it)->fractionY);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsManager::nosnapshot() {
|
||||
if (_snapshotSurface.getPixels())
|
||||
_snapshotSurface.free();
|
||||
}
|
||||
|
||||
void GraphicsManager::saveSnapshot(Common::WriteStream *stream) {
|
||||
if (_snapshotSurface.getPixels()) {
|
||||
stream->writeByte(1); // 1 for snapshot follows
|
||||
Image::writePNG(*stream, _snapshotSurface);
|
||||
} else {
|
||||
stream->writeByte(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsManager::snapshot() {
|
||||
nosnapshot();
|
||||
if (!freeze())
|
||||
return false;
|
||||
|
||||
// draw snapshot to rendersurface
|
||||
displayBase();
|
||||
_vm->_speechMan->display();
|
||||
g_sludge->_statusBar->draw();
|
||||
|
||||
// copy backdrop to snapshot
|
||||
_snapshotSurface.copyFrom(_renderSurface);
|
||||
|
||||
unfreeze(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GraphicsManager::restoreSnapshot(Common::SeekableReadStream *stream) {
|
||||
if (!(ImgLoader::loadImage(-1, NULL, stream, &_snapshotSurface))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsManager::killBackDrop() {
|
||||
if (_backdropSurface.getPixels())
|
||||
_backdropSurface.free();
|
||||
_backdropExists = false;
|
||||
}
|
||||
|
||||
void GraphicsManager::killLightMap() {
|
||||
if (_lightMap.getPixels()) {
|
||||
_lightMap.free();
|
||||
}
|
||||
_lightMapNumber = 0;
|
||||
}
|
||||
|
||||
bool GraphicsManager::reserveBackdrop() {
|
||||
_cameraX = 0;
|
||||
_cameraY = 0;
|
||||
_vm->_evtMan->mouseX() = (int)((float)_vm->_evtMan->mouseX() * _cameraZoom);
|
||||
_vm->_evtMan->mouseY() = (int)((float)_vm->_evtMan->mouseY() * _cameraZoom);
|
||||
_cameraZoom = 1.0;
|
||||
_vm->_evtMan->mouseX() = (int)((float)_vm->_evtMan->mouseX() / _cameraZoom);
|
||||
_vm->_evtMan->mouseY() = (int)((float)_vm->_evtMan->mouseY() / _cameraZoom);
|
||||
|
||||
_backdropSurface.create(_sceneWidth, _sceneHeight, *_vm->getScreenPixelFormat());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsManager::killAllBackDrop() {
|
||||
killLightMap();
|
||||
killBackDrop();
|
||||
g_sludge->_gfxMan->killParallax();
|
||||
killZBuffer();
|
||||
}
|
||||
|
||||
bool GraphicsManager::resizeBackdrop(int x, int y) {
|
||||
debugC(1, kSludgeDebugGraphics, "Load HSI");
|
||||
_sceneWidth = x;
|
||||
_sceneHeight = y;
|
||||
return reserveBackdrop();
|
||||
}
|
||||
|
||||
bool GraphicsManager::killResizeBackdrop(int x, int y) {
|
||||
killAllBackDrop();
|
||||
return resizeBackdrop(x, y);
|
||||
}
|
||||
|
||||
void GraphicsManager::loadBackDrop(int fileNum, int x, int y) {
|
||||
debugC(1, kSludgeDebugGraphics, "Load back drop of num %i at position %i, %i", fileNum, x, y);
|
||||
setResourceForFatal(fileNum);
|
||||
if (!g_sludge->_resMan->openFileFromNum(fileNum)) {
|
||||
fatal("Can't load overlay image");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!loadHSI(fileNum, g_sludge->_resMan->getData(), x, y, false)) {
|
||||
Common::String mess = Common::String::format("Can't paste overlay image outside scene dimensions\n\nX = %i\nY = %i\nWidth = %i\nHeight = %i", x, y, _sceneWidth, _sceneHeight);
|
||||
fatal(mess);
|
||||
}
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
|
||||
// reset zBuffer
|
||||
if (_zBuffer->originalNum >= 0) {
|
||||
setZBuffer(_zBuffer->originalNum);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsManager::mixBackDrop(int fileNum, int x, int y) {
|
||||
debugC(1, kSludgeDebugGraphics, "Mix back drop of num %i at position %i, %i", fileNum, x, y);
|
||||
setResourceForFatal(fileNum);
|
||||
if (!g_sludge->_resMan->openFileFromNum(fileNum)) {
|
||||
fatal("Can't load overlay image");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mixHSI(fileNum, g_sludge->_resMan->getData(), x, y)) {
|
||||
fatal("Can't paste overlay image outside screen dimensions");
|
||||
}
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
}
|
||||
|
||||
void GraphicsManager::blankScreen(int x1, int y1, int x2, int y2) {
|
||||
// in case of no backdrop added at all, create it
|
||||
if (!_backdropSurface.getPixels()) {
|
||||
_backdropSurface.create(_winWidth, _winHeight, _renderSurface.format);
|
||||
}
|
||||
|
||||
if (y1 < 0)
|
||||
y1 = 0;
|
||||
if (x1 < 0)
|
||||
x1 = 0;
|
||||
if (x2 > (int)_sceneWidth)
|
||||
x2 = (int)_sceneWidth;
|
||||
if (y2 > (int)_sceneHeight)
|
||||
y2 = (int)_sceneHeight;
|
||||
|
||||
_backdropSurface.fillRect(Common::Rect(x1, y1, x2, y2), _currentBlankColour);
|
||||
|
||||
// reset zBuffer
|
||||
if (_zBuffer->originalNum >= 0) {
|
||||
setZBuffer(_zBuffer->originalNum);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsManager::blankAllScreen() {
|
||||
blankScreen(0, 0, _sceneWidth, _sceneHeight);
|
||||
}
|
||||
|
||||
// This function is very useful for scrolling credits, but very little else
|
||||
void GraphicsManager::hardScroll(int distance) {
|
||||
// scroll 0 distance, return
|
||||
if (!distance)
|
||||
return;
|
||||
|
||||
// blank screen
|
||||
blankAllScreen();
|
||||
|
||||
// scroll more than backdrop height, screen stay blank
|
||||
if (ABS(distance) >= (int)_sceneHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
// copy part of the backdrop to it
|
||||
if (distance > 0) {
|
||||
_backdropSurface.copyRectToSurface(_origBackdropSurface, 0, 0,
|
||||
Common::Rect(0, distance, _backdropSurface.w, _backdropSurface.h));
|
||||
} else {
|
||||
_backdropSurface.copyRectToSurface(_origBackdropSurface, 0, -distance,
|
||||
Common::Rect(0, 0, _backdropSurface.w, _backdropSurface.h + distance));
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsManager::drawLine(uint x1, uint y1, uint x2, uint y2) {
|
||||
_backdropSurface.drawLine(x1, y1, x2, y2, _backdropSurface.format.ARGBToColor(255, 0, 0, 0));
|
||||
}
|
||||
|
||||
void GraphicsManager::drawVerticalLine(uint x, uint y1, uint y2) {
|
||||
drawLine(x, y1, x, y2);
|
||||
}
|
||||
|
||||
void GraphicsManager::drawHorizontalLine(uint x1, uint y, uint x2) {
|
||||
drawLine(x1, y, x2, y);
|
||||
}
|
||||
|
||||
void GraphicsManager::darkScreen() {
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(_backdropSurface);
|
||||
tmp.blendBlitTo(_backdropSurface, 0, 0, Graphics::FLIP_NONE, nullptr, MS_ARGB(255 >> 1, 0, 0, 0));
|
||||
|
||||
// reset zBuffer
|
||||
if (_zBuffer->originalNum >= 0) {
|
||||
setZBuffer(_zBuffer->originalNum);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsManager::drawBackDrop() {
|
||||
// TODO: apply lightmap shader
|
||||
drawParallax();
|
||||
|
||||
if (!_backdropExists && !_backdropSurface.getPixels())
|
||||
return;
|
||||
// draw backdrop
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(_backdropSurface);
|
||||
tmp.blendBlitTo(_renderSurface, -_cameraX, -_cameraY);
|
||||
}
|
||||
|
||||
bool GraphicsManager::loadLightMap(int v) {
|
||||
setResourceForFatal(v);
|
||||
if (!g_sludge->_resMan->openFileFromNum(v))
|
||||
return fatal("Can't open light map.");
|
||||
|
||||
killLightMap();
|
||||
_lightMapNumber = v;
|
||||
_lightMap.create(_sceneWidth, _sceneWidth, *_vm->getScreenPixelFormat());
|
||||
|
||||
Graphics::ManagedSurface tmp;
|
||||
|
||||
if (!ImgLoader::loadImage(v, "lightmap", g_sludge->_resMan->getData(), tmp.surfacePtr()))
|
||||
return false;
|
||||
|
||||
if (tmp.w != (int16)_sceneWidth || tmp.h != (int16)_sceneHeight) {
|
||||
if (_lightMapMode == LIGHTMAPMODE_HOTSPOT) {
|
||||
return fatal("Light map width and height don't match scene width and height. That is required for lightmaps in HOTSPOT mode.");
|
||||
} else if (_lightMapMode == LIGHTMAPMODE_PIXEL) {
|
||||
tmp.blendBlitTo(_lightMap, 0, 0, Graphics::FLIP_NONE, nullptr, MS_ARGB((uint)255, (uint)255, (uint)255, (uint)255), (int)_sceneWidth, (int)_sceneHeight);
|
||||
} else {
|
||||
_lightMap.copyFrom(tmp);
|
||||
}
|
||||
} else {
|
||||
_lightMap.copyFrom(tmp);
|
||||
}
|
||||
|
||||
tmp.free();
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsManager::saveLightMap(Common::WriteStream *stream) {
|
||||
if (_lightMap.getPixels()) {
|
||||
stream->writeByte(1);
|
||||
stream->writeUint16BE(_lightMapNumber);
|
||||
} else {
|
||||
stream->writeByte(0);
|
||||
}
|
||||
stream->writeByte(_lightMapMode);
|
||||
stream->writeByte(_fadeMode);
|
||||
}
|
||||
|
||||
bool GraphicsManager::loadLightMap(int ssgVersion, Common::SeekableReadStream *stream) {
|
||||
if (stream->readByte()) {
|
||||
if (!loadLightMap(stream->readUint16BE()))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ssgVersion >= VERSION(1, 4)) {
|
||||
_lightMapMode = stream->readByte() % 3;
|
||||
}
|
||||
|
||||
_fadeMode = stream->readByte();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GraphicsManager::loadHSI(int num, Common::SeekableReadStream *stream, int x, int y, bool reserve) {
|
||||
debugC(1, kSludgeDebugGraphics, "Load HSI");
|
||||
if (reserve) {
|
||||
killAllBackDrop(); // kill all
|
||||
}
|
||||
|
||||
Graphics::Surface tmp;
|
||||
|
||||
if (!ImgLoader::loadImage(num, "hsi", stream, &tmp, (int)reserve))
|
||||
return false;
|
||||
|
||||
uint realPicWidth = tmp.w;
|
||||
uint realPicHeight = tmp.h;
|
||||
|
||||
// resize backdrop
|
||||
if (reserve) {
|
||||
if (!resizeBackdrop(realPicWidth, realPicHeight)) {
|
||||
tmp.free();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (x == IN_THE_CENTRE)
|
||||
x = (_sceneWidth - realPicWidth) >> 1;
|
||||
if (y == IN_THE_CENTRE)
|
||||
y = (_sceneHeight - realPicHeight) >> 1;
|
||||
if (x < 0 || x + realPicWidth > _sceneWidth || y < 0 || y + realPicHeight > _sceneHeight) {
|
||||
debugC(0, kSludgeDebugGraphics, "Illegal back drop size");
|
||||
tmp.free();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_backdropExists)
|
||||
_backdropSurface.fillRect(Common::Rect(x, y, x + tmp.w, y + tmp.h), _renderSurface.format.ARGBToColor(0, 0, 0, 0));
|
||||
|
||||
// copy surface loaded to backdrop
|
||||
Graphics::ManagedSurface tmp_trans;
|
||||
tmp_trans.copyFrom(tmp);
|
||||
tmp_trans.blendBlitTo(_backdropSurface, x, y);
|
||||
tmp.free();
|
||||
|
||||
_origBackdropSurface.copyFrom(_backdropSurface);
|
||||
_backdropExists = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GraphicsManager::mixHSI(int num, Common::SeekableReadStream *stream, int x, int y) {
|
||||
debugC(1, kSludgeDebugGraphics, "Load mixHSI");
|
||||
Graphics::Surface mixSurface;
|
||||
if (!ImgLoader::loadImage(num, "mixhsi", stream, &mixSurface, 0))
|
||||
return false;
|
||||
|
||||
uint realPicWidth = mixSurface.w;
|
||||
uint realPicHeight = mixSurface.h;
|
||||
|
||||
if (x == IN_THE_CENTRE)
|
||||
x = (_sceneWidth - realPicWidth) >> 1;
|
||||
if (y == IN_THE_CENTRE)
|
||||
y = (_sceneHeight - realPicHeight) >> 1;
|
||||
if (x < 0 || x + realPicWidth > _sceneWidth || y < 0 || y + realPicHeight > _sceneHeight) {
|
||||
mixSurface.free();
|
||||
return false;
|
||||
}
|
||||
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(mixSurface);
|
||||
tmp.blendBlitTo(_backdropSurface, x, y, Graphics::FLIP_NONE, nullptr, MS_ARGB(255 >> 1, 255, 255, 255));
|
||||
mixSurface.free();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsManager::saveHSI(Common::WriteStream *stream) {
|
||||
Image::writePNG(*stream, _backdropSurface);
|
||||
}
|
||||
|
||||
void GraphicsManager::saveBackdrop(Common::WriteStream *stream) {
|
||||
stream->writeUint16BE(_cameraX);
|
||||
stream->writeUint16BE(_cameraY);
|
||||
stream->writeFloatLE(_cameraZoom);
|
||||
stream->writeByte(_brightnessLevel);
|
||||
saveHSI(stream);
|
||||
}
|
||||
|
||||
void GraphicsManager::loadBackdrop(int ssgVersion, Common::SeekableReadStream *stream) {
|
||||
int cameraX = stream->readUint16BE();
|
||||
int cameraY = stream->readUint16BE();
|
||||
float cameraZoom;
|
||||
if (ssgVersion >= VERSION(2, 0)) {
|
||||
cameraZoom = stream->readFloatLE();
|
||||
} else {
|
||||
cameraZoom = 1.0;
|
||||
}
|
||||
|
||||
_brightnessLevel = stream->readByte();
|
||||
|
||||
loadHSI(-1, stream, 0, 0, true);
|
||||
|
||||
_cameraX = cameraX;
|
||||
_cameraY = cameraY;
|
||||
_cameraZoom = cameraZoom;
|
||||
}
|
||||
|
||||
bool GraphicsManager::getRGBIntoStack(uint x, uint y, StackHandler *sH) {
|
||||
if (x >= _sceneWidth || y >= _sceneHeight) {
|
||||
return fatal("Co-ordinates are outside current scene!");
|
||||
}
|
||||
|
||||
Variable newValue;
|
||||
|
||||
newValue.varType = SVT_NULL;
|
||||
|
||||
byte *target = (byte *)_renderSurface.getBasePtr(x, y);
|
||||
|
||||
newValue.setVariable(SVT_INT, target[1]);
|
||||
if (!addVarToStackQuick(newValue, sH->first)) return false;
|
||||
sH->last = sH->first;
|
||||
|
||||
newValue.setVariable(SVT_INT, target[2]);
|
||||
if (!addVarToStackQuick(newValue, sH->first)) return false;
|
||||
|
||||
newValue.setVariable(SVT_INT, target[3]);
|
||||
if (!addVarToStackQuick(newValue, sH->first)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
351
engines/sludge/bg_effects.cpp
Normal file
351
engines/sludge/bg_effects.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/variable.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
#if 0
|
||||
// Raised
|
||||
static int s_matrixEffectDivide = 2;
|
||||
static int s_matrixEffectWidth = 3;
|
||||
static int s_matrixEffectHeight = 3;
|
||||
static int s_matrixEffectData[9] = {0, 0, 0, 0, -1, 0, 0, 0, 2};
|
||||
static int s_matrixEffectBase = 0;
|
||||
#elif 0
|
||||
// Stay put
|
||||
static int s_matrixEffectDivide = 1;
|
||||
static int s_matrixEffectWidth = 3;
|
||||
static int s_matrixEffectHeight = 3;
|
||||
static int s_matrixEffectData[9] = {0, 0, 0, 0, 1, 0, 0, 0, 0};
|
||||
static int s_matrixEffectBase = 0;
|
||||
#elif 0
|
||||
// Brighten
|
||||
static int s_matrixEffectDivide = 9;
|
||||
static int s_matrixEffectWidth = 1;
|
||||
static int s_matrixEffectHeight = 1;
|
||||
static int s_matrixEffectData[9] = {10};
|
||||
static int s_matrixEffectBase = 15;
|
||||
#elif 0
|
||||
// Raised up/left
|
||||
static int s_matrixEffectDivide = 4;
|
||||
static int s_matrixEffectWidth = 3;
|
||||
static int s_matrixEffectHeight = 3;
|
||||
static int s_matrixEffectData[9] = {-2, -1, 0, -1, 1, 1, 0, 1, 2};
|
||||
static int s_matrixEffectBase = 16;
|
||||
#elif 0
|
||||
// Standard emboss
|
||||
static int s_matrixEffectDivide = 2;
|
||||
static int s_matrixEffectWidth = 3;
|
||||
static int s_matrixEffectHeight = 3;
|
||||
static int s_matrixEffectData[9] = {-1, 0, 0, 0, 0, 0, 0, 0, 1};
|
||||
static int s_matrixEffectBase = 128;
|
||||
#elif 0
|
||||
// Horizontal blur
|
||||
static int s_matrixEffectDivide = 11;
|
||||
static int s_matrixEffectWidth = 5;
|
||||
static int s_matrixEffectHeight = 1;
|
||||
static int s_matrixEffectData[9] = {1, 3, 3, 3, 1};
|
||||
static int s_matrixEffectBase = 0;
|
||||
#elif 0
|
||||
// Double vision
|
||||
static int s_matrixEffectDivide = 6;
|
||||
static int s_matrixEffectWidth = 13;
|
||||
static int s_matrixEffectHeight = 2;
|
||||
static int s_matrixEffectData[26] = {2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3};
|
||||
static int s_matrixEffectBase = 0;
|
||||
#elif 0
|
||||
// Negative
|
||||
static int s_matrixEffectDivide = 1;
|
||||
static int s_matrixEffectWidth = 1;
|
||||
static int s_matrixEffectHeight = 1;
|
||||
static int s_matrixEffectData[9] = {-1};
|
||||
static int s_matrixEffectBase = 255;
|
||||
#elif 0
|
||||
// Fog
|
||||
static int s_matrixEffectDivide = 4;
|
||||
static int s_matrixEffectWidth = 1;
|
||||
static int s_matrixEffectHeight = 1;
|
||||
static int s_matrixEffectData[9] = {3};
|
||||
static int s_matrixEffectBase = 45;
|
||||
#elif 0
|
||||
// Blur
|
||||
static int s_matrixEffectDivide = 14;
|
||||
static int s_matrixEffectWidth = 3;
|
||||
static int s_matrixEffectHeight = 3;
|
||||
static int s_matrixEffectData[9] = {1, 2, 1, 2, 2, 2, 1, 2, 1};
|
||||
static int s_matrixEffectBase = 0;
|
||||
#else
|
||||
static int s_matrixEffectDivide = 0;
|
||||
static int s_matrixEffectWidth = 0;
|
||||
static int s_matrixEffectHeight = 0;
|
||||
static int *s_matrixEffectData = NULL;
|
||||
static int s_matrixEffectBase = 0;
|
||||
#endif
|
||||
|
||||
void GraphicsManager::blur_saveSettings(Common::WriteStream *stream) {
|
||||
if (s_matrixEffectData) {
|
||||
stream->writeUint32LE(s_matrixEffectDivide);
|
||||
stream->writeUint32LE(s_matrixEffectWidth);
|
||||
stream->writeUint32LE(s_matrixEffectHeight);
|
||||
stream->writeUint32LE(s_matrixEffectBase);
|
||||
stream->write(s_matrixEffectData, sizeof(int) * s_matrixEffectWidth * s_matrixEffectHeight);
|
||||
} else {
|
||||
stream->writeUint32LE(0);
|
||||
stream->writeUint32LE(0);
|
||||
stream->writeUint32LE(0);
|
||||
stream->writeUint32LE(0);
|
||||
}
|
||||
}
|
||||
|
||||
static int *blur_allocateMemoryForEffect() {
|
||||
free(s_matrixEffectData);
|
||||
s_matrixEffectData = NULL;
|
||||
|
||||
if (s_matrixEffectWidth && s_matrixEffectHeight) {
|
||||
s_matrixEffectData = (int *)malloc(sizeof(int) * s_matrixEffectHeight * s_matrixEffectWidth);
|
||||
checkNew(s_matrixEffectData);
|
||||
}
|
||||
return s_matrixEffectData;
|
||||
}
|
||||
|
||||
void GraphicsManager::blur_loadSettings(Common::SeekableReadStream *stream) {
|
||||
s_matrixEffectDivide = stream->readUint32LE();
|
||||
s_matrixEffectWidth = stream->readUint32LE();
|
||||
s_matrixEffectHeight = stream->readUint32LE();
|
||||
s_matrixEffectBase = stream->readUint32LE();
|
||||
|
||||
if (blur_allocateMemoryForEffect()) {
|
||||
uint bytes_read = stream->read(s_matrixEffectData, sizeof(int) * s_matrixEffectWidth * s_matrixEffectHeight);
|
||||
if (bytes_read != sizeof(int) * s_matrixEffectWidth * s_matrixEffectHeight && stream->err()) {
|
||||
debug("Reading error in blur_loadSettings.");
|
||||
}
|
||||
} else {
|
||||
stream->seek(sizeof(int) * s_matrixEffectWidth * s_matrixEffectHeight, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsManager::blur_createSettings(int numParams, VariableStack *&stack) {
|
||||
bool createNullThing = true;
|
||||
Common::String error = "";
|
||||
|
||||
if (numParams >= 3) {
|
||||
// PARAMETERS: base, divide, stack (, stack (, stack...))
|
||||
|
||||
int height = numParams - 2;
|
||||
int width = 0;
|
||||
|
||||
VariableStack *justToCheckSizes = stack;
|
||||
for (int a = 0; a < height; a++) {
|
||||
if (justToCheckSizes->thisVar.varType != SVT_STACK) {
|
||||
error = "Third and subsequent parameters in setBackgroundEffect should be arrays";
|
||||
break;
|
||||
} else {
|
||||
int w = justToCheckSizes->thisVar.varData.theStack->getStackSize();
|
||||
if (a) {
|
||||
if (w != width) {
|
||||
error = "Arrays in setBackgroundEffect must be the same size";
|
||||
break;
|
||||
}
|
||||
if (w < width) {
|
||||
width = w;
|
||||
}
|
||||
} else {
|
||||
width = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (width == 0 && error.empty()) {
|
||||
error = "Empty arrays found in setBackgroundEffect parameters";
|
||||
}
|
||||
|
||||
if (error.empty()) {
|
||||
s_matrixEffectWidth = width;
|
||||
s_matrixEffectHeight = height;
|
||||
|
||||
if (blur_allocateMemoryForEffect()) {
|
||||
for (int y = height - 1; y >= 0; y--) {
|
||||
VariableStack *eachNumber = stack->thisVar.varData.theStack->first;
|
||||
if (error.empty()) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int arraySlot = x + (y * width);
|
||||
// s_matrixEffectData[arraySlot] = (rand() % 4);
|
||||
if (!eachNumber->thisVar.getValueType(s_matrixEffectData[arraySlot], SVT_INT)) {
|
||||
error = "";
|
||||
break;
|
||||
}
|
||||
eachNumber = eachNumber->next;
|
||||
}
|
||||
trimStack(stack);
|
||||
}
|
||||
}
|
||||
if (error.empty() && !stack->thisVar.getValueType(s_matrixEffectDivide, SVT_INT))
|
||||
error = "";
|
||||
trimStack(stack);
|
||||
if (error.empty() && !stack->thisVar.getValueType(s_matrixEffectBase, SVT_INT))
|
||||
error = "";
|
||||
trimStack(stack);
|
||||
if (error.empty()) {
|
||||
if (s_matrixEffectDivide) {
|
||||
createNullThing = false;
|
||||
} else {
|
||||
error = "Second parameter of setBackgroundEffect (the 'divide' value) should not be 0!";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = "Couldn't allocate memory for effect";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (numParams) {
|
||||
error = "setBackgroundEffect should either have 0 parameters or more than 2";
|
||||
}
|
||||
}
|
||||
|
||||
if (createNullThing) {
|
||||
s_matrixEffectDivide = 0;
|
||||
s_matrixEffectWidth = 0;
|
||||
s_matrixEffectHeight = 0;
|
||||
s_matrixEffectBase = 0;
|
||||
delete s_matrixEffectData;
|
||||
s_matrixEffectData = NULL;
|
||||
}
|
||||
|
||||
if (!error.empty()) {
|
||||
fatal(error);
|
||||
}
|
||||
|
||||
return !createNullThing;
|
||||
}
|
||||
|
||||
static inline void blur_createSourceLine(byte *createLine, byte *fromLine, int overlapOnLeft, int width) {
|
||||
int miniX;
|
||||
memcpy(createLine + overlapOnLeft * 4, fromLine, width * 4);
|
||||
|
||||
for (miniX = 0; miniX < overlapOnLeft; miniX++) {
|
||||
createLine[miniX * 4] = fromLine[1];
|
||||
createLine[miniX * 4 + 1] = fromLine[2];
|
||||
createLine[miniX * 4 + 2] = fromLine[3];
|
||||
}
|
||||
|
||||
for (miniX = width + overlapOnLeft; miniX < width + s_matrixEffectWidth - 1; miniX++) {
|
||||
createLine[miniX * 4] = fromLine[width * 4 - 3];
|
||||
createLine[miniX * 4 + 1] = fromLine[width * 4 - 2];
|
||||
createLine[miniX * 4 + 2] = fromLine[width * 4 - 1];
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsManager::blurScreen() {
|
||||
if (s_matrixEffectWidth && s_matrixEffectHeight && s_matrixEffectDivide && s_matrixEffectData) {
|
||||
byte *thisLine;
|
||||
int y, x;
|
||||
bool ok = true;
|
||||
int overlapOnLeft = s_matrixEffectWidth / 2;
|
||||
int overlapAbove = s_matrixEffectHeight / 2;
|
||||
|
||||
byte **sourceLine = new byte *[s_matrixEffectHeight];
|
||||
if (!checkNew(sourceLine))
|
||||
return false;
|
||||
|
||||
for (y = 0; y < s_matrixEffectHeight; y++) {
|
||||
sourceLine[y] = new byte[(s_matrixEffectWidth - 1 + _sceneWidth) * 4];
|
||||
ok &= (sourceLine[y] != NULL);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
for (y = 0; y < s_matrixEffectHeight; y++) {
|
||||
int miniY = CLIP<int>(y - overlapAbove - 1, 0, _sceneHeight - 1);
|
||||
|
||||
blur_createSourceLine(sourceLine[y], (byte *)_backdropSurface.getBasePtr(0, miniY), overlapOnLeft, _sceneWidth);
|
||||
}
|
||||
|
||||
for (y = 0; y < (int)_sceneHeight; y++) {
|
||||
thisLine = (byte *)_backdropSurface.getBasePtr(0, y);
|
||||
|
||||
//-------------------------
|
||||
// Scroll source lines
|
||||
//-------------------------
|
||||
byte *tempLine = sourceLine[0];
|
||||
for (int miniY = 0; miniY < s_matrixEffectHeight - 1; miniY++) {
|
||||
sourceLine[miniY] = sourceLine[miniY + 1];
|
||||
}
|
||||
sourceLine[s_matrixEffectHeight - 1] = tempLine;
|
||||
{
|
||||
int h = s_matrixEffectHeight - 1;
|
||||
int miniY = CLIP<int>(y + (s_matrixEffectHeight - overlapAbove - 1), 0, _sceneHeight - 1);
|
||||
|
||||
blur_createSourceLine(sourceLine[h], (byte *)_backdropSurface.getBasePtr(0, miniY), overlapOnLeft, _sceneWidth);
|
||||
}
|
||||
for (x = 0; x < (int)_sceneWidth; x++) {
|
||||
int totalRed = 0;
|
||||
int totalGreen = 0;
|
||||
int totalBlue = 0;
|
||||
int *matrixElement = s_matrixEffectData;
|
||||
for (int miniY = 0; miniY < s_matrixEffectHeight; ++miniY) {
|
||||
byte *pixel = &sourceLine[miniY][x * 4];
|
||||
for (int miniX = 0; miniX < s_matrixEffectWidth; ++miniX) {
|
||||
|
||||
totalRed += pixel[1] **matrixElement;
|
||||
totalGreen += pixel[2] **matrixElement;
|
||||
totalBlue += pixel[3] **matrixElement;
|
||||
++matrixElement;
|
||||
pixel += 4;
|
||||
}
|
||||
}
|
||||
totalRed = (totalRed + s_matrixEffectDivide / 2) / s_matrixEffectDivide + s_matrixEffectBase;
|
||||
totalRed = (totalRed < 0) ? 0 : ((totalRed > 255) ? 255 : totalRed);
|
||||
|
||||
totalGreen = (totalGreen + s_matrixEffectDivide / 2) / s_matrixEffectDivide + s_matrixEffectBase;
|
||||
totalGreen = (totalGreen < 0) ? 0 : ((totalGreen > 255) ? 255 : totalGreen);
|
||||
|
||||
totalBlue = (totalBlue + s_matrixEffectDivide / 2) / s_matrixEffectDivide + s_matrixEffectBase;
|
||||
totalBlue = (totalBlue < 0) ? 0 : ((totalBlue > 255) ? 255 : totalBlue);
|
||||
|
||||
// *thisLine = totalAlpha;
|
||||
++thisLine;
|
||||
*thisLine = totalRed;
|
||||
++thisLine;
|
||||
*thisLine = totalGreen;
|
||||
++thisLine;
|
||||
*thisLine = totalBlue;
|
||||
++thisLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < s_matrixEffectHeight; y++) {
|
||||
delete[] sourceLine[y];
|
||||
}
|
||||
delete[] sourceLine;
|
||||
sourceLine = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
2653
engines/sludge/builtin.cpp
Normal file
2653
engines/sludge/builtin.cpp
Normal file
File diff suppressed because it is too large
Load Diff
46
engines/sludge/builtin.h
Normal file
46
engines/sludge/builtin.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_BUILTIN_H
|
||||
#define SLUDGE_BUILTIN_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct LoadedFunction;
|
||||
|
||||
enum BuiltReturn {
|
||||
BR_KEEP_AND_PAUSE,
|
||||
BR_ERROR,
|
||||
BR_CONTINUE,
|
||||
BR_PAUSE,
|
||||
BR_CALLAFUNC,
|
||||
BR_ALREADY_GONE
|
||||
};
|
||||
|
||||
bool failSecurityCheck(const Common::String &fn);
|
||||
BuiltReturn callBuiltIn(int whichFunc, int numParams, LoadedFunction *fun);
|
||||
const char *getBuiltInName(int num);
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
3
engines/sludge/configure.engine
Normal file
3
engines/sludge/configure.engine
Normal file
@@ -0,0 +1,3 @@
|
||||
# This file is included from the main "configure" script
|
||||
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
|
||||
add_engine sludge "Sludge" yes "" "" "16bit png" "vpx universaltracker"
|
||||
4
engines/sludge/credits.pl
Normal file
4
engines/sludge/credits.pl
Normal file
@@ -0,0 +1,4 @@
|
||||
begin_section("SLUDGE");
|
||||
add_person("Eugene Sandulenko", "sev", "");
|
||||
add_person("Simei Yin", "yinsimei", "GSoC Student");
|
||||
end_section();
|
||||
75
engines/sludge/csludge.h
Normal file
75
engines/sludge/csludge.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_CSLUDGE_H
|
||||
#define SLUDGE_CSLUDGE_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
enum SludgeCommand {
|
||||
SLU_UNKNOWN,
|
||||
SLU_RETURN,
|
||||
SLU_BRANCH,
|
||||
SLU_BR_ZERO,
|
||||
SLU_SET_GLOBAL,
|
||||
SLU_SET_LOCAL,
|
||||
SLU_LOAD_GLOBAL,
|
||||
SLU_LOAD_LOCAL,
|
||||
SLU_PLUS,
|
||||
SLU_MINUS,
|
||||
SLU_MULT,
|
||||
SLU_DIVIDE,
|
||||
SLU_AND,
|
||||
SLU_OR,
|
||||
SLU_EQUALS,
|
||||
SLU_NOT_EQ,
|
||||
SLU_MODULUS,
|
||||
SLU_LOAD_VALUE,
|
||||
SLU_LOAD_BUILT,
|
||||
SLU_LOAD_FUNC,
|
||||
SLU_CALLIT,
|
||||
SLU_LOAD_STRING,
|
||||
SLU_LOAD_FILE, /*SLU_LOAD_SCENE,*/
|
||||
SLU_LOAD_OBJTYPE,
|
||||
SLU_NOT,
|
||||
SLU_LOAD_NULL,
|
||||
SLU_STACK_PUSH,
|
||||
SLU_LESSTHAN,
|
||||
SLU_MORETHAN,
|
||||
SLU_NEGATIVE,
|
||||
SLU_UNREG,
|
||||
SLU_LESS_EQUAL,
|
||||
SLU_MORE_EQUAL,
|
||||
SLU_INCREMENT_LOCAL,
|
||||
SLU_DECREMENT_LOCAL,
|
||||
SLU_INCREMENT_GLOBAL,
|
||||
SLU_DECREMENT_GLOBAL,
|
||||
SLU_INDEXSET,
|
||||
SLU_INDEXGET,
|
||||
SLU_INCREMENT_INDEX,
|
||||
SLU_DECREMENT_INDEX,
|
||||
SLU_QUICK_PUSH,
|
||||
numSludgeCommands
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
142
engines/sludge/cursors.cpp
Normal file
142
engines/sludge/cursors.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
#include "sludge/cursors.h"
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/freeze.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
CursorManager::CursorManager(SludgeEngine *vm) {
|
||||
_vm = vm;
|
||||
init();
|
||||
}
|
||||
|
||||
CursorManager::~CursorManager() {
|
||||
kill();
|
||||
}
|
||||
|
||||
void CursorManager::init() {
|
||||
_mouseCursorAnim = new PersonaAnimation();
|
||||
_mouseCursorFrameNum = 0;
|
||||
_mouseCursorCountUp = 0;
|
||||
}
|
||||
|
||||
void CursorManager::kill() {
|
||||
if (_mouseCursorAnim) {
|
||||
delete _mouseCursorAnim;
|
||||
_mouseCursorAnim = nullptr;
|
||||
}
|
||||
_mouseCursorAnim = nullptr;
|
||||
}
|
||||
|
||||
void CursorManager::pickAnimCursor(PersonaAnimation *pp) {
|
||||
if (_mouseCursorAnim) {
|
||||
delete _mouseCursorAnim;
|
||||
_mouseCursorAnim = nullptr;
|
||||
}
|
||||
_mouseCursorAnim = pp;
|
||||
_mouseCursorFrameNum = 0;
|
||||
_mouseCursorCountUp = 0;
|
||||
}
|
||||
|
||||
void CursorManager::displayCursor() {
|
||||
if (_mouseCursorAnim && _mouseCursorAnim->numFrames) {
|
||||
|
||||
int spriteNum = _mouseCursorAnim->frames[_mouseCursorFrameNum].frameNum;
|
||||
int flipMe = 0;
|
||||
|
||||
if (spriteNum < 0) {
|
||||
spriteNum = -spriteNum;
|
||||
flipMe = 1;
|
||||
if (spriteNum >= _mouseCursorAnim->theSprites->bank.total)
|
||||
spriteNum = 0;
|
||||
} else {
|
||||
if (spriteNum >= _mouseCursorAnim->theSprites->bank.total)
|
||||
flipMe = 2;
|
||||
}
|
||||
|
||||
if (flipMe != 2) {
|
||||
if (flipMe) {
|
||||
_vm->_gfxMan->flipFontSprite(
|
||||
_vm->_evtMan->mouseX(), _vm->_evtMan->mouseY(),
|
||||
_mouseCursorAnim->theSprites->bank.sprites[spriteNum],
|
||||
_mouseCursorAnim->theSprites->bank.myPalette /* ( spritePalette&) NULL*/);
|
||||
} else {
|
||||
_vm->_gfxMan->fontSprite(
|
||||
_vm->_evtMan->mouseX(), _vm->_evtMan->mouseY(),
|
||||
_mouseCursorAnim->theSprites->bank.sprites[spriteNum],
|
||||
_mouseCursorAnim->theSprites->bank.myPalette /* ( spritePalette&) NULL*/);
|
||||
}
|
||||
}
|
||||
|
||||
if (++_mouseCursorCountUp >= _mouseCursorAnim->frames[_mouseCursorFrameNum].howMany) {
|
||||
_mouseCursorCountUp = 0;
|
||||
_mouseCursorFrameNum++;
|
||||
_mouseCursorFrameNum %= _mouseCursorAnim->numFrames;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CursorManager::pasteCursor(int x, int y, PersonaAnimation *c) {
|
||||
if (c->numFrames)
|
||||
_vm->_gfxMan->pasteSpriteToBackDrop(x, y, c->theSprites->bank.sprites[c->frames[0].frameNum], c->theSprites->bank.myPalette);
|
||||
}
|
||||
|
||||
void CursorManager::freeze(FrozenStuffStruct *frozenStuff) {
|
||||
frozenStuff->mouseCursorAnim = _mouseCursorAnim;
|
||||
frozenStuff->mouseCursorFrameNum = _mouseCursorFrameNum;
|
||||
_mouseCursorAnim = new PersonaAnimation();
|
||||
_mouseCursorFrameNum = 0;
|
||||
}
|
||||
|
||||
void CursorManager::resotre(FrozenStuffStruct *frozenStuff) {
|
||||
if (_mouseCursorAnim) {
|
||||
delete _mouseCursorAnim;
|
||||
_mouseCursorAnim = nullptr;
|
||||
}
|
||||
_mouseCursorAnim = frozenStuff->mouseCursorAnim;
|
||||
_mouseCursorFrameNum = frozenStuff->mouseCursorFrameNum;
|
||||
}
|
||||
|
||||
void CursorManager::saveCursor(Common::WriteStream *stream) {
|
||||
_mouseCursorAnim->save(stream);
|
||||
stream->writeUint16BE(_mouseCursorFrameNum);
|
||||
}
|
||||
|
||||
bool CursorManager::loadCursor(Common::SeekableReadStream *stream) {
|
||||
_mouseCursorAnim = new PersonaAnimation;
|
||||
if (!checkNew(_mouseCursorAnim))
|
||||
return false;
|
||||
if (!_mouseCursorAnim->load(stream))
|
||||
return false;
|
||||
_mouseCursorFrameNum = stream->readUint16BE();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
67
engines/sludge/cursors.h
Normal file
67
engines/sludge/cursors.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_CURSORS_H
|
||||
#define SLUDGE_CURSORS_H
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
class WriteStream;
|
||||
}
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class SludgeEngine;
|
||||
|
||||
struct FrozenStuffStruct;
|
||||
|
||||
class CursorManager {
|
||||
public:
|
||||
CursorManager(SludgeEngine *vm);
|
||||
virtual ~CursorManager();
|
||||
|
||||
void init();
|
||||
void kill();
|
||||
|
||||
// cursor
|
||||
void pickAnimCursor(struct PersonaAnimation *pp);
|
||||
void displayCursor();
|
||||
void pasteCursor(int x, int y, struct PersonaAnimation *c);
|
||||
|
||||
// freeze
|
||||
void freeze(FrozenStuffStruct *frozenStuff);
|
||||
void resotre(FrozenStuffStruct *frozenStuff);
|
||||
|
||||
// load & save
|
||||
void saveCursor(Common::WriteStream *stream);
|
||||
bool loadCursor(Common::SeekableReadStream *stream);
|
||||
|
||||
private:
|
||||
SludgeEngine *_vm;
|
||||
|
||||
PersonaAnimation *_mouseCursorAnim;
|
||||
int _mouseCursorFrameNum;
|
||||
int _mouseCursorCountUp;
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
62
engines/sludge/debugger.cpp
Normal file
62
engines/sludge/debugger.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sludge/debugger.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/fileset.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
Debugger::Debugger(SludgeEngine *vm) : GUI::Debugger(), _vm(vm) {
|
||||
registerCmd("listResources", WRAP_METHOD(Debugger, Cmd_ListResources));
|
||||
registerCmd("dumpResource", WRAP_METHOD(Debugger, Cmd_DumpResource));
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_ListResources(int argc, const char **argv) {
|
||||
if (argc != 1 && argc != 2) {
|
||||
debugPrintf("Usage: %s\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _vm->_resMan->getResourceNameCount(); i++) {
|
||||
const Common::String name = _vm->_resMan->resourceNameFromNum(i);
|
||||
if (argc == 1 || name.matchString(argv[1]))
|
||||
debugPrintf(" - %s\n", name.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::Cmd_DumpResource(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("Usage: %s\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_vm->_resMan->dumpFileFromName(argv[1])) {
|
||||
debugPrintf("Success\n");
|
||||
} else {
|
||||
debugPrintf("Failure\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
46
engines/sludge/debugger.h
Normal file
46
engines/sludge/debugger.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_DEBUGGER_H
|
||||
#define SLUDGE_DEBUGGER_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class SludgeEngine;
|
||||
|
||||
class Debugger : public GUI::Debugger {
|
||||
private:
|
||||
SludgeEngine *_vm;
|
||||
|
||||
public:
|
||||
Debugger(SludgeEngine *vm);
|
||||
~Debugger() override {}
|
||||
|
||||
protected:
|
||||
bool Cmd_ListResources(int argc, const char **argv);
|
||||
bool Cmd_DumpResource(int argc, const char **argv);
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
143
engines/sludge/detection.cpp
Normal file
143
engines/sludge/detection.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "common/file.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "sludge/detection.h"
|
||||
#include "sludge/sludge.h"
|
||||
|
||||
|
||||
static const DebugChannelDef debugFlagList[] = {
|
||||
{Sludge::kSludgeDebugFatal, "script", "Script debug level"},
|
||||
{Sludge::kSludgeDebugDataLoad, "loading", "Data loading debug level"},
|
||||
{Sludge::kSludgeDebugStackMachine, "stack", "Stack Machine debug level"},
|
||||
{Sludge::kSludgeDebugBuiltin, "builtin", "Built-in debug level"},
|
||||
{Sludge::kSludgeDebugGraphics, "graphics", "Graphics debug level"},
|
||||
{Sludge::kSludgeDebugZBuffer, "zBuffer", "ZBuffer debug level"},
|
||||
{Sludge::kSludgeDebugSound, "sound", "Sound debug level"},
|
||||
DEBUG_CHANNEL_END
|
||||
};
|
||||
|
||||
#include "sludge/detection_tables.h"
|
||||
|
||||
static Sludge::SludgeGameDescription s_fallbackDesc =
|
||||
{
|
||||
{
|
||||
"",
|
||||
"",
|
||||
AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
|
||||
Common::UNK_LANG,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
},
|
||||
0
|
||||
};
|
||||
|
||||
static char s_fallbackFileNameBuffer[51];
|
||||
|
||||
class SludgeMetaEngineDetection : public AdvancedMetaEngineDetection<Sludge::SludgeGameDescription> {
|
||||
public:
|
||||
SludgeMetaEngineDetection() : AdvancedMetaEngineDetection(Sludge::gameDescriptions, Sludge::sludgeGames) {
|
||||
_maxScanDepth = 1;
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "sludge";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Sludge";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "Sludge (C) 2000-2014 Hungry Software and contributors";
|
||||
}
|
||||
|
||||
const DebugChannelDef *getDebugChannels() const override {
|
||||
return debugFlagList;
|
||||
}
|
||||
|
||||
// for fall back detection
|
||||
ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist, ADDetectedGameExtraInfo **extra) const override;
|
||||
};
|
||||
|
||||
ADDetectedGame SludgeMetaEngineDetection::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist, ADDetectedGameExtraInfo **extra) const {
|
||||
// reset fallback description
|
||||
s_fallbackDesc.desc.gameId = "sludge";
|
||||
s_fallbackDesc.desc.extra = "";
|
||||
s_fallbackDesc.desc.language = Common::EN_ANY;
|
||||
s_fallbackDesc.desc.flags = ADGF_UNSTABLE;
|
||||
s_fallbackDesc.desc.platform = Common::kPlatformUnknown;
|
||||
s_fallbackDesc.desc.guiOptions = GUIO1(GUIO_NOMIDI);
|
||||
s_fallbackDesc.languageID = 0;
|
||||
|
||||
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
|
||||
if (file->isDirectory())
|
||||
continue;
|
||||
|
||||
Common::Path fileName = file->getPathInArchive();
|
||||
fileName.toLowercase();
|
||||
if (!(fileName.baseName().hasSuffix(".slg") || fileName == "gamedata"))
|
||||
continue;
|
||||
|
||||
Common::File f;
|
||||
if (!f.open(*file))
|
||||
continue;
|
||||
|
||||
bool headerBad = false;
|
||||
if (f.readByte() != 'S')
|
||||
headerBad = true;
|
||||
if (f.readByte() != 'L')
|
||||
headerBad = true;
|
||||
if (f.readByte() != 'U')
|
||||
headerBad = true;
|
||||
if (f.readByte() != 'D')
|
||||
headerBad = true;
|
||||
if (f.readByte() != 'G')
|
||||
headerBad = true;
|
||||
if (f.readByte() != 'E')
|
||||
headerBad = true;
|
||||
if (headerBad) {
|
||||
continue;
|
||||
}
|
||||
|
||||
strncpy(s_fallbackFileNameBuffer, fileName.toString('/').c_str(), 50);
|
||||
s_fallbackFileNameBuffer[50] = '\0';
|
||||
s_fallbackDesc.desc.filesDescriptions[0].fileName = s_fallbackFileNameBuffer;
|
||||
|
||||
ADDetectedGame game;
|
||||
game.desc = &s_fallbackDesc.desc;
|
||||
|
||||
FileProperties tmp;
|
||||
if (getFileProperties(allFiles, kMD5Head, fileName, tmp)) {
|
||||
game.hasUnknownFiles = true;
|
||||
game.matchedFiles[fileName] = tmp;
|
||||
}
|
||||
|
||||
return game;
|
||||
}
|
||||
|
||||
return ADDetectedGame();
|
||||
}
|
||||
|
||||
REGISTER_PLUGIN_STATIC(SLUDGE_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, SludgeMetaEngineDetection);
|
||||
36
engines/sludge/detection.h
Normal file
36
engines/sludge/detection.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_DETECTION_H
|
||||
#define SLUDGE_DETECTION_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct SludgeGameDescription {
|
||||
AD_GAME_DESCRIPTION_HELPERS(desc);
|
||||
|
||||
ADGameDescription desc;
|
||||
uint languageID;
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif // SLUDGE_DETECTION_H
|
||||
173
engines/sludge/detection_tables.h
Normal file
173
engines/sludge/detection_tables.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
static const PlainGameDescriptor sludgeGames[] = {
|
||||
{ "sludge", "Sludge Game" },
|
||||
{ "welcome", "Welcome Example" },
|
||||
{ "verbcoin", "Verb Coin" },
|
||||
{ "verbcoin2", "Verb Coin 2"},
|
||||
{ "parallax", "Parallax Demo" },
|
||||
{ "robinsrescue", "Robin's Rescue" },
|
||||
{ "outoforder", "Out Of Order" },
|
||||
{ "frasse", "Frasse and the Peas of Kejick" },
|
||||
{ "interview", "The Interview" },
|
||||
{ "life", "Life Flashes By" },
|
||||
{ "tgttpoacs", "The Game That Takes Place on a Cruise Ship" },
|
||||
{ "mandy", "Mandy Christmas Adventure" },
|
||||
{ "cubert", "Cubert Badbone, P.I." },
|
||||
{ "gjgagsas", "The Game Jam Game About Games, Secrets and Stuff" },
|
||||
{ "tsotc", "The Secret of Tremendous Corporation" },
|
||||
{ "nsc", "Nathan's Second Chance" },
|
||||
{ "atw", "Above The Waves" },
|
||||
{ "leptonsquest", "Lepton's Quest" },
|
||||
{ "otto", "Otto Experiment" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
#define GAME1l(t, e, f1, m1, s1, lang, pl, langId) { { t, e, AD_ENTRY1s(f1, m1, s1), lang, pl, ADGF_NO_FLAGS, GUIO1(GUIO_NOMIDI) }, langId }
|
||||
#define GAME1(t, e, f1, m1, s1) GAME1l(t, e, f1, m1, s1, Common::EN_ANY, Common::kPlatformUnknown, 0)
|
||||
#define GAME2l(t, e, f1, m1, s1, f2, m2, s2, lang, pl, langId) { { t, e, AD_ENTRY2s(f1, m1, s1, f2, m2, s2), lang, pl, ADGF_NO_FLAGS, GUIO1(GUIO_NOMIDI) }, langId }
|
||||
#define GAME2(t, e, f1, m1, s1, f2, m2, s2) GAME2l(t, e, f1, m1, s1, f2, m2, s2, Common::EN_ANY, Common::kPlatformUnknown, 0)
|
||||
|
||||
|
||||
static const SludgeGameDescription gameDescriptions[] = {
|
||||
GAME1("welcome", "", "Welcome.slg", "50445503761cf6684fe3270d0860a4c3", 51736),
|
||||
|
||||
GAME1("verbcoin", "", "Verb Coin.slg", "e39ec315dcbf3a1137481f0a5fe1617d", 980270),
|
||||
GAME1l("verbcoin", "", "Verb Coin.slg", "e39ec315dcbf3a1137481f0a5fe1617d", 980270, Common::DE_DEU, Common::kPlatformUnknown, 1),
|
||||
GAME1("verbcoin2", "", "Verb Coin.slg", "483b315990309c718617c7c47fa132d8", 1067575),
|
||||
GAME1l("verbcoin2", "", "Verb Coin.slg", "483b315990309c718617c7c47fa132d8", 1067575, Common::DE_DEU, Common::kPlatformUnknown, 1),
|
||||
|
||||
GAME1("parallax", "", "Parallax_demo.slg", "daae3f75c6695bed47e5e633cd406a47", 65881),
|
||||
|
||||
GAME1("robinsrescue", "", "robins_rescue.slg", "16cbf2bf916ed89f9c1b14fab133cf96", 14413769),
|
||||
GAME1("robinsrescue", "v1.0", "Gamedata.slg", "16cbf2bf916ed89f9c1b14fab133cf96", 14413754),
|
||||
GAME1l("robinsrescue", "v1.0", "Gamedata.slg", "16cbf2bf916ed89f9c1b14fab133cf96", 14413754, Common::EN_ANY, Common::kPlatformLinux, 0),
|
||||
|
||||
GAME2l("outoforder", "v1.0", "gamedata", "4d72dbad0ff170169cd7e4e7e389a90d", 21122647,
|
||||
"out-of-order.xpm", "407086751ac167884c6585c4cad5b664", 2601,
|
||||
Common::EN_ANY, Common::kPlatformLinux, 0),
|
||||
GAME2l("outoforder", "v1.0", "gamedata", "4d72dbad0ff170169cd7e4e7e389a90d", 21122647, // 2003-02-08
|
||||
"Out Of Order.exe", "064d221103ca4bb7f187432b69c70efd", 68096,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
GAME2l("outoforder", "v1.0", "gamedata", "4d72dbad0ff170169cd7e4e7e389a90d", 21122647, // 2003-06-05
|
||||
"Out Of Order.exe", "ebc386dd0cb77df68dd12d72742eb310", 68608,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
|
||||
GAME2("frasse", "v1.03", "gamedata", "5a985d772f9909a8cc98e1e9edf0875d", 38186227,
|
||||
"frasse.exe", "7016ef8ab67133a1d6fce20b8b70cd1d", 83968),
|
||||
GAME2("frasse", "v1.04", "gamedata", "13934872c16391de3ddd6644e3bfcd15", 38154596,
|
||||
"frasse.exe", "7016ef8ab67133a1d6fce20b8b70cd1d", 83968),
|
||||
GAME1l("frasse", "v2.02", "Gamedata.slg", "25e4a63ae10f69f5032c58ad2fd51fac", 88582783, Common::EN_ANY, Common::kPlatformMacintosh, 0),
|
||||
GAME1l("frasse", "v2.03", "Gamedata.slg", "e4eb4eca6117bb9b77870bb74af453b4", 88582819, Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
|
||||
GAME2("interview", "", "gamedata", "6ca8f6e44f30d09bd68e008be4c20e8d", 2570140,
|
||||
"interview.exe", "7974f71566c423c3a344862dcbb827dd", 83968),
|
||||
|
||||
GAME1("life", "", "LifeFlashesBy.slg", "a471759e071e5d2c0e8e6887607df778", 163794266),
|
||||
GAME2("life", "", "gamedata", "a471759e071e5d2c0e8e6887607df778", 163794266,
|
||||
"sludge.bmp", "69db99963fb7e93af6d48dfd7f4246ee", 13846),
|
||||
GAME2("life", "", "gamedata", "a471759e071e5d2c0e8e6887607df778", 163794266,
|
||||
"Life Flashes By.exe", "d33c957eefa85defde8b8c29a0bb5a9b", 972800),
|
||||
|
||||
GAME2l("tgttpoacs", "", "gamedata", "d5ec4d7d8440f7744335d25d25e1e943", 40368,
|
||||
"gert.ico", "b76b5b38e8d5cd6843636085947bfd29", 3638,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
GAME1l("tgttpoacs", "", "tgttpoacs.dat", "e61d3d050793689d55487d3ad01b6693", 23817174, Common::EN_ANY, Common::kPlatformLinux, 0),
|
||||
|
||||
GAME2l("mandy", "v1.2", "data", "df4a0c113b93b89ff2fe7991fb018bae", 7099447,
|
||||
"Mandy.exe", "596478e1a7b4445fc0bd7f5ec2696125", 71168,
|
||||
Common::SK_SVK, Common::kPlatformWindows, 0),
|
||||
GAME2l("mandy", "v1.2", "data", "df4a0c113b93b89ff2fe7991fb018bae", 7099447,
|
||||
"Mandy.exe", "596478e1a7b4445fc0bd7f5ec2696125", 71168,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 1),
|
||||
GAME2l("mandy", "v1.3", "data", "b732ffe04367c787c6ce70fbcb7aa6aa", 7100976,
|
||||
"Mandy.exe", "596478e1a7b4445fc0bd7f5ec2696125", 71168,
|
||||
Common::SK_SVK, Common::kPlatformWindows, 0),
|
||||
GAME2l("mandy", "v1.3", "data", "b732ffe04367c787c6ce70fbcb7aa6aa", 7100976,
|
||||
"Mandy.exe", "596478e1a7b4445fc0bd7f5ec2696125", 71168,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 1),
|
||||
GAME2l("mandy", "v1.3", "data", "b732ffe04367c787c6ce70fbcb7aa6aa", 7100976,
|
||||
"Mandy.exe", "596478e1a7b4445fc0bd7f5ec2696125", 71168,
|
||||
Common::IT_ITA, Common::kPlatformWindows, 2),
|
||||
GAME2l("mandy", "v1.4", "data", "705f6ca5f5da0c40c1f547231dd5139f", 7141292,
|
||||
"Mandy.exe", "7016ef8ab67133a1d6fce20b8b70cd1d", 83968,
|
||||
Common::SK_SVK, Common::kPlatformWindows, 0),
|
||||
GAME2l("mandy", "v1.4", "data", "705f6ca5f5da0c40c1f547231dd5139f", 7141292,
|
||||
"Mandy.exe", "7016ef8ab67133a1d6fce20b8b70cd1d", 83968,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 1),
|
||||
GAME2l("mandy", "v1.4", "data", "705f6ca5f5da0c40c1f547231dd5139f", 7141292,
|
||||
"Mandy.exe", "7016ef8ab67133a1d6fce20b8b70cd1d", 83968,
|
||||
Common::IT_ITA, Common::kPlatformWindows, 2),
|
||||
GAME2l("mandy", "v1.4", "data", "705f6ca5f5da0c40c1f547231dd5139f", 7141292,
|
||||
"Mandy.exe", "7016ef8ab67133a1d6fce20b8b70cd1d", 83968,
|
||||
Common::PL_POL, Common::kPlatformWindows, 3),
|
||||
|
||||
// August 4, 2002
|
||||
GAME2l("cubert", "v1.1", "Gamedata", "dfb7f8012a29631349a14351ba1cfd49", 27303861,
|
||||
"Cubert.exe", "055b5b5c30265ba32e4235b012eb90bb", 64000,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
// June 11, 2003
|
||||
GAME2l("cubert", "v1.1", "Gamedata", "dfb7f8012a29631349a14351ba1cfd49", 27303861,
|
||||
"Cubert Badbone.exe", "055b5b5c30265ba32e4235b012eb90bb", 64000,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
// August 16, 2002
|
||||
GAME2l("cubert", "v1.2", "Gamedata", "245b043e4b2ade16f56118f8d98fb940", 27304149,
|
||||
"Cubert.exe", "055b5b5c30265ba32e4235b012eb90bb", 64000,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
// September 5, 2002
|
||||
GAME2l("cubert", "v1.25", "gamedata", "d1d9b27d0c43a37952c1bef7bc848623", 27306453,
|
||||
"Cubert.exe", "acc9fb7b4be7e7824a003c88942d778d", 67072,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
// Mar 9, 2004
|
||||
GAME1l("cubert", "", "cubert.dat", "cabc424d4e39ecdba4b0afd4033b5ea8", 19696514, Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
GAME1l("cubert", "", "cubert.dat", "cabc424d4e39ecdba4b0afd4033b5ea8", 19696514, Common::IT_ITA, Common::kPlatformWindows, 1),
|
||||
GAME1l("cubert", "", "cubert.dat", "cabc424d4e39ecdba4b0afd4033b5ea8", 19696514, Common::SV_SWE, Common::kPlatformWindows, 2),
|
||||
GAME1l("cubert", "", "cubert.dat", "cabc424d4e39ecdba4b0afd4033b5ea8", 19696514, Common::DE_DEU, Common::kPlatformWindows, 3),
|
||||
// Dec 15, 2005
|
||||
GAME1l("cubert", "", "cubert.dat", "e70050692a0ab96e8753109793157ccd", 19677815, Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
GAME1l("cubert", "", "cubert.dat", "e70050692a0ab96e8753109793157ccd", 19677815, Common::IT_ITA, Common::kPlatformWindows, 1),
|
||||
GAME1l("cubert", "", "cubert.dat", "e70050692a0ab96e8753109793157ccd", 19677815, Common::SV_SWE, Common::kPlatformWindows, 2),
|
||||
GAME1l("cubert", "", "cubert.dat", "e70050692a0ab96e8753109793157ccd", 19677815, Common::DE_DEU, Common::kPlatformWindows, 3),
|
||||
|
||||
GAME1("nsc", "v1.03", "gamedata.slg", "57f318cc09e93a1e0685b790a956ebdc", 12733871),
|
||||
GAME2l("nsc", "v1.03", "gamedata", "57f318cc09e93a1e0685b790a956ebdc", 12733871,
|
||||
"Nathan's Second Chance.exe", "9bb4492fc7f7fc38bc1772bb9f15f787", 71680,
|
||||
Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
|
||||
GAME1("gjgagsas", "", "gamedata.slg", "f438946f2ee79d52918f44c4a67eb37b", 27527984),
|
||||
|
||||
GAME1("tsotc", "v6", "gamedata.slg", "7d677e79fb842df00c4602864da13829", 34740918),
|
||||
|
||||
GAME1("atw", "", "atw.slg", "41ae22ac9fa5051e0499468a9fbe600e", 27808575),
|
||||
|
||||
GAME1l("leptonsquest", "", "game.slg", "763d4020dcd55a4af4c01664f79584da", 71233234, Common::EN_ANY, Common::kPlatformWindows, 0),
|
||||
GAME1l("leptonsquest", "", "Gamedata.slg", "763d4020dcd55a4af4c01664f79584da", 71233239, Common::EN_ANY, Common::kPlatformMacintosh, 0),
|
||||
GAME1l("leptonsquest", "", "LeptonsQuest.slg", "763d4020dcd55a4af4c01664f79584da", 71233239, Common::EN_ANY, Common::kPlatformLinux, 0),
|
||||
|
||||
GAME1("otto", "", "gamedata", "c93b1bd849cdb6a23fb8eb389f5c1955", 154427),
|
||||
|
||||
{ AD_TABLE_END_MARKER, 0 }
|
||||
};
|
||||
|
||||
} // End of namespace Wage
|
||||
75
engines/sludge/errors.h
Normal file
75
engines/sludge/errors.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_ERRRORS_H
|
||||
#define SLUDGE_ERRRORS_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
#define _NO_MEMORY_GENERAL_ "\n\nTry closing down any programs you don't really need running (or freeing up a bit of disk space, which will give you more virtual memory - that should help too)."
|
||||
|
||||
//---------------------------------------
|
||||
// Fatal errors
|
||||
//---------------------------------------
|
||||
|
||||
#define ERROR_VERSION_TOO_LOW_1 "This SLUDGE file requires a more recent version of the SLUDGE engine"
|
||||
#define ERROR_VERSION_TOO_LOW_2 "(it was created for v%i.%i).\n\nVisit http://opensludge.github.io/ to download the most recent version."
|
||||
#define ERROR_VERSION_TOO_HIGH_1 "This SLUDGE file was created for an older version of the SLUDGE engine"
|
||||
#define ERROR_VERSION_TOO_HIGH_2 "(v%i.%i).\n\nPlease contact the author of this game to obtain a version compatible with your SLUDGE engine (v" TEXT_VERSION ")."
|
||||
#define ERROR_BAD_HEADER "Bad header information... this isn't a valid SLUDGE game"
|
||||
#define ERROR_HACKER "What have you been up to? Think we're a hacker, do we? Nice try."
|
||||
|
||||
#define ERROR_GAME_LOAD_NO "This isn't a SLUDGE saved game!\n"
|
||||
#define ERROR_GAME_LOAD_WRONG "Can't load this saved game! It was either created by...\n\n (a) a different SLUDGE game to the one which you're playing, or...\n (b) a different (newer or older) version of the same game.\n\nFilename"
|
||||
#define ERROR_GAME_SAVE_FROZEN "Can't save games while I'm frozen"
|
||||
#define ERROR_GAME_LOAD_CORRUPT "This saved game appears to be corrupted"
|
||||
|
||||
#define ERROR_NON_EMPTY_STACK "Returning from function with non-empty stack"
|
||||
#define ERROR_UNKNOWN_MCODE "Unknown SLUDGE machine code"
|
||||
#define ERROR_CALL_NONFUNCTION "Call of non-function"
|
||||
#define ERROR_INCDEC_UNKNOWN "Tried to increment/decrement index of an undefined variable"
|
||||
#define ERROR_INDEX_EMPTY "Tried to index an empty stack"
|
||||
#define ERROR_INDEX_NONSTACK "Tried to index a non-stack variable"
|
||||
#define ERROR_NOSTACK "Corrupt file - no stack"
|
||||
#define ERROR_UNKNOWN_CODE "Unimplemented internal SLUDGE command code."
|
||||
#define ERROR_OUT_OF_MEMORY "Out of memory!" _NO_MEMORY_GENERAL_
|
||||
|
||||
#define ERROR_MUSIC_MEMORY_LOW "Your computer doesn't have enough memory available to load a music resource that needs playing." _NO_MEMORY_GENERAL_
|
||||
#define ERROR_SOUND_MEMORY_LOW "Your computer doesn't have enough memory available to load a sound resource that needs playing." _NO_MEMORY_GENERAL_
|
||||
#define ERROR_MUSIC_UNKNOWN "I can't understand a piece of music which I've been told to play!\n\n" \
|
||||
"Maybe it's stored in a format that SLUDGE doesn't know about... " \
|
||||
"make sure you've got a recent version of the SLUDGE engine from http://opensludge.github.io/. " \
|
||||
"Failing that, maybe the resource in question isn't a valid music format at all... in which case, contact the game's author and tell them what's happened."
|
||||
#define ERROR_SOUND_UNKNOWN "I can't understand a sample which I've been told to play!\nMake sure you've got the latest SLUDGE engine from http://opensludge.github.io/. Failing that, maybe the resource in question isn't a valid sound at all... in which case, contact the game's author and tell them what's happened."
|
||||
#define ERROR_MUSIC_ODDNESS "I can't load a music resource I've been told to play. Sorry."
|
||||
#define ERROR_SOUND_ODDNESS "I can't load a sound resource I've been told to play. Sorry."
|
||||
#define ERROR_MOVIE_ODDNESS "I can't load a music resource I've been told to play. Sorry."
|
||||
|
||||
//---------------------------------------
|
||||
// Startup warnings
|
||||
//---------------------------------------
|
||||
|
||||
#define WARNING_BASS_WRONG_VERSION "Incompatible version of BASS.DLL found!"
|
||||
#define WARNING_BASS_FAIL "Can't initialise sound engine."
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
359
engines/sludge/event.cpp
Normal file
359
engines/sludge/event.cpp
Normal file
@@ -0,0 +1,359 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/system.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "gui/message.h"
|
||||
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/freeze.h"
|
||||
#include "sludge/function.h"
|
||||
#include "sludge/movie.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/objtypes.h"
|
||||
#include "sludge/region.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
extern VariableStack *noStack;
|
||||
|
||||
EventManager::EventManager(SludgeEngine *vm) {
|
||||
_vm = vm;
|
||||
_currentEvents = new EventHandlers;
|
||||
init();
|
||||
}
|
||||
|
||||
EventManager::~EventManager() {
|
||||
kill();
|
||||
if (_currentEvents) {
|
||||
delete _currentEvents;
|
||||
_currentEvents = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::init() {
|
||||
_weAreDoneSoQuit = 0;
|
||||
_reallyWantToQuit = false;
|
||||
|
||||
_input.leftClick = _input.rightClick = _input.justMoved = _input.leftRelease = _input.rightRelease = false;
|
||||
_input.keyPressed = 0;
|
||||
|
||||
for (uint i = 0; i < EVENT_FUNC_NB; ++i) {
|
||||
_currentEvents->func[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::kill() {
|
||||
}
|
||||
|
||||
void EventManager::checkInput() {
|
||||
float cameraZoom = _vm->_gfxMan->getCamZoom();
|
||||
//static bool fakeRightclick = false;
|
||||
Common::Event event;
|
||||
|
||||
/* Check for events */
|
||||
while (g_system->getEventManager()->pollEvent(event)) {
|
||||
switch (event.type) {
|
||||
#if 0
|
||||
case SDL_VIDEORESIZE:
|
||||
realWinWidth = event.resize.w;
|
||||
realWinHeight = event.resize.h;
|
||||
setGraphicsWindow(false, true, true);
|
||||
break;
|
||||
#endif
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
_input.justMoved = true;
|
||||
_input.mouseX = event.mouse.x * cameraZoom;
|
||||
_input.mouseY = event.mouse.y * cameraZoom;
|
||||
break;
|
||||
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
if (g_system->getEventManager()->getModifierState() & Common::KBD_CTRL) {
|
||||
_input.rightClick = true;
|
||||
//fakeRightclick = true;
|
||||
} else {
|
||||
_input.leftClick = true;
|
||||
//fakeRightclick = false;
|
||||
}
|
||||
|
||||
_input.mouseX = event.mouse.x * cameraZoom;
|
||||
_input.mouseY = event.mouse.y * cameraZoom;
|
||||
break;
|
||||
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
_input.rightClick = true;
|
||||
_input.mouseX = event.mouse.x * cameraZoom;
|
||||
_input.mouseY = event.mouse.y * cameraZoom;
|
||||
break;
|
||||
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
_input.leftRelease = true;
|
||||
_input.mouseX = event.mouse.x * cameraZoom;
|
||||
_input.mouseY = event.mouse.y * cameraZoom;
|
||||
break;
|
||||
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
_input.rightRelease = true;
|
||||
_input.mouseX = event.mouse.x * cameraZoom;
|
||||
_input.mouseY = event.mouse.y * cameraZoom;
|
||||
break;
|
||||
|
||||
case Common::EVENT_KEYDOWN:
|
||||
switch (event.kbd.keycode) {
|
||||
case Common::KEYCODE_BACKSPACE:
|
||||
// fall through
|
||||
case Common::KEYCODE_DELETE:
|
||||
_input.keyPressed = Common::KEYCODE_DELETE;
|
||||
break;
|
||||
default:
|
||||
_input.keyPressed = event.kbd.keycode;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Common::EVENT_QUIT:
|
||||
case Common::EVENT_RETURN_TO_LAUNCHER: {
|
||||
if (!_weAreDoneSoQuit) {
|
||||
g_system->getEventManager()->resetQuit();
|
||||
g_system->getEventManager()->resetReturnToLauncher();
|
||||
|
||||
GUI::MessageDialog dialog(_(g_sludge->_resMan->getNumberedString(2)), _("Yes"), _("No"));
|
||||
if (dialog.runModal() == GUI::kMessageOK) {
|
||||
_weAreDoneSoQuit = 1;
|
||||
g_system->getEventManager()->pushEvent(event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EventManager::handleInput() {
|
||||
if (!_vm->_regionMan->getOverRegion())
|
||||
_vm->_regionMan->updateOverRegion();
|
||||
|
||||
if (_input.justMoved) {
|
||||
if (_currentEvents->func[kMoveMouse]) {
|
||||
if (!startNewFunctionNum(_currentEvents->func[kMoveMouse], 0, nullptr, noStack))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
_input.justMoved = false;
|
||||
|
||||
if (_vm-> _regionMan->isRegionChanged()&& _currentEvents->func[kFocus]) {
|
||||
VariableStack *tempStack = new VariableStack;
|
||||
if (!checkNew(tempStack))
|
||||
return false;
|
||||
|
||||
ScreenRegion *overRegion = _vm->_regionMan->getOverRegion();
|
||||
if (overRegion) {
|
||||
tempStack->thisVar.setVariable(SVT_OBJTYPE, overRegion->thisType->objectNum);
|
||||
} else {
|
||||
tempStack->thisVar.setVariable(SVT_INT, 0);
|
||||
}
|
||||
tempStack->next = nullptr;
|
||||
if (!startNewFunctionNum(_currentEvents->func[kFocus], 1, nullptr, tempStack))
|
||||
return false;
|
||||
}
|
||||
if (_input.leftRelease && _currentEvents->func[kLeftMouseUp]) {
|
||||
if (!startNewFunctionNum(_currentEvents->func[kLeftMouseUp], 0, nullptr, noStack))
|
||||
return false;
|
||||
}
|
||||
if (_input.rightRelease && _currentEvents->func[kRightMouseUp]) {
|
||||
if (!startNewFunctionNum(_currentEvents->func[kRightMouseUp], 0, nullptr, noStack))
|
||||
return false;
|
||||
}
|
||||
if (_input.leftClick && _currentEvents->func[kLeftMouse])
|
||||
if (!startNewFunctionNum(_currentEvents->func[kLeftMouse], 0, nullptr, noStack))
|
||||
return false;
|
||||
if (_input.rightClick && _currentEvents->func[kRightMouse]) {
|
||||
if (!startNewFunctionNum(_currentEvents->func[kRightMouse], 0, nullptr, noStack))
|
||||
return false;
|
||||
}
|
||||
if (_input.keyPressed && _currentEvents->func[kSpace]) {
|
||||
Common::String tempString = "";
|
||||
switch (_input.keyPressed) {
|
||||
case Common::KEYCODE_DELETE:
|
||||
tempString = "BACKSPACE";
|
||||
break;
|
||||
case Common::KEYCODE_TAB:
|
||||
tempString = "TAB";
|
||||
break;
|
||||
case Common::KEYCODE_RETURN:
|
||||
tempString = "ENTER";
|
||||
break;
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
tempString = "ESCAPE";
|
||||
break;
|
||||
/*
|
||||
case 1112: tempString = copyString ("ALT+F1"); break;
|
||||
case 1113: tempString = copyString ("ALT+F2"); break;
|
||||
case 1114: tempString = copyString ("ALT+F3"); break;
|
||||
case 1115: tempString = copyString ("ALT+F4"); break;
|
||||
case 1116: tempString = copyString ("ALT+F5"); break;
|
||||
case 1117: tempString = copyString ("ALT+F6"); break;
|
||||
case 1118: tempString = copyString ("ALT+F7"); break;
|
||||
case 1119: tempString = copyString ("ALT+F8"); break;
|
||||
case 1120: tempString = copyString ("ALT+F9"); break;
|
||||
case 1121: tempString = copyString ("ALT+F10"); break;
|
||||
case 1122: tempString = copyString ("ALT+F11"); break;
|
||||
case 1123: tempString = copyString ("ALT+F12"); break;
|
||||
|
||||
case 2019: tempString = copyString ("PAUSE"); break;
|
||||
*/
|
||||
case Common::KEYCODE_PAGEUP:
|
||||
tempString = "PAGE UP";
|
||||
break;
|
||||
case Common::KEYCODE_PAGEDOWN:
|
||||
tempString = "PAGE DOWN";
|
||||
break;
|
||||
case Common::KEYCODE_END:
|
||||
tempString = "END";
|
||||
break;
|
||||
case Common::KEYCODE_HOME:
|
||||
tempString = "HOME";
|
||||
break;
|
||||
case Common::KEYCODE_LEFT:
|
||||
tempString = "LEFT";
|
||||
break;
|
||||
case Common::KEYCODE_UP:
|
||||
tempString = "UP";
|
||||
break;
|
||||
case Common::KEYCODE_RIGHT:
|
||||
tempString = "RIGHT";
|
||||
break;
|
||||
case Common::KEYCODE_DOWN:
|
||||
tempString = "DOWN";
|
||||
break;
|
||||
/*
|
||||
case 2045: tempString = copyString ("INSERT"); break;
|
||||
case 2046: tempString = copyString ("DELETE"); break;
|
||||
*/
|
||||
case Common::KEYCODE_F1:
|
||||
tempString = "F1";
|
||||
break;
|
||||
case Common::KEYCODE_F2:
|
||||
tempString = "F2";
|
||||
break;
|
||||
case Common::KEYCODE_F3:
|
||||
tempString = "F3";
|
||||
break;
|
||||
case Common::KEYCODE_F4:
|
||||
tempString = "F4";
|
||||
break;
|
||||
case Common::KEYCODE_F5:
|
||||
tempString = "F5";
|
||||
break;
|
||||
case Common::KEYCODE_F6:
|
||||
tempString = "F6";
|
||||
break;
|
||||
case Common::KEYCODE_F7:
|
||||
tempString = "F7";
|
||||
break;
|
||||
case Common::KEYCODE_F8:
|
||||
tempString = "F8";
|
||||
break;
|
||||
case Common::KEYCODE_F9:
|
||||
tempString = "F9";
|
||||
break;
|
||||
case Common::KEYCODE_F10:
|
||||
tempString = "F10";
|
||||
break;
|
||||
case Common::KEYCODE_F11:
|
||||
tempString = "F11";
|
||||
break;
|
||||
case Common::KEYCODE_F12:
|
||||
tempString = "F12";
|
||||
break;
|
||||
|
||||
default:
|
||||
if (_input.keyPressed >= 256) {
|
||||
char tmp[7] = "ABCDEF";
|
||||
Common::sprintf_s(tmp, "%i", _input.keyPressed);
|
||||
tempString = tmp;
|
||||
//}
|
||||
} else {
|
||||
char tmp[2] = " ";
|
||||
tmp[0] = _input.keyPressed;
|
||||
tempString = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tempString.empty()) {
|
||||
if (isMoviePlaying())
|
||||
stopMovie();
|
||||
VariableStack *tempStack = new VariableStack;
|
||||
if (!checkNew(tempStack))
|
||||
return false;
|
||||
tempStack->thisVar.makeTextVar(tempString);
|
||||
tempStack->next = nullptr;
|
||||
if (!startNewFunctionNum(_currentEvents->func[kSpace], 1, nullptr, tempStack))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
_input.rightClick = false;
|
||||
_input.leftClick = false;
|
||||
_input.rightRelease = false;
|
||||
_input.leftRelease = false;
|
||||
_input.keyPressed = 0;
|
||||
_vm->_regionMan->updateLastRegion();
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventManager::loadHandlers(Common::SeekableReadStream *stream) {
|
||||
for (uint i = 0; i < EVENT_FUNC_NB; ++i) {
|
||||
_currentEvents->func[i] = stream->readUint16BE();
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::saveHandlers(Common::WriteStream *stream) {
|
||||
for (uint i = 0; i < EVENT_FUNC_NB; ++i) {
|
||||
stream->writeUint16BE(_currentEvents->func[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool EventManager::freeze(FrozenStuffStruct *frozenStuff) {
|
||||
frozenStuff->currentEvents = _currentEvents;
|
||||
_currentEvents = new EventHandlers;
|
||||
if (!checkNew(_currentEvents))
|
||||
return false;
|
||||
for (uint i = 0; i < EVENT_FUNC_NB; ++i) {
|
||||
_currentEvents->func[i] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventManager::restore(FrozenStuffStruct *frozenStuff) {
|
||||
delete _currentEvents;
|
||||
_currentEvents = frozenStuff->currentEvents;
|
||||
}
|
||||
|
||||
} /* namespace Sludge */
|
||||
97
engines/sludge/event.h
Normal file
97
engines/sludge/event.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_EVENT_H
|
||||
#define SLUDGE_EVENT_H
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
class WriteStream;
|
||||
}
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct FrozenStuffStruct;
|
||||
|
||||
struct InputType {
|
||||
bool leftClick, rightClick, justMoved, leftRelease, rightRelease;
|
||||
int mouseX, mouseY, keyPressed;
|
||||
};
|
||||
|
||||
enum EventFunctions {
|
||||
kLeftMouse,
|
||||
kLeftMouseUp,
|
||||
kRightMouse,
|
||||
kRightMouseUp,
|
||||
kMoveMouse,
|
||||
kFocus,
|
||||
kSpace,
|
||||
EVENT_FUNC_NB
|
||||
};
|
||||
|
||||
struct EventHandlers {
|
||||
int func[EVENT_FUNC_NB];
|
||||
};
|
||||
|
||||
class SludgeEngine;
|
||||
|
||||
class EventManager {
|
||||
public:
|
||||
EventManager(SludgeEngine *vm);
|
||||
virtual ~EventManager();
|
||||
|
||||
void init();
|
||||
void kill();
|
||||
|
||||
// Input
|
||||
void checkInput();
|
||||
bool handleInput();
|
||||
|
||||
int mouseX() const { return _input.mouseX; }
|
||||
int mouseY() const { return _input.mouseY; }
|
||||
int &mouseX() { return _input.mouseX; }
|
||||
int &mouseY() { return _input.mouseY; }
|
||||
|
||||
// Events
|
||||
void setEventFunction(EventFunctions event, int funcNum) { _currentEvents->func[event] = funcNum; };
|
||||
void loadHandlers(Common::SeekableReadStream *stream);
|
||||
void saveHandlers(Common::WriteStream *stream);
|
||||
bool freeze(FrozenStuffStruct *frozenStuff);
|
||||
void restore(FrozenStuffStruct *frozenStuff);
|
||||
|
||||
// Quit
|
||||
void startGame() { _weAreDoneSoQuit = false; }
|
||||
void quitGame() { _weAreDoneSoQuit = true; /* _reallyWantToQuit = true; */ }
|
||||
bool quit() { return _weAreDoneSoQuit; }
|
||||
|
||||
private:
|
||||
SludgeEngine *_vm;
|
||||
InputType _input;
|
||||
|
||||
int _weAreDoneSoQuit;
|
||||
bool _reallyWantToQuit;
|
||||
|
||||
EventHandlers *_currentEvents;
|
||||
};
|
||||
|
||||
} /* namespace Sludge */
|
||||
|
||||
#endif /* ENGINES_SLUDGE_EVENT_H_ */
|
||||
344
engines/sludge/fileset.cpp
Normal file
344
engines/sludge/fileset.cpp
Normal file
@@ -0,0 +1,344 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/moreio.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/version.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
ResourceManager::ResourceManager() {
|
||||
init();
|
||||
}
|
||||
|
||||
ResourceManager::~ResourceManager() {
|
||||
kill();
|
||||
}
|
||||
|
||||
void ResourceManager::init() {
|
||||
_sliceBusy = true;
|
||||
_bigDataFile = nullptr;
|
||||
_startOfDataIndex = 0;
|
||||
_startOfTextIndex = 0;
|
||||
_startOfSubIndex = 0;
|
||||
_startOfObjectIndex = 0;
|
||||
_startIndex = 0;
|
||||
_allResourceNames.clear();
|
||||
}
|
||||
void ResourceManager::kill() {
|
||||
if (_bigDataFile) {
|
||||
delete _bigDataFile;
|
||||
_bigDataFile = nullptr;
|
||||
}
|
||||
_allResourceNames.clear();
|
||||
}
|
||||
|
||||
bool ResourceManager::openSubSlice(int num) {
|
||||
if (_sliceBusy) {
|
||||
fatal("Can't read from data file", "I'm already reading something");
|
||||
return false;
|
||||
}
|
||||
_bigDataFile->seek(_startOfSubIndex + (num << 2), 0);
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), 0);
|
||||
|
||||
return _sliceBusy = true;
|
||||
}
|
||||
|
||||
bool ResourceManager::openObjectSlice(int num) {
|
||||
if (_sliceBusy) {
|
||||
fatal("Can't read from data file", "I'm already reading something");
|
||||
return false;
|
||||
}
|
||||
|
||||
_bigDataFile->seek(_startOfObjectIndex + (num << 2), 0);
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), 0);
|
||||
return _sliceBusy = true;
|
||||
}
|
||||
|
||||
uint ResourceManager::openFileFromNum(int num) {
|
||||
if (_sliceBusy) {
|
||||
fatal("Can't read from data file", "I'm already reading something");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_bigDataFile->seek(_startOfDataIndex + (num << 2), 0);
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), 1);
|
||||
_sliceBusy = true;
|
||||
|
||||
return _bigDataFile->readUint32LE();
|
||||
}
|
||||
|
||||
uint32 ResourceManager::_cp1250ToUTF32[128] = {
|
||||
/* 0x80 */
|
||||
0x20ac, 0xfffd, 0x201a, 0xfffd, 0x201e, 0x2026, 0x2020, 0x2021,
|
||||
0xfffd, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
|
||||
/* 0x90 */
|
||||
0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
|
||||
0xfffd, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
|
||||
/* 0xa0 */
|
||||
0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
|
||||
0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
|
||||
/* 0xb0 */
|
||||
0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
|
||||
/* 0xc0 */
|
||||
0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
|
||||
0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
|
||||
/* 0xd0 */
|
||||
0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
|
||||
0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
|
||||
/* 0xe0 */
|
||||
0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
|
||||
0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
|
||||
/* 0xf0 */
|
||||
0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
|
||||
0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
|
||||
};
|
||||
|
||||
// Converts a string from ISO8859-2 or CP1250 to UTF8.
|
||||
// This is needed for old games.
|
||||
Common::String ResourceManager::convertString(const Common::String &s) {
|
||||
Common::String res;
|
||||
Common::U32String tmp;
|
||||
|
||||
// Convert CP1250 to UTF32
|
||||
for (uint i = 0; i < s.size(); ++i) {
|
||||
const byte c = s[i];
|
||||
if (c < 0x80) {
|
||||
tmp += c;
|
||||
} else {
|
||||
uint32 utf32 = _cp1250ToUTF32[c - 0x80];
|
||||
if (utf32) {
|
||||
tmp += utf32;
|
||||
} else {
|
||||
// It's an invalid CP1250 character...
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert UTF32 to UTF8
|
||||
for (uint i = 0; i < tmp.size(); ++i) {
|
||||
uint32 wc = tmp[i];
|
||||
int count;
|
||||
if (wc < 0x80)
|
||||
count = 1;
|
||||
else if (wc < 0x800)
|
||||
count = 2;
|
||||
else if (wc < 0x10000) {
|
||||
if (wc < 0xd800 || wc >= 0xe000) {
|
||||
count = 3;
|
||||
} else {
|
||||
// It's an invalid UTF32 character...
|
||||
return s;
|
||||
}
|
||||
} else if (wc < 0x110000) {
|
||||
count = 4;
|
||||
} else {
|
||||
// It's an invalid UTF32 character...
|
||||
return s;
|
||||
}
|
||||
Common::String r = "";
|
||||
switch (count) {
|
||||
case 4:
|
||||
r = (char)(0x80 | (wc & 0x3f)) + r;
|
||||
wc = wc >> 6;
|
||||
wc |= 0x10000;
|
||||
// falls through
|
||||
case 3:
|
||||
r = (char)(0x80 | (wc & 0x3f)) + r;
|
||||
wc = wc >> 6;
|
||||
wc |= 0x800;
|
||||
// falls through
|
||||
case 2:
|
||||
r = (char)(0x80 | (wc & 0x3f)) + r;
|
||||
wc = wc >> 6;
|
||||
wc |= 0xc0;
|
||||
// falls through
|
||||
case 1:
|
||||
r = wc + r;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
res += r;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Common::String ResourceManager::getNumberedString(int value) {
|
||||
uint32 pos = _bigDataFile->pos();
|
||||
|
||||
_bigDataFile->seek((value << 2) + _startOfTextIndex, 0);
|
||||
value = _bigDataFile->readUint32LE();
|
||||
_bigDataFile->seek(value, 0);
|
||||
|
||||
Common::String s = readString(_bigDataFile);
|
||||
|
||||
if (gameVersion < VERSION(2, 2)) {
|
||||
// This is an older game - We need to convert the string to UTF-8
|
||||
s = convertString(s);
|
||||
}
|
||||
|
||||
if (_sliceBusy)
|
||||
_bigDataFile->seek(pos);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool ResourceManager::startAccess() {
|
||||
int wasBusy = _sliceBusy;
|
||||
_sliceBusy = true;
|
||||
return wasBusy;
|
||||
}
|
||||
void ResourceManager::finishAccess() {
|
||||
_sliceBusy = false;
|
||||
}
|
||||
|
||||
void ResourceManager::dumpFile(int num, const char *pattern) {
|
||||
if (!g_sludge->_dumpScripts)
|
||||
return;
|
||||
|
||||
Common::DumpFile dumpFile;
|
||||
dumpFile.open(Common::Path("dumps/").appendComponent(Common::String::format(pattern, num)));
|
||||
uint32 pos = _bigDataFile->pos();
|
||||
|
||||
_bigDataFile->seek(_startOfDataIndex + (num << 2), 0);
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), 1);
|
||||
|
||||
uint fsize = _bigDataFile->readUint32LE();
|
||||
|
||||
byte *data = (byte *)malloc(fsize);
|
||||
|
||||
_bigDataFile->read(data, fsize);
|
||||
dumpFile.write(data, fsize);
|
||||
dumpFile.close();
|
||||
|
||||
free(data);
|
||||
|
||||
_bigDataFile->seek(pos);
|
||||
}
|
||||
|
||||
bool ResourceManager::dumpFileFromName(const char *name) {
|
||||
int num = -1;
|
||||
for (int i = 0; i < getResourceNameCount(); i++) {
|
||||
if (name != resourceNameFromNum(i))
|
||||
continue;
|
||||
num = i;
|
||||
break;
|
||||
}
|
||||
if (num < 0)
|
||||
return false;
|
||||
|
||||
Common::DumpFile dumpFile;
|
||||
dumpFile.open(Common::Path("dumps/").append(name), true);
|
||||
uint32 pos = _bigDataFile->pos();
|
||||
|
||||
_bigDataFile->seek(_startOfDataIndex + (num << 2), 0);
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), 1);
|
||||
|
||||
uint fsize = _bigDataFile->readUint32LE();
|
||||
|
||||
byte *data = (byte *)malloc(fsize);
|
||||
|
||||
_bigDataFile->read(data, fsize);
|
||||
dumpFile.write(data, fsize);
|
||||
dumpFile.close();
|
||||
|
||||
free(data);
|
||||
|
||||
_bigDataFile->seek(pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResourceManager::readResourceNames(Common::SeekableReadStream *readStream) {
|
||||
int numResourceNames = readStream->readUint16BE();
|
||||
debugC(2, kSludgeDebugDataLoad, "numResourceNames %i", numResourceNames);
|
||||
_allResourceNames.reserve(numResourceNames);
|
||||
|
||||
for (int fn = 0; fn < numResourceNames; fn++) {
|
||||
_allResourceNames.push_back(readString(readStream));
|
||||
debugC(2, kSludgeDebugDataLoad, "Resource %i: %s", fn, _allResourceNames[fn].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
const Common::String ResourceManager::resourceNameFromNum(int i) {
|
||||
if (i == -1)
|
||||
return "";
|
||||
|
||||
if (_allResourceNames.empty())
|
||||
return "RESOURCE";
|
||||
|
||||
if (i < (int)_allResourceNames.size())
|
||||
return _allResourceNames[i];
|
||||
|
||||
return "Unknown resource";
|
||||
}
|
||||
|
||||
void ResourceManager::setData(Common::File *fp) {
|
||||
_bigDataFile = fp;
|
||||
_startIndex = fp->pos();
|
||||
}
|
||||
|
||||
void ResourceManager::setFileIndices(uint numLanguages, uint skipBefore) {
|
||||
_bigDataFile->seek(_startIndex, SEEK_SET);
|
||||
_sliceBusy = false;
|
||||
|
||||
if (skipBefore > numLanguages) {
|
||||
warning("Not a valid language ID! Using default instead.");
|
||||
skipBefore = 0;
|
||||
}
|
||||
|
||||
// STRINGS
|
||||
int skipAfter = numLanguages - skipBefore;
|
||||
while (skipBefore) {
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), SEEK_SET);
|
||||
skipBefore--;
|
||||
}
|
||||
_startOfTextIndex = _bigDataFile->pos() + 4;
|
||||
debugC(2, kSludgeDebugDataLoad, "startOfTextIndex: %i", _startOfTextIndex);
|
||||
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), SEEK_SET);
|
||||
|
||||
while (skipAfter) {
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), SEEK_SET);
|
||||
skipAfter--;
|
||||
}
|
||||
|
||||
_startOfSubIndex = _bigDataFile->pos() + 4;
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), SEEK_CUR);
|
||||
debugC(2, kSludgeDebugDataLoad, "startOfSubIndex: %i", _startOfSubIndex);
|
||||
|
||||
_startOfObjectIndex = _bigDataFile->pos() + 4;
|
||||
_bigDataFile->seek(_bigDataFile->readUint32LE(), SEEK_CUR);
|
||||
debugC(2, kSludgeDebugDataLoad, "startOfObjectIndex: %i", _startOfObjectIndex);
|
||||
|
||||
// Remember that the data section starts here
|
||||
_startOfDataIndex = _bigDataFile->pos();
|
||||
debugC(2, kSludgeDebugDataLoad, "startOfDataIndex: %i", _startOfDataIndex);
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
74
engines/sludge/fileset.h
Normal file
74
engines/sludge/fileset.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_FILESET_H
|
||||
#define SLUDGE_FILESET_H
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class ResourceManager {
|
||||
|
||||
public:
|
||||
ResourceManager();
|
||||
~ResourceManager();
|
||||
|
||||
void init();
|
||||
void kill();
|
||||
|
||||
void setData(Common::File *readStream);
|
||||
void setFileIndices(uint, uint);
|
||||
Common::SeekableReadStream *getData() { return _bigDataFile; }
|
||||
|
||||
uint openFileFromNum(int num);
|
||||
bool openSubSlice(int num);
|
||||
bool openObjectSlice(int num);
|
||||
Common::String getNumberedString(int value);
|
||||
|
||||
// Access control flag
|
||||
bool startAccess();
|
||||
void finishAccess();
|
||||
|
||||
// Resource names
|
||||
void readResourceNames(Common::SeekableReadStream *readStream);
|
||||
const Common::String resourceNameFromNum(int i);
|
||||
bool hasResourceNames() const { return !_allResourceNames.empty(); }
|
||||
int getResourceNameCount() const { return _allResourceNames.size(); }
|
||||
|
||||
void dumpFile(int num, const char *pattern);
|
||||
bool dumpFileFromName(const char *name);
|
||||
|
||||
private:
|
||||
bool _sliceBusy;
|
||||
Common::File *_bigDataFile;
|
||||
uint32 _startOfDataIndex, _startOfTextIndex, _startOfSubIndex, _startOfObjectIndex;
|
||||
int32 _startIndex;
|
||||
|
||||
Common::Array<Common::String> _allResourceNames;
|
||||
|
||||
private:
|
||||
static uint32 _cp1250ToUTF32[128];
|
||||
Common::String convertString(const Common::String &s);
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
447
engines/sludge/floor.cpp
Normal file
447
engines/sludge/floor.cpp
Normal file
@@ -0,0 +1,447 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/floor.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/sludge.h"
|
||||
|
||||
#define ANGLEFIX (180.0 / 3.14157)
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
FloorManager::FloorManager(SludgeEngine *vm) {
|
||||
_vm = vm;
|
||||
_currentFloor = nullptr;
|
||||
}
|
||||
|
||||
FloorManager::~FloorManager() {
|
||||
kill();
|
||||
}
|
||||
|
||||
bool FloorManager::pointInFloorPolygon(FloorPolygon &floorPoly, int x, int y) {
|
||||
int i = 0, j, c = 0;
|
||||
float xp_i, yp_i;
|
||||
float xp_j, yp_j;
|
||||
|
||||
for (j = floorPoly.numVertices - 1; i < floorPoly.numVertices; j = i++) {
|
||||
|
||||
xp_i = _currentFloor->vertex[floorPoly.vertexID[i]].x;
|
||||
yp_i = _currentFloor->vertex[floorPoly.vertexID[i]].y;
|
||||
xp_j = _currentFloor->vertex[floorPoly.vertexID[j]].x;
|
||||
yp_j = _currentFloor->vertex[floorPoly.vertexID[j]].y;
|
||||
|
||||
if ((((yp_i <= y) && (y < yp_j)) || ((yp_j <= y) && (y < yp_i))) && (x < (xp_j - xp_i) * (y - yp_i) / (yp_j - yp_i) + xp_i)) {
|
||||
c = !c;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
bool FloorManager::getMatchingCorners(FloorPolygon &a, FloorPolygon &b, int &cornerA, int &cornerB) {
|
||||
int sharedVertices = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < a.numVertices; i++) {
|
||||
for (j = 0; j < b.numVertices; j++) {
|
||||
if (a.vertexID[i] == b.vertexID[j]) {
|
||||
if (sharedVertices++) {
|
||||
cornerB = a.vertexID[i];
|
||||
return true;
|
||||
} else {
|
||||
cornerA = a.vertexID[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FloorManager::polysShareSide(FloorPolygon &a, FloorPolygon &b) {
|
||||
int sharedVertices = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < a.numVertices; i++) {
|
||||
for (j = 0; j < b.numVertices; j++) {
|
||||
if (a.vertexID[i] == b.vertexID[j]) {
|
||||
if (sharedVertices++)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FloorManager::init() {
|
||||
_currentFloor = new Floor;
|
||||
if (!checkNew(_currentFloor))
|
||||
return false;
|
||||
_currentFloor->numPolygons = 0;
|
||||
_currentFloor->polygon = nullptr;
|
||||
_currentFloor->vertex = nullptr;
|
||||
_currentFloor->matrix = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FloorManager::setFloorNull() {
|
||||
if (_currentFloor) {
|
||||
for (int i = 0; i < _currentFloor->numPolygons; i++) {
|
||||
delete[] _currentFloor->polygon[i].vertexID;
|
||||
delete[] _currentFloor->matrix[i];
|
||||
}
|
||||
_currentFloor->numPolygons = 0;
|
||||
delete[] _currentFloor->polygon;
|
||||
_currentFloor->polygon = nullptr;
|
||||
delete[] _currentFloor->vertex;
|
||||
_currentFloor->vertex = nullptr;
|
||||
delete[] _currentFloor->matrix;
|
||||
_currentFloor->matrix = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void FloorManager::kill() {
|
||||
setFloorNull();
|
||||
if (_currentFloor) {
|
||||
delete _currentFloor;
|
||||
_currentFloor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool FloorManager::setFloor(int fileNum) {
|
||||
|
||||
int i, j;
|
||||
|
||||
setFloorNull();
|
||||
|
||||
setResourceForFatal(fileNum);
|
||||
|
||||
if (!g_sludge->_resMan->openFileFromNum(fileNum))
|
||||
return false;
|
||||
|
||||
g_sludge->_resMan->dumpFile(fileNum, "floor%04d.flo.comp");
|
||||
|
||||
// Find out how many polygons there are and reserve memory
|
||||
|
||||
_currentFloor->originalNum = fileNum;
|
||||
_currentFloor->numPolygons = g_sludge->_resMan->getData()->readByte();
|
||||
_currentFloor->polygon = new FloorPolygon[_currentFloor->numPolygons];
|
||||
if (!checkNew(_currentFloor->polygon))
|
||||
return false;
|
||||
|
||||
// Read in each polygon
|
||||
|
||||
for (i = 0; i < _currentFloor->numPolygons; i++) {
|
||||
// Find out how many vertex IDs there are and reserve memory
|
||||
_currentFloor->polygon[i].numVertices = g_sludge->_resMan->getData()->readByte();
|
||||
_currentFloor->polygon[i].vertexID = new int[_currentFloor->polygon[i].numVertices];
|
||||
if (!checkNew(_currentFloor->polygon[i].vertexID))
|
||||
return false;
|
||||
|
||||
// Read in each vertex ID
|
||||
for (j = 0; j < _currentFloor->polygon[i].numVertices; j++) {
|
||||
_currentFloor->polygon[i].vertexID[j] = g_sludge->_resMan->getData()->readUint16BE();
|
||||
}
|
||||
}
|
||||
|
||||
// Find out how many vertices there are and reserve memory
|
||||
|
||||
i = g_sludge->_resMan->getData()->readUint16BE();
|
||||
_currentFloor->vertex = new Common::Point[i];
|
||||
if (!checkNew(_currentFloor->vertex))
|
||||
return false;
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
_currentFloor->vertex[j].x = g_sludge->_resMan->getData()->readUint16BE();
|
||||
_currentFloor->vertex[j].y = g_sludge->_resMan->getData()->readUint16BE();
|
||||
}
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
|
||||
dumpFloor(fileNum);
|
||||
|
||||
// Now build the movement martix
|
||||
|
||||
_currentFloor->matrix = new int *[_currentFloor->numPolygons];
|
||||
if (!checkNew(_currentFloor->matrix))
|
||||
return false;
|
||||
|
||||
int **distanceMatrix = new int *[_currentFloor->numPolygons];
|
||||
if (!checkNew(distanceMatrix))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < _currentFloor->numPolygons; i++) {
|
||||
_currentFloor->matrix[i] = new int[_currentFloor->numPolygons];
|
||||
distanceMatrix[i] = new int[_currentFloor->numPolygons];
|
||||
if (!checkNew(_currentFloor->matrix[i]))
|
||||
return false;
|
||||
for (j = 0; j < _currentFloor->numPolygons; j++) {
|
||||
_currentFloor->matrix[i][j] = -1;
|
||||
distanceMatrix[i][j] = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < _currentFloor->numPolygons; i++) {
|
||||
for (j = 0; j < _currentFloor->numPolygons; j++) {
|
||||
if (i != j) {
|
||||
if (polysShareSide(_currentFloor->polygon[i], _currentFloor->polygon[j])) {
|
||||
_currentFloor->matrix[i][j] = j;
|
||||
distanceMatrix[i][j] = 1;
|
||||
}
|
||||
} else {
|
||||
_currentFloor->matrix[i][j] = -2;
|
||||
distanceMatrix[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool madeChange;
|
||||
int lookForDistance = 0;
|
||||
|
||||
do {
|
||||
lookForDistance++;
|
||||
madeChange = false;
|
||||
for (i = 0; i < _currentFloor->numPolygons; i++) {
|
||||
for (j = 0; j < _currentFloor->numPolygons; j++) {
|
||||
if (_currentFloor->matrix[i][j] == -1) {
|
||||
|
||||
// OK, so we don't know how to get from i to j...
|
||||
for (int d = 0; d < _currentFloor->numPolygons; d++) {
|
||||
if (d != i && d != j) {
|
||||
if (_currentFloor->matrix[i][d] == d && _currentFloor->matrix[d][j] >= 0 && distanceMatrix[d][j] <= lookForDistance) {
|
||||
_currentFloor->matrix[i][j] = d;
|
||||
distanceMatrix[i][j] = lookForDistance + 1;
|
||||
madeChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (madeChange);
|
||||
|
||||
for (i = 0; i < _currentFloor->numPolygons; i++) {
|
||||
delete[] distanceMatrix[i];
|
||||
}
|
||||
|
||||
delete []distanceMatrix;
|
||||
distanceMatrix = nullptr;
|
||||
|
||||
setResourceForFatal(-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FloorManager::dumpFloor(int fileNum) {
|
||||
if (!g_sludge->_dumpScripts)
|
||||
return;
|
||||
|
||||
Common::DumpFile dumpFile;
|
||||
dumpFile.open(Common::Path(Common::String::format("dumps/floor%04d.flo", fileNum)));
|
||||
|
||||
for (int i = 0; i < _currentFloor->numPolygons; i++) {
|
||||
int nV = _currentFloor->polygon[i].numVertices;
|
||||
if (nV > 1) {
|
||||
int vert = _currentFloor->polygon[i].vertexID[0];
|
||||
dumpFile.writeString(Common::String::format("* %d, %d", _currentFloor->vertex[vert].x, _currentFloor->vertex[vert].y));
|
||||
for (int j = 1; j < nV; j++) {
|
||||
vert = _currentFloor->polygon[i].vertexID[j];
|
||||
dumpFile.writeString(Common::String::format("; %d, %d", _currentFloor->vertex[vert].x, _currentFloor->vertex[vert].y));
|
||||
}
|
||||
dumpFile.writeString("\n");
|
||||
}
|
||||
}
|
||||
|
||||
dumpFile.close();
|
||||
}
|
||||
|
||||
void FloorManager::drawFloor() {
|
||||
int i, j, nV;
|
||||
for (i = 0; i < _currentFloor->numPolygons; i++) {
|
||||
nV = _currentFloor->polygon[i].numVertices;
|
||||
if (nV > 1) {
|
||||
for (j = 1; j < nV; j++) {
|
||||
g_sludge->_gfxMan->drawLine(_currentFloor->vertex[_currentFloor->polygon[i].vertexID[j - 1]].x, _currentFloor->vertex[_currentFloor->polygon[i].vertexID[j - 1]].y,
|
||||
_currentFloor->vertex[_currentFloor->polygon[i].vertexID[j]].x, _currentFloor->vertex[_currentFloor->polygon[i].vertexID[j]].y);
|
||||
}
|
||||
g_sludge->_gfxMan->drawLine(_currentFloor->vertex[_currentFloor->polygon[i].vertexID[0]].x, _currentFloor->vertex[_currentFloor->polygon[i].vertexID[0]].y,
|
||||
_currentFloor->vertex[_currentFloor->polygon[i].vertexID[nV - 1]].x, _currentFloor->vertex[_currentFloor->polygon[i].vertexID[nV - 1]].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FloorManager::inFloor(int x, int y) {
|
||||
int i, r = -1;
|
||||
|
||||
for (i = 0; i < _currentFloor->numPolygons; i++)
|
||||
if (pointInFloorPolygon(_currentFloor->polygon[i], x, y))
|
||||
r = i;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
bool FloorManager::closestPointOnLine(int &closestX, int &closestY, int x1, int y1, int x2, int y2, int xP, int yP) {
|
||||
int xDiff = x2 - x1;
|
||||
int yDiff = y2 - y1;
|
||||
|
||||
double m = xDiff * (xP - x1) + yDiff * (yP - y1);
|
||||
m /= (xDiff * xDiff) + (yDiff * yDiff);
|
||||
|
||||
if (m < 0) {
|
||||
closestX = x1;
|
||||
closestY = y1;
|
||||
} else if (m > 1) {
|
||||
closestX = x2;
|
||||
closestY = y2;
|
||||
} else {
|
||||
closestX = x1 + m * xDiff;
|
||||
closestY = y1 + m * yDiff;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FloorManager::handleClosestPoint(int &setX, int &setY, int &setPoly) {
|
||||
int gotX = 320, gotY = 200, gotPoly = -1, i, j, xTest1, yTest1, xTest2, yTest2, closestX, closestY, oldJ, currentDistance = 0xFFFFF, thisDistance;
|
||||
|
||||
for (i = 0; i < _currentFloor->numPolygons; i++) {
|
||||
oldJ = _currentFloor->polygon[i].numVertices - 1;
|
||||
for (j = 0; j < _currentFloor->polygon[i].numVertices; j++) {
|
||||
xTest1 = _currentFloor->vertex[_currentFloor->polygon[i].vertexID[j]].x;
|
||||
yTest1 = _currentFloor->vertex[_currentFloor->polygon[i].vertexID[j]].y;
|
||||
xTest2 = _currentFloor->vertex[_currentFloor->polygon[i].vertexID[oldJ]].x;
|
||||
yTest2 = _currentFloor->vertex[_currentFloor->polygon[i].vertexID[oldJ]].y;
|
||||
closestPointOnLine(closestX, closestY, xTest1, yTest1, xTest2, yTest2, setX, setY);
|
||||
xTest1 = setX - closestX;
|
||||
yTest1 = setY - closestY;
|
||||
thisDistance = xTest1 * xTest1 + yTest1 * yTest1;
|
||||
|
||||
if (thisDistance < currentDistance) {
|
||||
currentDistance = thisDistance;
|
||||
gotX = closestX;
|
||||
gotY = closestY;
|
||||
gotPoly = i;
|
||||
}
|
||||
oldJ = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (gotPoly == -1)
|
||||
return false;
|
||||
setX = gotX;
|
||||
setY = gotY;
|
||||
setPoly = gotPoly;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FloorManager::doBorderStuff(OnScreenPerson *moveMe) {
|
||||
if (moveMe->inPoly == moveMe->walkToPoly) {
|
||||
moveMe->inPoly = -1;
|
||||
moveMe->thisStepX = moveMe->walkToX;
|
||||
moveMe->thisStepY = moveMe->walkToY;
|
||||
} else {
|
||||
// The section in which we need to be next...
|
||||
int newPoly = _currentFloor->matrix[moveMe->inPoly][moveMe->walkToPoly];
|
||||
if (newPoly == -1)
|
||||
return false;
|
||||
|
||||
// Grab the index of the second matching corner...
|
||||
int ID, ID2;
|
||||
if (!getMatchingCorners(_currentFloor->polygon[moveMe->inPoly], _currentFloor->polygon[newPoly], ID, ID2))
|
||||
return fatal("Not a valid floor plan!");
|
||||
|
||||
// Remember that we're walking to the new polygon...
|
||||
moveMe->inPoly = newPoly;
|
||||
|
||||
// Calculate the destination position on the coincidantal line...
|
||||
int x1 = moveMe->x, y1 = moveMe->y;
|
||||
int x2 = moveMe->walkToX, y2 = moveMe->walkToY;
|
||||
int x3 = _currentFloor->vertex[ID].x, y3 = _currentFloor->vertex[ID].y;
|
||||
int x4 = _currentFloor->vertex[ID2].x, y4 = _currentFloor->vertex[ID2].y;
|
||||
|
||||
int xAB = x1 - x2;
|
||||
int yAB = y1 - y2;
|
||||
int xCD = x4 - x3;
|
||||
int yCD = y4 - y3;
|
||||
|
||||
double m = (yAB * (x3 - x1) - xAB * (y3 - y1));
|
||||
m /= ((xAB * yCD) - (yAB * xCD));
|
||||
|
||||
if (m > 0 && m < 1) {
|
||||
moveMe->thisStepX = x3 + m * xCD;
|
||||
moveMe->thisStepY = y3 + m * yCD;
|
||||
} else {
|
||||
int dx13 = x1 - x3, dx14 = x1 - x4, dx23 = x2 - x3, dx24 = x2 - x4;
|
||||
int dy13 = y1 - y3, dy14 = y1 - y4, dy23 = y2 - y3, dy24 = y2 - y4;
|
||||
|
||||
dx13 *= dx13;
|
||||
dx14 *= dx14;
|
||||
dx23 *= dx23;
|
||||
dx24 *= dx24;
|
||||
dy13 *= dy13;
|
||||
dy14 *= dy14;
|
||||
dy23 *= dy23;
|
||||
dy24 *= dy24;
|
||||
|
||||
if (sqrt((double)dx13 + dy13) + sqrt((double)dx23 + dy23) < sqrt((double)dx14 + dy14) + sqrt((double)dx24 + dy24)) {
|
||||
moveMe->thisStepX = x3;
|
||||
moveMe->thisStepY = y3;
|
||||
} else {
|
||||
moveMe->thisStepX = x4;
|
||||
moveMe->thisStepY = y4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float yDiff = moveMe->thisStepY - moveMe->y;
|
||||
float xDiff = moveMe->x - moveMe->thisStepX;
|
||||
if (xDiff || yDiff) {
|
||||
moveMe->wantAngle = 180 + ANGLEFIX * atan2(xDiff, yDiff * 2);
|
||||
moveMe->spinning = true;
|
||||
}
|
||||
|
||||
moveMe->makeTalker();
|
||||
return true;
|
||||
}
|
||||
|
||||
void FloorManager::save(Common::WriteStream *stream) {
|
||||
if (_currentFloor->numPolygons) {
|
||||
stream->writeByte(1);
|
||||
stream->writeUint16BE(_currentFloor->originalNum);
|
||||
} else {
|
||||
stream->writeByte(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool FloorManager::load(Common::SeekableReadStream *stream) {
|
||||
if (stream->readByte()) {
|
||||
if (!setFloor(stream->readUint16BE()))
|
||||
return false;
|
||||
} else {
|
||||
setFloorNull();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
83
engines/sludge/floor.h
Normal file
83
engines/sludge/floor.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_FLOOR_H
|
||||
#define SLUDGE_FLOOR_H
|
||||
|
||||
namespace Common {
|
||||
struct Point;
|
||||
class SeekableReadStream;
|
||||
class WriteStream;
|
||||
}
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class SludgeEngine;
|
||||
struct OnScreenPerson;
|
||||
|
||||
struct FloorPolygon {
|
||||
int numVertices;
|
||||
int *vertexID;
|
||||
};
|
||||
|
||||
struct Floor {
|
||||
int originalNum;
|
||||
Common::Point *vertex;
|
||||
int numPolygons;
|
||||
FloorPolygon *polygon;
|
||||
int **matrix;
|
||||
};
|
||||
|
||||
class FloorManager {
|
||||
public:
|
||||
FloorManager(SludgeEngine *vm);
|
||||
~FloorManager();
|
||||
|
||||
bool init();
|
||||
void kill();
|
||||
|
||||
void setFloorNull();
|
||||
bool setFloor(int fileNum);
|
||||
void drawFloor();
|
||||
int inFloor(int x, int y);
|
||||
bool isFloorNoPolygon() { return !_currentFloor || _currentFloor->numPolygons == 0; }
|
||||
|
||||
// For Person collision detection
|
||||
bool handleClosestPoint(int &setX, int &setY, int &setPoly);
|
||||
bool doBorderStuff(OnScreenPerson *moveMe);
|
||||
|
||||
// Save & load
|
||||
void save(Common::WriteStream *stream);
|
||||
bool load(Common::SeekableReadStream *stream);
|
||||
|
||||
private:
|
||||
Floor *_currentFloor;
|
||||
SludgeEngine *_vm;
|
||||
|
||||
bool getMatchingCorners(FloorPolygon &, FloorPolygon &, int &, int &);
|
||||
bool closestPointOnLine(int &closestX, int &closestY, int x1, int y1, int x2, int y2, int xP, int yP);
|
||||
bool pointInFloorPolygon(FloorPolygon &floorPoly, int x, int y);
|
||||
bool polysShareSide(FloorPolygon &a, FloorPolygon &b);
|
||||
void dumpFloor(int fileNum);
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
211
engines/sludge/fonttext.cpp
Normal file
211
engines/sludge/fonttext.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
#include "sludge/fonttext.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/moreio.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/version.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
TextManager::TextManager() {
|
||||
init();
|
||||
}
|
||||
|
||||
TextManager::~TextManager() {
|
||||
kill();
|
||||
}
|
||||
|
||||
void TextManager::init() {
|
||||
_theFont.total = 0;
|
||||
_theFont.sprites = nullptr;
|
||||
|
||||
_fontHeight = 0;
|
||||
_numFontColours = 0;
|
||||
_loadedFontNum = 0;
|
||||
_fontSpace = -1;
|
||||
|
||||
_pastePalette.init();
|
||||
_fontTable.clear();
|
||||
}
|
||||
|
||||
void TextManager::kill() {
|
||||
GraphicsManager::forgetSpriteBank(_theFont);
|
||||
_pastePalette.kill();
|
||||
}
|
||||
|
||||
bool TextManager::isInFont(const Common::String &theText) {
|
||||
if (_fontTable.empty())
|
||||
return 0;
|
||||
if (theText.empty())
|
||||
return 0;
|
||||
|
||||
Common::U32String str32 = theText.decode(Common::kUtf8);
|
||||
|
||||
// We don't want to compare strings. Only single characters allowed!
|
||||
if (str32.size() > 1)
|
||||
return false;
|
||||
|
||||
uint32 c = str32[0];
|
||||
|
||||
// check if font order contains the utf8 char
|
||||
return _fontOrder.contains(c);
|
||||
}
|
||||
|
||||
int TextManager::stringLength(const Common::String &theText) {
|
||||
Common::U32String str32 = theText.decode(Common::kUtf8);
|
||||
return str32.size();
|
||||
}
|
||||
|
||||
int TextManager::stringWidth(const Common::String &theText) {
|
||||
int xOff = 0;
|
||||
|
||||
if (_fontTable.empty())
|
||||
return 0;
|
||||
|
||||
Common::U32String str32 = theText.decode(Common::kUtf8);
|
||||
|
||||
for (uint i = 0; i < str32.size(); ++i) {
|
||||
uint32 c = str32[i];
|
||||
xOff += _theFont.sprites[fontInTable(c)].surface.w + _fontSpace;
|
||||
}
|
||||
|
||||
return xOff;
|
||||
}
|
||||
|
||||
void TextManager::pasteString(const Common::String &theText, int xOff, int y, SpritePalette &thePal) {
|
||||
if (_fontTable.empty())
|
||||
return;
|
||||
|
||||
xOff += (int)((float)(_fontSpace >> 1) / g_sludge->_gfxMan->getCamZoom());
|
||||
|
||||
Common::U32String str32 = theText.decode(Common::kUtf8);
|
||||
|
||||
for (uint32 i = 0; i < str32.size(); ++i) {
|
||||
uint32 c = str32[i];
|
||||
Sprite *mySprite = &_theFont.sprites[fontInTable(c)];
|
||||
g_sludge->_gfxMan->fontSprite(xOff, y, *mySprite, thePal);
|
||||
xOff += (int)((double)(mySprite->surface.w + _fontSpace) / g_sludge->_gfxMan->getCamZoom());
|
||||
}
|
||||
}
|
||||
|
||||
void TextManager::pasteStringToBackdrop(const Common::String &theText, int xOff, int y) {
|
||||
if (_fontTable.empty())
|
||||
return;
|
||||
|
||||
Common::U32String str32 = theText.decode(Common::kUtf8);
|
||||
|
||||
xOff += _fontSpace >> 1;
|
||||
for (uint32 i = 0; i < str32.size(); ++i) {
|
||||
uint32 c = str32[i];
|
||||
Sprite *mySprite = &_theFont.sprites[fontInTable(c)];
|
||||
g_sludge->_gfxMan->pasteSpriteToBackDrop(xOff, y, *mySprite, _pastePalette);
|
||||
xOff += mySprite->surface.w + _fontSpace;
|
||||
}
|
||||
}
|
||||
|
||||
void TextManager::burnStringToBackdrop(const Common::String &theText, int xOff, int y) {
|
||||
if (_fontTable.empty())
|
||||
return;
|
||||
|
||||
Common::U32String str32 = theText.decode(Common::kUtf8);
|
||||
|
||||
xOff += _fontSpace >> 1;
|
||||
for (uint i = 0; i < str32.size(); ++i) {
|
||||
uint32 c = str32[i];
|
||||
Sprite *mySprite = &_theFont.sprites[fontInTable(c)];
|
||||
g_sludge->_gfxMan->burnSpriteToBackDrop(xOff, y, *mySprite, _pastePalette);
|
||||
xOff += mySprite->surface.w + _fontSpace;
|
||||
}
|
||||
}
|
||||
|
||||
bool TextManager::loadFont(int filenum, const Common::String &charOrder, int h) {
|
||||
_fontOrder = charOrder.decode(Common::kUtf8);
|
||||
|
||||
g_sludge->_gfxMan->forgetSpriteBank(_theFont);
|
||||
|
||||
_loadedFontNum = filenum;
|
||||
|
||||
// get max value among all utf8 chars
|
||||
Common::U32String fontOrderString = _fontOrder;
|
||||
|
||||
// create an index table from utf8 char to the index
|
||||
if (!_fontTable.empty()) {
|
||||
_fontTable.clear();
|
||||
}
|
||||
|
||||
for (uint i = 0; i < fontOrderString.size(); ++i) {
|
||||
uint32 c = fontOrderString[i];
|
||||
_fontTable[c] = i;
|
||||
}
|
||||
|
||||
if (!g_sludge->_gfxMan->loadSpriteBank(filenum, _theFont, true)) {
|
||||
fatal("Can't load font");
|
||||
return false;
|
||||
}
|
||||
|
||||
_numFontColours = _theFont.myPalette.total;
|
||||
_fontHeight = h;
|
||||
return true;
|
||||
}
|
||||
|
||||
// load & save
|
||||
void TextManager::saveFont(Common::WriteStream *stream) {
|
||||
stream->writeByte(!_fontTable.empty());
|
||||
if (!_fontTable.empty()) {
|
||||
stream->writeUint16BE(_loadedFontNum);
|
||||
stream->writeUint16BE(_fontHeight);
|
||||
writeString(_fontOrder.encode(Common::kUtf8), stream);
|
||||
}
|
||||
stream->writeSint16LE(_fontSpace);
|
||||
}
|
||||
|
||||
void TextManager::loadFont(int ssgVersion, Common::SeekableReadStream *stream) {
|
||||
bool fontLoaded = stream->readByte();
|
||||
int fontNum = 0;
|
||||
Common::String charOrder = "";
|
||||
if (fontLoaded) {
|
||||
fontNum = stream->readUint16BE();
|
||||
_fontHeight = stream->readUint16BE();
|
||||
|
||||
if (ssgVersion < VERSION(2, 2)) {
|
||||
char *tmp = new char[257];
|
||||
for (int a = 0; a < 256; a++) {
|
||||
int x = stream->readByte();
|
||||
tmp[x] = a;
|
||||
}
|
||||
tmp[256] = 0;
|
||||
charOrder = tmp;
|
||||
delete []tmp;
|
||||
} else {
|
||||
charOrder = readString(stream);
|
||||
}
|
||||
}
|
||||
loadFont(fontNum, charOrder, _fontHeight);
|
||||
|
||||
_fontSpace = stream->readSint16LE();
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
80
engines/sludge/fonttext.h
Normal file
80
engines/sludge/fonttext.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_FONTTEXT_H
|
||||
#define SLUDGE_FONTTEXT_H
|
||||
|
||||
#include "common/hashmap.h"
|
||||
#include "common/ustr.h"
|
||||
|
||||
#include "sludge/sprites.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
class WriteStream;
|
||||
}
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct SpriteBank;
|
||||
class SpritePalette;
|
||||
|
||||
class TextManager {
|
||||
public:
|
||||
TextManager();
|
||||
virtual ~TextManager();
|
||||
|
||||
void init();
|
||||
void kill();
|
||||
|
||||
int stringWidth(const Common::String &theText);
|
||||
int stringLength(const Common::String &theText);
|
||||
|
||||
bool loadFont(int filenum, const Common::String &charOrder, int);
|
||||
void pasteString(const Common::String &theText, int, int, SpritePalette &);
|
||||
void pasteStringToBackdrop(const Common::String &theText, int xOff, int y);
|
||||
void burnStringToBackdrop(const Common::String &theText, int xOff, int y);
|
||||
bool isInFont(const Common::String &theText);
|
||||
|
||||
// setter & getter
|
||||
void setFontSpace(int fontSpace) { _fontSpace = fontSpace; }
|
||||
int getFontHeight() const { return _fontHeight; }
|
||||
void setPasterColor(byte r, byte g, byte b) { _pastePalette.setColor(r, g, b); }
|
||||
|
||||
// load & save
|
||||
void saveFont(Common::WriteStream *stream);
|
||||
void loadFont(int ssgVersion, Common::SeekableReadStream *stream);
|
||||
|
||||
private:
|
||||
SpriteBank _theFont;
|
||||
int _fontHeight, _numFontColours, _loadedFontNum;
|
||||
Common::U32String _fontOrder;
|
||||
int16 _fontSpace;
|
||||
SpritePalette _pastePalette;
|
||||
|
||||
Common::HashMap<uint32, uint32> _fontTable;
|
||||
|
||||
inline uint32 fontInTable(uint32 x) { return _fontTable[x]; }
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
169
engines/sludge/freeze.cpp
Normal file
169
engines/sludge/freeze.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sludge/cursors.h"
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/freeze.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/region.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
#include "sludge/speech.h"
|
||||
#include "sludge/statusba.h"
|
||||
#include "sludge/zbuffer.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
void GraphicsManager::freezeGraphics() {
|
||||
|
||||
int w = _winWidth;
|
||||
int h = _winHeight;
|
||||
|
||||
_freezeSurface.create(w, h, *g_sludge->getScreenPixelFormat());
|
||||
|
||||
displayBase();
|
||||
_freezeSurface.copyFrom(_renderSurface);
|
||||
}
|
||||
|
||||
bool GraphicsManager::freeze() {
|
||||
FrozenStuffStruct *newFreezer = new FrozenStuffStruct;
|
||||
if (!checkNew(newFreezer))
|
||||
return false;
|
||||
|
||||
// Grab a copy of the current scene
|
||||
freezeGraphics();
|
||||
newFreezer->backdropSurface.copyFrom(_backdropSurface);
|
||||
newFreezer->sceneWidth = _sceneWidth;
|
||||
newFreezer->sceneHeight = _sceneHeight;
|
||||
newFreezer->cameraX = _cameraX;
|
||||
newFreezer->cameraY = _cameraY;
|
||||
newFreezer->cameraZoom = _cameraZoom;
|
||||
|
||||
newFreezer->lightMapSurface.copyFrom(_lightMap);
|
||||
newFreezer->lightMapNumber = _lightMapNumber;
|
||||
|
||||
newFreezer->parallaxLayers = _parallaxLayers;
|
||||
_parallaxLayers = NULL;
|
||||
|
||||
newFreezer->zBufferTex = _zBuffer->tex;
|
||||
newFreezer->zBufferNumber = _zBuffer->originalNum;
|
||||
newFreezer->zPanels = _zBuffer->numPanels;
|
||||
_zBuffer->tex = NULL;
|
||||
// resizeBackdrop kills parallax stuff, light map, z-buffer...
|
||||
if (!killResizeBackdrop(_winWidth, _winHeight))
|
||||
return fatal("Can't create new temporary backdrop buffer");
|
||||
|
||||
// Copy the old scene to the new backdrop
|
||||
_backdropSurface.copyFrom(_freezeSurface);
|
||||
_backdropExists = true;
|
||||
|
||||
_vm->_peopleMan->freeze(newFreezer);
|
||||
|
||||
StatusStuff *newStatusStuff = new StatusStuff;
|
||||
if (!checkNew(newStatusStuff))
|
||||
return false;
|
||||
newFreezer->frozenStatus = _vm->_statusBar->copyStatusBarStuff(newStatusStuff);
|
||||
|
||||
_vm->_regionMan->freeze(newFreezer);
|
||||
_vm->_cursorMan->freeze(newFreezer);
|
||||
_vm->_speechMan->freeze(newFreezer);
|
||||
_vm->_evtMan->freeze(newFreezer);
|
||||
|
||||
newFreezer->next = _frozenStuff;
|
||||
_frozenStuff = newFreezer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int GraphicsManager::howFrozen() {
|
||||
int a = 0;
|
||||
FrozenStuffStruct *f = _frozenStuff;
|
||||
while (f) {
|
||||
a++;
|
||||
f = f->next;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void GraphicsManager::unfreeze(bool killImage) {
|
||||
FrozenStuffStruct *killMe = _frozenStuff;
|
||||
|
||||
if (!_frozenStuff)
|
||||
return;
|
||||
|
||||
_sceneWidth = _frozenStuff->sceneWidth;
|
||||
_sceneHeight = _frozenStuff->sceneHeight;
|
||||
|
||||
_cameraX = _frozenStuff->cameraX;
|
||||
_cameraY = _frozenStuff->cameraY;
|
||||
_vm->_evtMan->mouseX() = (int)(_vm->_evtMan->mouseX() * _cameraZoom);
|
||||
_vm->_evtMan->mouseY() = (int)(_vm->_evtMan->mouseY() * _cameraZoom);
|
||||
_cameraZoom = _frozenStuff->cameraZoom;
|
||||
_vm->_evtMan->mouseX() = (int)(_vm->_evtMan->mouseX() / _cameraZoom);
|
||||
_vm->_evtMan->mouseY() = (int)(_vm->_evtMan->mouseY() / _cameraZoom);
|
||||
|
||||
g_sludge->_peopleMan->resotre(_frozenStuff);
|
||||
g_sludge->_regionMan->resotre(_frozenStuff);
|
||||
|
||||
killLightMap();
|
||||
|
||||
_lightMap.copyFrom(_frozenStuff->lightMapSurface);
|
||||
_lightMapNumber = _frozenStuff->lightMapNumber;
|
||||
if (_lightMapNumber) {
|
||||
loadLightMap(_lightMapNumber);
|
||||
}
|
||||
|
||||
if (killImage)
|
||||
killBackDrop();
|
||||
_backdropSurface.copyFrom(_frozenStuff->backdropSurface);
|
||||
_backdropExists = true;
|
||||
|
||||
_zBuffer->tex = _frozenStuff->zBufferTex;
|
||||
killZBuffer();
|
||||
_zBuffer->originalNum = _frozenStuff->zBufferNumber;
|
||||
_zBuffer->numPanels = _frozenStuff->zPanels;
|
||||
if (_zBuffer->numPanels) {
|
||||
setZBuffer(_zBuffer->originalNum);
|
||||
}
|
||||
|
||||
killParallax();
|
||||
_parallaxLayers = _frozenStuff->parallaxLayers;
|
||||
|
||||
_vm->_cursorMan->resotre(_frozenStuff);
|
||||
_vm->_statusBar->restoreBarStuff(_frozenStuff->frozenStatus);
|
||||
_vm->_evtMan->restore(_frozenStuff);
|
||||
_vm->_speechMan->restore(_frozenStuff);
|
||||
|
||||
_frozenStuff = _frozenStuff->next;
|
||||
|
||||
// free current frozen screen struct
|
||||
if (killMe->backdropSurface.getPixels())
|
||||
killMe->backdropSurface.free();
|
||||
if (killMe->lightMapSurface.getPixels())
|
||||
killMe->lightMapSurface.free();
|
||||
delete killMe;
|
||||
killMe = NULL;
|
||||
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
63
engines/sludge/freeze.h
Normal file
63
engines/sludge/freeze.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_FREEZE_H
|
||||
#define SLUDGE_FREEZE_H
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct OnScreenPerson;
|
||||
struct PersonaAnimation;
|
||||
struct ScreenRegion;
|
||||
struct SpeechStruct;
|
||||
struct StatusStuff;
|
||||
struct EventHandlers;
|
||||
struct ScreenRegion;
|
||||
|
||||
typedef Common::List<ScreenRegion *> ScreenRegionList;
|
||||
typedef Common::List<OnScreenPerson *> OnScreenPersonList;
|
||||
|
||||
class Parallax;
|
||||
|
||||
struct FrozenStuffStruct {
|
||||
OnScreenPersonList *allPeople;
|
||||
ScreenRegionList *allScreenRegions;
|
||||
Graphics::Surface backdropSurface;
|
||||
Graphics::Surface lightMapSurface;
|
||||
uint8 *zBufferTex;
|
||||
int zPanels;
|
||||
ParallaxLayers *parallaxLayers;
|
||||
int lightMapNumber, zBufferNumber;
|
||||
SpeechStruct *speech;
|
||||
StatusStuff *frozenStatus;
|
||||
EventHandlers *currentEvents;
|
||||
PersonaAnimation *mouseCursorAnim;
|
||||
int mouseCursorFrameNum;
|
||||
int cameraX, cameraY, sceneWidth, sceneHeight;
|
||||
float cameraZoom;
|
||||
|
||||
FrozenStuffStruct *next;
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
858
engines/sludge/function.cpp
Normal file
858
engines/sludge/function.cpp
Normal file
@@ -0,0 +1,858 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sludge/builtin.h"
|
||||
#include "sludge/errors.h"
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/function.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sound.h"
|
||||
#include "sludge/speech.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
int numBIFNames = 0;
|
||||
Common::String *allBIFNames = NULL;
|
||||
int numUserFunc = 0;
|
||||
Common::String *allUserFunc = NULL;
|
||||
|
||||
LoadedFunction *saverFunc;
|
||||
LoadedFunction *allRunningFunctions = NULL;
|
||||
VariableStack *noStack = NULL;
|
||||
Variable *globalVars = NULL;
|
||||
|
||||
const char *sludgeText[] = { "?????", "RETURN", "BRANCH", "BR_ZERO",
|
||||
"SET_GLOBAL", "SET_LOCAL", "LOAD_GLOBAL", "LOAD_LOCAL", "PLUS", "MINUS",
|
||||
"MULT", "DIVIDE", "AND", "OR", "EQUALS", "NOT_EQ", "MODULUS",
|
||||
"LOAD_VALUE", "LOAD_BUILT", "LOAD_FUNC", "CALLIT", "LOAD_STRING",
|
||||
"LOAD_FILE", "LOAD_OBJTYPE", "NOT", "LOAD_NULL", "STACK_PUSH",
|
||||
"LESSTHAN", "MORETHAN", "NEGATIVE", "U", "LESS_EQUAL", "MORE_EQUAL",
|
||||
"INC_LOCAL", "DEC_LOCAL", "INC_GLOBAL", "DEC_GLOBAL", "INDEXSET",
|
||||
"INDEXGET", "INC_INDEX", "DEC_INDEX", "QUICK_PUSH" };
|
||||
|
||||
void pauseFunction(LoadedFunction *fun) {
|
||||
LoadedFunction **huntAndDestroy = &allRunningFunctions;
|
||||
while (*huntAndDestroy) {
|
||||
if (fun == *huntAndDestroy) {
|
||||
(*huntAndDestroy) = (*huntAndDestroy)->next;
|
||||
fun->next = NULL;
|
||||
} else {
|
||||
huntAndDestroy = &(*huntAndDestroy)->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printStack(VariableStack *ptr) {
|
||||
if (ptr == NULL)
|
||||
debugN("<empty stack>");
|
||||
|
||||
while (ptr != NULL) {
|
||||
ptr->thisVar.debugPrint();
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
debug("%s", "");
|
||||
}
|
||||
|
||||
void printLocals(Variable *localVars, int count) {
|
||||
if (count == 0)
|
||||
debugN("<none>");
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
localVars[i].debugPrint();
|
||||
|
||||
debug("%s", "");
|
||||
}
|
||||
|
||||
void restartFunction(LoadedFunction *fun) {
|
||||
fun->next = allRunningFunctions;
|
||||
allRunningFunctions = fun;
|
||||
}
|
||||
|
||||
void killSpeechTimers() {
|
||||
LoadedFunction *thisFunction = allRunningFunctions;
|
||||
|
||||
while (thisFunction) {
|
||||
if (thisFunction->freezerLevel == 0 && thisFunction->isSpeech
|
||||
&& thisFunction->timeLeft) {
|
||||
thisFunction->timeLeft = 0;
|
||||
thisFunction->isSpeech = false;
|
||||
}
|
||||
thisFunction = thisFunction->next;
|
||||
}
|
||||
|
||||
g_sludge->_speechMan->kill();
|
||||
}
|
||||
|
||||
void completeTimers() {
|
||||
LoadedFunction *thisFunction = allRunningFunctions;
|
||||
|
||||
while (thisFunction) {
|
||||
if (thisFunction->freezerLevel == 0)
|
||||
thisFunction->timeLeft = 0;
|
||||
thisFunction = thisFunction->next;
|
||||
}
|
||||
}
|
||||
|
||||
void finishFunction(LoadedFunction *fun) {
|
||||
int a;
|
||||
|
||||
pauseFunction(fun);
|
||||
if (fun->stack)
|
||||
fatal(ERROR_NON_EMPTY_STACK);
|
||||
delete[] fun->compiledLines;
|
||||
for (a = 0; a < fun->numLocals; a++)
|
||||
fun->localVars[a].unlinkVar();
|
||||
delete[] fun->localVars;
|
||||
fun->reg.unlinkVar();
|
||||
delete fun;
|
||||
fun = NULL;
|
||||
}
|
||||
|
||||
void abortFunction(LoadedFunction *fun) {
|
||||
int a;
|
||||
|
||||
pauseFunction(fun);
|
||||
while (fun->stack)
|
||||
trimStack(fun->stack);
|
||||
delete []fun->compiledLines;
|
||||
for (a = 0; a < fun->numLocals; a++)
|
||||
fun->localVars[a].unlinkVar();
|
||||
delete []fun->localVars;
|
||||
fun->reg.unlinkVar();
|
||||
if (fun->calledBy)
|
||||
abortFunction(fun->calledBy);
|
||||
delete fun;
|
||||
fun = NULL;
|
||||
}
|
||||
|
||||
int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself) {
|
||||
int n = 0;
|
||||
killedMyself = false;
|
||||
|
||||
LoadedFunction *fun = allRunningFunctions;
|
||||
while (fun) {
|
||||
if (fun->originalNumber == funcNum) {
|
||||
fun->cancelMe = true;
|
||||
n++;
|
||||
if (fun == myself)
|
||||
killedMyself = true;
|
||||
}
|
||||
fun = fun->next;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void freezeSubs() {
|
||||
LoadedFunction *thisFunction = allRunningFunctions;
|
||||
|
||||
while (thisFunction) {
|
||||
if (thisFunction->unfreezable) {
|
||||
//msgBox ("SLUDGE debugging bollocks!", "Trying to freeze an unfreezable function!");
|
||||
} else {
|
||||
thisFunction->freezerLevel++;
|
||||
}
|
||||
thisFunction = thisFunction->next;
|
||||
}
|
||||
}
|
||||
|
||||
void unfreezeSubs() {
|
||||
LoadedFunction *thisFunction = allRunningFunctions;
|
||||
|
||||
while (thisFunction) {
|
||||
if (thisFunction->freezerLevel)
|
||||
thisFunction->freezerLevel--;
|
||||
thisFunction = thisFunction->next;
|
||||
}
|
||||
}
|
||||
|
||||
Common::String getCommandParameter(int com, int param) {
|
||||
switch(com) {
|
||||
case SLU_LOAD_BUILT:
|
||||
return getBuiltInName(param);
|
||||
|
||||
case SLU_SET_GLOBAL:
|
||||
return Common::String::format("global%d", param);
|
||||
|
||||
case SLU_LOAD_STRING:
|
||||
return Common::String::format("\"%s\"", g_sludge->_resMan->getNumberedString(param).c_str());
|
||||
|
||||
default:
|
||||
return Common::String::format("%d", param);
|
||||
}
|
||||
}
|
||||
|
||||
bool continueFunction(LoadedFunction *fun) {
|
||||
bool keepLooping = true;
|
||||
bool advanceNow;
|
||||
uint param;
|
||||
SludgeCommand com;
|
||||
|
||||
if (fun->cancelMe) {
|
||||
abortFunction(fun);
|
||||
return true;
|
||||
}
|
||||
|
||||
while (keepLooping) {
|
||||
advanceNow = true;
|
||||
param = fun->compiledLines[fun->runThisLine].param;
|
||||
com = fun->compiledLines[fun->runThisLine].theCommand;
|
||||
|
||||
if (debugChannelSet(-1, kSludgeDebugStackMachine)) {
|
||||
debugN(" Stack before: ");
|
||||
printStack(fun->stack);
|
||||
|
||||
debugN(" Reg before: ");
|
||||
fun->reg.debugPrint();
|
||||
debug("%s", "");
|
||||
|
||||
debugN(" Locals before: ");
|
||||
printLocals(fun->localVars, fun->numLocals);
|
||||
}
|
||||
|
||||
debugC(1, kSludgeDebugStackMachine, "Executing command function %d line %i: %s(%s)", fun->originalNumber, fun->runThisLine, sludgeText[com], getCommandParameter(com, param).c_str());
|
||||
|
||||
if (numBIFNames) {
|
||||
setFatalInfo((fun->originalNumber < numUserFunc) ? allUserFunc[fun->originalNumber] : "Unknown user function", (com < numSludgeCommands) ? sludgeText[com] : ERROR_UNKNOWN_MCODE);
|
||||
}
|
||||
|
||||
switch (com) {
|
||||
case SLU_RETURN:
|
||||
if (fun->calledBy) {
|
||||
LoadedFunction *returnTo = fun->calledBy;
|
||||
if (fun->returnSomething)
|
||||
returnTo->reg.copyFrom(fun->reg);
|
||||
finishFunction(fun);
|
||||
fun = returnTo;
|
||||
restartFunction(fun);
|
||||
} else {
|
||||
finishFunction(fun);
|
||||
advanceNow = false; // So we don't do anything else with "fun"
|
||||
keepLooping = false; // So we drop out of the loop
|
||||
}
|
||||
break;
|
||||
|
||||
case SLU_CALLIT:
|
||||
switch (fun->reg.varType) {
|
||||
case SVT_FUNC:
|
||||
pauseFunction(fun);
|
||||
if (numBIFNames)
|
||||
setFatalInfo(
|
||||
(fun->originalNumber < numUserFunc) ?
|
||||
allUserFunc[fun->originalNumber] :
|
||||
"Unknown user function",
|
||||
(fun->reg.varData.intValue < numUserFunc) ?
|
||||
allUserFunc[fun->reg.varData.intValue] :
|
||||
"Unknown user function");
|
||||
|
||||
if (!startNewFunctionNum(fun->reg.varData.intValue, param, fun,
|
||||
fun->stack))
|
||||
return false;
|
||||
fun = allRunningFunctions;
|
||||
advanceNow = false; // So we don't do anything else with "fun"
|
||||
break;
|
||||
|
||||
case SVT_BUILT: {
|
||||
debugC(1, kSludgeDebugStackMachine, "Built-in init value: %i",
|
||||
fun->reg.varData.intValue);
|
||||
BuiltReturn br = callBuiltIn(fun->reg.varData.intValue, param,
|
||||
fun);
|
||||
|
||||
switch (br) {
|
||||
case BR_ERROR:
|
||||
return fatal(
|
||||
"Unknown error. This shouldn't happen. Please notify the SLUDGE developers.");
|
||||
|
||||
case BR_PAUSE:
|
||||
pauseFunction(fun);
|
||||
// fall through
|
||||
|
||||
case BR_KEEP_AND_PAUSE:
|
||||
keepLooping = false;
|
||||
break;
|
||||
|
||||
case BR_ALREADY_GONE:
|
||||
keepLooping = false;
|
||||
advanceNow = false;
|
||||
break;
|
||||
|
||||
case BR_CALLAFUNC: {
|
||||
int i = fun->reg.varData.intValue;
|
||||
fun->reg.setVariable(SVT_INT, 1);
|
||||
pauseFunction(fun);
|
||||
if (numBIFNames)
|
||||
setFatalInfo(
|
||||
(fun->originalNumber < numUserFunc) ?
|
||||
allUserFunc[fun->originalNumber] :
|
||||
"Unknown user function",
|
||||
(i < numUserFunc) ?
|
||||
allUserFunc[i] :
|
||||
"Unknown user function");
|
||||
if (!startNewFunctionNum(i, 0, fun, noStack, false))
|
||||
return false;
|
||||
fun = allRunningFunctions;
|
||||
advanceNow = false; // So we don't do anything else with "fun"
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return fatal(ERROR_CALL_NONFUNCTION);
|
||||
}
|
||||
break;
|
||||
|
||||
// These all grab things and shove 'em into the register
|
||||
|
||||
case SLU_LOAD_NULL:
|
||||
fun->reg.setVariable(SVT_NULL, 0);
|
||||
break;
|
||||
|
||||
case SLU_LOAD_FILE:
|
||||
fun->reg.setVariable(SVT_FILE, param);
|
||||
break;
|
||||
|
||||
case SLU_LOAD_VALUE:
|
||||
fun->reg.setVariable(SVT_INT, param);
|
||||
break;
|
||||
|
||||
case SLU_LOAD_LOCAL:
|
||||
if (!fun->reg.copyFrom(fun->localVars[param]))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SLU_AND:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
fun->reg.getBoolean() && fun->stack->thisVar.getBoolean());
|
||||
trimStack(fun->stack);
|
||||
break;
|
||||
|
||||
case SLU_OR:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
fun->reg.getBoolean() || fun->stack->thisVar.getBoolean());
|
||||
trimStack(fun->stack);
|
||||
break;
|
||||
|
||||
case SLU_LOAD_FUNC:
|
||||
fun->reg.setVariable(SVT_FUNC, param);
|
||||
break;
|
||||
|
||||
case SLU_LOAD_BUILT:
|
||||
fun->reg.setVariable(SVT_BUILT, param);
|
||||
break;
|
||||
|
||||
case SLU_LOAD_OBJTYPE:
|
||||
fun->reg.setVariable(SVT_OBJTYPE, param);
|
||||
break;
|
||||
|
||||
case SLU_UNREG:
|
||||
break;
|
||||
|
||||
case SLU_LOAD_STRING:
|
||||
if (!fun->reg.loadStringToVar(param)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case SLU_INDEXGET:
|
||||
case SLU_INCREMENT_INDEX:
|
||||
case SLU_DECREMENT_INDEX:
|
||||
switch (fun->stack->thisVar.varType) {
|
||||
case SVT_NULL:
|
||||
if (com == SLU_INDEXGET) {
|
||||
fun->reg.setVariable(SVT_NULL, 0);
|
||||
trimStack(fun->stack);
|
||||
} else {
|
||||
return fatal(ERROR_INCDEC_UNKNOWN);
|
||||
}
|
||||
break;
|
||||
|
||||
case SVT_FASTARRAY:
|
||||
case SVT_STACK:
|
||||
if (fun->stack->thisVar.varData.theStack->first == NULL) {
|
||||
return fatal(ERROR_INDEX_EMPTY);
|
||||
} else {
|
||||
int ii;
|
||||
if (!fun->reg.getValueType(ii, SVT_INT))
|
||||
return false;
|
||||
Variable *grab =
|
||||
(fun->stack->thisVar.varType == SVT_FASTARRAY) ?
|
||||
fun->stack->thisVar.varData.fastArray->fastArrayGetByIndex(ii) :
|
||||
fun->stack->thisVar.varData.theStack->first->stackGetByIndex(ii);
|
||||
|
||||
trimStack(fun->stack);
|
||||
|
||||
if (!grab) {
|
||||
fun->reg.setVariable(SVT_NULL, 0);
|
||||
} else {
|
||||
int kk;
|
||||
switch (com) {
|
||||
case SLU_INCREMENT_INDEX:
|
||||
if (!grab->getValueType(kk, SVT_INT))
|
||||
return false;
|
||||
fun->reg.setVariable(SVT_INT, kk);
|
||||
grab->varData.intValue = kk + 1;
|
||||
break;
|
||||
|
||||
case SLU_DECREMENT_INDEX:
|
||||
if (!grab->getValueType(kk, SVT_INT))
|
||||
return false;
|
||||
fun->reg.setVariable(SVT_INT, kk);
|
||||
grab->varData.intValue = kk - 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!fun->reg.copyFrom(*grab))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return fatal(ERROR_INDEX_NONSTACK);
|
||||
}
|
||||
break;
|
||||
|
||||
case SLU_INDEXSET:
|
||||
switch (fun->stack->thisVar.varType) {
|
||||
case SVT_STACK:
|
||||
if (fun->stack->thisVar.varData.theStack->first == NULL) {
|
||||
return fatal(ERROR_INDEX_EMPTY);
|
||||
} else {
|
||||
int ii;
|
||||
if (!fun->reg.getValueType(ii, SVT_INT))
|
||||
return false;
|
||||
if (!fun->stack->thisVar.varData.theStack->first->stackSetByIndex(ii, fun->stack->next->thisVar)) {
|
||||
return false;
|
||||
}
|
||||
trimStack(fun->stack);
|
||||
trimStack(fun->stack);
|
||||
}
|
||||
break;
|
||||
|
||||
case SVT_FASTARRAY: {
|
||||
int ii;
|
||||
if (!fun->reg.getValueType(ii, SVT_INT))
|
||||
return false;
|
||||
Variable *v = fun->stack->thisVar.varData.fastArray->fastArrayGetByIndex(ii);
|
||||
if (v == NULL)
|
||||
return fatal("Not within bounds of fast array.");
|
||||
if (!v->copyFrom(fun->stack->next->thisVar))
|
||||
return false;
|
||||
trimStack(fun->stack);
|
||||
trimStack(fun->stack);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return fatal(ERROR_INDEX_NONSTACK);
|
||||
}
|
||||
break;
|
||||
|
||||
// What can we do with the register? Well, we can copy it into a local
|
||||
// variable, a global or onto the stack...
|
||||
|
||||
case SLU_INCREMENT_LOCAL: {
|
||||
int ii;
|
||||
if (!fun->localVars[param].getValueType(ii, SVT_INT))
|
||||
return false;
|
||||
fun->reg.setVariable(SVT_INT, ii);
|
||||
fun->localVars[param].setVariable(SVT_INT, ii + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SLU_INCREMENT_GLOBAL: {
|
||||
int ii;
|
||||
if (!globalVars[param].getValueType(ii, SVT_INT))
|
||||
return false;
|
||||
fun->reg.setVariable(SVT_INT, ii);
|
||||
globalVars[param].setVariable(SVT_INT, ii + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SLU_DECREMENT_LOCAL: {
|
||||
int ii;
|
||||
if (!fun->localVars[param].getValueType(ii, SVT_INT))
|
||||
return false;
|
||||
fun->reg.setVariable(SVT_INT, ii);
|
||||
fun->localVars[param].setVariable(SVT_INT, ii - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SLU_DECREMENT_GLOBAL: {
|
||||
int ii;
|
||||
if (!globalVars[param].getValueType(ii, SVT_INT))
|
||||
return false;
|
||||
fun->reg.setVariable(SVT_INT, ii);
|
||||
globalVars[param].setVariable(SVT_INT, ii - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SLU_SET_LOCAL:
|
||||
if (!fun->localVars[param].copyFrom(fun->reg))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SLU_SET_GLOBAL:
|
||||
if (!globalVars[param].copyFrom(fun->reg))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SLU_LOAD_GLOBAL:
|
||||
if (!fun->reg.copyFrom(globalVars[param]))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SLU_STACK_PUSH:
|
||||
if (!addVarToStack(fun->reg, fun->stack))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SLU_QUICK_PUSH:
|
||||
if (!addVarToStackQuick(fun->reg, fun->stack))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SLU_NOT:
|
||||
fun->reg.setVariable(SVT_INT, !fun->reg.getBoolean());
|
||||
break;
|
||||
|
||||
case SLU_BR_ZERO:
|
||||
if (!fun->reg.getBoolean()) {
|
||||
advanceNow = false;
|
||||
fun->runThisLine = param;
|
||||
}
|
||||
break;
|
||||
|
||||
case SLU_BRANCH:
|
||||
advanceNow = false;
|
||||
fun->runThisLine = param;
|
||||
break;
|
||||
|
||||
case SLU_NEGATIVE: {
|
||||
int i;
|
||||
if (!fun->reg.getValueType(i, SVT_INT))
|
||||
return false;
|
||||
fun->reg.setVariable(SVT_INT, -i);
|
||||
}
|
||||
break;
|
||||
|
||||
// All these things rely on there being somet' on the stack
|
||||
|
||||
case SLU_MULT:
|
||||
case SLU_PLUS:
|
||||
case SLU_MINUS:
|
||||
case SLU_MODULUS:
|
||||
case SLU_DIVIDE:
|
||||
case SLU_EQUALS:
|
||||
case SLU_NOT_EQ:
|
||||
case SLU_LESSTHAN:
|
||||
case SLU_MORETHAN:
|
||||
case SLU_LESS_EQUAL:
|
||||
case SLU_MORE_EQUAL:
|
||||
if (fun->stack) {
|
||||
int firstValue, secondValue;
|
||||
|
||||
switch (com) {
|
||||
case SLU_PLUS:
|
||||
fun->reg.addVariablesInSecond(fun->stack->thisVar);
|
||||
trimStack(fun->stack);
|
||||
break;
|
||||
|
||||
case SLU_EQUALS:
|
||||
fun->reg.compareVariablesInSecond(fun->stack->thisVar);
|
||||
trimStack(fun->stack);
|
||||
break;
|
||||
|
||||
case SLU_NOT_EQ:
|
||||
fun->reg.compareVariablesInSecond(fun->stack->thisVar);
|
||||
trimStack(fun->stack);
|
||||
fun->reg.varData.intValue = !fun->reg.varData.intValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!fun->stack->thisVar.getValueType(firstValue, SVT_INT))
|
||||
return false;
|
||||
if (!fun->reg.getValueType(secondValue, SVT_INT))
|
||||
return false;
|
||||
trimStack(fun->stack);
|
||||
|
||||
switch (com) {
|
||||
case SLU_MULT:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
firstValue * secondValue);
|
||||
break;
|
||||
|
||||
case SLU_MINUS:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
firstValue - secondValue);
|
||||
break;
|
||||
|
||||
case SLU_MODULUS:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
firstValue % secondValue);
|
||||
break;
|
||||
|
||||
case SLU_DIVIDE:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
firstValue / secondValue);
|
||||
break;
|
||||
|
||||
case SLU_LESSTHAN:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
firstValue < secondValue);
|
||||
break;
|
||||
|
||||
case SLU_MORETHAN:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
firstValue > secondValue);
|
||||
break;
|
||||
|
||||
case SLU_LESS_EQUAL:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
firstValue <= secondValue);
|
||||
break;
|
||||
|
||||
case SLU_MORE_EQUAL:
|
||||
fun->reg.setVariable(SVT_INT,
|
||||
firstValue >= secondValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return fatal(ERROR_NOSTACK);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return fatal(ERROR_UNKNOWN_CODE);
|
||||
}
|
||||
|
||||
if (advanceNow) {
|
||||
if (debugChannelSet(-1, kSludgeDebugStackMachine)) {
|
||||
debugN(" Stack after: ");
|
||||
|
||||
printStack(fun->stack);
|
||||
|
||||
debugN(" Reg after: ");
|
||||
fun->reg.debugPrint();
|
||||
debug("%s", "");
|
||||
|
||||
debugN(" Locals after: ");
|
||||
printLocals(fun->localVars, fun->numLocals);
|
||||
}
|
||||
|
||||
fun->runThisLine++;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void killAllFunctions() {
|
||||
while (allRunningFunctions)
|
||||
finishFunction(allRunningFunctions);
|
||||
}
|
||||
|
||||
bool loadFunctionCode(LoadedFunction *newFunc) {
|
||||
uint numLines, numLinesRead;
|
||||
|
||||
if (!g_sludge->_resMan->openSubSlice(newFunc->originalNumber))
|
||||
return false;
|
||||
|
||||
debugC(3, kSludgeDebugDataLoad, "Load function code");
|
||||
|
||||
Common::SeekableReadStream *readStream = g_sludge->_resMan->getData();
|
||||
newFunc->unfreezable = readStream->readByte();
|
||||
numLines = readStream->readUint16BE();
|
||||
debugC(3, kSludgeDebugDataLoad, "numLines: %i", numLines);
|
||||
newFunc->numArgs = readStream->readUint16BE();
|
||||
debugC(3, kSludgeDebugDataLoad, "numArgs: %i", newFunc->numArgs);
|
||||
newFunc->numLocals = readStream->readUint16BE();
|
||||
debugC(3, kSludgeDebugDataLoad, "numLocals: %i", newFunc->numLocals);
|
||||
newFunc->compiledLines = new LineOfCode[numLines];
|
||||
if (!checkNew(newFunc->compiledLines))
|
||||
return false;
|
||||
|
||||
for (numLinesRead = 0; numLinesRead < numLines; numLinesRead++) {
|
||||
byte com = readStream->readByte();
|
||||
uint16 param = readStream->readUint16BE();
|
||||
newFunc->compiledLines[numLinesRead].theCommand = (SludgeCommand)com;
|
||||
newFunc->compiledLines[numLinesRead].param = param;
|
||||
debugC(3, kSludgeDebugDataLoad, "command line %i: %s(%s)", numLinesRead,
|
||||
sludgeText[com], getCommandParameter(com, param).c_str());
|
||||
}
|
||||
g_sludge->_resMan->finishAccess();
|
||||
|
||||
// Now we need to reserve memory for the local variables
|
||||
newFunc->localVars = new Variable[newFunc->numLocals];
|
||||
if (!checkNew(newFunc->localVars))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int startNewFunctionNum(uint funcNum, uint numParamsExpected,
|
||||
LoadedFunction *calledBy, VariableStack *&vStack, bool returnSommet) {
|
||||
LoadedFunction *newFunc = new LoadedFunction;
|
||||
checkNew(newFunc);
|
||||
newFunc->originalNumber = funcNum;
|
||||
|
||||
loadFunctionCode(newFunc);
|
||||
|
||||
if (newFunc->numArgs != (int)numParamsExpected)
|
||||
return fatal("Wrong number of parameters!");
|
||||
if (newFunc->numArgs > newFunc->numLocals)
|
||||
return fatal("More arguments than local Variable space!");
|
||||
|
||||
// Now, lets copy the parameters from the calling function's stack...
|
||||
|
||||
while (numParamsExpected) {
|
||||
numParamsExpected--;
|
||||
if (vStack == NULL)
|
||||
return fatal(
|
||||
"Corrupted file!The stack's empty and there were still parameters expected");
|
||||
newFunc->localVars[numParamsExpected].copyFrom(vStack->thisVar);
|
||||
trimStack(vStack);
|
||||
}
|
||||
|
||||
newFunc->cancelMe = false;
|
||||
newFunc->timeLeft = 0;
|
||||
newFunc->returnSomething = returnSommet;
|
||||
newFunc->calledBy = calledBy;
|
||||
newFunc->stack = NULL;
|
||||
newFunc->freezerLevel = 0;
|
||||
newFunc->runThisLine = 0;
|
||||
newFunc->isSpeech = 0;
|
||||
|
||||
restartFunction(newFunc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool runAllFunctions() {
|
||||
|
||||
LoadedFunction *thisFunction = allRunningFunctions;
|
||||
LoadedFunction *nextFunction;
|
||||
|
||||
while (thisFunction) {
|
||||
nextFunction = thisFunction->next;
|
||||
|
||||
if (!thisFunction->freezerLevel) {
|
||||
if (thisFunction->timeLeft) {
|
||||
if (thisFunction->timeLeft < 0) {
|
||||
if (!g_sludge->_soundMan->stillPlayingSound(
|
||||
g_sludge->_speechMan->getLastSpeechSound())) {
|
||||
thisFunction->timeLeft = 0;
|
||||
}
|
||||
} else if (!--(thisFunction->timeLeft)) {
|
||||
}
|
||||
} else {
|
||||
if (thisFunction->isSpeech) {
|
||||
thisFunction->isSpeech = false;
|
||||
g_sludge->_speechMan->kill();
|
||||
}
|
||||
if (!continueFunction(thisFunction))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
thisFunction = nextFunction;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void saveFunction(LoadedFunction *fun, Common::WriteStream *stream) {
|
||||
int a;
|
||||
stream->writeUint16BE(fun->originalNumber);
|
||||
if (fun->calledBy) {
|
||||
stream->writeByte(1);
|
||||
saveFunction(fun->calledBy, stream);
|
||||
} else {
|
||||
stream->writeByte(0);
|
||||
}
|
||||
stream->writeUint32LE(fun->timeLeft);
|
||||
stream->writeUint16BE(fun->runThisLine);
|
||||
stream->writeByte(fun->cancelMe);
|
||||
stream->writeByte(fun->returnSomething);
|
||||
stream->writeByte(fun->isSpeech);
|
||||
fun->reg.save(stream);
|
||||
|
||||
if (fun->freezerLevel) {
|
||||
fatal(ERROR_GAME_SAVE_FROZEN);
|
||||
}
|
||||
saveStack(fun->stack, stream);
|
||||
for (a = 0; a < fun->numLocals; a++) {
|
||||
fun->localVars[a].save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
LoadedFunction *loadFunction(Common::SeekableReadStream *stream) {
|
||||
int a;
|
||||
|
||||
// Reserve memory...
|
||||
|
||||
LoadedFunction *buildFunc = new LoadedFunction;
|
||||
if (!checkNew(buildFunc))
|
||||
return NULL;
|
||||
|
||||
// See what it was called by and load if we need to...
|
||||
|
||||
buildFunc->originalNumber = stream->readUint16BE();
|
||||
buildFunc->calledBy = NULL;
|
||||
if (stream->readByte()) {
|
||||
buildFunc->calledBy = loadFunction(stream);
|
||||
if (!buildFunc->calledBy) {
|
||||
delete buildFunc;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
buildFunc->timeLeft = stream->readUint32LE();
|
||||
buildFunc->runThisLine = stream->readUint16BE();
|
||||
buildFunc->freezerLevel = 0;
|
||||
buildFunc->cancelMe = stream->readByte();
|
||||
buildFunc->returnSomething = stream->readByte();
|
||||
buildFunc->isSpeech = stream->readByte();
|
||||
buildFunc->reg.load(stream);
|
||||
loadFunctionCode(buildFunc);
|
||||
|
||||
buildFunc->stack = loadStack(stream, NULL);
|
||||
|
||||
for (a = 0; a < buildFunc->numLocals; a++) {
|
||||
buildFunc->localVars[a].load(stream);
|
||||
}
|
||||
|
||||
return buildFunc;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
71
engines/sludge/function.h
Normal file
71
engines/sludge/function.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_FUNCTION_H
|
||||
#define SLUDGE_FUNCTION_H
|
||||
|
||||
#include "sludge/csludge.h"
|
||||
#include "sludge/variable.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct Variable;
|
||||
struct VariableStack;
|
||||
|
||||
struct LineOfCode {
|
||||
SludgeCommand theCommand;
|
||||
int32 param;
|
||||
};
|
||||
|
||||
struct LoadedFunction {
|
||||
int originalNumber;
|
||||
LineOfCode *compiledLines;
|
||||
int numLocals, timeLeft, numArgs;
|
||||
Variable *localVars;
|
||||
VariableStack *stack;
|
||||
Variable reg;
|
||||
uint runThisLine;
|
||||
LoadedFunction *calledBy;
|
||||
LoadedFunction *next;
|
||||
bool returnSomething, isSpeech, unfreezable, cancelMe;
|
||||
byte freezerLevel;
|
||||
};
|
||||
|
||||
bool runAllFunctions();
|
||||
int startNewFunctionNum(uint, uint, LoadedFunction *, VariableStack*&, bool = true);
|
||||
void restartFunction(LoadedFunction *fun);
|
||||
bool loadFunctionCode(LoadedFunction *newFunc);
|
||||
void killAllFunctions();
|
||||
|
||||
void finishFunction(LoadedFunction *fun);
|
||||
void abortFunction(LoadedFunction *fun);
|
||||
|
||||
void freezeSubs();
|
||||
void unfreezeSubs();
|
||||
void completeTimers();
|
||||
void killSpeechTimers();
|
||||
int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself);
|
||||
|
||||
LoadedFunction *loadFunction(Common::SeekableReadStream *stream);
|
||||
void saveFunction(LoadedFunction *fun, Common::WriteStream *stream);
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
205
engines/sludge/functionlist.h
Normal file
205
engines/sludge/functionlist.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
This is the list of the built in functions
|
||||
|
||||
true or false states if it's a used function
|
||||
in the current version of the engine,
|
||||
but that value currently isn't used anywhere
|
||||
*/
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
#define FUNC(special,name,paramNum) {#name, builtIn_ ## name, paramNum},
|
||||
static builtInFunctionData builtInFunctionArray[] = {
|
||||
FUNC(true, say, -1)
|
||||
FUNC(true, skipSpeech, 0)
|
||||
FUNC(true, statusText, 1)
|
||||
FUNC(true, pause, 1)
|
||||
FUNC(true, onLeftMouse, -1)
|
||||
FUNC(true, onRightMouse, -1)
|
||||
FUNC(true, setCursor, 1)
|
||||
FUNC(true, addOverlay, 3)
|
||||
FUNC(true, addCharacter, 4)
|
||||
FUNC(true, playSound, 1)
|
||||
FUNC(true, getMouseX, 0)
|
||||
FUNC(true, getMouseY, 0)
|
||||
FUNC(true, addScreenRegion, 8)
|
||||
FUNC(true, onMoveMouse, -1)
|
||||
FUNC(true, onFocusChange, -1)
|
||||
FUNC(true, getOverObject, 0)
|
||||
FUNC(true, blankScreen, 0)
|
||||
FUNC(true, moveCharacter, -1)
|
||||
FUNC(true, onKeyboard, -1)
|
||||
FUNC(true, getObjectX, 1)
|
||||
FUNC(true, getObjectY, 1)
|
||||
FUNC(true, random, 1)
|
||||
FUNC(true, spawnSub, 1)
|
||||
FUNC(true, blankArea, 4)
|
||||
FUNC(true, hideCharacter, 1)
|
||||
FUNC(true, showCharacter, 1)
|
||||
FUNC(true, callEvent, 2)
|
||||
FUNC(true, removeScreenRegion, 1)
|
||||
FUNC(true, animate, 2)
|
||||
FUNC(true, turnCharacter, 2)
|
||||
FUNC(true, removeAllCharacters, 0)
|
||||
FUNC(true, removeAllScreenRegions, 0)
|
||||
FUNC(true, setScale, 2)
|
||||
FUNC(true, newStack, -1)
|
||||
FUNC(true, pushToStack, 2)
|
||||
FUNC(true, popFromStack, 1)
|
||||
FUNC(true, clearStatus, 0)
|
||||
FUNC(true, addStatus, 0)
|
||||
FUNC(true, removeLastStatus, 0)
|
||||
FUNC(true, lightStatus, 1)
|
||||
FUNC(true, getStatusText, 0)
|
||||
FUNC(true, setStatusColour, 3)
|
||||
FUNC(true, deleteFromStack, 2)
|
||||
FUNC(true, freeze, 0)
|
||||
FUNC(true, unfreeze, 0)
|
||||
FUNC(true, pasteImage, 3)
|
||||
FUNC(true, copyStack, 1)
|
||||
FUNC(true, completeTimers, 0)
|
||||
FUNC(true, setCharacterDrawMode, 2)
|
||||
FUNC(true, anim, -1)
|
||||
FUNC(true, costume, -1)
|
||||
FUNC(true, pickOne, -1)
|
||||
FUNC(true, setCostume, 2)
|
||||
FUNC(true, wait, 2)
|
||||
FUNC(true, somethingSpeaking, 0)
|
||||
FUNC(true, substring, 3)
|
||||
FUNC(true, stringLength, 1)
|
||||
FUNC(true, darkBackground, 0)
|
||||
FUNC(true, saveGame, 1)
|
||||
FUNC(true, loadGame, 1)
|
||||
FUNC(true, quitGame, 0)
|
||||
FUNC(true, rename, 2)
|
||||
FUNC(true, stackSize, 1)
|
||||
FUNC(true, pasteString, 3)
|
||||
FUNC(true, startMusic, 3)
|
||||
FUNC(true, setDefaultMusicVolume, 1)
|
||||
FUNC(true, setMusicVolume, 2)
|
||||
FUNC(true, stopMusic, 1)
|
||||
FUNC(true, stopSound, 1)
|
||||
FUNC(true, setFont, 3)
|
||||
FUNC(true, alignStatus, 1)
|
||||
FUNC(true, showFloor, 0)
|
||||
FUNC(true, showBoxes, 0)
|
||||
FUNC(true, positionStatus, 2)
|
||||
FUNC(true, setFloor, 1)
|
||||
FUNC(true, forceCharacter, -1)
|
||||
FUNC(true, jumpCharacter, -1)
|
||||
FUNC(true, peekStart, 1)
|
||||
FUNC(true, peekEnd, 1)
|
||||
FUNC(true, enqueue, 2)
|
||||
FUNC(true, setZBuffer, 1)
|
||||
FUNC(true, getMatchingFiles, 1)
|
||||
FUNC(true, inFont, 1)
|
||||
FUNC(true, onLeftMouseUp, -1)
|
||||
FUNC(true, onRightMouseUp, -1)
|
||||
FUNC(true, loopSound, -1)
|
||||
FUNC(true, removeCharacter, 1)
|
||||
FUNC(true, stopCharacter, 1)
|
||||
FUNC(true, launch, 1)
|
||||
FUNC(true, howFrozen, 0)
|
||||
FUNC(true, setPasteColour, 3)
|
||||
FUNC(true, setLitStatusColour, 3)
|
||||
FUNC(true, fileExists, 1)
|
||||
FUNC(true, floatCharacter, 2)
|
||||
FUNC(true, cancelSub, 1)
|
||||
FUNC(true, setCharacterWalkSpeed, 2)
|
||||
FUNC(true, deleteAllFromStack, 2)
|
||||
FUNC(true, setCharacterExtra, 2)
|
||||
FUNC(true, mixOverlay, 3)
|
||||
FUNC(true, pasteCharacter, 1)
|
||||
FUNC(true, setSceneDimensions, 2)
|
||||
FUNC(true, aimCamera, 2)
|
||||
FUNC(true, getMouseScreenX, 0)
|
||||
FUNC(true, getMouseScreenY, 0)
|
||||
FUNC(true, setDefaultSoundVolume, 1)
|
||||
FUNC(true, setSoundVolume, 2)
|
||||
FUNC(true, setSoundLoopPoints, 3)
|
||||
FUNC(true, setSpeechMode, 1)
|
||||
FUNC(true, setLightMap, -1)
|
||||
FUNC(true, think, -1)
|
||||
FUNC(true, getCharacterDirection, 1)
|
||||
FUNC(true, isCharacter, 1)
|
||||
FUNC(true, isScreenRegion, 1)
|
||||
FUNC(true, isMoving, 1)
|
||||
FUNC(true, deleteFile, 1)
|
||||
FUNC(true, renameFile, 2)
|
||||
FUNC(true, hardScroll, 1)
|
||||
FUNC(true, stringWidth, 1)
|
||||
FUNC(true, setSpeechSpeed, 1)
|
||||
FUNC(true, normalCharacter, 1)
|
||||
FUNC(true, fetchEvent, 2)
|
||||
FUNC(true, transitionLevel, 1)
|
||||
FUNC(true, spinCharacter, 2)
|
||||
FUNC(true, setFontSpacing, 1)
|
||||
FUNC(true, burnString, 3)
|
||||
FUNC(true, captureAllKeys, 1)
|
||||
FUNC(true, cacheSound, 1)
|
||||
FUNC(true, setCharacterSpinSpeed, 2)
|
||||
FUNC(true, transitionMode, 1)
|
||||
FUNC(false, _rem_movieStart, 1)
|
||||
FUNC(false, _rem_movieAbort, 0)
|
||||
FUNC(false, _rem_moviePlaying, 0)
|
||||
FUNC(false, _rem_updateDisplay, 1)
|
||||
FUNC(true, getSoundCache, 0)
|
||||
FUNC(true, saveCustomData, 2)
|
||||
FUNC(true, loadCustomData, 1)
|
||||
FUNC(true, setCustomEncoding, 1)
|
||||
FUNC(true, freeSound, 1)
|
||||
FUNC(true, parallaxAdd, 3)
|
||||
FUNC(true, parallaxClear, 0)
|
||||
FUNC(true, setBlankColour, 3)
|
||||
FUNC(true, setBurnColour, 3)
|
||||
FUNC(true, getPixelColour, 2)
|
||||
FUNC(true, makeFastArray, 1)
|
||||
FUNC(true, getCharacterScale, 1)
|
||||
FUNC(true, getLanguageID, 0)
|
||||
FUNC(false, _rem_launchWith, 2)
|
||||
FUNC(true, getFramesPerSecond, 0)
|
||||
FUNC(true, showThumbnail, 3)
|
||||
FUNC(true, setThumbnailSize, 2)
|
||||
FUNC(true, hasFlag, 2)
|
||||
FUNC(true, snapshotGrab, 0)
|
||||
FUNC(true, snapshotClear, 0)
|
||||
FUNC(true, bodgeFilenames, 1)
|
||||
FUNC(false, _rem_registryGetString, 2)
|
||||
FUNC(true, quitWithFatalError, 1)
|
||||
FUNC(true, _rem_setCharacterAA, 4)
|
||||
FUNC(true, _rem_setMaximumAA, 3)
|
||||
FUNC(true, setBackgroundEffect, -1)
|
||||
FUNC(true, doBackgroundEffect, 0)
|
||||
FUNC(true, setCharacterAngleOffset, 2)
|
||||
FUNC(true, setCharacterTransparency, 2)
|
||||
FUNC(true, setCharacterColourise, 5)
|
||||
FUNC(true, zoomCamera, 1)
|
||||
FUNC(true, playMovie, 1)
|
||||
FUNC(true, stopMovie, 0)
|
||||
FUNC(true, pauseMovie, 0)
|
||||
};
|
||||
#undef FUNC
|
||||
|
||||
const static int NUM_FUNCS = (sizeof (builtInFunctionArray) / sizeof (builtInFunctionArray[0]));
|
||||
|
||||
} // End of namespace Sludge
|
||||
218
engines/sludge/graphics.cpp
Normal file
218
engines/sludge/graphics.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
#include "engines/util.h"
|
||||
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/freeze.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
#include "sludge/zbuffer.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
GraphicsManager::GraphicsManager(SludgeEngine *vm) {
|
||||
_vm = vm;
|
||||
init();
|
||||
}
|
||||
|
||||
GraphicsManager::~GraphicsManager() {
|
||||
kill();
|
||||
}
|
||||
|
||||
void GraphicsManager::init() {
|
||||
// Init screen surface
|
||||
_winWidth = _sceneWidth = 640;
|
||||
_winHeight = _sceneHeight = 480;
|
||||
|
||||
// LightMap
|
||||
_lightMapMode = LIGHTMAPMODE_PIXEL;
|
||||
_lightMapNumber = 0;
|
||||
|
||||
_parallaxLayers = nullptr;
|
||||
|
||||
// Camera
|
||||
_cameraZoom = 1.0;
|
||||
_cameraX = _cameraY = 0;
|
||||
|
||||
// Freeze
|
||||
_frozenStuff = nullptr;
|
||||
|
||||
// Back drop
|
||||
_backdropExists = false;
|
||||
|
||||
// Sprite Bank
|
||||
_allLoadedBanks.clear();
|
||||
|
||||
// ZBuffer
|
||||
_zBuffer = new ZBufferData;
|
||||
_zBuffer->originalNum = -1;
|
||||
_zBuffer->tex = nullptr;
|
||||
_zBufferSurface = nullptr;
|
||||
|
||||
// Colors
|
||||
_currentBlankColour = _renderSurface.format.ARGBToColor(0xff, 0, 0, 0);
|
||||
_currentBurnR = 0;
|
||||
_currentBurnG = 0;
|
||||
_currentBurnB = 0;
|
||||
|
||||
// Thumbnail
|
||||
_thumbWidth = 0;
|
||||
_thumbHeight = 0;
|
||||
|
||||
// Transition
|
||||
resetRandW();
|
||||
_brightnessLevel = 255;
|
||||
_fadeMode = 2;
|
||||
_transitionTexture = nullptr;
|
||||
}
|
||||
|
||||
void GraphicsManager::kill() {
|
||||
killParallax();
|
||||
|
||||
// kill frozen stuff
|
||||
FrozenStuffStruct *killMe = _frozenStuff;
|
||||
while (killMe) {
|
||||
_frozenStuff = _frozenStuff->next;
|
||||
if (killMe->backdropSurface.getPixels())
|
||||
killMe->backdropSurface.free();
|
||||
if (killMe->lightMapSurface.getPixels())
|
||||
killMe->lightMapSurface.free();
|
||||
delete killMe;
|
||||
killMe = nullptr;
|
||||
killMe = _frozenStuff;
|
||||
}
|
||||
|
||||
// kill sprite banks
|
||||
LoadedSpriteBanks::iterator it;
|
||||
for (it = _allLoadedBanks.begin(); it != _allLoadedBanks.end(); ++it) {
|
||||
delete (*it);
|
||||
(*it) = nullptr;
|
||||
}
|
||||
_allLoadedBanks.clear();
|
||||
|
||||
// kill zbuffer
|
||||
if (_zBuffer) {
|
||||
killZBuffer();
|
||||
delete _zBuffer;
|
||||
_zBuffer = nullptr;
|
||||
}
|
||||
|
||||
// kill surfaces
|
||||
if (_renderSurface.getPixels())
|
||||
_renderSurface.free();
|
||||
|
||||
if (_zBufferSurface) {
|
||||
delete[] _zBufferSurface;
|
||||
_zBufferSurface = nullptr;
|
||||
}
|
||||
|
||||
if (_snapshotSurface.getPixels())
|
||||
_snapshotSurface.free();
|
||||
|
||||
if (_backdropSurface.getPixels())
|
||||
_backdropSurface.free();
|
||||
|
||||
if (_origBackdropSurface.getPixels())
|
||||
_origBackdropSurface.free();
|
||||
|
||||
if (_transitionTexture) {
|
||||
_transitionTexture->free();
|
||||
delete _transitionTexture;
|
||||
_transitionTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsManager::initGfx() {
|
||||
initGraphics(_winWidth, _winHeight, _vm->getScreenPixelFormat());
|
||||
_renderSurface.create(_winWidth, _winHeight, *_vm->getScreenPixelFormat());
|
||||
|
||||
_zBufferSurface = new uint8[_winWidth * _winHeight];
|
||||
|
||||
if (!killResizeBackdrop(_winWidth, _winHeight))
|
||||
return fatal("Couldn't allocate memory for backdrop");
|
||||
|
||||
blankAllScreen();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsManager::display() {
|
||||
if (_brightnessLevel < 255)
|
||||
fixBrightness();
|
||||
|
||||
g_system->copyRectToScreen((byte *)_renderSurface.getPixels(), _renderSurface.pitch, 0, 0, _renderSurface.w, _renderSurface.h);
|
||||
g_system->updateScreen();
|
||||
}
|
||||
|
||||
void GraphicsManager::clear() {
|
||||
_renderSurface.fillRect(Common::Rect(0, 0, _backdropSurface.w, _backdropSurface.h), _renderSurface.format.ARGBToColor(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
void GraphicsManager::aimCamera(int cameraX, int cameraY) {
|
||||
_cameraX = cameraX;
|
||||
_cameraY = cameraY;
|
||||
_cameraX -= (float)(_winWidth >> 1) / _cameraZoom;
|
||||
_cameraY -= (float)(_winHeight >> 1) / _cameraZoom;
|
||||
|
||||
if (_cameraX < 0)
|
||||
_cameraX = 0;
|
||||
else if (_cameraX > _sceneWidth - (float)_winWidth / _cameraZoom)
|
||||
_cameraX = _sceneWidth - (float)_winWidth / _cameraZoom;
|
||||
if (_cameraY < 0)
|
||||
_cameraY = 0;
|
||||
else if (_cameraY > _sceneHeight - (float)_winHeight / _cameraZoom)
|
||||
_cameraY = _sceneHeight - (float)_winHeight / _cameraZoom;
|
||||
}
|
||||
|
||||
void GraphicsManager::zoomCamera(int z) {
|
||||
_vm->_evtMan->mouseX() = _vm->_evtMan->mouseX() * _cameraZoom;
|
||||
_vm->_evtMan->mouseY() = _vm->_evtMan->mouseY() * _cameraZoom;
|
||||
|
||||
_cameraZoom = (float)z * 0.01;
|
||||
if ((float)_winWidth / _cameraZoom > _sceneWidth)
|
||||
_cameraZoom = (float)_winWidth / _sceneWidth;
|
||||
if ((float)_winHeight / _cameraZoom > _sceneHeight)
|
||||
_cameraZoom = (float)_winHeight / _sceneHeight;
|
||||
|
||||
_vm->_evtMan->mouseX() = _vm->_evtMan->mouseX() / _cameraZoom;
|
||||
_vm->_evtMan->mouseY() = _vm->_evtMan->mouseY() / _cameraZoom;
|
||||
}
|
||||
|
||||
void GraphicsManager::saveColors(Common::WriteStream *stream) {
|
||||
stream->writeUint16BE(_currentBlankColour);
|
||||
stream->writeByte(_currentBurnR);
|
||||
stream->writeByte(_currentBurnG);
|
||||
stream->writeByte(_currentBurnB);
|
||||
}
|
||||
|
||||
void GraphicsManager::loadColors(Common::SeekableReadStream *stream) {
|
||||
_currentBlankColour = stream->readUint16BE();
|
||||
_currentBurnR = stream->readByte();
|
||||
_currentBurnG = stream->readByte();
|
||||
_currentBurnB = stream->readByte();
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
278
engines/sludge/graphics.h
Normal file
278
engines/sludge/graphics.h
Normal file
@@ -0,0 +1,278 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_GRAPHICS_H
|
||||
#define SLUDGE_GRAPHICS_H
|
||||
|
||||
#include "sludge/sprbanks.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
class WriteStream;
|
||||
}
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class Parallax;
|
||||
class SludgeEngine;
|
||||
class SpritePalette;
|
||||
|
||||
struct StackHandler;
|
||||
struct FrozenStuffStruct;
|
||||
struct LoadedSpriteBank;
|
||||
struct OnScreenPerson;
|
||||
struct SpriteBank;
|
||||
struct Sprite;
|
||||
struct VariableStack;
|
||||
struct ZBufferData;
|
||||
|
||||
enum ELightMapMode {
|
||||
LIGHTMAPMODE_NONE = -1,
|
||||
LIGHTMAPMODE_HOTSPOT,
|
||||
LIGHTMAPMODE_PIXEL,
|
||||
LIGHTMAPMODE_NUM
|
||||
};
|
||||
|
||||
// Parallax
|
||||
struct ParallaxLayer {
|
||||
Graphics::Surface surface;
|
||||
int speedX, speedY;
|
||||
bool wrapS, wrapT;
|
||||
uint16 fileNum, fractionX, fractionY;
|
||||
int cameraX, cameraY;
|
||||
};
|
||||
typedef Common::List<ParallaxLayer *> ParallaxLayers;
|
||||
|
||||
class GraphicsManager {
|
||||
public:
|
||||
GraphicsManager(SludgeEngine *vm);
|
||||
virtual ~GraphicsManager();
|
||||
|
||||
void init();
|
||||
void kill();
|
||||
|
||||
// graphics
|
||||
void setWindowSize(uint winWidth, uint winHeight) { _winWidth = winWidth; _winHeight = winHeight; }
|
||||
bool initGfx();
|
||||
void display();
|
||||
void clear();
|
||||
|
||||
// Parallax
|
||||
bool loadParallax(uint16 v, uint16 fracX, uint16 fracY);
|
||||
void killParallax();
|
||||
void saveParallax(Common::WriteStream *fp);
|
||||
void drawParallax();
|
||||
|
||||
// Backdrop
|
||||
void killAllBackDrop();
|
||||
bool resizeBackdrop(int x, int y);
|
||||
bool killResizeBackdrop(int x, int y);
|
||||
void killBackDrop();
|
||||
void loadBackDrop(int fileNum, int x, int y);
|
||||
void mixBackDrop(int fileNum, int x, int y);
|
||||
void drawBackDrop();
|
||||
void blankScreen(int x1, int y1, int x2, int y2);
|
||||
void blankAllScreen();
|
||||
void darkScreen();
|
||||
void saveHSI(Common::WriteStream *stream);
|
||||
bool loadHSI(int num, Common::SeekableReadStream *stream, int, int, bool);
|
||||
bool mixHSI(int num, Common::SeekableReadStream *stream, int x = 0, int y = 0);
|
||||
void drawLine(uint, uint, uint, uint);
|
||||
void drawHorizontalLine(uint, uint, uint);
|
||||
void drawVerticalLine(uint, uint, uint);
|
||||
void hardScroll(int distance);
|
||||
bool getRGBIntoStack(uint x, uint y, StackHandler *sH);
|
||||
void saveBackdrop(Common::WriteStream *stream); // To game save
|
||||
void loadBackdrop(int ssgVersion, Common::SeekableReadStream *streamn); // From game save
|
||||
|
||||
// Lightmap
|
||||
int _lightMapMode;
|
||||
void killLightMap();
|
||||
bool loadLightMap(int v);
|
||||
void saveLightMap(Common::WriteStream *stream);
|
||||
bool loadLightMap(int ssgVersion, Common::SeekableReadStream *stream);
|
||||
|
||||
// Snapshot
|
||||
void nosnapshot();
|
||||
bool snapshot();
|
||||
void saveSnapshot(Common::WriteStream *stream);
|
||||
bool restoreSnapshot(Common::SeekableReadStream *stream);
|
||||
|
||||
// Camera
|
||||
int getCamX() { return _cameraX; }
|
||||
int getCamY() { return _cameraY; }
|
||||
float getCamZoom() { return _cameraZoom; }
|
||||
void aimCamera(int cameraX, int cameraY);
|
||||
void zoomCamera(int z);
|
||||
|
||||
// Screen
|
||||
int getCenterX(int width) { return (_winWidth - width) >> 1; }
|
||||
int checkSizeValide(int width, int height) { return ((width >= 0) && (height >= 0) && (width < (int)_winWidth) && (height < (int)_winHeight)); }
|
||||
|
||||
// Freeze
|
||||
bool freeze();
|
||||
void unfreeze(bool killImage = true);
|
||||
int howFrozen();
|
||||
bool isFrozen() { return (_frozenStuff != nullptr); }
|
||||
|
||||
// Sprites
|
||||
static void forgetSpriteBank(SpriteBank &forgetme);
|
||||
bool loadSpriteBank(char *filename, SpriteBank &loadhere);
|
||||
bool loadSpriteBank(int fileNum, SpriteBank &loadhere, bool isFont);
|
||||
|
||||
void fontSprite(int x1, int y1, Sprite &single, const SpritePalette &fontPal);
|
||||
void flipFontSprite(int x1, int y1, Sprite &single, const SpritePalette &fontPal);
|
||||
|
||||
bool scaleSprite(Sprite &single, const SpritePalette &fontPal, OnScreenPerson *thisPerson, bool mirror);
|
||||
void fixScaleSprite(int x1, int y1, Sprite &single, const SpritePalette &fontPal, OnScreenPerson *thisPerson, const int camX, const int camY, bool);
|
||||
|
||||
void pasteSpriteToBackDrop(int x1, int y1, Sprite &single, const SpritePalette &fontPal);
|
||||
bool reserveSpritePal(SpritePalette &sP, int n);
|
||||
void burnSpriteToBackDrop(int x1, int y1, Sprite &single, const SpritePalette &fontPal);
|
||||
|
||||
// Sprite Bank
|
||||
LoadedSpriteBank *loadBankForAnim(int ID);
|
||||
|
||||
// ZBuffer
|
||||
bool setZBuffer(int y);
|
||||
void killZBuffer();
|
||||
void drawZBuffer(int x, int y, bool upsidedown);
|
||||
void saveZBuffer(Common::WriteStream *stream);
|
||||
bool loadZBuffer(Common::SeekableReadStream *stream);
|
||||
|
||||
void drawSpriteToZBuffer(int x, int y, uint8 depth, const Graphics::Surface &surface);
|
||||
void fillZBuffer(uint8 d);
|
||||
|
||||
// Colors
|
||||
void setBlankColor(int r, int g, int b) { _currentBlankColour = _renderSurface.format.RGBToColor(r & 255, g & 255, b & 255);};
|
||||
void setBurnColor(int r, int g, int b) {
|
||||
_currentBurnR = r;
|
||||
_currentBurnG = g;
|
||||
_currentBurnB = b;
|
||||
}
|
||||
void saveColors(Common::WriteStream *stream);
|
||||
void loadColors(Common::SeekableReadStream *stream);
|
||||
|
||||
// Thumbnail
|
||||
bool setThumbnailSize(int thumbWidth, int thumbHeight);
|
||||
bool saveThumbnail(Common::WriteStream *stream);
|
||||
bool skipThumbnail(Common::SeekableReadStream *stream);
|
||||
void showThumbnail(const Common::String &filename, int x, int y);
|
||||
|
||||
// Transition
|
||||
void setBrightnessLevel(int brightnessLevel);
|
||||
void setFadeMode(int fadeMode) { _fadeMode = fadeMode; };
|
||||
void fixBrightness();
|
||||
void resetRandW();
|
||||
void reserveTransitionTexture();
|
||||
|
||||
void transitionFader();
|
||||
void transitionDisolve();
|
||||
void transitionTV();
|
||||
void transitionBlinds();
|
||||
void transitionSnapshotBox();
|
||||
void transitionCrossFader();
|
||||
|
||||
// BG effects
|
||||
bool blurScreen();
|
||||
void blur_saveSettings(Common::WriteStream *stream);
|
||||
void blur_loadSettings(Common::SeekableReadStream *stream);
|
||||
bool blur_createSettings(int numParams, VariableStack *&stack);
|
||||
|
||||
uint getWinWidth() { return _winWidth; }
|
||||
uint getWinHeight() { return _winHeight; }
|
||||
|
||||
private:
|
||||
SludgeEngine *_vm;
|
||||
|
||||
uint _winWidth, _winHeight, _sceneWidth, _sceneHeight;
|
||||
|
||||
// renderSurface
|
||||
Graphics::Surface _renderSurface;
|
||||
|
||||
// Z Buffer Surface
|
||||
uint8 *_zBufferSurface = nullptr;
|
||||
|
||||
// Snapshot
|
||||
Graphics::Surface _snapshotSurface;
|
||||
|
||||
// LightMap
|
||||
int _lightMapNumber;
|
||||
Graphics::Surface _lightMap;
|
||||
|
||||
// Camera
|
||||
float _cameraZoom;
|
||||
int _cameraX, _cameraY;
|
||||
|
||||
// Freeze
|
||||
FrozenStuffStruct *_frozenStuff;
|
||||
Graphics::Surface _freezeSurface;
|
||||
void freezeGraphics();
|
||||
|
||||
// Back drop
|
||||
Graphics::Surface _backdropSurface;
|
||||
Graphics::Surface _origBackdropSurface;
|
||||
bool _backdropExists;
|
||||
bool reserveBackdrop();
|
||||
|
||||
// Sprites
|
||||
void fontSprite(bool flip, int x, int y, Sprite &single, const SpritePalette &fontPal);
|
||||
Graphics::Surface *duplicateSurface(Graphics::Surface *surface);
|
||||
void blendColor(Graphics::Surface * surface, uint32 color, Graphics::TSpriteBlendMode mode);
|
||||
Graphics::Surface *applyLightmapToSprite(Graphics::Surface *&blitted, OnScreenPerson *thisPerson, bool mirror, int x, int y, int x1, int y1, int diffX, int diffY);
|
||||
|
||||
// Sprite banks
|
||||
LoadedSpriteBanks _allLoadedBanks;
|
||||
|
||||
// ZBuffer
|
||||
ZBufferData *_zBuffer;
|
||||
void sortZPal(int *oldpal, int *newpal, int size);
|
||||
|
||||
// Colors
|
||||
uint _currentBlankColour;
|
||||
byte _currentBurnR, _currentBurnG, _currentBurnB;
|
||||
|
||||
// Thumbnail
|
||||
int _thumbWidth;
|
||||
int _thumbHeight;
|
||||
|
||||
// Transition
|
||||
byte _brightnessLevel;
|
||||
byte _fadeMode;
|
||||
|
||||
#define RANDKK 17
|
||||
|
||||
uint32 _randbuffer[RANDKK][2];
|
||||
int _randp1, _randp2;
|
||||
Graphics::ManagedSurface *_transitionTexture;
|
||||
|
||||
// Parallax
|
||||
ParallaxLayers *_parallaxLayers;
|
||||
|
||||
inline int sortOutPCamera(int cX, int fX, int sceneMax, int boxMax) {
|
||||
return (fX == 65535) ? (sceneMax ? ((cX * boxMax) / sceneMax) : 0) : ((cX * fX) / 100);
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
|
||||
#endif // SLUDGE_GRAPHICS_H
|
||||
86
engines/sludge/hsi.cpp
Normal file
86
engines/sludge/hsi.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "sludge/hsi.h"
|
||||
#include "sludge/sludge.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
HSIDecoder::HSIDecoder() : _surface(nullptr), _palette(0), _reserve(-1) {
|
||||
}
|
||||
|
||||
HSIDecoder::~HSIDecoder() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void HSIDecoder::destroy() {
|
||||
if (_surface != nullptr) {
|
||||
_surface->free();
|
||||
delete _surface;
|
||||
_surface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool HSIDecoder::loadStream(Common::SeekableReadStream &stream) {
|
||||
destroy();
|
||||
int32 transCol = _reserve > 0 ? -1 : 63519;
|
||||
int n;
|
||||
uint16 width = stream.readUint16BE();
|
||||
debugC(2, kSludgeDebugGraphics, "picWidth : %i", width);
|
||||
uint16 height = stream.readUint16BE();
|
||||
debugC(2, kSludgeDebugGraphics, "picHeight : %i", height);
|
||||
|
||||
_surface = new Graphics::Surface();
|
||||
_surface->create(width, height, *g_sludge->getScreenPixelFormat());
|
||||
for (uint16 y = 0; y < height; y++) {
|
||||
uint16 x = 0;
|
||||
while (x < width) {
|
||||
uint16 c = stream.readUint16BE();
|
||||
if (c & 32) {
|
||||
n = stream.readByte() + 1;
|
||||
c -= 32;
|
||||
} else {
|
||||
n = 1;
|
||||
}
|
||||
while (n--) {
|
||||
byte *target = (byte *)_surface->getBasePtr(x, y);
|
||||
if (_reserve != -1 && (c == transCol || c == 2015)) {
|
||||
target[0] = (byte)0;
|
||||
target[1] = (byte)0;
|
||||
target[2] = (byte)0;
|
||||
target[3] = (byte)0;
|
||||
} else {
|
||||
target[0] = (byte)255;
|
||||
g_sludge->getOrigPixelFormat()->colorToRGB(c, target[3], target[2], target[1]);
|
||||
}
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
49
engines/sludge/hsi.h
Normal file
49
engines/sludge/hsi.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_HSI_H
|
||||
#define SLUDGE_HSI_H
|
||||
|
||||
#include "graphics/palette.h"
|
||||
#include "image/image_decoder.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class HSIDecoder : public Image::ImageDecoder {
|
||||
public:
|
||||
HSIDecoder();
|
||||
~HSIDecoder() override;
|
||||
|
||||
// ImageDecoder API
|
||||
void destroy() override;
|
||||
bool loadStream(Common::SeekableReadStream &stream) override;
|
||||
Graphics::Surface *getSurface() const override { return _surface; }
|
||||
const Graphics::Palette &getPalette() const override { return _palette; }
|
||||
void setReserve(bool reserve) { _reserve = reserve; }
|
||||
|
||||
private:
|
||||
Graphics::Surface *_surface;
|
||||
Graphics::Palette _palette;
|
||||
int _reserve;
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
111
engines/sludge/imgloader.cpp
Normal file
111
engines/sludge/imgloader.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include "image/png.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/hsi.h"
|
||||
#include "sludge/imgloader.h"
|
||||
#include "sludge/sludge.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
bool ImgLoader::loadImage(int num, const char *fname, Common::SeekableReadStream *stream, Graphics::Surface *dest, int reserve) {
|
||||
debugC(3, kSludgeDebugGraphics, "Loading image at position: %d", (int)stream->pos());
|
||||
|
||||
bool dumpPng = false;
|
||||
|
||||
int32 start_ptr = stream->pos();
|
||||
if (!loadPNGImage(stream, dest)) {
|
||||
stream->seek(start_ptr);
|
||||
if (!loadHSIImage(stream, dest, reserve)) {
|
||||
return false;
|
||||
} else {
|
||||
if (num != -1) {
|
||||
g_sludge->_resMan->dumpFile(num, Common::String::format("%s%%04d.slx", fname).c_str());
|
||||
dumpPng = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (num != -1)
|
||||
g_sludge->_resMan->dumpFile(num, Common::String::format("%s%%04d.png", fname).c_str());
|
||||
}
|
||||
|
||||
if (!g_sludge->_dumpScripts)
|
||||
return true;
|
||||
|
||||
if (dumpPng || (fname && num == -1)) {
|
||||
// Debug code to output light map image
|
||||
Common::DumpFile *outFile = new Common::DumpFile();
|
||||
Common::Path outName;
|
||||
|
||||
if (dumpPng)
|
||||
outName = Common::Path(Common::String::format("dumps/%s%04d.png", fname, num));
|
||||
else
|
||||
outName = Common::Path(Common::String::format("dumps/%s.png", fname));
|
||||
|
||||
outFile->open(outName);
|
||||
Image::writePNG(*outFile, *dest);
|
||||
outFile->finalize();
|
||||
outFile->close();
|
||||
delete outFile;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImgLoader::loadPNGImage(Common::SeekableReadStream *stream, Graphics::Surface *dest, bool checkSig) {
|
||||
::Image::PNGDecoder png;
|
||||
|
||||
// set skip signature
|
||||
if (!checkSig) {
|
||||
png.setSkipSignature(true);
|
||||
}
|
||||
|
||||
if (!png.loadStream(*stream))
|
||||
return false;
|
||||
|
||||
// set value back
|
||||
if (!checkSig) {
|
||||
png.setSkipSignature(false);
|
||||
}
|
||||
|
||||
const Graphics::Surface *sourceSurface = png.getSurface();
|
||||
Graphics::Surface *pngSurface = sourceSurface->convertTo(*g_sludge->getScreenPixelFormat(), png.getPalette().data(), png.getPalette().size());
|
||||
dest->copyFrom(*pngSurface);
|
||||
pngSurface->free();
|
||||
delete pngSurface;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImgLoader::loadHSIImage(Common::SeekableReadStream *stream, Graphics::Surface *dest, int reserve) {
|
||||
HSIDecoder hsiDecoder;
|
||||
hsiDecoder.setReserve(reserve);
|
||||
if (!hsiDecoder.loadStream(*stream)) {
|
||||
return false;
|
||||
}
|
||||
dest->copyFrom(*(hsiDecoder.getSurface()));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
41
engines/sludge/imgloader.h
Normal file
41
engines/sludge/imgloader.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_IMGLOADER_H
|
||||
#define SLUDGE_IMGLOADER_H
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class ImgLoader {
|
||||
protected:
|
||||
ImgLoader() {}
|
||||
|
||||
public:
|
||||
static bool loadImage(int num, const char *fname, Common::SeekableReadStream *stream, Graphics::Surface *dest, int reserve = -1);
|
||||
static bool loadPNGImage(Common::SeekableReadStream *stream, Graphics::Surface *dest, bool checkSig = true);
|
||||
static bool loadHSIImage(Common::SeekableReadStream *stream, Graphics::Surface *dest, int reserve = -1);
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
603
engines/sludge/keymapper_tables.h
Normal file
603
engines/sludge/keymapper_tables.h
Normal file
@@ -0,0 +1,603 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
#include "backends/keymapper/standard-actions.h"
|
||||
|
||||
#include "common/translation.h"
|
||||
|
||||
namespace Sludge {
|
||||
inline Common::KeymapArray getSludgeKeymaps(const char *target, const Common::String &gameId) {
|
||||
|
||||
using namespace Common;
|
||||
|
||||
Keymap *gameKeyMap = new Keymap(Keymap::kKeymapTypeGame, "game-shortcuts", _("Game keymappings"));
|
||||
Keymap *debugKeyMap = new Keymap(Keymap::kKeymapTypeGame, "debug", _("Debug keymappings"));
|
||||
Keymap *menuKeymap = new Keymap(Keymap::kKeymapTypeGame, "menu", _("Menu keymappings"));
|
||||
Keymap *minigameKeymap = new Keymap(Keymap::kKeymapTypeGame, "minigame", _("Minigame keymappings"));
|
||||
Action *act;
|
||||
|
||||
if (gameId == "outoforder") {
|
||||
act = new Action(kStandardActionLeftClick, _("Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Change action"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("INVENTORY", _("Inventory"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_SPACE, ASCII_SPACE));
|
||||
act->addDefaultInputMapping("SPACE");
|
||||
act->addDefaultInputMapping("JOY_Y");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SAVE", _("Quick save"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_s, 's'));
|
||||
act->addDefaultInputMapping("s");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SPEEDUP", _("Speed up dialog"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_PLUS, '+'));
|
||||
act->addDefaultInputMapping("PLUS");
|
||||
act->addDefaultInputMapping("JOY_UP");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SPEEDDOWN", _("Slow down dialog"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_MINUS, '-'));
|
||||
act->addDefaultInputMapping("MINUS");
|
||||
act->addDefaultInputMapping("JOY_DOWN");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "tsotc") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Skip dialog"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUIT", _("Quit"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOADAUTOSAVE", _("Load auto save"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_a, 'a'));
|
||||
act->addDefaultInputMapping("a");
|
||||
act->addDefaultInputMapping("JOY_X");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SAVE", _("Save game"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_s, 's'));
|
||||
act->addDefaultInputMapping("s");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOAD", _("Load save"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_l, 'l'));
|
||||
act->addDefaultInputMapping("l");
|
||||
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("INVENTORY", _("Inventory"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_i, 'i'));
|
||||
act->addDefaultInputMapping("i");
|
||||
act->addDefaultInputMapping("JOY_Y");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("PAUSE", _("Pause"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_SPACE, ASCII_SPACE));
|
||||
act->addDefaultInputMapping("SPACE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "gjgagsas") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Skip dialog"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUIT", _("Quit"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOADAUTOSAVE", _("Load auto save"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_a, 'a'));
|
||||
act->addDefaultInputMapping("a");
|
||||
act->addDefaultInputMapping("JOY_X");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SAVE", _("Save game"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_s, 's'));
|
||||
act->addDefaultInputMapping("s");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOAD", _("Load save"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_l, 'l'));
|
||||
act->addDefaultInputMapping("l");
|
||||
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("INVENTORY", _("Inventory"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_i, 'i'));
|
||||
act->addDefaultInputMapping("i");
|
||||
act->addDefaultInputMapping("JOY_Y");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "robinsrescue") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Inventory"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("q");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SKIPDLG", _("Skip dialog"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_PERIOD, '.'));
|
||||
act->addDefaultInputMapping("PERIOD");
|
||||
act->addDefaultInputMapping("JOY_X");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SHOWFLOOR", _("DEBUG: Show floor"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_f, 'f'));
|
||||
act->addDefaultInputMapping("f");
|
||||
debugKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SHOWBOXES", _("DEBUG: Show boxes"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_b, 'b'));
|
||||
act->addDefaultInputMapping("b");
|
||||
debugKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "atw") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Inventory"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUIT", _("Quit"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("q");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "cubert") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Inventory / Examine"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "frasse") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Inventory"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SKIPDLG", _("Skip dialog"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_PERIOD, '.'));
|
||||
act->addDefaultInputMapping("PERIOD");
|
||||
act->addDefaultInputMapping("JOY_X");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "tgttpoacs") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Examine / Skip dialog"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause / Skip cutscene"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SPEEDUP", _("Speed up dialog"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_PLUS, '+'));
|
||||
act->addDefaultInputMapping("PLUS");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SPEEDDOWN", _("Slow down dialog"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_MINUS, '-'));
|
||||
act->addDefaultInputMapping("MINUS");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SAVE", _("Quick save"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_s, 's'));
|
||||
act->addDefaultInputMapping("s");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOAD", _("Quick load"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_l, 'l'));
|
||||
act->addDefaultInputMapping("l");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("EXAMINE", _("Examine"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_e, 'e'));
|
||||
act->addDefaultInputMapping("e");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("PICKUP", _("Pick up"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_p, 'p'));
|
||||
act->addDefaultInputMapping("p");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("TALK", _("Talk to"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_t, 't'));
|
||||
act->addDefaultInputMapping("t");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SMELL", _("Smell"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_m, 'm'));
|
||||
act->addDefaultInputMapping("m");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("USE", _("Use"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_u, 'u'));
|
||||
act->addDefaultInputMapping("u");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("CONSUME", _("Consume"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_c, 'c'));
|
||||
act->addDefaultInputMapping("c");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUIT", _("Quit"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_q, 'q'));
|
||||
act->addDefaultInputMapping("q");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("START", _("Start"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_RETURN, ASCII_RETURN));
|
||||
act->addDefaultInputMapping("RETURN");
|
||||
act->addDefaultInputMapping("JOY_Y");
|
||||
minigameKeymap->addAction(act);
|
||||
|
||||
act = new Action("QUIT", _("Quit"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_q, 'q'));
|
||||
act->addDefaultInputMapping("q");
|
||||
act->addDefaultInputMapping("JOY_X");
|
||||
minigameKeymap->addAction(act);
|
||||
|
||||
act = new Action("CASTEARTH", _("Cast earth spell"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_z, 'z'));
|
||||
act->addDefaultInputMapping("z");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
minigameKeymap->addAction(act);
|
||||
|
||||
act = new Action("CASTAIR", _("Cast air spell"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_x, 'x'));
|
||||
act->addDefaultInputMapping("x");
|
||||
act->addDefaultInputMapping("JOY_UP");
|
||||
minigameKeymap->addAction(act);
|
||||
|
||||
act = new Action("CASTFIRE", _("Cast fire spell"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_c, 'c'));
|
||||
act->addDefaultInputMapping("c");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
minigameKeymap->addAction(act);
|
||||
|
||||
act = new Action("CASTWATER", _("Cast water spell"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_v, 'v'));
|
||||
act->addDefaultInputMapping("v");
|
||||
act->addDefaultInputMapping("JOY_DOWN");
|
||||
minigameKeymap->addAction(act);
|
||||
|
||||
} else if (gameId == "interview") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Skip dialog"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause / Skip cutscene"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOAD", _("Quick load"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_l, 'l'));
|
||||
act->addDefaultInputMapping("l");
|
||||
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SAVE", _("Quick save"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_s, 's'));
|
||||
act->addDefaultInputMapping("s");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUIT", _("Quit"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_q, 'q'));
|
||||
act->addDefaultInputMapping("q");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "leptonsquest") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact / Skip dialog"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUIT", _("Quit"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SHOWFLOOR", _("DEBUG: Show floor"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_f, 'f'));
|
||||
act->addDefaultInputMapping("f");
|
||||
debugKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SHOWBOXES", _("DEBUG: Show boxes"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_b, 'b'));
|
||||
act->addDefaultInputMapping("b");
|
||||
debugKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "life") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SKIPDLG", _("Skip dialog"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping(".");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SAVE", _("Quick save"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_s, 's'));
|
||||
act->addDefaultInputMapping("s");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOAD", _("Quick load"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_l, 'l'));
|
||||
act->addDefaultInputMapping("l");
|
||||
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "mandy") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Skip dialog"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SAVE", _("Quick save"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_s, 's'));
|
||||
act->addDefaultInputMapping("s");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LOAD", _("Quick load"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_l, 'l'));
|
||||
act->addDefaultInputMapping("l");
|
||||
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
|
||||
} else if (gameId == "nsc") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact / Skip dialog"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Inventory / Skip dialog"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause / Skip cutscene"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
} else if (gameId == "verbcoin") {
|
||||
act = new Action(kStandardActionLeftClick, _("Move / Interact"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Skip dialog"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUIT", _("Quit"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SHOWBOXES", _("DEBUG: Show boxes"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_SPACE, ASCII_SPACE));
|
||||
act->addDefaultInputMapping("SPACE");
|
||||
debugKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SHOWFLOOR", _("DEBUG: Show floor"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_f, 'f'));
|
||||
act->addDefaultInputMapping("f");
|
||||
debugKeyMap->addAction(act);
|
||||
|
||||
} else {
|
||||
// Default keymap for other games
|
||||
warning("Game-specific keymap is not defined. Using default SLUDGE engine keymap");
|
||||
|
||||
act = new Action(kStandardActionLeftClick, _("Left click"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Right click"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause game"));
|
||||
act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
gameKeyMap->addAction(act);
|
||||
}
|
||||
|
||||
act = new Action(kStandardActionLeftClick, _("Left click"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
menuKeymap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Right click"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
menuKeymap->addAction(act);
|
||||
|
||||
KeymapArray keyMaps(4);
|
||||
keyMaps[0] = gameKeyMap;
|
||||
keyMaps[1] = debugKeyMap;
|
||||
keyMaps[2] = menuKeymap;
|
||||
keyMaps[3] = minigameKeymap;
|
||||
|
||||
menuKeymap->setEnabled(false);
|
||||
|
||||
return keyMaps;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
125
engines/sludge/language.cpp
Normal file
125
engines/sludge/language.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/language.h"
|
||||
#include "sludge/moreio.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/version.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
LanguageManager::LanguageManager() {
|
||||
init();
|
||||
}
|
||||
|
||||
LanguageManager::~LanguageManager() {
|
||||
kill();
|
||||
}
|
||||
|
||||
void LanguageManager::init() {
|
||||
_languageID = 0;
|
||||
_languageIdx = -1;
|
||||
_numLanguages = 0;
|
||||
_languageTable = nullptr;
|
||||
_languageNames = nullptr;
|
||||
}
|
||||
|
||||
void LanguageManager::kill() {
|
||||
if (_languageTable) {
|
||||
delete []_languageTable;
|
||||
_languageTable = nullptr;
|
||||
}
|
||||
|
||||
if (_languageNames) {
|
||||
delete []_languageNames;
|
||||
_languageNames = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageManager::createTable(Common::File *fp) {
|
||||
// get number of languages
|
||||
_numLanguages =
|
||||
(gameVersion >= VERSION(1, 3)) ? (fp->readByte()) : 0;
|
||||
debugC(2, kSludgeDebugDataLoad, "numLanguages : %c", _numLanguages);
|
||||
|
||||
// make language table
|
||||
_languageTable = new uint[_numLanguages + 1];
|
||||
if (!checkNew(_languageTable))
|
||||
return;
|
||||
|
||||
_languageNames = new Common::String[_numLanguages + 1];
|
||||
if (!checkNew(_languageNames))
|
||||
return;
|
||||
|
||||
for (uint i = 0; i <= _numLanguages; i++) {
|
||||
_languageTable[i] = i ? fp->readUint16BE() : 0;
|
||||
debugC(2, kSludgeDebugDataLoad, "languageTable %i: %i", i, _languageTable[i]);
|
||||
_languageNames[i].clear();
|
||||
if (gameVersion >= VERSION(2, 0)) {
|
||||
if (_numLanguages) {
|
||||
_languageNames[i] = readString(fp);
|
||||
debugC(2, kSludgeDebugDataLoad, "languageName %i: %s\n", i, _languageNames[i].c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageManager::setLanguageID(uint id) {
|
||||
_languageID = id;
|
||||
// get index of language
|
||||
setLanguageIndex(getLanguageForFileB());
|
||||
}
|
||||
|
||||
int LanguageManager::getLanguageForFileB() {
|
||||
int indexNum = -1;
|
||||
for (uint i = 0; i <= _numLanguages; i++) {
|
||||
if (_languageTable[i] == _languageID)
|
||||
indexNum = i;
|
||||
}
|
||||
return indexNum;
|
||||
}
|
||||
|
||||
void LanguageManager::saveLanguageSetting(Common::WriteStream *writeStream) {
|
||||
writeStream->writeByte(_numLanguages);
|
||||
}
|
||||
|
||||
void LanguageManager::loadLanguageSetting(Common::SeekableReadStream *readStream) {
|
||||
uint languageIdx = readStream->readByte();
|
||||
setLanguageIndex(languageIdx);
|
||||
}
|
||||
|
||||
void LanguageManager::setLanguageIndex(int idx) {
|
||||
if (idx < 0)
|
||||
fatal("Can't find the translation data specified!");
|
||||
|
||||
if (idx != _languageIdx) {
|
||||
// Load the saved language!
|
||||
_languageIdx = idx;
|
||||
// Now set file indices properly to the chosen language.
|
||||
g_sludge->_resMan->setFileIndices(_numLanguages, _languageIdx);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
54
engines/sludge/language.h
Normal file
54
engines/sludge/language.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_LANGUAGE_H
|
||||
#define SLUDGE_LANGUAGE_H
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class LanguageManager {
|
||||
public:
|
||||
LanguageManager();
|
||||
~LanguageManager();
|
||||
|
||||
void init();
|
||||
void kill();
|
||||
|
||||
void createTable(Common::File *table);
|
||||
void setLanguageID(uint id);
|
||||
void saveLanguageSetting(Common::WriteStream *writeStream);
|
||||
void loadLanguageSetting(Common::SeekableReadStream *readStream);
|
||||
|
||||
private:
|
||||
uint _languageID; // id of selected language
|
||||
int _languageIdx; // index of selected language in table
|
||||
uint _numLanguages; // number of existing languages in game
|
||||
uint *_languageTable; // indexes of existing languages
|
||||
Common::String *_languageNames; // language names
|
||||
|
||||
int getLanguageForFileB();
|
||||
void setLanguageIndex(int idx);
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
81
engines/sludge/main_loop.cpp
Normal file
81
engines/sludge/main_loop.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/function.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/saveload.h"
|
||||
#include "sludge/sound.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
#include "sludge/timing.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
extern VariableStack *noStack;
|
||||
|
||||
int main_loop(Common::String filename) {
|
||||
|
||||
if (!initSludge(filename)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_sludge->_gfxMan->initGfx();
|
||||
|
||||
startNewFunctionNum(0, 0, NULL, noStack);
|
||||
|
||||
g_sludge->_evtMan->startGame();
|
||||
g_sludge->_timer->init();
|
||||
|
||||
int saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
|
||||
if (saveSlot != -1)
|
||||
g_sludge->loadNow = g_sludge->getSaveStateName(saveSlot);
|
||||
|
||||
while (!g_sludge->_evtMan->quit()) {
|
||||
g_sludge->_evtMan->checkInput();
|
||||
g_sludge->_peopleMan->walkAllPeople();
|
||||
if (g_sludge->_evtMan->handleInput()) {
|
||||
runAllFunctions();
|
||||
handleSaveLoad();
|
||||
}
|
||||
sludgeDisplay();
|
||||
g_sludge->_soundMan->handleSoundLists();
|
||||
g_sludge->_timer->waitFrame();
|
||||
}
|
||||
|
||||
killSludge();
|
||||
|
||||
// Load next game
|
||||
if (!g_sludge->launchNext.empty()) {
|
||||
Common::String name = g_sludge->launchNext;
|
||||
g_sludge->launchNext.clear();
|
||||
main_loop(name);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
}
|
||||
// End of namespace Sludge
|
||||
30
engines/sludge/main_loop.h
Normal file
30
engines/sludge/main_loop.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_MAIN_LOOP_H
|
||||
#define SLUDGE_MAIN_LOOP_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
int main_loop(Common::String filename);
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
69
engines/sludge/metaengine.cpp
Normal file
69
engines/sludge/metaengine.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/detection.h"
|
||||
#include "sludge/keymapper_tables.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
uint SludgeEngine::getLanguageID() const { return _gameDescription->languageID; }
|
||||
const char *SludgeEngine::getGameId() const { return _gameDescription->desc.gameId;}
|
||||
uint32 SludgeEngine::getFeatures() const { return _gameDescription->desc.flags; }
|
||||
Common::Language SludgeEngine::getLanguage() const { return _gameDescription->desc.language; }
|
||||
const char *SludgeEngine::getGameFile() const {
|
||||
return _gameDescription->desc.filesDescriptions[0].fileName;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
class SludgeMetaEngine : public AdvancedMetaEngine<Sludge::SludgeGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "sludge";
|
||||
}
|
||||
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const Sludge::SludgeGameDescription *desc) const override {
|
||||
*engine = new Sludge::SludgeEngine(syst, desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::KeymapArray initKeymaps(const char *target) const override;
|
||||
};
|
||||
|
||||
bool SludgeMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return checkExtendedSaves(f) || (f == kSupportsLoadingDuringStartup);
|
||||
}
|
||||
|
||||
Common::KeymapArray SludgeMetaEngine::initKeymaps(const char *target) const {
|
||||
Common::String gameId = ConfMan.get("gameid", target);
|
||||
return Sludge::getSludgeKeymaps(target, gameId);
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(SLUDGE)
|
||||
REGISTER_PLUGIN_DYNAMIC(SLUDGE, PLUGIN_TYPE_ENGINE, SludgeMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(SLUDGE, PLUGIN_TYPE_ENGINE, SludgeMetaEngine);
|
||||
#endif
|
||||
54
engines/sludge/module.mk
Normal file
54
engines/sludge/module.mk
Normal file
@@ -0,0 +1,54 @@
|
||||
MODULE := engines/sludge
|
||||
|
||||
MODULE_OBJS := \
|
||||
backdrop.o \
|
||||
bg_effects.o \
|
||||
builtin.o \
|
||||
cursors.o \
|
||||
debugger.o \
|
||||
event.o \
|
||||
fileset.o \
|
||||
floor.o \
|
||||
freeze.o \
|
||||
fonttext.o \
|
||||
function.o \
|
||||
graphics.o \
|
||||
hsi.o \
|
||||
imgloader.o \
|
||||
language.o \
|
||||
main_loop.o \
|
||||
metaengine.o \
|
||||
moreio.o \
|
||||
movie.o \
|
||||
newfatal.o \
|
||||
objtypes.o \
|
||||
people.o \
|
||||
region.o \
|
||||
savedata.o \
|
||||
saveload.o \
|
||||
sludge.o \
|
||||
sludger.o \
|
||||
sound.o \
|
||||
speech.o \
|
||||
sprbanks.o \
|
||||
sprites.o \
|
||||
statusba.o \
|
||||
thumbnail.o \
|
||||
timing.o \
|
||||
transition.o \
|
||||
variable.o \
|
||||
zbuffer.o \
|
||||
|
||||
MODULE_DIRS += \
|
||||
engines/sludge
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_SLUDGE), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
176
engines/sludge/moreio.cpp
Normal file
176
engines/sludge/moreio.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
#include "sludge/newfatal.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
bool allowAnyFilename = true;
|
||||
|
||||
void writeString(Common::String s, Common::WriteStream *stream) {
|
||||
int a, len = s.size();
|
||||
stream->writeUint16BE(len);
|
||||
for (a = 0; a < len; a++) {
|
||||
stream->writeByte(s[a] + 1);
|
||||
}
|
||||
}
|
||||
|
||||
Common::String readString(Common::SeekableReadStream *stream) {
|
||||
int len = stream->readUint16BE();
|
||||
Common::String res = "";
|
||||
for (int a = 0; a < len; a++) {
|
||||
res += (char)(stream->readByte() - 1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Common::String encodeFilename(const Common::String &nameIn) {
|
||||
Common::String newName = "";
|
||||
if (nameIn.empty())
|
||||
return newName;
|
||||
if (allowAnyFilename) {
|
||||
for (uint i = 0; i < nameIn.size(); ++i) {
|
||||
switch (nameIn[i]) {
|
||||
case '<':
|
||||
newName += '_';
|
||||
newName += 'L';
|
||||
break;
|
||||
case '>':
|
||||
newName += '_';
|
||||
newName += 'G';
|
||||
break;
|
||||
case '|':
|
||||
newName += '_';
|
||||
newName += 'P';
|
||||
break;
|
||||
case '_':
|
||||
newName += '_';
|
||||
newName += 'U';
|
||||
break;
|
||||
case '\"':
|
||||
newName += '_';
|
||||
newName += 'S';
|
||||
break;
|
||||
case '\\':
|
||||
newName += '_';
|
||||
newName += 'B';
|
||||
break;
|
||||
case '/':
|
||||
newName += '_';
|
||||
newName += 'F';
|
||||
break;
|
||||
case ':':
|
||||
newName += '_';
|
||||
newName += 'C';
|
||||
break;
|
||||
case '*':
|
||||
newName += '_';
|
||||
newName += 'A';
|
||||
break;
|
||||
case '?':
|
||||
newName += '_';
|
||||
newName += 'Q';
|
||||
break;
|
||||
|
||||
default:
|
||||
newName += nameIn[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newName.clear();
|
||||
newName = nameIn;
|
||||
for (uint i = 0; i < newName.size(); ++i) {
|
||||
if (newName[i] == '\\')
|
||||
newName.setChar('/', i);
|
||||
}
|
||||
}
|
||||
return newName;
|
||||
}
|
||||
|
||||
Common::String decodeFilename(const Common::String &nameIn) {
|
||||
Common::String newName ="";
|
||||
if (allowAnyFilename) {
|
||||
for (uint i = 0; i < nameIn.size(); ++i) {
|
||||
if (nameIn[i] == '_') {
|
||||
++i;
|
||||
switch (nameIn[i]) {
|
||||
case 'L':
|
||||
newName += '<';
|
||||
break;
|
||||
case 'G':
|
||||
newName += '>';
|
||||
break;
|
||||
case 'P':
|
||||
newName += '|';
|
||||
break;
|
||||
case 'U':
|
||||
newName += '_';
|
||||
break;
|
||||
case 'S':
|
||||
newName += '\"';
|
||||
break;
|
||||
case 'B':
|
||||
newName += '\\';
|
||||
break;
|
||||
case 'F':
|
||||
newName += '/';
|
||||
break;
|
||||
case 'C':
|
||||
newName += ':';
|
||||
break;
|
||||
case 'A':
|
||||
newName += '*';
|
||||
break;
|
||||
case 'Q':
|
||||
newName += '?';
|
||||
break;
|
||||
default:
|
||||
newName += '_';
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
newName += nameIn[i];
|
||||
}
|
||||
}
|
||||
return newName;
|
||||
} else {
|
||||
newName.clear();
|
||||
newName = nameIn;
|
||||
}
|
||||
return newName;
|
||||
}
|
||||
|
||||
char *createCString(const Common::String &s) {
|
||||
uint n = s.size() + 1;
|
||||
char *res = new char[n];
|
||||
if (!checkNew(res)) {
|
||||
fatal("createCString : Unable to copy String");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(res, s.c_str(), n);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
37
engines/sludge/moreio.h
Normal file
37
engines/sludge/moreio.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_MOREIO_H
|
||||
#define SLUDGE_MOREIO_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
// Read & Write
|
||||
Common::String readString(Common::SeekableReadStream *stream);
|
||||
void writeString(Common::String s, Common::WriteStream *stream);
|
||||
|
||||
Common::String encodeFilename(const Common::String &nameIn);
|
||||
Common::String decodeFilename(const Common::String &nameIn);
|
||||
|
||||
char *createCString(const Common::String &s);
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
141
engines/sludge/movie.cpp
Normal file
141
engines/sludge/movie.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/movie.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sound.h"
|
||||
|
||||
#include "common/scummsys.h" // for USE_VPX
|
||||
#include "common/substream.h"
|
||||
#include "video/mkv_decoder.h"
|
||||
#include "graphics/blit.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
MovieStates movieIsPlaying = kMovieNothing;
|
||||
int movieIsEnding = 0;
|
||||
float movieAspect = 1.6F;
|
||||
|
||||
int playMovie(int fileNumber) {
|
||||
uint fsize;
|
||||
if (!(fsize = g_sludge->_resMan->openFileFromNum(fileNumber)))
|
||||
return fatal("playMovie(): Can't open movie");
|
||||
|
||||
#if !defined(USE_VPX)
|
||||
warning("Sludge::playMovie - VPX support not compiled in, skipping movie");
|
||||
#else
|
||||
Video::MKVDecoder decoder;
|
||||
|
||||
|
||||
Common::SeekableReadStream *stream = g_sludge->_resMan->getData();
|
||||
Common::SeekableSubReadStream *video = new Common::SeekableSubReadStream(stream, stream->pos(), stream->pos() + fsize);
|
||||
|
||||
if (decoder.loadStream(video))
|
||||
movieIsPlaying = kMoviePlaying;
|
||||
|
||||
decoder.start();
|
||||
|
||||
debug(1, "movieIsPlaying %d", movieIsPlaying);
|
||||
while (movieIsPlaying) {
|
||||
g_sludge->_evtMan->checkInput();
|
||||
if (g_sludge->_evtMan->quit())
|
||||
break;
|
||||
|
||||
g_sludge->_evtMan->handleInput();
|
||||
|
||||
if (decoder.isVideoLoaded()) {
|
||||
if (decoder.endOfVideo()) {
|
||||
debug(1, "End of video");
|
||||
// Movie complete, so unload the movie
|
||||
break;
|
||||
} else if (decoder.needsUpdate()) {
|
||||
const Graphics::Surface *s = decoder.decodeNextFrame();
|
||||
if (s) {
|
||||
// Transfer the next frame
|
||||
assert(s->format.bytesPerPixel == 4);
|
||||
if (((uint)s->w != g_sludge->_gfxMan->getWinWidth()) || ((uint)s->h != g_sludge->_gfxMan->getWinHeight())) {
|
||||
Graphics::Surface *surf = g_system->lockScreen();
|
||||
Graphics::scaleBlit((byte*)surf->getPixels(), (const byte*)s->getPixels(), surf->pitch, s->pitch,
|
||||
g_sludge->_gfxMan->getWinWidth(), g_sludge->_gfxMan->getWinHeight(), s->w, s->h, s->format);
|
||||
g_system->unlockScreen();
|
||||
} else {
|
||||
g_system->copyRectToScreen(s->getPixels(), s->pitch, 0, 0, s->w, s->h);
|
||||
}
|
||||
g_system->updateScreen();
|
||||
} else {
|
||||
warning("s is false");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
movieIsPlaying = kMovieNothing;
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MovieStates isMoviePlaying() {
|
||||
return movieIsPlaying;
|
||||
}
|
||||
|
||||
int stopMovie() {
|
||||
int r = movieIsPlaying;
|
||||
movieIsPlaying = kMovieNothing;
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int pauseMovie() {
|
||||
#if 0
|
||||
if (movieIsPlaying == kMoviePlaying) {
|
||||
ALuint source = getSoundSource(movieAudioIndex);
|
||||
if (source) {
|
||||
|
||||
alurePauseSource(source);
|
||||
|
||||
}
|
||||
movieIsPlaying = kMoviePaused;
|
||||
fprintf(stderr, "** Pausing **\n");
|
||||
} else if (movieIsPlaying == kMoviePaused) {
|
||||
ALuint source = getSoundSource(movieAudioIndex);
|
||||
if (source) {
|
||||
|
||||
alureResumeSource(source);
|
||||
|
||||
}
|
||||
fprintf(stderr, "** Restarted movie ** sound: %d source: %d\n", movieSoundPlaying, source);
|
||||
movieIsPlaying = kMoviePlaying;
|
||||
}
|
||||
#endif
|
||||
return movieIsPlaying;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
44
engines/sludge/movie.h
Normal file
44
engines/sludge/movie.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_MOVIE_H
|
||||
#define SLUDGE_MOVIE_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
/*
|
||||
movieIsPlaying tracks the state of movie playing
|
||||
*/
|
||||
enum MovieStates {
|
||||
kMovieNothing = 0,
|
||||
kMoviePlaying,
|
||||
kMoviePaused
|
||||
};
|
||||
extern MovieStates movieIsPlaying;
|
||||
extern int movieIsEnding;
|
||||
|
||||
int playMovie(int fileNumber);
|
||||
int stopMovie();
|
||||
MovieStates isMoviePlaying();
|
||||
int pauseMovie();
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
97
engines/sludge/newfatal.cpp
Normal file
97
engines/sludge/newfatal.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include "sludge/errors.h"
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sound.h"
|
||||
|
||||
namespace Common {
|
||||
DECLARE_SINGLETON(Sludge::FatalMsgManager);
|
||||
}
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
int inFatal(const Common::String &str) {
|
||||
g_sludge->_soundMan->killSoundStuff();
|
||||
error("%s", str.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
FatalMsgManager::FatalMsgManager() {
|
||||
reset();
|
||||
}
|
||||
|
||||
FatalMsgManager::~FatalMsgManager() {
|
||||
}
|
||||
|
||||
void FatalMsgManager::reset() {
|
||||
_fatalMessage = "";
|
||||
_fatalInfo = "Initialisation error! Something went wrong before we even got started!";
|
||||
_resourceForFatal = -1;
|
||||
}
|
||||
|
||||
bool FatalMsgManager::hasFatal() {
|
||||
if (!_fatalMessage.empty())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void FatalMsgManager::setFatalInfo(const Common::String &userFunc, const Common::String &BIF) {
|
||||
_fatalInfo = "Currently in this sub: " + userFunc + "\nCalling: " + BIF;
|
||||
debugC(0, kSludgeDebugFatal, "%s", _fatalInfo.c_str());
|
||||
}
|
||||
|
||||
void FatalMsgManager::setResourceForFatal(int n) {
|
||||
_resourceForFatal = n;
|
||||
}
|
||||
|
||||
int FatalMsgManager::fatal(const Common::String &str1) {
|
||||
ResourceManager *resMan = g_sludge->_resMan;
|
||||
if (resMan->hasResourceNames() && _resourceForFatal != -1) {
|
||||
Common::String r = resMan->resourceNameFromNum(_resourceForFatal);
|
||||
Common::String newStr = _fatalInfo + "\nResource: " + r + "\n\n" + str1;
|
||||
inFatal(newStr);
|
||||
} else {
|
||||
Common::String newStr = _fatalInfo + "\n\n" + str1;
|
||||
inFatal(newStr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkNew(const void *mem) {
|
||||
if (mem == NULL) {
|
||||
inFatal(ERROR_OUT_OF_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fatal(const Common::String &str1, const Common::String &str2) {
|
||||
Common::String newStr = str1 + " " + str2;
|
||||
fatal(newStr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
69
engines/sludge/newfatal.h
Normal file
69
engines/sludge/newfatal.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_NEWFATAL_H
|
||||
#define SLUDGE_NEWFATAL_H
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/singleton.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class FatalMsgManager : public Common::Singleton<Sludge::FatalMsgManager>{
|
||||
public:
|
||||
FatalMsgManager();
|
||||
~FatalMsgManager() override;
|
||||
|
||||
void reset();
|
||||
|
||||
bool hasFatal();
|
||||
int fatal(const Common::String &str);
|
||||
void setFatalInfo(const Common::String &userFunc, const Common::String &BIF);
|
||||
void setResourceForFatal(int n);
|
||||
|
||||
private:
|
||||
Common::String _fatalMessage;
|
||||
Common::String _fatalInfo;
|
||||
|
||||
int _resourceForFatal;
|
||||
};
|
||||
|
||||
inline bool hasFatal() {
|
||||
return FatalMsgManager::instance().hasFatal();
|
||||
}
|
||||
|
||||
inline int fatal(const Common::String &str) {
|
||||
return FatalMsgManager::instance().fatal(str);
|
||||
}
|
||||
|
||||
inline void setFatalInfo(const Common::String &userFunc, const Common::String &BIF) {
|
||||
FatalMsgManager::instance().setFatalInfo(userFunc, BIF);
|
||||
}
|
||||
|
||||
inline void setResourceForFatal(int n) {
|
||||
FatalMsgManager::instance().setResourceForFatal(n);
|
||||
}
|
||||
|
||||
int checkNew(const void *mem);
|
||||
int fatal(const Common::String &str1, const Common::String &str2);
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
145
engines/sludge/objtypes.cpp
Normal file
145
engines/sludge/objtypes.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/moreio.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/objtypes.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/version.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
ObjectManager::~ObjectManager() {
|
||||
kill();
|
||||
}
|
||||
|
||||
bool ObjectManager::init() {
|
||||
_allObjectTypes.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjectManager::kill() {
|
||||
ObjectTypeList::iterator it;
|
||||
for (it = _allObjectTypes.begin(); it != _allObjectTypes.end(); ++it) {
|
||||
delete [](*it)->allCombis;
|
||||
delete (*it);
|
||||
(*it) = nullptr;
|
||||
}
|
||||
_allObjectTypes.clear();
|
||||
}
|
||||
|
||||
ObjectType *ObjectManager::findObjectType(int i, bool skipLoad) {
|
||||
ObjectTypeList::iterator it;
|
||||
for (it = _allObjectTypes.begin(); it != _allObjectTypes.end(); ++it) {
|
||||
if ((*it)->objectNum == i) {
|
||||
return (*it);
|
||||
}
|
||||
}
|
||||
|
||||
if (skipLoad)
|
||||
return nullptr;
|
||||
|
||||
return loadObjectType(i);
|
||||
}
|
||||
|
||||
ObjectType *ObjectManager::loadObjectType(int i) {
|
||||
int a, nameNum;
|
||||
ObjectType *newType = new ObjectType;
|
||||
ResourceManager *rm = _vm->_resMan;
|
||||
|
||||
if (checkNew(newType)) {
|
||||
if (rm->openObjectSlice(i)) {
|
||||
Common::SeekableReadStream *readStream = rm->getData();
|
||||
nameNum = readStream->readUint16BE();
|
||||
newType->r = (byte)readStream->readByte();
|
||||
newType->g = (byte)readStream->readByte();
|
||||
newType->b = (byte)readStream->readByte();
|
||||
newType->speechGap = readStream->readByte();
|
||||
newType->walkSpeed = readStream->readByte();
|
||||
newType->wrapSpeech = readStream->readUint32LE();
|
||||
newType->spinSpeed = readStream->readUint16BE();
|
||||
|
||||
if (gameVersion >= VERSION(1, 6)) {
|
||||
// aaLoad
|
||||
readStream->readByte();
|
||||
readStream->readFloatLE();
|
||||
readStream->readFloatLE();
|
||||
}
|
||||
|
||||
if (gameVersion >= VERSION(1, 4)) {
|
||||
newType->flags = readStream->readUint16BE();
|
||||
} else {
|
||||
newType->flags = 0;
|
||||
}
|
||||
|
||||
newType->numCom = readStream->readUint16BE();
|
||||
newType->allCombis = (newType->numCom) ? new Combination[newType->numCom] : nullptr;
|
||||
|
||||
|
||||
for (a = 0; a < newType->numCom; a++) {
|
||||
newType->allCombis[a].withObj = readStream->readUint16BE();
|
||||
newType->allCombis[a].funcNum = readStream->readUint16BE();
|
||||
}
|
||||
|
||||
rm->finishAccess();
|
||||
newType->screenName = rm->getNumberedString(nameNum);
|
||||
newType->objectNum = i;
|
||||
_allObjectTypes.push_back(newType);
|
||||
return newType;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ObjectType *ObjectManager::loadObjectRef(Common::SeekableReadStream *stream) {
|
||||
ObjectType *r = loadObjectType(stream->readUint16BE());
|
||||
r->screenName.clear();
|
||||
r->screenName = readString(stream);
|
||||
return r;
|
||||
}
|
||||
|
||||
void ObjectManager::saveObjectRef(ObjectType *r, Common::WriteStream *stream) {
|
||||
stream->writeUint16BE(r->objectNum);
|
||||
writeString(r->screenName, stream);
|
||||
}
|
||||
|
||||
int ObjectManager::getCombinationFunction(int withThis, int thisObject) {
|
||||
int i, num = 0;
|
||||
ObjectType *obj = findObjectType(thisObject);
|
||||
|
||||
for (i = 0; i < obj->numCom; i++) {
|
||||
if (obj->allCombis[i].withObj == withThis) {
|
||||
num = obj->allCombis[i].funcNum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
void ObjectManager::removeObjectType(ObjectType *oT) {
|
||||
delete []oT->allCombis;
|
||||
_allObjectTypes.remove(oT);
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
66
engines/sludge/objtypes.h
Normal file
66
engines/sludge/objtypes.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_OBJTYPES_H
|
||||
#define SLUDGE_OBJTYPES_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class SludgeEngine;
|
||||
|
||||
struct Combination {
|
||||
int withObj, funcNum;
|
||||
};
|
||||
|
||||
struct ObjectType {
|
||||
Common::String screenName;
|
||||
int objectNum;
|
||||
byte r, g, b;
|
||||
int numCom;
|
||||
int speechGap, walkSpeed, wrapSpeech, spinSpeed;
|
||||
uint16 flags;
|
||||
Combination *allCombis;
|
||||
};
|
||||
|
||||
typedef Common::List<ObjectType *> ObjectTypeList;
|
||||
|
||||
class ObjectManager {
|
||||
public:
|
||||
ObjectManager(SludgeEngine *vm) : _vm(vm) { init(); }
|
||||
~ObjectManager();
|
||||
|
||||
bool init();
|
||||
void kill();
|
||||
|
||||
ObjectType *findObjectType(int i, bool skipLoad = false);
|
||||
ObjectType *loadObjectType(int i);
|
||||
int getCombinationFunction(int a, int b);
|
||||
void removeObjectType(ObjectType *oT);
|
||||
void saveObjectRef(ObjectType *r, Common::WriteStream *stream);
|
||||
ObjectType *loadObjectRef(Common::SeekableReadStream *stream);
|
||||
|
||||
private:
|
||||
ObjectTypeList _allObjectTypes;
|
||||
SludgeEngine *_vm;
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
1039
engines/sludge/people.cpp
Normal file
1039
engines/sludge/people.cpp
Normal file
File diff suppressed because it is too large
Load Diff
173
engines/sludge/people.h
Normal file
173
engines/sludge/people.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_PEOPLE_H
|
||||
#define SLUDGE_PEOPLE_H
|
||||
|
||||
#include "common/list.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct FrozenStuffStruct;
|
||||
struct LoadedSpriteBank;
|
||||
struct ScreenRegion;
|
||||
struct VariableStack;
|
||||
|
||||
class SludgeEngine;
|
||||
|
||||
struct AnimFrame {
|
||||
int frameNum, howMany;
|
||||
int noise;
|
||||
};
|
||||
|
||||
#define EXTRA_FRONT 1
|
||||
#define EXTRA_FIXEDSIZE 2
|
||||
#define EXTRA_NOSCALE 2 // Alternative name
|
||||
#define EXTRA_NOZB 4
|
||||
#define EXTRA_FIXTOSCREEN 8
|
||||
#define EXTRA_NOLITE 16
|
||||
#define EXTRA_NOREMOVE 32
|
||||
#define EXTRA_RECTANGULAR 64
|
||||
|
||||
struct PersonaAnimation {
|
||||
LoadedSpriteBank *theSprites;
|
||||
AnimFrame *frames;
|
||||
int numFrames;
|
||||
|
||||
PersonaAnimation();
|
||||
PersonaAnimation(int num, VariableStack *&stacky);
|
||||
PersonaAnimation(PersonaAnimation *orig);
|
||||
~PersonaAnimation();
|
||||
|
||||
// Setter & getter
|
||||
int getTotalTime();
|
||||
|
||||
// Save & load
|
||||
bool save(Common::WriteStream *stream);
|
||||
bool load(Common::SeekableReadStream *stream);
|
||||
};
|
||||
|
||||
struct Persona {
|
||||
PersonaAnimation **animation;
|
||||
int numDirections;
|
||||
|
||||
// Save & load
|
||||
bool save(Common::WriteStream *stream);
|
||||
bool load(Common::SeekableReadStream *stream);
|
||||
};
|
||||
|
||||
struct OnScreenPerson {
|
||||
float x, y;
|
||||
int height, floaty, walkSpeed;
|
||||
float scale;
|
||||
int walkToX, walkToY, thisStepX, thisStepY, inPoly, walkToPoly;
|
||||
bool walking, spinning;
|
||||
struct LoadedFunction *continueAfterWalking;
|
||||
PersonaAnimation *myAnim;
|
||||
PersonaAnimation *lastUsedAnim;
|
||||
Persona *myPersona;
|
||||
int frameNum, frameTick, angle, wantAngle, angleOffset;
|
||||
bool show;
|
||||
int direction, directionWhenDoneWalking;
|
||||
struct ObjectType *thisType;
|
||||
int extra, spinSpeed;
|
||||
byte r, g, b, colourmix, transparency;
|
||||
|
||||
void makeTalker();
|
||||
void makeSilent();
|
||||
void setFrames(int a);
|
||||
};
|
||||
|
||||
typedef Common::List<OnScreenPerson *> OnScreenPersonList;
|
||||
|
||||
class PeopleManager {
|
||||
public:
|
||||
PeopleManager(SludgeEngine *vm);
|
||||
~PeopleManager();
|
||||
|
||||
// Initialisation and creation
|
||||
bool init();
|
||||
bool addPerson(int x, int y, int objNum, Persona *p);
|
||||
|
||||
// Draw to screen and to backdrop
|
||||
void drawPeople();
|
||||
void freezePeople(int, int);
|
||||
|
||||
// Removalisationisms
|
||||
void kill();
|
||||
void killMostPeople();
|
||||
void removeOneCharacter(int i);
|
||||
|
||||
// Things which affect or use all characters
|
||||
OnScreenPerson *findPerson(int v);
|
||||
void setScale(int16 h, int16 d);
|
||||
|
||||
// Things which affect one character
|
||||
void setShown(bool h, int ob);
|
||||
void setDrawMode(int h, int ob);
|
||||
void setPersonTransparency(int ob, byte x);
|
||||
void setPersonColourise(int ob, byte r, byte g, byte b, byte colourmix);
|
||||
|
||||
// Moving 'em
|
||||
void movePerson(int x, int y, int objNum);
|
||||
bool makeWalkingPerson(int x, int y, int objNum, struct LoadedFunction *func, int di);
|
||||
bool forceWalkingPerson(int x, int y, int objNum, struct LoadedFunction *func, int di);
|
||||
void jumpPerson(int x, int y, int objNum);
|
||||
void walkAllPeople();
|
||||
bool turnPersonToFace(int thisNum, int direc);
|
||||
bool stopPerson(int o);
|
||||
bool floatCharacter(int f, int objNum);
|
||||
bool setCharacterWalkSpeed(int f, int objNum);
|
||||
|
||||
// Animating 'em
|
||||
void animatePerson(int obj, PersonaAnimation *);
|
||||
void animatePerson(int obj, Persona *per);
|
||||
bool setPersonExtra(int f, int newSetting);
|
||||
|
||||
// Loading and saving
|
||||
bool savePeople(Common::WriteStream *stream);
|
||||
bool loadPeople(Common::SeekableReadStream *stream);
|
||||
|
||||
// Freeze
|
||||
void freeze(FrozenStuffStruct *frozenStuff);
|
||||
void resotre(FrozenStuffStruct *frozenStuff);
|
||||
|
||||
private:
|
||||
ScreenRegion *_personRegion;
|
||||
OnScreenPersonList *_allPeople;
|
||||
int16 _scaleHorizon;
|
||||
int16 _scaleDivide;
|
||||
|
||||
SludgeEngine *_vm;
|
||||
|
||||
void shufflePeople();
|
||||
|
||||
// OnScreenPerson manipulation
|
||||
void turnMeAngle(OnScreenPerson *thisPerson, int direc);
|
||||
void spinStep(OnScreenPerson *thisPerson);
|
||||
void rethinkAngle(OnScreenPerson *thisPerson);
|
||||
void moveAndScale(OnScreenPerson &me, float x, float y);
|
||||
void setMyDrawMode(OnScreenPerson *moveMe, int h);
|
||||
bool walkMe(OnScreenPerson *thisPerson, bool move = true);
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
173
engines/sludge/region.cpp
Normal file
173
engines/sludge/region.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/freeze.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/objtypes.h"
|
||||
#include "sludge/region.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
RegionManager::RegionManager(SludgeEngine *vm) {
|
||||
_vm = vm;
|
||||
_allScreenRegions = new ScreenRegionList;
|
||||
_allScreenRegions->clear();
|
||||
_lastRegion = nullptr;
|
||||
_overRegion = nullptr;
|
||||
}
|
||||
|
||||
RegionManager::~RegionManager() {
|
||||
kill();
|
||||
|
||||
delete _allScreenRegions;
|
||||
_allScreenRegions = nullptr;
|
||||
}
|
||||
|
||||
void RegionManager::showBoxes() {
|
||||
for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
|
||||
g_sludge->_gfxMan->drawVerticalLine((*it)->x1, (*it)->y1, (*it)->y2);
|
||||
g_sludge->_gfxMan->drawVerticalLine((*it)->x2, (*it)->y1, (*it)->y2);
|
||||
g_sludge->_gfxMan->drawHorizontalLine((*it)->x1, (*it)->y1, (*it)->x2);
|
||||
g_sludge->_gfxMan->drawHorizontalLine((*it)->x1, (*it)->y2, (*it)->x2);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionManager::removeScreenRegion(int objectNum) {
|
||||
for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
|
||||
if ((*it)->thisType->objectNum == objectNum) {
|
||||
ScreenRegion *killMe = *it;
|
||||
g_sludge->_objMan->removeObjectType(killMe->thisType);
|
||||
if (killMe == _overRegion)
|
||||
_overRegion = nullptr;
|
||||
delete killMe;
|
||||
killMe = nullptr;
|
||||
it = _allScreenRegions->reverse_erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegionManager::saveRegions(Common::WriteStream *stream) {
|
||||
uint numRegions = _allScreenRegions->size();
|
||||
stream->writeUint16BE(numRegions);
|
||||
for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
|
||||
stream->writeUint16BE((*it)->x1);
|
||||
stream->writeUint16BE((*it)->y1);
|
||||
stream->writeUint16BE((*it)->x2);
|
||||
stream->writeUint16BE((*it)->y2);
|
||||
stream->writeUint16BE((*it)->sX);
|
||||
stream->writeUint16BE((*it)->sY);
|
||||
stream->writeSint16BE((*it)->di);
|
||||
g_sludge->_objMan->saveObjectRef((*it)->thisType, stream);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionManager::loadRegions(Common::SeekableReadStream *stream) {
|
||||
int numRegions = stream->readUint16BE();
|
||||
while (numRegions--) {
|
||||
ScreenRegion *newRegion = new ScreenRegion;
|
||||
_allScreenRegions->push_back(newRegion);
|
||||
newRegion->x1 = stream->readUint16BE();
|
||||
newRegion->y1 = stream->readUint16BE();
|
||||
newRegion->x2 = stream->readUint16BE();
|
||||
newRegion->y2 = stream->readUint16BE();
|
||||
newRegion->sX = stream->readUint16BE();
|
||||
newRegion->sY = stream->readUint16BE();
|
||||
newRegion->di = stream->readSint16BE();
|
||||
newRegion->thisType = g_sludge->_objMan->loadObjectRef(stream);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionManager::kill() {
|
||||
for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
|
||||
ScreenRegion *killRegion = (*it);
|
||||
g_sludge->_objMan->removeObjectType(killRegion->thisType);
|
||||
delete killRegion;
|
||||
}
|
||||
_allScreenRegions->clear();
|
||||
_overRegion = nullptr;
|
||||
_lastRegion = nullptr;
|
||||
}
|
||||
|
||||
bool RegionManager::addScreenRegion(int x1, int y1, int x2, int y2, int sX, int sY, int di,
|
||||
int objectNum) {
|
||||
ScreenRegion *newRegion = new ScreenRegion;
|
||||
if (!checkNew(newRegion))
|
||||
return false;
|
||||
newRegion->di = di;
|
||||
newRegion->x1 = x1;
|
||||
newRegion->y1 = y1;
|
||||
newRegion->x2 = x2;
|
||||
newRegion->y2 = y2;
|
||||
newRegion->sX = sX;
|
||||
newRegion->sY = sY;
|
||||
newRegion->thisType = g_sludge->_objMan->loadObjectType(objectNum);
|
||||
_allScreenRegions->push_front(newRegion);
|
||||
return (bool) (newRegion->thisType != nullptr);
|
||||
}
|
||||
|
||||
void RegionManager::updateOverRegion() {
|
||||
int cameraX = g_sludge->_gfxMan->getCamX();
|
||||
int cameraY = g_sludge->_gfxMan->getCamY();
|
||||
for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
|
||||
if ((g_sludge->_evtMan->mouseX() >= (*it)->x1 - cameraX)
|
||||
&& (g_sludge->_evtMan->mouseY() >= (*it)->y1 - cameraY)
|
||||
&& (g_sludge->_evtMan->mouseX() <= (*it)->x2 - cameraX)
|
||||
&& (g_sludge->_evtMan->mouseY() <= (*it)->y2 - cameraY)) {
|
||||
_overRegion = (*it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_overRegion = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
ScreenRegion *RegionManager::getRegionForObject(int obj) {
|
||||
for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
|
||||
if (obj == (*it)->thisType->objectNum) {
|
||||
return (*it);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RegionManager::freeze(FrozenStuffStruct *frozenStuff) {
|
||||
frozenStuff->allScreenRegions = _allScreenRegions;
|
||||
_allScreenRegions = new ScreenRegionList;
|
||||
_overRegion = nullptr;
|
||||
}
|
||||
|
||||
void RegionManager::resotre(FrozenStuffStruct *frozenStuff) {
|
||||
// kill
|
||||
kill();
|
||||
delete _allScreenRegions;
|
||||
_allScreenRegions = nullptr;
|
||||
|
||||
// restore
|
||||
_allScreenRegions = frozenStuff->allScreenRegions;
|
||||
_overRegion = nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
77
engines/sludge/region.h
Normal file
77
engines/sludge/region.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_REGION_H
|
||||
#define SLUDGE_REGION_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct ObjectType;
|
||||
|
||||
struct ScreenRegion {
|
||||
int x1, y1, x2, y2, sX, sY, di;
|
||||
ObjectType *thisType;
|
||||
};
|
||||
typedef Common::List<ScreenRegion *> ScreenRegionList;
|
||||
|
||||
class RegionManager {
|
||||
public:
|
||||
RegionManager(SludgeEngine *vm);
|
||||
~RegionManager();
|
||||
|
||||
// Kill
|
||||
void kill();
|
||||
|
||||
// Add & remove region
|
||||
bool addScreenRegion(int x1, int y1, int x2, int y2, int, int, int, int objectNum);
|
||||
void removeScreenRegion(int objectNum);
|
||||
|
||||
// Save & load
|
||||
void loadRegions(Common::SeekableReadStream *stream);
|
||||
void saveRegions(Common::WriteStream *stream);
|
||||
|
||||
// Draw
|
||||
void showBoxes();
|
||||
|
||||
// Setter & getter
|
||||
ScreenRegion *getRegionForObject(int obj);
|
||||
ScreenRegion *getOverRegion() const { return _overRegion; }
|
||||
void setOverRegion(ScreenRegion *newRegion) { _overRegion = newRegion; }
|
||||
void updateOverRegion();
|
||||
bool isRegionChanged() const { return _lastRegion != _overRegion; }
|
||||
void updateLastRegion() { _lastRegion = _overRegion; }
|
||||
void resetOverRegion() { _overRegion = nullptr; }
|
||||
void resetLastRegion() { _lastRegion = nullptr; }
|
||||
|
||||
// Freeze
|
||||
void freeze(FrozenStuffStruct *frozenStuff);
|
||||
void resotre(FrozenStuffStruct *frozenStuff);
|
||||
|
||||
private:
|
||||
SludgeEngine *_vm;
|
||||
|
||||
ScreenRegionList *_allScreenRegions;
|
||||
ScreenRegion *_overRegion;
|
||||
ScreenRegion *_lastRegion;
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
247
engines/sludge/savedata.cpp
Normal file
247
engines/sludge/savedata.cpp
Normal file
@@ -0,0 +1,247 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/savedata.h"
|
||||
#include "sludge/variable.h"
|
||||
|
||||
#define LOAD_ERROR "Can't load custom data...\n\n"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
const char CustomSaveHelper::UTF8_CHECKER[] = {'U', 'N', '\xef', '\xbf', '\xbd', 'L', 'O', '\xef', '\xbf', '\xbd', 'C', 'K', 'E', 'D', '\0'};
|
||||
uint16 CustomSaveHelper::_saveEncoding = false;
|
||||
char CustomSaveHelper::_encode1 = 0;
|
||||
char CustomSaveHelper::_encode2 = 0;
|
||||
|
||||
void CustomSaveHelper::writeStringEncoded(const Common::String &checker, Common::WriteStream *stream) {
|
||||
int len = checker.size();
|
||||
|
||||
stream->writeUint16BE(len);
|
||||
for (int a = 0; a < len; a++) {
|
||||
stream->writeByte(checker[a] ^ _encode1);
|
||||
_encode1 += _encode2;
|
||||
}
|
||||
}
|
||||
|
||||
Common::String CustomSaveHelper::readStringEncoded(Common::SeekableReadStream *fp) {
|
||||
int len = fp->readUint16BE();
|
||||
Common::String res = "";
|
||||
|
||||
for (int a = 0; a < len; a++) {
|
||||
res += (char)(fp->readByte() ^ _encode1);
|
||||
_encode1 += _encode2;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
char *CustomSaveHelper::readTextPlain(Common::SeekableReadStream *fp) {
|
||||
int32 startPos;
|
||||
|
||||
uint32 stringSize = 0;
|
||||
bool keepGoing = true;
|
||||
char gotChar;
|
||||
char *reply;
|
||||
|
||||
startPos = fp->pos();
|
||||
|
||||
while (keepGoing) {
|
||||
gotChar = (char)fp->readByte();
|
||||
if ((gotChar == '\n') || (fp->eos())) {
|
||||
keepGoing = false;
|
||||
} else {
|
||||
stringSize++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((stringSize == 0) && (fp->eos())) {
|
||||
return NULL;
|
||||
} else {
|
||||
fp->seek(startPos, SEEK_SET);
|
||||
reply = new char[stringSize + 1];
|
||||
if (reply == NULL)
|
||||
return NULL;
|
||||
uint bytes_read = fp->read(reply, stringSize);
|
||||
if (bytes_read != stringSize && fp->err()) {
|
||||
warning("Reading error in readTextPlain.");
|
||||
}
|
||||
fp->readByte(); // Skip the newline character
|
||||
reply[stringSize] = 0;
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
bool CustomSaveHelper::fileToStack(const Common::String &filename, StackHandler *sH) {
|
||||
Variable stringVar;
|
||||
stringVar.varType = SVT_NULL;
|
||||
Common::String checker = _saveEncoding ? "[Custom data (encoded)]\r\n" : "[Custom data (ASCII)]\n";
|
||||
|
||||
Common::InSaveFile *fp = g_system->getSavefileManager()->openForLoading(filename);
|
||||
|
||||
if (fp == NULL) {
|
||||
// Try looking inside game folder
|
||||
Common::File *f = new Common::File();
|
||||
if (!f->open(Common::Path(filename)))
|
||||
return fatal("No such file", filename); //TODO: false value
|
||||
fp = f;
|
||||
|
||||
// WORKAROUND: For Otto Experiment, when looking for the otto.ini
|
||||
// for the first time, include CRLF line ending to checker for both encoded and ASCII
|
||||
// data. This is needed since the original otto.ini that comes with the installer
|
||||
// have CRLF line ending.
|
||||
Common::String gameId = g_sludge->getGameId();
|
||||
if (gameId == "otto") {
|
||||
checker = _saveEncoding ? "[Custom data (encoded)]\r\n" : "[Custom data (ASCII)]\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
_encode1 = (byte)_saveEncoding & 255;
|
||||
_encode2 = (byte)(_saveEncoding >> 8);
|
||||
|
||||
for (uint i = 0; i < checker.size(); ++i) {
|
||||
if (fp->readByte() != checker[i]) {
|
||||
delete fp;
|
||||
return fatal(LOAD_ERROR "This isn't a SLUDGE custom data file:", filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (_saveEncoding) {
|
||||
checker = readStringEncoded(fp);
|
||||
if (checker != UTF8_CHECKER) {
|
||||
delete fp;
|
||||
return fatal(LOAD_ERROR "The current file encoding setting does not match the encoding setting used when this file was created:", filename);
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (_saveEncoding) {
|
||||
char i = fp->readByte() ^ _encode1;
|
||||
|
||||
if (fp->eos())
|
||||
break;
|
||||
switch (i) {
|
||||
case 0: {
|
||||
Common::String g = readStringEncoded(fp);
|
||||
stringVar.makeTextVar(g);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
stringVar.setVariable(SVT_INT, fp->readUint32LE());
|
||||
break;
|
||||
|
||||
case 2:
|
||||
stringVar.setVariable(SVT_INT, fp->readByte());
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal(LOAD_ERROR "Corrupt custom data file:", filename);
|
||||
delete fp;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
char *line = readTextPlain(fp);
|
||||
if (!line)
|
||||
break;
|
||||
stringVar.makeTextVar(line);
|
||||
}
|
||||
|
||||
if (sH->first == NULL) {
|
||||
// Adds to the TOP of the array... oops!
|
||||
if (!addVarToStackQuick(stringVar, sH->first))
|
||||
return false;
|
||||
sH->last = sH->first;
|
||||
} else {
|
||||
// Adds to the END of the array... much better
|
||||
if (!addVarToStackQuick(stringVar, sH->last->next))
|
||||
return false;
|
||||
sH->last = sH->last->next;
|
||||
}
|
||||
}
|
||||
|
||||
delete fp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CustomSaveHelper::stackToFile(const Common::String &filename, const Variable &from) {
|
||||
Common::OutSaveFile *fp = g_system->getSavefileManager()->openForSaving(filename);
|
||||
if (fp == NULL) {
|
||||
return fatal("Can't create file", filename);
|
||||
}
|
||||
|
||||
VariableStack *hereWeAre = from.varData.theStack -> first;
|
||||
|
||||
_encode1 = (byte)_saveEncoding & 255;
|
||||
_encode2 = (byte)(_saveEncoding >> 8);
|
||||
|
||||
if (_saveEncoding) {
|
||||
fp->writeString("[Custom data (encoded)]\r\n");
|
||||
writeStringEncoded(UTF8_CHECKER, fp);
|
||||
} else {
|
||||
fp->writeString("[Custom data (ASCII)]\n");
|
||||
}
|
||||
|
||||
while (hereWeAre) {
|
||||
if (_saveEncoding) {
|
||||
switch (hereWeAre -> thisVar.varType) {
|
||||
case SVT_STRING:
|
||||
fp->writeByte(_encode1);
|
||||
writeStringEncoded(hereWeAre -> thisVar.varData.theString, fp);
|
||||
break;
|
||||
|
||||
case SVT_INT:
|
||||
// Small enough to be stored as a char
|
||||
if (hereWeAre -> thisVar.varData.intValue >= 0 && hereWeAre -> thisVar.varData.intValue < 256) {
|
||||
fp->writeByte(2 ^ _encode1);
|
||||
fp->writeByte(hereWeAre -> thisVar.varData.intValue);
|
||||
} else {
|
||||
fp->writeByte(1 ^ _encode1);
|
||||
fp->writeUint32LE(hereWeAre -> thisVar.varData.intValue);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Can't create an encoded custom data file containing anything other than numbers and strings", filename);
|
||||
delete fp;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Common::String makeSureItsText = hereWeAre->thisVar.getTextFromAnyVar();
|
||||
|
||||
fp->writeString((makeSureItsText + "\n").c_str());
|
||||
}
|
||||
|
||||
hereWeAre = hereWeAre -> next;
|
||||
}
|
||||
|
||||
delete fp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
49
engines/sludge/savedata.h
Normal file
49
engines/sludge/savedata.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_SAVEDATA_H
|
||||
#define SLUDGE_SAVEDATA_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct StackHandler;
|
||||
struct Variable;
|
||||
|
||||
class CustomSaveHelper {
|
||||
public:
|
||||
static bool fileToStack(const Common::String &filename, StackHandler *sH);
|
||||
static bool stackToFile(const Common::String &filename, const Variable &from);
|
||||
|
||||
static uint16 _saveEncoding;
|
||||
|
||||
private:
|
||||
static const char UTF8_CHECKER[];
|
||||
static char _encode1;
|
||||
static char _encode2;
|
||||
|
||||
static void writeStringEncoded(const Common::String &checker, Common::WriteStream *stream);
|
||||
static Common::String readStringEncoded(Common::SeekableReadStream *fp);
|
||||
static char *readTextPlain(Common::SeekableReadStream *fp);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
357
engines/sludge/saveload.cpp
Normal file
357
engines/sludge/saveload.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
|
||||
#include "engines/metaengine.h"
|
||||
|
||||
#include "sludge/cursors.h"
|
||||
#include "sludge/errors.h"
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/floor.h"
|
||||
#include "sludge/fonttext.h"
|
||||
#include "sludge/function.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/language.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/region.h"
|
||||
#include "sludge/savedata.h"
|
||||
#include "sludge/saveload.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
#include "sludge/sound.h"
|
||||
#include "sludge/statusba.h"
|
||||
#include "sludge/speech.h"
|
||||
#include "sludge/version.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// From elsewhere
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
extern LoadedFunction *saverFunc; // In function.cpp
|
||||
extern LoadedFunction *allRunningFunctions; // In sludger.cpp
|
||||
extern int numGlobals; // In sludger.cpp
|
||||
extern Variable *globalVars; // In sludger.cpp
|
||||
extern FILETIME fileTime; // In sludger.cpp
|
||||
extern bool allowAnyFilename;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Save everything
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
bool handleSaveLoad() {
|
||||
if (!g_sludge->loadNow.empty()) {
|
||||
if (g_sludge->loadNow[0] == ':') {
|
||||
Common::String saveName = g_sludge->loadNow.c_str() + 1;
|
||||
uint extensionLength = saveName.size() - saveName.rfind('.');
|
||||
saveName = saveName.substr(0, saveName.size() - extensionLength);
|
||||
|
||||
int slot = -1;
|
||||
if (g_sludge->_saveNameToSlot.contains(saveName)) {
|
||||
slot = g_sludge->_saveNameToSlot[saveName];
|
||||
} else {
|
||||
// Find next available save slot
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
int maxSaveSlot = g_sludge->getMetaEngine()->getMaximumSaveSlot();
|
||||
int autosaveSlot = g_sludge->getMetaEngine()->getAutosaveSlot();
|
||||
for (int i = 0; i <= maxSaveSlot; ++i) {
|
||||
if (i == autosaveSlot)
|
||||
continue;
|
||||
const Common::String filename = g_sludge->getMetaEngine()->getSavegameFile(i, g_sludge->getTargetName().c_str());
|
||||
if (!saveFileMan->exists(filename)) {
|
||||
slot = i;
|
||||
break;
|
||||
} else {
|
||||
// If the game uses only one save for everything (like robinsresque)
|
||||
// use that save
|
||||
Common::InSaveFile *fp = g_system->getSavefileManager()->openForLoading(filename);
|
||||
ExtendedSavegameHeader header;
|
||||
if (MetaEngine::readSavegameHeader(fp, &header)) {
|
||||
if (saveName == header.description) {
|
||||
slot = i;
|
||||
g_sludge->_saveNameToSlot[saveName] = slot;
|
||||
delete fp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete fp;
|
||||
}
|
||||
}
|
||||
if (slot == -1) {
|
||||
slot = g_sludge->getMetaEngine()->getMaximumSaveSlot();
|
||||
}
|
||||
}
|
||||
|
||||
g_sludge->saveGameState(slot, saveName, false);
|
||||
saverFunc->reg.setVariable(SVT_INT, 1);
|
||||
} else {
|
||||
if (!loadGame(g_sludge->loadNow))
|
||||
return false;
|
||||
}
|
||||
g_sludge->loadNow.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool saveGame(Common::OutSaveFile *saveFile) {
|
||||
if (saveFile == NULL)
|
||||
return false;
|
||||
|
||||
saveFile->writeString("SLUDSA");
|
||||
saveFile->writeByte(0);
|
||||
saveFile->writeByte(0);
|
||||
saveFile->writeByte(MAJOR_VERSION);
|
||||
saveFile->writeByte(MINOR_VERSION);
|
||||
|
||||
if (!g_sludge->_gfxMan->saveThumbnail(saveFile))
|
||||
return false;
|
||||
|
||||
saveFile->write(&fileTime, sizeof(FILETIME));
|
||||
|
||||
// DON'T ADD ANYTHING NEW BEFORE THIS POINT!
|
||||
|
||||
saveFile->writeByte(allowAnyFilename);
|
||||
saveFile->writeByte(false); // deprecated captureAllKeys
|
||||
saveFile->writeByte(true);
|
||||
g_sludge->_txtMan->saveFont(saveFile);
|
||||
|
||||
// Save backdrop
|
||||
g_sludge->_gfxMan->saveBackdrop(saveFile);
|
||||
|
||||
// Save event handlers
|
||||
g_sludge->_evtMan->saveHandlers(saveFile);
|
||||
|
||||
// Save regions
|
||||
g_sludge->_regionMan->saveRegions(saveFile);
|
||||
|
||||
g_sludge->_cursorMan->saveCursor(saveFile);
|
||||
|
||||
// Save functions
|
||||
LoadedFunction *thisFunction = allRunningFunctions;
|
||||
int countFunctions = 0;
|
||||
while (thisFunction) {
|
||||
countFunctions++;
|
||||
thisFunction = thisFunction->next;
|
||||
}
|
||||
saveFile->writeUint16BE(countFunctions);
|
||||
|
||||
thisFunction = allRunningFunctions;
|
||||
while (thisFunction) {
|
||||
saveFunction(thisFunction, saveFile);
|
||||
thisFunction = thisFunction->next;
|
||||
}
|
||||
|
||||
for (int a = 0; a < numGlobals; a++) {
|
||||
globalVars[a].save(saveFile);
|
||||
}
|
||||
|
||||
g_sludge->_peopleMan->savePeople(saveFile);
|
||||
|
||||
g_sludge->_floorMan->save(saveFile);
|
||||
|
||||
g_sludge->_gfxMan->saveZBuffer(saveFile);
|
||||
g_sludge->_gfxMan->saveLightMap(saveFile);
|
||||
|
||||
g_sludge->_speechMan->save(saveFile);
|
||||
g_sludge->_statusBar->saveStatusBars(saveFile);
|
||||
g_sludge->_soundMan->saveSounds(saveFile);
|
||||
|
||||
saveFile->writeUint16BE(CustomSaveHelper::_saveEncoding);
|
||||
|
||||
g_sludge->_gfxMan->blur_saveSettings(saveFile);
|
||||
|
||||
g_sludge->_gfxMan->saveColors(saveFile);
|
||||
|
||||
g_sludge->_gfxMan->saveParallax(saveFile);
|
||||
saveFile->writeByte(0);
|
||||
|
||||
g_sludge->_languageMan->saveLanguageSetting(saveFile);
|
||||
|
||||
g_sludge->_gfxMan->saveSnapshot(saveFile);
|
||||
|
||||
clearStackLib();
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Load everything
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
int ssgVersion;
|
||||
|
||||
bool loadGame(const Common::String &fname) {
|
||||
Common::InSaveFile *fp = g_system->getSavefileManager()->openForLoading(fname);
|
||||
FILETIME savedGameTime;
|
||||
|
||||
while (allRunningFunctions)
|
||||
finishFunction(allRunningFunctions);
|
||||
|
||||
if (fp == NULL)
|
||||
return false;
|
||||
|
||||
bool headerBad = false;
|
||||
if (fp->readByte() != 'S')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'L')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'U')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'D')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'S')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'A')
|
||||
headerBad = true;
|
||||
if (headerBad) {
|
||||
fatal(ERROR_GAME_LOAD_NO, fname);
|
||||
return false;
|
||||
}
|
||||
char c;
|
||||
c = fp->readByte();
|
||||
while ((c = fp->readByte()))
|
||||
;
|
||||
|
||||
int majVersion = fp->readByte();
|
||||
int minVersion = fp->readByte();
|
||||
ssgVersion = VERSION(majVersion, minVersion);
|
||||
|
||||
if (ssgVersion >= VERSION(1, 4)) {
|
||||
if (!g_sludge->_gfxMan->skipThumbnail(fp))
|
||||
return fatal(ERROR_GAME_LOAD_CORRUPT, fname);
|
||||
}
|
||||
|
||||
uint32 bytes_read = fp->read(&savedGameTime, sizeof(FILETIME));
|
||||
if (bytes_read != sizeof(FILETIME) && fp->err()) {
|
||||
warning("Reading error in loadGame.");
|
||||
}
|
||||
|
||||
if (savedGameTime.dwLowDateTime != fileTime.dwLowDateTime || savedGameTime.dwHighDateTime != fileTime.dwHighDateTime) {
|
||||
return fatal(ERROR_GAME_LOAD_WRONG, fname);
|
||||
}
|
||||
|
||||
// DON'T ADD ANYTHING NEW BEFORE THIS POINT!
|
||||
|
||||
if (ssgVersion >= VERSION(1, 4)) {
|
||||
allowAnyFilename = fp->readByte();
|
||||
}
|
||||
fp->readByte(); // deprecated captureAllKeys
|
||||
fp->readByte(); // updateDisplay (part of movie playing)
|
||||
|
||||
g_sludge->_txtMan->loadFont(ssgVersion, fp);
|
||||
|
||||
g_sludge->_regionMan->kill();
|
||||
|
||||
g_sludge->_gfxMan->loadBackdrop(ssgVersion, fp);
|
||||
|
||||
g_sludge->_evtMan->loadHandlers(fp);
|
||||
|
||||
g_sludge->_regionMan->loadRegions(fp);
|
||||
|
||||
if (!g_sludge->_cursorMan->loadCursor(fp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LoadedFunction *rFunc;
|
||||
LoadedFunction **buildList = &allRunningFunctions;
|
||||
|
||||
int countFunctions = fp->readUint16BE();
|
||||
while (countFunctions--) {
|
||||
rFunc = loadFunction(fp);
|
||||
rFunc->next = NULL;
|
||||
(*buildList) = rFunc;
|
||||
buildList = &(rFunc->next);
|
||||
}
|
||||
|
||||
for (int a = 0; a < numGlobals; a++) {
|
||||
globalVars[a].unlinkVar();
|
||||
globalVars[a].load(fp);
|
||||
}
|
||||
|
||||
g_sludge->_peopleMan->loadPeople(fp);
|
||||
|
||||
if (!g_sludge->_floorMan->load(fp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!g_sludge->_gfxMan->loadZBuffer(fp))
|
||||
return false;
|
||||
|
||||
if (!g_sludge->_gfxMan->loadLightMap(ssgVersion, fp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_sludge->_speechMan->load(fp);
|
||||
g_sludge->_statusBar->loadStatusBars(fp);
|
||||
g_sludge->_soundMan->loadSounds(fp);
|
||||
|
||||
CustomSaveHelper::_saveEncoding = fp->readUint16BE();
|
||||
|
||||
if (ssgVersion >= VERSION(1, 6)) {
|
||||
if (ssgVersion < VERSION(2, 0)) {
|
||||
// aaLoad
|
||||
fp->readByte();
|
||||
fp->readFloatLE();
|
||||
fp->readFloatLE();
|
||||
}
|
||||
|
||||
g_sludge->_gfxMan->blur_loadSettings(fp);
|
||||
}
|
||||
|
||||
if (ssgVersion >= VERSION(1, 3)) {
|
||||
g_sludge->_gfxMan->loadColors(fp);
|
||||
|
||||
// Read parallax layers
|
||||
while (fp->readByte()) {
|
||||
int im = fp->readUint16BE();
|
||||
int fx = fp->readUint16BE();
|
||||
int fy = fp->readUint16BE();
|
||||
|
||||
if (!g_sludge->_gfxMan->loadParallax(im, fx, fy))
|
||||
return false;
|
||||
}
|
||||
|
||||
g_sludge->_languageMan->loadLanguageSetting(fp);
|
||||
}
|
||||
|
||||
g_sludge->_gfxMan->nosnapshot();
|
||||
if (ssgVersion >= VERSION(1, 4)) {
|
||||
if (fp->readByte()) {
|
||||
if (!g_sludge->_gfxMan->restoreSnapshot(fp))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ExtendedSavegameHeader header;
|
||||
if (MetaEngine::readSavegameHeader(fp, &header))
|
||||
g_sludge->setTotalPlayTime(header.playtime);
|
||||
|
||||
delete fp;
|
||||
|
||||
clearStackLib();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
36
engines/sludge/saveload.h
Normal file
36
engines/sludge/saveload.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_LOADSAVE_H
|
||||
#define SLUDGE_LOADSAVE_H
|
||||
|
||||
namespace Common {
|
||||
class OutSaveFile;
|
||||
}
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
bool handleSaveLoad();
|
||||
bool saveGame(Common::OutSaveFile *saveFile);
|
||||
bool loadGame(const Common::String &fname);
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
204
engines/sludge/sludge.cpp
Normal file
204
engines/sludge/sludge.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "common/config-manager.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/error.h"
|
||||
#include "common/random.h"
|
||||
#include "common/savefile.h"
|
||||
|
||||
#include "engines/metaengine.h"
|
||||
|
||||
#include "sludge/cursors.h"
|
||||
#include "sludge/debugger.h"
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/fonttext.h"
|
||||
#include "sludge/floor.h"
|
||||
#include "sludge/function.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/language.h"
|
||||
#include "sludge/main_loop.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/objtypes.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/region.h"
|
||||
#include "sludge/saveload.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sound.h"
|
||||
#include "sludge/speech.h"
|
||||
#include "sludge/statusba.h"
|
||||
#include "sludge/timing.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
extern LoadedFunction *allRunningFunctions; // In function.cpp
|
||||
|
||||
SludgeEngine *g_sludge;
|
||||
|
||||
Graphics::PixelFormat *SludgeEngine::getScreenPixelFormat() const { return _pixelFormat; }
|
||||
Graphics::PixelFormat *SludgeEngine::getOrigPixelFormat() const { return _origFormat; }
|
||||
|
||||
SludgeEngine::SludgeEngine(OSystem *syst, const SludgeGameDescription *gameDesc) :
|
||||
Engine(syst), _gameDescription(gameDesc) {
|
||||
|
||||
// register your random source
|
||||
_rnd = new Common::RandomSource("sludge");
|
||||
|
||||
//DebugMan.enableDebugChannel("loading");
|
||||
//DebugMan.enableDebugChannel("builtin");
|
||||
|
||||
_dumpScripts = ConfMan.getBool("dump_scripts");
|
||||
|
||||
// init graphics
|
||||
_origFormat = new Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
|
||||
_pixelFormat = new Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
||||
|
||||
// Init Strings
|
||||
launchNext = "";
|
||||
loadNow = "";
|
||||
gamePath = "";
|
||||
|
||||
// Init managers
|
||||
_timer = new Timer();
|
||||
_fatalMan = new FatalMsgManager();
|
||||
_peopleMan = new PeopleManager(this);
|
||||
_resMan = new ResourceManager();
|
||||
_languageMan = new LanguageManager();
|
||||
_objMan = new ObjectManager(this);
|
||||
_gfxMan = new GraphicsManager(this);
|
||||
_evtMan = new EventManager(this);
|
||||
_soundMan = new SoundManager();
|
||||
_txtMan = new TextManager();
|
||||
_cursorMan = new CursorManager(this);
|
||||
_speechMan = new SpeechManager(this);
|
||||
_regionMan = new RegionManager(this);
|
||||
_floorMan = new FloorManager(this);
|
||||
_statusBar = new StatusBarManager(this);
|
||||
}
|
||||
|
||||
SludgeEngine::~SludgeEngine() {
|
||||
|
||||
// Dispose resources
|
||||
delete _rnd;
|
||||
_rnd = nullptr;
|
||||
|
||||
// Dispose pixel formats
|
||||
delete _origFormat;
|
||||
_origFormat = nullptr;
|
||||
delete _pixelFormat;
|
||||
_pixelFormat = nullptr;
|
||||
|
||||
// Dispose managers
|
||||
delete _cursorMan;
|
||||
_cursorMan = nullptr;
|
||||
delete _txtMan;
|
||||
_txtMan = nullptr;
|
||||
delete _soundMan;
|
||||
_soundMan = nullptr;
|
||||
delete _evtMan;
|
||||
_evtMan = nullptr;
|
||||
delete _gfxMan;
|
||||
_gfxMan = nullptr;
|
||||
delete _objMan;
|
||||
_objMan = nullptr;
|
||||
delete _languageMan;
|
||||
_languageMan = nullptr;
|
||||
delete _resMan;
|
||||
_resMan = nullptr;
|
||||
delete _speechMan;
|
||||
_speechMan = nullptr;
|
||||
delete _regionMan;
|
||||
_regionMan = nullptr;
|
||||
delete _peopleMan;
|
||||
_peopleMan = nullptr;
|
||||
delete _floorMan;
|
||||
_floorMan = nullptr;
|
||||
delete _fatalMan;
|
||||
_fatalMan = nullptr;
|
||||
delete _statusBar;
|
||||
delete _timer;
|
||||
}
|
||||
|
||||
bool SludgeEngine::canLoadGameStateCurrently(Common::U32String *msg) {
|
||||
return !g_sludge->_evtMan->quit();
|
||||
}
|
||||
|
||||
bool SludgeEngine::canSaveGameStateCurrently(Common::U32String *msg) {
|
||||
if (g_sludge->_evtMan->quit())
|
||||
return false;
|
||||
|
||||
if (g_sludge->_gfxMan->isFrozen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Sludge::LoadedFunction *thisFunction = allRunningFunctions;
|
||||
while (thisFunction) {
|
||||
if (thisFunction->freezerLevel)
|
||||
return false;
|
||||
thisFunction = thisFunction->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::Error SludgeEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
||||
Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(getSaveStateName(slot));
|
||||
|
||||
if (!saveFile)
|
||||
return Common::kWritingFailed;
|
||||
|
||||
Common::Error result = saveGame(saveFile) ? Common::kNoError : Common::kWritingFailed;
|
||||
if (result.getCode() == Common::kNoError) {
|
||||
getMetaEngine()->appendExtendedSave(saveFile, getTotalPlayTime(), desc, isAutosave);
|
||||
|
||||
saveFile->finalize();
|
||||
}
|
||||
|
||||
delete saveFile;
|
||||
return result;
|
||||
}
|
||||
|
||||
Common::Error SludgeEngine::loadGameState(int slot) {
|
||||
saveAutosaveIfEnabled();
|
||||
|
||||
Common::Error result = loadGame(getSaveStateName(slot)) ? Common::kNoError : Common::kReadingFailed;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SludgeEngine::hasFeature(EngineFeature f) const {
|
||||
return (f == kSupportsReturnToLauncher) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
Common::Error SludgeEngine::run() {
|
||||
// set global variable
|
||||
g_sludge = this;
|
||||
|
||||
setDebugger(new Debugger(this));
|
||||
|
||||
// debug log
|
||||
main_loop(getGameFile());
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
138
engines/sludge/sludge.h
Normal file
138
engines/sludge/sludge.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_SLUDGE_H
|
||||
#define SLUDGE_SLUDGE_H
|
||||
|
||||
#include "common/hash-str.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Common {
|
||||
class RandomSource;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
struct PixelFormat;
|
||||
}
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class CursorManager;
|
||||
class EventManager;
|
||||
class FatalMsgManager;
|
||||
class FloorManager;
|
||||
class GraphicsManager;
|
||||
class LanguageManager;
|
||||
class ObjectManager;
|
||||
class PeopleManager;
|
||||
class ResourceManager;
|
||||
class RegionManager;
|
||||
class SoundManager;
|
||||
class SpeechManager;
|
||||
class StatusBarManager;
|
||||
class TextManager;
|
||||
class Timer;
|
||||
|
||||
struct SludgeGameDescription;
|
||||
|
||||
#define IN_THE_CENTRE 65535
|
||||
|
||||
// debug channels
|
||||
enum {
|
||||
kSludgeDebugFatal = 1,
|
||||
kSludgeDebugDataLoad,
|
||||
kSludgeDebugStackMachine,
|
||||
kSludgeDebugBuiltin,
|
||||
kSludgeDebugGraphics,
|
||||
kSludgeDebugZBuffer,
|
||||
kSludgeDebugSound,
|
||||
};
|
||||
|
||||
class SludgeEngine: public Engine {
|
||||
protected:
|
||||
// Engine APIs
|
||||
Common::Error run() override;
|
||||
|
||||
public:
|
||||
// global String variables
|
||||
Common::String launchNext;
|
||||
Common::String loadNow;
|
||||
Common::String gamePath;
|
||||
|
||||
// timer
|
||||
Timer *_timer;
|
||||
|
||||
// managers
|
||||
ResourceManager *_resMan;
|
||||
LanguageManager *_languageMan;
|
||||
ObjectManager *_objMan;
|
||||
GraphicsManager *_gfxMan;
|
||||
EventManager *_evtMan;
|
||||
SoundManager *_soundMan;
|
||||
TextManager *_txtMan;
|
||||
CursorManager *_cursorMan;
|
||||
SpeechManager *_speechMan;
|
||||
RegionManager *_regionMan;
|
||||
PeopleManager *_peopleMan;
|
||||
FloorManager *_floorMan;
|
||||
FatalMsgManager *_fatalMan;
|
||||
StatusBarManager *_statusBar;
|
||||
|
||||
bool _dumpScripts;
|
||||
|
||||
SludgeEngine(OSystem *syst, const SludgeGameDescription *gameDesc);
|
||||
~SludgeEngine() override;
|
||||
|
||||
uint getLanguageID() const;
|
||||
const char *getGameId() const;
|
||||
uint32 getFeatures() const;
|
||||
Common::String getTargetName() const { return _targetName; }
|
||||
Common::Language getLanguage() const;
|
||||
Graphics::PixelFormat *getScreenPixelFormat() const;
|
||||
Graphics::PixelFormat *getOrigPixelFormat() const;
|
||||
Common::RandomSource *getRandomSource() const { return _rnd; };
|
||||
|
||||
const char *getGameFile() const;
|
||||
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
|
||||
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave) override;
|
||||
Common::Error loadGameState(int slot) override;
|
||||
|
||||
const SludgeGameDescription *_gameDescription;
|
||||
|
||||
Common::HashMap<Common::String, int> _saveNameToSlot;
|
||||
|
||||
private:
|
||||
Common::RandomSource *_rnd;
|
||||
Graphics::PixelFormat *_pixelFormat;
|
||||
Graphics::PixelFormat *_origFormat;
|
||||
};
|
||||
|
||||
extern SludgeEngine *g_sludge;
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
306
engines/sludge/sludger.cpp
Normal file
306
engines/sludge/sludger.cpp
Normal file
@@ -0,0 +1,306 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "sludge/cursors.h"
|
||||
#include "sludge/errors.h"
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/fonttext.h"
|
||||
#include "sludge/floor.h"
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/function.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/imgloader.h"
|
||||
#include "sludge/language.h"
|
||||
#include "sludge/moreio.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/objtypes.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/region.h"
|
||||
#include "sludge/savedata.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
#include "sludge/sound.h"
|
||||
#include "sludge/speech.h"
|
||||
#include "sludge/statusba.h"
|
||||
#include "sludge/timing.h"
|
||||
#include "sludge/version.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
extern int numBIFNames;
|
||||
extern Common::String *allBIFNames;
|
||||
extern int numUserFunc;
|
||||
extern Common::String *allUserFunc;
|
||||
|
||||
int selectedLanguage = 0;
|
||||
|
||||
int gameVersion;
|
||||
FILETIME fileTime;
|
||||
|
||||
int numGlobals = 0;
|
||||
|
||||
extern Variable *globalVars;
|
||||
extern VariableStack *noStack;
|
||||
|
||||
extern bool allowAnyFilename;
|
||||
|
||||
Common::File *openAndVerify(const Common::String &filename, char extra1, char extra2,
|
||||
const char *er, int &fileVersion) {
|
||||
Common::File *fp = new Common::File();
|
||||
if (!fp->open(Common::Path(filename))) {
|
||||
fatal("Can't open file", filename);
|
||||
return NULL;
|
||||
}
|
||||
bool headerBad = false;
|
||||
if (fp->readByte() != 'S')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'L')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'U')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'D')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != extra1)
|
||||
headerBad = true;
|
||||
if (fp->readByte() != extra2)
|
||||
headerBad = true;
|
||||
if (headerBad) {
|
||||
fatal(er, filename);
|
||||
return NULL;
|
||||
}
|
||||
char c;
|
||||
c = fp->readByte();
|
||||
while ((c = fp->readByte()))
|
||||
;
|
||||
|
||||
int majVersion = fp->readByte();
|
||||
debugC(2, kSludgeDebugDataLoad, "majVersion %i", majVersion);
|
||||
int minVersion = fp->readByte();
|
||||
debugC(2, kSludgeDebugDataLoad, "minVersion %i", minVersion);
|
||||
fileVersion = majVersion * 256 + minVersion;
|
||||
|
||||
Common::String txtVer = "";
|
||||
|
||||
if (fileVersion > WHOLE_VERSION) {
|
||||
txtVer = Common::String::format(ERROR_VERSION_TOO_LOW_2, majVersion, minVersion);
|
||||
fatal(ERROR_VERSION_TOO_LOW_1, txtVer);
|
||||
return NULL;
|
||||
} else if (fileVersion < MINIM_VERSION) {
|
||||
txtVer = Common::String::format(ERROR_VERSION_TOO_HIGH_2, majVersion, minVersion);
|
||||
fatal(ERROR_VERSION_TOO_HIGH_1, txtVer);
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
void initSludge() {
|
||||
g_sludge->_timer->reset();
|
||||
g_sludge->_languageMan->init();
|
||||
g_sludge->_gfxMan->init();
|
||||
g_sludge->_resMan->init();
|
||||
g_sludge->_peopleMan->init();
|
||||
g_sludge->_floorMan->init();
|
||||
g_sludge->_objMan->init();
|
||||
g_sludge->_speechMan->init();
|
||||
g_sludge->_statusBar->init();
|
||||
g_sludge->_evtMan->init();
|
||||
g_sludge->_txtMan->init();
|
||||
g_sludge->_cursorMan->init();
|
||||
|
||||
g_sludge->_soundMan->init();
|
||||
if (!ConfMan.hasKey("mute") || !ConfMan.getBool("mute")) {
|
||||
g_sludge->_soundMan->initSoundStuff();
|
||||
}
|
||||
|
||||
CustomSaveHelper::_saveEncoding = false;
|
||||
|
||||
// global variables
|
||||
numGlobals = 0;
|
||||
|
||||
allowAnyFilename = true;
|
||||
noStack = nullptr;
|
||||
numBIFNames = numUserFunc = 0;
|
||||
allUserFunc = allBIFNames = nullptr;
|
||||
}
|
||||
|
||||
void killSludge() {
|
||||
killAllFunctions();
|
||||
g_sludge->_speechMan->kill();
|
||||
g_sludge->_peopleMan->kill();
|
||||
g_sludge->_regionMan->kill();
|
||||
g_sludge->_floorMan->kill();
|
||||
g_sludge->_languageMan->kill();
|
||||
g_sludge->_gfxMan->kill();
|
||||
g_sludge->_resMan->kill();
|
||||
g_sludge->_objMan->kill();
|
||||
g_sludge->_soundMan->killSoundStuff();
|
||||
g_sludge->_evtMan->kill();
|
||||
g_sludge->_txtMan->kill();
|
||||
g_sludge->_cursorMan->kill();
|
||||
|
||||
// global variables
|
||||
numBIFNames = numUserFunc = 0;
|
||||
delete []allUserFunc;
|
||||
delete []allBIFNames;
|
||||
}
|
||||
|
||||
bool initSludge(const Common::String &filename) {
|
||||
initSludge();
|
||||
|
||||
Common::File *fp = openAndVerify(filename, 'G', 'E', ERROR_BAD_HEADER, gameVersion);
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
char c = fp->readByte();
|
||||
if (c) {
|
||||
numBIFNames = fp->readUint16BE();
|
||||
debugC(2, kSludgeDebugDataLoad, "numBIFNames %i", numBIFNames);
|
||||
allBIFNames = new Common::String[numBIFNames];
|
||||
if (!checkNew(allBIFNames)) {
|
||||
delete fp;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int fn = 0; fn < numBIFNames; fn++) {
|
||||
allBIFNames[fn].clear();
|
||||
allBIFNames[fn] = readString(fp);
|
||||
}
|
||||
numUserFunc = fp->readUint16BE();
|
||||
debugC(2, kSludgeDebugDataLoad, "numUserFunc %i", numUserFunc);
|
||||
allUserFunc = new Common::String[numUserFunc];
|
||||
if (!checkNew(allUserFunc)) {
|
||||
delete fp;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int fn = 0; fn < numUserFunc; fn++) {
|
||||
allUserFunc[fn].clear();
|
||||
allUserFunc[fn] = readString(fp);
|
||||
}
|
||||
|
||||
if (gameVersion >= VERSION(1, 3)) {
|
||||
g_sludge->_resMan->readResourceNames(fp);
|
||||
}
|
||||
}
|
||||
|
||||
int winWidth = fp->readUint16BE();
|
||||
debugC(2, kSludgeDebugDataLoad, "winWidth : %i", winWidth);
|
||||
int winHeight = fp->readUint16BE();
|
||||
debugC(2, kSludgeDebugDataLoad, "winHeight : %i", winHeight);
|
||||
g_sludge->_gfxMan->setWindowSize(winWidth, winHeight);
|
||||
|
||||
int specialSettings = fp->readByte();
|
||||
debugC(2, kSludgeDebugDataLoad, "specialSettings : %i", specialSettings);
|
||||
g_sludge->_timer->setDesiredFPS(1000 / fp->readByte());
|
||||
|
||||
readString(fp); // Unused - was used for registration purposes.
|
||||
|
||||
uint bytes_read = fp->read(&fileTime, sizeof(FILETIME));
|
||||
if (bytes_read != sizeof(FILETIME) && fp->err()) {
|
||||
debug(0, "Reading error in initSludge.");
|
||||
}
|
||||
|
||||
Common::String dataFol = (gameVersion >= VERSION(1, 3)) ? readString(fp) : "";
|
||||
debugC(2, kSludgeDebugDataLoad, "dataFol : %s", dataFol.c_str());
|
||||
|
||||
g_sludge->_languageMan->createTable(fp);
|
||||
|
||||
if (gameVersion >= VERSION(1, 6)) {
|
||||
fp->readByte();
|
||||
// aaLoad
|
||||
fp->readByte();
|
||||
fp->readFloatLE();
|
||||
fp->readFloatLE();
|
||||
}
|
||||
|
||||
Common::String checker = readString(fp);
|
||||
debugC(2, kSludgeDebugDataLoad, "checker : %s", checker.c_str());
|
||||
|
||||
if (checker != "okSoFar")
|
||||
return fatal(ERROR_BAD_HEADER, filename);
|
||||
|
||||
byte customIconLogo = fp->readByte();
|
||||
debugC(2, kSludgeDebugDataLoad, "Game icon type: %i", customIconLogo);
|
||||
|
||||
if (customIconLogo & 1) {
|
||||
// There is an icon - read it!
|
||||
debugC(2, kSludgeDebugDataLoad, "There is an icon - read it!");
|
||||
|
||||
// read game icon
|
||||
Graphics::Surface gameIcon;
|
||||
if (!ImgLoader::loadImage(-1, "icon", fp, &gameIcon, false)) {
|
||||
delete fp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (customIconLogo & 2) {
|
||||
// There is a logo - read it!
|
||||
debugC(2, kSludgeDebugDataLoad, "There is a logo - read it!");
|
||||
|
||||
// read game logo
|
||||
Graphics::Surface gameLogo;
|
||||
if (!ImgLoader::loadImage(-1, "logo", fp, &gameLogo)) {
|
||||
delete fp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
numGlobals = fp->readUint16BE();
|
||||
debugC(2, kSludgeDebugDataLoad, "numGlobals : %i", numGlobals);
|
||||
|
||||
globalVars = new Variable[numGlobals];
|
||||
if (!checkNew(globalVars)) {
|
||||
delete fp;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get language selected by user
|
||||
g_sludge->_resMan->setData(fp);
|
||||
g_sludge->_languageMan->setLanguageID(g_sludge->getLanguageID());
|
||||
|
||||
if (!dataFol.empty()) {
|
||||
Common::String dataFolder = encodeFilename(dataFol);
|
||||
}
|
||||
|
||||
g_sludge->_statusBar->positionStatus(10, winHeight - 15);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void displayBase() {
|
||||
g_sludge->_gfxMan->clear(); // Clear screen
|
||||
g_sludge->_gfxMan->drawBackDrop();// Draw Backdrop
|
||||
g_sludge->_gfxMan->drawZBuffer(g_sludge->_gfxMan->getCamX(), g_sludge->_gfxMan->getCamY(), false);
|
||||
g_sludge->_peopleMan->drawPeople();// Then add any moving characters...
|
||||
}
|
||||
|
||||
void sludgeDisplay() {
|
||||
displayBase();
|
||||
g_sludge->_speechMan->display();
|
||||
g_sludge->_statusBar->draw();
|
||||
g_sludge->_cursorMan->displayCursor();
|
||||
g_sludge->_gfxMan->display();
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
44
engines/sludge/sludger.h
Normal file
44
engines/sludge/sludger.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGER_H
|
||||
#define SLUDGER_H
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
typedef struct _FILETIME {
|
||||
uint32 dwLowDateTime;
|
||||
uint32 dwHighDateTime;
|
||||
} FILETIME;
|
||||
|
||||
bool initSludge(const Common::String &);
|
||||
void initSludge();
|
||||
void killSludge();
|
||||
|
||||
void displayBase();
|
||||
void sludgeDisplay();
|
||||
|
||||
Common::File *openAndVerify(const Common::String &filename, char extra1, char extra2, const char *er, int &fileVersion);
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
606
engines/sludge/sound.cpp
Normal file
606
engines/sludge/sound.cpp
Normal file
@@ -0,0 +1,606 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "audio/decoders/wave.h"
|
||||
#include "audio/decoders/mp3.h"
|
||||
#include "audio/decoders/vorbis.h"
|
||||
#include "audio/mods/mod_xm_s3m.h"
|
||||
#include "audio/mods/universaltracker.h"
|
||||
|
||||
#include "sludge/errors.h"
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sound.h"
|
||||
#include "sludge/variable.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
const int SoundManager::MAX_SAMPLES = 8;
|
||||
const int SoundManager::MAX_MODS = 3;
|
||||
|
||||
SoundManager::SoundManager() {
|
||||
_soundCache = nullptr;
|
||||
_soundCache = new SoundThing[MAX_SAMPLES];
|
||||
|
||||
_modCache = nullptr;
|
||||
_modCache = new SoundThing[MAX_MODS];
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
SoundManager::~SoundManager() {
|
||||
killSoundStuff();
|
||||
|
||||
delete []_soundCache;
|
||||
_soundCache = nullptr;
|
||||
|
||||
delete []_modCache;
|
||||
_modCache = nullptr;
|
||||
}
|
||||
|
||||
void SoundManager::init() {
|
||||
// there's possibility that several sound list played at the same time
|
||||
_soundListHandles.clear();
|
||||
|
||||
_soundOK = false;
|
||||
_silenceIKillYou = false;
|
||||
_isHandlingSoundList = false;
|
||||
|
||||
_defVol = 128;
|
||||
_defSoundVol = 255;
|
||||
_modLoudness = 0.95f;
|
||||
|
||||
_emptySoundSlot = 0;
|
||||
}
|
||||
|
||||
bool SoundManager::initSoundStuff() {
|
||||
for (int a = 0; a < MAX_SAMPLES; ++a) {
|
||||
_soundCache[a].fileLoaded = -1;
|
||||
_soundCache[a].looping = false;
|
||||
_soundCache[a].inSoundList = false;
|
||||
}
|
||||
|
||||
for (int a = 0; a < MAX_MODS; ++a) {
|
||||
_modCache[a].fileLoaded = -1;
|
||||
_modCache[a].looping = false;
|
||||
_modCache[a].inSoundList = false;
|
||||
}
|
||||
|
||||
return _soundOK = true;
|
||||
}
|
||||
|
||||
void SoundManager::killSoundStuff() {
|
||||
if (!_soundOK)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < MAX_SAMPLES; ++i)
|
||||
freeSound(i);
|
||||
|
||||
for (int i = 0; i < MAX_MODS; ++i)
|
||||
stopMOD(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some setters:
|
||||
*/
|
||||
void SoundManager::setMusicVolume(int a, int v) {
|
||||
if (!_soundOK)
|
||||
return;
|
||||
|
||||
if (g_sludge->_mixer->isSoundHandleActive(_modCache[a].handle)) {
|
||||
_modCache[a].vol = v;
|
||||
g_sludge->_mixer->setChannelVolume(_modCache[a].handle, _modLoudness * v);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::setDefaultMusicVolume(int v) {
|
||||
_defVol = v;
|
||||
}
|
||||
|
||||
void SoundManager::setSoundVolume(int a, int v) {
|
||||
if (!_soundOK)
|
||||
return;
|
||||
int ch = findInSoundCache(a);
|
||||
if (ch != -1) {
|
||||
if (g_sludge->_mixer->isSoundHandleActive(_soundCache[ch].handle)) {
|
||||
_soundCache[ch].vol = v;
|
||||
g_sludge->_mixer->setChannelVolume(_soundCache[ch].handle, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::setDefaultSoundVolume(int v) {
|
||||
_defSoundVol = v;
|
||||
}
|
||||
|
||||
void SoundManager::setSoundLoop(int a, int s, int e) {
|
||||
//#pragma unused (a,s,e)
|
||||
}
|
||||
|
||||
int SoundManager::findInSoundCache(int a) {
|
||||
int i;
|
||||
for (i = 0; i < MAX_SAMPLES; i++) {
|
||||
if (_soundCache[i].fileLoaded == a) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SoundManager::stopMOD(int i) {
|
||||
if (!_soundOK)
|
||||
return;
|
||||
|
||||
if (_modCache[i].fileLoaded >= 0) {
|
||||
if (g_sludge->_mixer->isSoundHandleActive(_modCache[i].handle)) {
|
||||
g_sludge->_mixer->stopHandle(_modCache[i].handle);
|
||||
}
|
||||
}
|
||||
_modCache[i].fileLoaded = -1;
|
||||
}
|
||||
|
||||
void SoundManager::huntKillSound(int filenum) {
|
||||
if (!_soundOK)
|
||||
return;
|
||||
|
||||
int gotSlot = findInSoundCache(filenum);
|
||||
if (gotSlot == -1)
|
||||
return;
|
||||
|
||||
freeSound(gotSlot);
|
||||
}
|
||||
|
||||
void SoundManager::freeSound(int a) {
|
||||
if (!_soundOK)
|
||||
return;
|
||||
|
||||
_silenceIKillYou = true;
|
||||
if (_soundCache[a].fileLoaded >= 0) {
|
||||
if (g_sludge->_mixer->isSoundHandleActive(_soundCache[a].handle)) {
|
||||
g_sludge->_mixer->stopHandle(_soundCache[a].handle);
|
||||
if (_soundCache[a].inSoundList)
|
||||
handleSoundLists();
|
||||
}
|
||||
}
|
||||
|
||||
_soundCache[a].inSoundList = false;
|
||||
_soundCache[a].looping = false;
|
||||
_soundCache[a].fileLoaded = -1;
|
||||
|
||||
_silenceIKillYou = false;
|
||||
}
|
||||
|
||||
void SoundManager::huntKillFreeSound(int filenum) {
|
||||
if (!_soundOK)
|
||||
return;
|
||||
int gotSlot = findInSoundCache(filenum);
|
||||
if (gotSlot == -1)
|
||||
return;
|
||||
freeSound(gotSlot);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loading and playing:
|
||||
*/
|
||||
bool SoundManager::playMOD(int f, int a, int fromTrack) {
|
||||
if (!_soundOK)
|
||||
return true;
|
||||
stopMOD(a);
|
||||
|
||||
// load sound
|
||||
setResourceForFatal(f);
|
||||
uint length = g_sludge->_resMan->openFileFromNum(f);
|
||||
if (length == 0) {
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_sludge->_resMan->dumpFile(f, "music%04d.xm");
|
||||
|
||||
// make audio stream
|
||||
Common::SeekableReadStream *readStream = g_sludge->_resMan->getData();
|
||||
Common::SeekableReadStream *memImage = readStream->readStream(length);
|
||||
|
||||
if (memImage->size() != (int)length || readStream->err()) {
|
||||
return fatal("SoundManager::playMOD(): Sound reading failed");
|
||||
}
|
||||
Audio::RewindableAudioStream *mod = nullptr;
|
||||
|
||||
if (Audio::probeModXmS3m(memImage)) {
|
||||
mod = Audio::makeModXmS3mStream(memImage, DisposeAfterUse::NO, fromTrack);
|
||||
if (mod) {
|
||||
delete memImage;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mod) {
|
||||
mod = Audio::makeUniversalTrackerStream(memImage, DisposeAfterUse::YES);
|
||||
}
|
||||
|
||||
if (!mod) {
|
||||
warning("Could not load MOD file");
|
||||
g_sludge->_resMan->finishAccess();
|
||||
return false;
|
||||
}
|
||||
|
||||
Audio::LoopingAudioStream *stream = new Audio::LoopingAudioStream(mod, 0, DisposeAfterUse::YES, false);
|
||||
|
||||
if (stream) {
|
||||
// play sound
|
||||
_modCache[a].fileLoaded = f;
|
||||
_modCache[a].vol = _defVol;
|
||||
g_sludge->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_modCache[a].handle, stream, -1, _modCache[a].vol);
|
||||
} else {
|
||||
_modCache[a].fileLoaded = -1;
|
||||
}
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoundManager::stillPlayingSound(int ch) {
|
||||
if (_soundOK)
|
||||
if (ch != -1)
|
||||
if (_soundCache[ch].fileLoaded != -1)
|
||||
if (g_sludge->_mixer->isSoundHandleActive(_soundCache[ch].handle))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SoundManager::forceRemoveSound() {
|
||||
for (int a = 0; a < MAX_SAMPLES; a++) {
|
||||
if (_soundCache[a].fileLoaded != -1) {
|
||||
freeSound(a);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SoundManager::findEmptySoundSlot() {
|
||||
for (int t = 0; t < MAX_SAMPLES; t++) {
|
||||
_emptySoundSlot++;
|
||||
_emptySoundSlot %= MAX_SAMPLES;
|
||||
if (!g_sludge->_mixer->isSoundHandleActive(_soundCache[_emptySoundSlot].handle) && !_soundCache[_emptySoundSlot].inSoundList)
|
||||
return _emptySoundSlot;
|
||||
}
|
||||
|
||||
// Argh! They're all playing! Let's trash the oldest that's not looping...
|
||||
|
||||
for (int t = 0; t < MAX_SAMPLES; t++) {
|
||||
_emptySoundSlot++;
|
||||
_emptySoundSlot %= MAX_SAMPLES;
|
||||
if (!_soundCache[_emptySoundSlot].looping && !_soundCache[_emptySoundSlot].inSoundList)
|
||||
return _emptySoundSlot;
|
||||
}
|
||||
|
||||
// Holy crap, they're all looping! What's this twat playing at?
|
||||
|
||||
_emptySoundSlot++;
|
||||
_emptySoundSlot %= MAX_SAMPLES;
|
||||
return _emptySoundSlot;
|
||||
}
|
||||
|
||||
int SoundManager::cacheSound(int f) {
|
||||
return 0; // don't load source in advance
|
||||
}
|
||||
|
||||
int SoundManager::makeSoundAudioStream(int f, Audio::AudioStream *&audiostream, bool loopy) {
|
||||
if (!_soundOK)
|
||||
return -1;
|
||||
|
||||
int a = findInSoundCache(f);
|
||||
if (a == -1) {
|
||||
if (f == -2)
|
||||
return -1;
|
||||
a = findEmptySoundSlot();
|
||||
}
|
||||
freeSound(a);
|
||||
|
||||
setResourceForFatal(f);
|
||||
uint32 length = g_sludge->_resMan->openFileFromNum(f);
|
||||
if (!length)
|
||||
return -1;
|
||||
|
||||
g_sludge->_resMan->dumpFile(f, "sound%04d.ogg");
|
||||
|
||||
Common::SeekableReadStream *readStream = g_sludge->_resMan->getData();
|
||||
uint curr_ptr = readStream->pos();
|
||||
|
||||
uint32 tag = readStream->readUint32BE();
|
||||
readStream->seek(curr_ptr);
|
||||
|
||||
Audio::RewindableAudioStream *stream = nullptr;
|
||||
switch (tag) {
|
||||
case MKTAG('R','I','F','F'):
|
||||
stream = Audio::makeWAVStream(readStream->readStream(length), DisposeAfterUse::YES);
|
||||
break;
|
||||
case MKTAG('O','g','g','S'):
|
||||
#ifdef USE_VORBIS
|
||||
stream = Audio::makeVorbisStream(readStream->readStream(length), DisposeAfterUse::YES);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
// TODO: Detect this correctly
|
||||
#ifdef USE_MAD
|
||||
stream = Audio::makeMP3Stream(readStream->readStream(length), DisposeAfterUse::YES);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
|
||||
if (stream) {
|
||||
audiostream = Audio::makeLoopingAudioStream(stream, loopy ? 0 : 1);
|
||||
_soundCache[a].fileLoaded = f;
|
||||
_soundCache[a].looping = loopy;
|
||||
setResourceForFatal(-1);
|
||||
} else {
|
||||
audiostream = nullptr;
|
||||
warning("SoundManager::makeSoundAudioStream(): Unsupported sound format %s", tag2str(tag));
|
||||
_soundCache[a].fileLoaded = -1;
|
||||
_soundCache[a].looping = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
bool SoundManager::startSound(int f, bool loopy) {
|
||||
if (_soundOK) {
|
||||
// Load sound
|
||||
Audio::AudioStream *stream = nullptr;
|
||||
int a = makeSoundAudioStream(f, stream, loopy);
|
||||
if (a == -1) {
|
||||
warning("Failed to cache sound!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// play sound
|
||||
_soundCache[a].looping = loopy;
|
||||
_soundCache[a].vol = _defSoundVol;
|
||||
g_sludge->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundCache[a].handle, stream, -1, _soundCache[a].vol);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SoundManager::saveSounds(Common::WriteStream *stream) {
|
||||
if (_soundOK) {
|
||||
for (int i = 0; i < MAX_SAMPLES; i++) {
|
||||
if (_soundCache[i].looping) {
|
||||
stream->writeByte(1);
|
||||
stream->writeUint16BE(_soundCache[i].fileLoaded);
|
||||
stream->writeUint16BE(_soundCache[i].vol);
|
||||
}
|
||||
}
|
||||
}
|
||||
stream->writeByte(0);
|
||||
stream->writeUint16BE(_defSoundVol);
|
||||
stream->writeUint16BE(_defVol);
|
||||
}
|
||||
|
||||
void SoundManager::loadSounds(Common::SeekableReadStream *stream) {
|
||||
for (int i = 0; i < MAX_SAMPLES; i++)
|
||||
freeSound(i);
|
||||
|
||||
while (stream->readByte()) {
|
||||
int fileLoaded = stream->readUint16BE();
|
||||
_defSoundVol = stream->readUint16BE();
|
||||
startSound(fileLoaded, 1);
|
||||
}
|
||||
|
||||
_defSoundVol = stream->readUint16BE();
|
||||
_defVol = stream->readUint16BE();
|
||||
}
|
||||
|
||||
bool SoundManager::getSoundCacheStack(StackHandler *sH) {
|
||||
Variable newFileHandle;
|
||||
newFileHandle.varType = SVT_NULL;
|
||||
|
||||
for (int a = 0; a < MAX_SAMPLES; a++) {
|
||||
if (_soundCache[a].fileLoaded != -1) {
|
||||
newFileHandle.setVariable(SVT_FILE, _soundCache[a].fileLoaded);
|
||||
if (!addVarToStackQuick(newFileHandle, sH->first))
|
||||
return false;
|
||||
if (sH->last == NULL)
|
||||
sH->last = sH->first;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoundManager::deleteSoundFromList(SoundList*&s) {
|
||||
// Don't delete a playing sound.
|
||||
if (s->cacheIndex)
|
||||
return false;
|
||||
|
||||
SoundList*o = NULL;
|
||||
if (!s->next) {
|
||||
o = s->prev;
|
||||
if (o)
|
||||
o->next = NULL;
|
||||
delete s;
|
||||
s = o;
|
||||
return (s != NULL);
|
||||
}
|
||||
if (s != s->next) {
|
||||
o = s->next;
|
||||
o->prev = s->prev;
|
||||
if (o->prev)
|
||||
o->prev->next = o;
|
||||
}
|
||||
delete s;
|
||||
s = o;
|
||||
return (s != NULL);
|
||||
}
|
||||
|
||||
void SoundManager::handleSoundLists() {
|
||||
if (_isHandlingSoundList)
|
||||
return;
|
||||
_isHandlingSoundList = true;
|
||||
for (SoundListHandles::iterator it = _soundListHandles.begin(); it != _soundListHandles.end(); ++it) {
|
||||
SoundList*s = (*it);
|
||||
int a = s->cacheIndex;
|
||||
bool remove = false;
|
||||
if (!g_sludge->_mixer->isSoundHandleActive(_soundCache[a].handle)) { // reach the end of stream
|
||||
s->cacheIndex = false;
|
||||
_soundCache[a].inSoundList = false;
|
||||
if (_silenceIKillYou) {
|
||||
while (deleteSoundFromList(s))
|
||||
;
|
||||
remove = (s == NULL); // s not null if still playing
|
||||
} else {
|
||||
if (s->next) {
|
||||
if (s->next == s) { // loop the same sound
|
||||
int v = _defSoundVol;
|
||||
_defSoundVol = _soundCache[a].vol;
|
||||
startSound(s->sound, true);
|
||||
_defSoundVol = v;
|
||||
while (deleteSoundFromList(s))
|
||||
;
|
||||
remove = (s == NULL); // s not null if still playing
|
||||
} else { // repush the next sound list
|
||||
s->next->vol = _soundCache[a].vol;
|
||||
playSoundList(s->next);
|
||||
remove = true; // remove this one
|
||||
}
|
||||
|
||||
} else {
|
||||
while (deleteSoundFromList(s))
|
||||
;
|
||||
remove = (s == NULL); // s not null if still playing
|
||||
}
|
||||
}
|
||||
}
|
||||
if (remove) {
|
||||
it = _soundListHandles.reverse_erase(it);
|
||||
}
|
||||
}
|
||||
_isHandlingSoundList = false;
|
||||
}
|
||||
|
||||
// loop a list of sound
|
||||
void SoundManager::playSoundList(SoundList*s) {
|
||||
if (_soundOK) {
|
||||
// Load sound
|
||||
Audio::AudioStream *stream;
|
||||
int a = makeSoundAudioStream(s->sound, stream, false);
|
||||
if (a == -1) {
|
||||
warning("Failed to cache sound!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Play sound
|
||||
_soundCache[a].looping = false;
|
||||
if (s->vol < 0)
|
||||
_soundCache[a].vol = _defSoundVol;
|
||||
else
|
||||
_soundCache[a].vol = s->vol;
|
||||
s-> cacheIndex = a;
|
||||
g_sludge->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundCache[a].handle, stream, -1, _soundCache[a].vol);
|
||||
_soundCache[a].inSoundList = true;
|
||||
|
||||
// push sound list
|
||||
_soundListHandles.push_back(s);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void playMovieStream(int a) {
|
||||
#if 0
|
||||
if (! soundOK) return;
|
||||
ALboolean ok;
|
||||
ALuint src;
|
||||
|
||||
alGenSources(1, &src);
|
||||
if (alGetError() != AL_NO_ERROR) {
|
||||
debugOut("Failed to create OpenAL source!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
alSourcef(src, AL_GAIN, (float) soundCache[a].vol / 256);
|
||||
|
||||
ok = alurePlaySourceStream(src, soundCache[a].stream,
|
||||
10, 0, sound_eos_callback, &intpointers[a]);
|
||||
if (!ok) {
|
||||
debugOut("Failed to play stream: %s\n", alureGetErrorString());
|
||||
alDeleteSources(1, &src);
|
||||
if (alGetError() != AL_NO_ERROR) {
|
||||
debugOut("Failed to delete OpenAL source!\n");
|
||||
}
|
||||
|
||||
soundCache[a].playingOnSource = 0;
|
||||
} else {
|
||||
soundCache[a].playingOnSource = src;
|
||||
soundCache[a].playing = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
int initMovieSound(int f, ALenum format, int audioChannels, ALuint samplerate,
|
||||
ALuint(*callback)(void *userdata, ALubyte *data, ALuint bytes)) {
|
||||
if (! soundOK) return 0;
|
||||
|
||||
int retval;
|
||||
int a = findEmptySoundSlot();
|
||||
freeSound(a);
|
||||
|
||||
soundCache[a].looping = false;
|
||||
#if 0
|
||||
// audioChannel * sampleRate gives us a buffer of half a second. Not much, but it should be enough.
|
||||
soundCache[a].stream = alureCreateStreamFromCallback(
|
||||
callback,
|
||||
&intpointers[a], format, samplerate,
|
||||
audioChannels * samplerate, 0, NULL);
|
||||
#endif
|
||||
if (soundCache[a].stream != NULL) {
|
||||
soundCache[a].fileLoaded = f;
|
||||
soundCache[a].vol = defSoundVol;
|
||||
retval = a;
|
||||
} else {
|
||||
#if 0
|
||||
debugOut("Failed to create stream from sound: %s\n",
|
||||
alureGetErrorString());
|
||||
#endif
|
||||
warning(ERROR_SOUND_ODDNESS);
|
||||
soundCache[a].stream = NULL;
|
||||
soundCache[a].playing = false;
|
||||
soundCache[a].playingOnSource = 0;
|
||||
soundCache[a].fileLoaded = -1;
|
||||
retval = -1;
|
||||
}
|
||||
//fprintf (stderr, "Stream %d created. Sample rate: %d Channels: %d\n", retval, samplerate, audioChannels);
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint SoundManager::getSoundSource(int index) {
|
||||
warning("getSoundSource, Unimplemented");
|
||||
return 0; /*soundCache[index].playingOnSource;*/
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
124
engines/sludge/sound.h
Normal file
124
engines/sludge/sound.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SLUDGE_SOUND_H
|
||||
#define SLUDGE_SOUND_H
|
||||
|
||||
#include "common/list.h"
|
||||
|
||||
#include "audio/mixer.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
class WriteStream;
|
||||
}
|
||||
|
||||
//#include "sludge/variable.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct StackHandler;
|
||||
|
||||
// Sound list stuff
|
||||
struct SoundList{
|
||||
int sound;
|
||||
struct SoundList*next;
|
||||
struct SoundList*prev;
|
||||
int cacheIndex;
|
||||
int vol;
|
||||
};
|
||||
|
||||
class SoundManager {
|
||||
public:
|
||||
SoundManager();
|
||||
virtual ~SoundManager();
|
||||
|
||||
// Sound list
|
||||
void playSoundList(SoundList*s);
|
||||
void handleSoundLists(); // to produce the same effects as end of stream call back functions
|
||||
|
||||
// GENERAL...
|
||||
void init();
|
||||
bool initSoundStuff();
|
||||
void killSoundStuff();
|
||||
|
||||
// MUSIC...
|
||||
bool playMOD(int, int, int);
|
||||
void stopMOD(int);
|
||||
void setMusicVolume(int a, int v);
|
||||
void setDefaultMusicVolume(int v);
|
||||
|
||||
// SAMPLES...
|
||||
int cacheSound(int f);
|
||||
bool startSound(int, bool = false);
|
||||
void huntKillSound(int a);
|
||||
void huntKillFreeSound(int filenum);
|
||||
void setSoundVolume(int a, int v);
|
||||
void setDefaultSoundVolume(int v);
|
||||
void setSoundLoop(int a, int s, int e);
|
||||
bool stillPlayingSound(int ch);
|
||||
bool getSoundCacheStack(StackHandler *sH);
|
||||
int findInSoundCache(int a);
|
||||
|
||||
// Load & save
|
||||
void loadSounds(Common::SeekableReadStream *stream);
|
||||
void saveSounds(Common::WriteStream *stream);
|
||||
|
||||
uint getSoundSource(int index);
|
||||
|
||||
private:
|
||||
const static int MAX_SAMPLES;
|
||||
const static int MAX_MODS;
|
||||
|
||||
struct SoundThing {
|
||||
Audio::SoundHandle handle;
|
||||
int fileLoaded, vol; //Used for wav/ogg sounds only. (sound saving/loading)
|
||||
bool looping; //Used for wav/ogg sounds only. (sound saving/loading)
|
||||
bool inSoundList; //Used for wav/ogg sounds only
|
||||
};
|
||||
typedef Common::List<SoundList *> SoundListHandles;
|
||||
|
||||
// there's possibility that several sound list played at the same time
|
||||
SoundListHandles _soundListHandles;
|
||||
|
||||
bool _soundOK;
|
||||
bool _silenceIKillYou;
|
||||
bool _isHandlingSoundList;
|
||||
|
||||
SoundThing *_soundCache;
|
||||
SoundThing *_modCache;
|
||||
|
||||
int _defVol;
|
||||
int _defSoundVol;
|
||||
float _modLoudness;
|
||||
|
||||
int _emptySoundSlot;
|
||||
|
||||
void freeSound(int a);
|
||||
bool forceRemoveSound();
|
||||
bool deleteSoundFromList(SoundList*&s);
|
||||
int findEmptySoundSlot();
|
||||
int makeSoundAudioStream(int f, Audio::AudioStream *&audiostream, bool loopy);
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
297
engines/sludge/speech.cpp
Normal file
297
engines/sludge/speech.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
#include "sludge/fonttext.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/freeze.h"
|
||||
#include "sludge/moreio.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/objtypes.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/region.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sludger.h"
|
||||
#include "sludge/sound.h"
|
||||
#include "sludge/speech.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
void SpeechManager::init() {
|
||||
_speechMode = 0;
|
||||
_speechSpeed = 1;
|
||||
_speech = new SpeechStruct;
|
||||
if (checkNew(_speech)) {
|
||||
_speech->currentTalker = NULL;
|
||||
_speech->allSpeech.clear();
|
||||
_speech->speechY = 0;
|
||||
_speech->lastFile = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void SpeechManager::kill() {
|
||||
if (!_speech)
|
||||
return;
|
||||
|
||||
if (_speech->lastFile != -1) {
|
||||
_vm->_soundMan->huntKillSound(_speech->lastFile);
|
||||
_speech->lastFile = -1;
|
||||
}
|
||||
|
||||
if (_speech->currentTalker) {
|
||||
_speech->currentTalker->makeSilent();
|
||||
_speech->currentTalker = nullptr;
|
||||
}
|
||||
|
||||
for (SpeechLineList::iterator it = _speech->allSpeech.begin(); it != _speech->allSpeech.end(); ++it) {
|
||||
SpeechLine *killMe = *it;
|
||||
delete killMe;
|
||||
killMe = nullptr;
|
||||
}
|
||||
_speech->allSpeech.clear();
|
||||
}
|
||||
|
||||
void SpeechManager::setObjFontColour(ObjectType *t) {
|
||||
_speech->talkCol.setColor(t->r, t->g, t->b);
|
||||
}
|
||||
|
||||
void SpeechManager::addSpeechLine(const Common::String &theLine, int x, int &offset) {
|
||||
float cameraZoom = g_sludge->_gfxMan->getCamZoom();
|
||||
int halfWidth = (g_sludge->_txtMan->stringWidth(theLine) >> 1) / cameraZoom;
|
||||
int xx1 = x - (halfWidth);
|
||||
int xx2 = x + (halfWidth);
|
||||
|
||||
// Create new speech line
|
||||
SpeechLine *newLine = new SpeechLine;
|
||||
checkNew(newLine);
|
||||
newLine->textLine.clear();
|
||||
newLine->textLine = theLine;
|
||||
newLine->x = xx1;
|
||||
_speech->allSpeech.push_front(newLine);
|
||||
|
||||
// Calculate offset
|
||||
if ((xx1 < 5) && (offset < (5 - xx1))) {
|
||||
offset = 5 - xx1;
|
||||
} else if ((xx2 >= ((float) g_system->getWidth() / cameraZoom) - 5)
|
||||
&& (offset > (((float) g_system->getWidth() / cameraZoom) - 5 - xx2))) {
|
||||
offset = ((float) g_system->getWidth() / cameraZoom) - 5 - xx2;
|
||||
}
|
||||
}
|
||||
|
||||
int SpeechManager::isThereAnySpeechGoingOn() {
|
||||
return _speech->allSpeech.empty() ? -1 : _speech->lookWhosTalking;
|
||||
}
|
||||
|
||||
int SpeechManager::getLastSpeechSound() {
|
||||
return _vm->_soundMan->findInSoundCache(_speech->lastFile);
|
||||
}
|
||||
|
||||
int SpeechManager::wrapSpeechXY(const Common::String &theText, int x, int y, int wrap, int sampleFile) {
|
||||
float cameraZoom = g_sludge->_gfxMan->getCamZoom();
|
||||
int fontHeight = g_sludge->_txtMan->getFontHeight();
|
||||
int cameraY = g_sludge->_gfxMan->getCamY();
|
||||
|
||||
int a, offset = 0;
|
||||
|
||||
kill();
|
||||
|
||||
int speechTime = (theText.size() + 20) * _speechSpeed;
|
||||
if (speechTime < 1)
|
||||
speechTime = 1;
|
||||
if (sampleFile != -1) {
|
||||
if (_speechMode >= 1) {
|
||||
if (g_sludge->_soundMan->startSound(sampleFile, false)) {
|
||||
speechTime = -10;
|
||||
_speech->lastFile = sampleFile;
|
||||
if (_speechMode == 2) return -10;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
_speech->speechY = y;
|
||||
|
||||
char *tmp, *txt;
|
||||
tmp = txt = createCString(theText);
|
||||
while ((int)strlen(txt) > wrap) {
|
||||
a = wrap;
|
||||
while (txt[a] != ' ') {
|
||||
a--;
|
||||
if (a == 0) {
|
||||
a = wrap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
txt[a] = 0;
|
||||
addSpeechLine(txt, x, offset);
|
||||
txt[a] = ' ';
|
||||
txt += a + 1;
|
||||
y -= fontHeight / cameraZoom;
|
||||
}
|
||||
addSpeechLine(txt, x, offset);
|
||||
y -= fontHeight / cameraZoom;
|
||||
delete []tmp;
|
||||
|
||||
if (y < 0)
|
||||
_speech->speechY -= y;
|
||||
else if (_speech->speechY > cameraY + (float) (g_system->getHeight() - fontHeight / 3) / cameraZoom)
|
||||
_speech->speechY = cameraY
|
||||
+ (float) (g_system->getHeight() - fontHeight / 3) / cameraZoom;
|
||||
|
||||
if (offset) {
|
||||
for (SpeechLineList::iterator it = _speech->allSpeech.begin(); it != _speech->allSpeech.end(); ++it) {
|
||||
(*it)->x += offset;
|
||||
}
|
||||
}
|
||||
return speechTime;
|
||||
}
|
||||
|
||||
int SpeechManager::wrapSpeechPerson(const Common::String &theText, OnScreenPerson &thePerson, int sampleFile, bool animPerson) {
|
||||
int cameraX = g_sludge->_gfxMan->getCamX();
|
||||
int cameraY = g_sludge->_gfxMan->getCamY();
|
||||
int i = wrapSpeechXY(theText, thePerson.x - cameraX,
|
||||
thePerson.y - cameraY
|
||||
- (thePerson.scale * (thePerson.height - thePerson.floaty))
|
||||
- thePerson.thisType->speechGap,
|
||||
thePerson.thisType->wrapSpeech, sampleFile);
|
||||
if (animPerson) {
|
||||
thePerson.makeTalker();
|
||||
_speech->currentTalker = &thePerson;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int SpeechManager::wrapSpeech(const Common::String &theText, int objT, int sampleFile, bool animPerson) {
|
||||
int i;
|
||||
int cameraX = g_sludge->_gfxMan->getCamX();
|
||||
int cameraY = g_sludge->_gfxMan->getCamY();
|
||||
|
||||
_speech->lookWhosTalking = objT;
|
||||
OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(objT);
|
||||
if (thisPerson) {
|
||||
setObjFontColour(thisPerson->thisType);
|
||||
i = wrapSpeechPerson(theText, *thisPerson, sampleFile, animPerson);
|
||||
} else {
|
||||
ScreenRegion *thisRegion = g_sludge->_regionMan->getRegionForObject(objT);
|
||||
if (thisRegion) {
|
||||
setObjFontColour(thisRegion->thisType);
|
||||
i = wrapSpeechXY(theText,
|
||||
((thisRegion->x1 + thisRegion->x2) >> 1) - cameraX,
|
||||
thisRegion->y1 - thisRegion->thisType->speechGap - cameraY,
|
||||
thisRegion->thisType->wrapSpeech, sampleFile);
|
||||
} else {
|
||||
ObjectType *temp = g_sludge->_objMan->findObjectType(objT);
|
||||
setObjFontColour(temp);
|
||||
i = wrapSpeechXY(theText, g_system->getWidth() >> 1, 10, temp->wrapSpeech,
|
||||
sampleFile);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void SpeechManager::display() {
|
||||
float cameraZoom = g_sludge->_gfxMan->getCamZoom();
|
||||
int fontHeight = g_sludge->_txtMan->getFontHeight();
|
||||
int viewY = _speech->speechY;
|
||||
for (SpeechLineList::iterator it = _speech->allSpeech.begin(); it != _speech->allSpeech.end(); ++it) {
|
||||
g_sludge->_txtMan->pasteString((*it)->textLine, (*it)->x, viewY, _speech->talkCol);
|
||||
viewY -= fontHeight / cameraZoom;
|
||||
}
|
||||
}
|
||||
|
||||
void SpeechManager::save(Common::WriteStream *stream) {
|
||||
stream->writeByte(_speechMode);
|
||||
stream->writeByte(_speech->talkCol.originalRed);
|
||||
stream->writeByte(_speech->talkCol.originalGreen);
|
||||
stream->writeByte(_speech->talkCol.originalBlue);
|
||||
|
||||
stream->writeFloatLE(_speechSpeed);
|
||||
|
||||
// Write y co-ordinate
|
||||
stream->writeUint16BE(_speech->speechY);
|
||||
|
||||
// Write which character's talking
|
||||
stream->writeUint16BE(_speech->lookWhosTalking);
|
||||
if (_speech->currentTalker) {
|
||||
stream->writeByte(1);
|
||||
stream->writeUint16BE(_speech->currentTalker->thisType->objectNum);
|
||||
} else {
|
||||
stream->writeByte(0);
|
||||
}
|
||||
|
||||
// Write what's being said
|
||||
for (SpeechLineList::iterator it = _speech->allSpeech.begin(); it != _speech->allSpeech.end(); ++it) {
|
||||
stream->writeByte(1);
|
||||
writeString((*it)->textLine, stream);
|
||||
stream->writeUint16BE((*it)->x);
|
||||
}
|
||||
stream->writeByte(0);
|
||||
}
|
||||
|
||||
bool SpeechManager::load(Common::SeekableReadStream *stream) {
|
||||
// read speech mode
|
||||
_speechMode = stream->readByte();
|
||||
|
||||
_speech->currentTalker = nullptr;
|
||||
kill();
|
||||
byte r = stream->readByte();
|
||||
byte g = stream->readByte();
|
||||
byte b = stream->readByte();
|
||||
_speech->talkCol.setColor(r, g, b);
|
||||
_speechSpeed = stream->readFloatLE();
|
||||
|
||||
// Read y co-ordinate
|
||||
_speech->speechY = stream->readUint16BE();
|
||||
|
||||
// Read which character's talking
|
||||
_speech->lookWhosTalking = stream->readUint16BE();
|
||||
|
||||
if (stream->readByte()) {
|
||||
_speech->currentTalker = g_sludge->_peopleMan->findPerson(stream->readUint16BE());
|
||||
} else {
|
||||
_speech->currentTalker = NULL;
|
||||
}
|
||||
|
||||
// Read what's being said
|
||||
_speech->lastFile = -1;
|
||||
while (stream->readByte()) {
|
||||
SpeechLine *newOne = new SpeechLine;
|
||||
if (!checkNew(newOne))
|
||||
return false;
|
||||
newOne->textLine = readString(stream);
|
||||
newOne->x = stream->readUint16BE();
|
||||
_speech->allSpeech.push_back(newOne);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpeechManager::freeze(FrozenStuffStruct *frozenStuff) {
|
||||
frozenStuff->speech = _speech;
|
||||
init();
|
||||
}
|
||||
|
||||
void SpeechManager::restore(FrozenStuffStruct *frozenStuff) {
|
||||
kill();
|
||||
delete _speech;
|
||||
_speech = frozenStuff->speech;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
86
engines/sludge/speech.h
Normal file
86
engines/sludge/speech.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_TALK_H
|
||||
#define SLUDGE_TALK_H
|
||||
|
||||
#include "sludge/sprites.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct ObjectType;
|
||||
|
||||
struct SpeechLine {
|
||||
Common::String textLine;
|
||||
int x;
|
||||
};
|
||||
|
||||
typedef Common::List<SpeechLine *> SpeechLineList;
|
||||
|
||||
struct SpeechStruct {
|
||||
OnScreenPerson *currentTalker;
|
||||
SpeechLineList allSpeech;
|
||||
int speechY, lastFile, lookWhosTalking;
|
||||
SpritePalette talkCol;
|
||||
};
|
||||
|
||||
class SpeechManager {
|
||||
public:
|
||||
SpeechManager(SludgeEngine *vm) : _vm(vm) { init(); }
|
||||
~SpeechManager() { kill(); }
|
||||
|
||||
void init();
|
||||
void kill();
|
||||
|
||||
int wrapSpeech(const Common::String &theText, int objT, int sampleFile, bool);
|
||||
void display();
|
||||
|
||||
int isThereAnySpeechGoingOn();
|
||||
bool isCurrentTalker(OnScreenPerson *person) { return person == _speech->currentTalker; }
|
||||
int getLastSpeechSound();
|
||||
|
||||
// setters & getters
|
||||
void setObjFontColour(ObjectType *t);
|
||||
void setSpeechSpeed(float speed) { _speechSpeed = speed; }
|
||||
float getSpeechSpeed() { return _speechSpeed; }
|
||||
void setSpeechMode(int speechMode) { _speechMode = speechMode; }
|
||||
|
||||
// load & save
|
||||
void save(Common::WriteStream *stream);
|
||||
bool load(Common::SeekableReadStream *stream);
|
||||
|
||||
// freeze & restore
|
||||
void freeze(FrozenStuffStruct *frozenStuff);
|
||||
void restore(FrozenStuffStruct *frozenStuff);
|
||||
|
||||
private:
|
||||
SludgeEngine *_vm;
|
||||
int _speechMode;
|
||||
SpeechStruct *_speech;
|
||||
float _speechSpeed;
|
||||
|
||||
void addSpeechLine(const Common::String &theLine, int x, int &offset);
|
||||
int wrapSpeechXY(const Common::String &theText, int x, int y, int wrap, int sampleFile);
|
||||
int wrapSpeechPerson(const Common::String &theText, OnScreenPerson &thePerson, int sampleFile, bool animPerson);
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
54
engines/sludge/sprbanks.cpp
Normal file
54
engines/sludge/sprbanks.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sludge.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
LoadedSpriteBank *GraphicsManager::loadBankForAnim(int ID) {
|
||||
// Check if already exist
|
||||
LoadedSpriteBanks::iterator it;
|
||||
for (it = _allLoadedBanks.begin(); it != _allLoadedBanks.end(); ++it) {
|
||||
if ((*it)->ID == ID) {
|
||||
return (*it);
|
||||
}
|
||||
}
|
||||
|
||||
// Else create a new sprite bank
|
||||
LoadedSpriteBank *returnMe = new LoadedSpriteBank;
|
||||
if (checkNew(returnMe)) {
|
||||
returnMe->ID = ID;
|
||||
if (loadSpriteBank(ID, returnMe->bank, false)) {
|
||||
returnMe->timesUsed = 0;
|
||||
debugC(3, kSludgeDebugDataLoad, "loadBankForAnim: New sprite bank created OK");
|
||||
_allLoadedBanks.push_back(returnMe);
|
||||
return returnMe;
|
||||
} else {
|
||||
debugC(3, kSludgeDebugDataLoad, "loadBankForAnim: I guess I couldn't load the sprites...");
|
||||
return nullptr;
|
||||
}
|
||||
} else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
36
engines/sludge/sprbanks.h
Normal file
36
engines/sludge/sprbanks.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_SPRBANKS_H
|
||||
#define SLUDGE_SPRBANKS_H
|
||||
|
||||
#include "sludge/sprites.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct LoadedSpriteBank {
|
||||
int ID, timesUsed;
|
||||
SpriteBank bank;
|
||||
};
|
||||
typedef Common::List<LoadedSpriteBank *> LoadedSpriteBanks;
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
599
engines/sludge/sprites.cpp
Normal file
599
engines/sludge/sprites.cpp
Normal file
@@ -0,0 +1,599 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sludge/event.h"
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/imgloader.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/zbuffer.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
// This function is only used to kill text font
|
||||
void GraphicsManager::forgetSpriteBank(SpriteBank &forgetme) {
|
||||
// kill the sprite bank
|
||||
if (forgetme.myPalette.pal) {
|
||||
delete[] forgetme.myPalette.pal;
|
||||
forgetme.myPalette.pal = NULL;
|
||||
delete[] forgetme.myPalette.r;
|
||||
forgetme.myPalette.r = NULL;
|
||||
delete[] forgetme.myPalette.g;
|
||||
forgetme.myPalette.g = NULL;
|
||||
delete[] forgetme.myPalette.b;
|
||||
forgetme.myPalette.b = NULL;
|
||||
}
|
||||
|
||||
if (forgetme.sprites) {
|
||||
for (int i = 0; i < forgetme.total; ++i) {
|
||||
forgetme.sprites[i].surface.free();
|
||||
forgetme.sprites[i].burnSurface.free();
|
||||
}
|
||||
|
||||
delete []forgetme.sprites;
|
||||
forgetme.sprites = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsManager::reserveSpritePal(SpritePalette &sP, int n) {
|
||||
if (sP.pal) {
|
||||
delete[] sP.pal;
|
||||
delete[] sP.r;
|
||||
delete[] sP.g;
|
||||
delete[] sP.b;
|
||||
}
|
||||
|
||||
sP.pal = new uint16[n];
|
||||
if (!checkNew(sP.pal))
|
||||
return false;
|
||||
|
||||
sP.r = new byte[n];
|
||||
if (!checkNew(sP.r))
|
||||
return false;
|
||||
sP.g = new byte[n];
|
||||
if (!checkNew(sP.g))
|
||||
return false;
|
||||
sP.b = new byte[n];
|
||||
if (!checkNew(sP.b))
|
||||
return false;
|
||||
sP.total = n;
|
||||
return (bool)(sP.pal != NULL) && (sP.r != NULL) && (sP.g != NULL) && (sP.b != NULL);
|
||||
}
|
||||
|
||||
bool GraphicsManager::loadSpriteBank(int fileNum, SpriteBank &loadhere, bool isFont) {
|
||||
|
||||
int total, spriteBankVersion = 0, howmany = 0, startIndex = 0;
|
||||
byte *data;
|
||||
|
||||
setResourceForFatal(fileNum);
|
||||
if (!g_sludge->_resMan->openFileFromNum(fileNum))
|
||||
return fatal("Can't open sprite bank / font");
|
||||
|
||||
g_sludge->_resMan->dumpFile(fileNum, "bank%04d.duc");
|
||||
|
||||
loadhere.isFont = isFont;
|
||||
|
||||
Common::SeekableReadStream *readStream = g_sludge->_resMan->getData();
|
||||
total = readStream->readUint16BE();
|
||||
if (!total) {
|
||||
spriteBankVersion = readStream->readByte();
|
||||
if (spriteBankVersion == 1) {
|
||||
total = 0;
|
||||
} else {
|
||||
total = readStream->readUint16BE();
|
||||
}
|
||||
}
|
||||
|
||||
if (total <= 0)
|
||||
return fatal("No sprites in bank or invalid sprite bank file");
|
||||
if (spriteBankVersion > 3)
|
||||
return fatal("Unsupported sprite bank file format");
|
||||
|
||||
loadhere.total = total;
|
||||
loadhere.sprites = new Sprite[total];
|
||||
if (!checkNew(loadhere.sprites))
|
||||
return false;
|
||||
byte **spriteData = new byte *[total];
|
||||
if (!checkNew(spriteData))
|
||||
return false;
|
||||
|
||||
// version 1, 2, read how many now
|
||||
if (spriteBankVersion && spriteBankVersion < 3) {
|
||||
howmany = readStream->readByte();
|
||||
startIndex = 1;
|
||||
}
|
||||
|
||||
// version 3, sprite is png
|
||||
if (spriteBankVersion == 3) {
|
||||
debugC(2, kSludgeDebugGraphics, "png sprite");
|
||||
for (int i = 0; i < total; i++) {
|
||||
loadhere.sprites[i].xhot = readStream->readSint16LE();
|
||||
loadhere.sprites[i].yhot = readStream->readSint16LE();
|
||||
if (!ImgLoader::loadPNGImage(readStream, &loadhere.sprites[i].surface, false)) {
|
||||
return fatal("fail to read png sprite");
|
||||
}
|
||||
}
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// version 0, 1, 2
|
||||
for (int i = 0; i < total; i++) {
|
||||
uint picwidth, picheight;
|
||||
// load sprite width, height, relative position
|
||||
if (spriteBankVersion == 2) {
|
||||
picwidth = readStream->readUint16BE();
|
||||
picheight = readStream->readUint16BE();
|
||||
loadhere.sprites[i].xhot = readStream->readSint16LE();
|
||||
loadhere.sprites[i].yhot = readStream->readSint16LE();
|
||||
} else {
|
||||
picwidth = (byte)readStream->readByte();
|
||||
picheight = (byte)readStream->readByte();
|
||||
loadhere.sprites[i].xhot = readStream->readByte();
|
||||
loadhere.sprites[i].yhot = readStream->readByte();
|
||||
}
|
||||
|
||||
// init data
|
||||
loadhere.sprites[i].surface.create(picwidth, picheight, *g_sludge->getScreenPixelFormat());
|
||||
if (isFont) {
|
||||
loadhere.sprites[i].burnSurface.create(picwidth, picheight, *g_sludge->getScreenPixelFormat());
|
||||
}
|
||||
data = (byte *)new byte[picwidth * (picheight + 1)];
|
||||
if (!checkNew(data))
|
||||
return false;
|
||||
memset(data + picwidth * picheight, 0, picwidth);
|
||||
spriteData[i] = data;
|
||||
|
||||
// read color
|
||||
if (spriteBankVersion == 2) { // RUN LENGTH COMPRESSED DATA
|
||||
uint size = picwidth * picheight;
|
||||
uint pip = 0;
|
||||
|
||||
while (pip < size) {
|
||||
byte col = readStream->readByte();
|
||||
int looper;
|
||||
if (col > howmany) {
|
||||
col -= howmany + 1;
|
||||
looper = readStream->readByte() + 1;
|
||||
} else
|
||||
looper = 1;
|
||||
|
||||
while (looper--) {
|
||||
data[pip++] = col;
|
||||
}
|
||||
}
|
||||
} else { // RAW DATA
|
||||
uint bytes_read = readStream->read(data, picwidth * picheight);
|
||||
if (bytes_read != picwidth * picheight && readStream->err()) {
|
||||
warning("Reading error in loadSpriteBank.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read howmany for version 0
|
||||
if (!spriteBankVersion) {
|
||||
howmany = readStream->readByte();
|
||||
startIndex = readStream->readByte();
|
||||
}
|
||||
|
||||
// Make palette for version 0, 1, 2
|
||||
if (!reserveSpritePal(loadhere.myPalette, howmany + startIndex))
|
||||
return false;
|
||||
for (int i = 0; i < howmany; i++) {
|
||||
loadhere.myPalette.r[i + startIndex] = (byte)readStream->readByte();
|
||||
loadhere.myPalette.g[i + startIndex] = (byte)readStream->readByte();
|
||||
loadhere.myPalette.b[i + startIndex] = (byte)readStream->readByte();
|
||||
loadhere.myPalette.pal[i + startIndex] =
|
||||
(uint16)g_sludge->getOrigPixelFormat()->RGBToColor(
|
||||
loadhere.myPalette.r[i + startIndex],
|
||||
loadhere.myPalette.g[i + startIndex],
|
||||
loadhere.myPalette.b[i + startIndex]);
|
||||
}
|
||||
loadhere.myPalette.originalRed = loadhere.myPalette.originalGreen = loadhere.myPalette.originalBlue = 255;
|
||||
|
||||
// convert
|
||||
for (int i = 0; i < total; i++) {
|
||||
int fromhere = 0;
|
||||
int transColour = -1;
|
||||
int size = loadhere.sprites[i].surface.w * loadhere.sprites[i].surface.h;
|
||||
while (fromhere < size) {
|
||||
byte s = spriteData[i][fromhere++];
|
||||
if (s) {
|
||||
transColour = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fromhere = 0;
|
||||
for (int y = 0; y < loadhere.sprites[i].surface.h; y++) {
|
||||
for (int x = 0; x < loadhere.sprites[i].surface.w; x++) {
|
||||
byte *target = (byte *)loadhere.sprites[i].surface.getBasePtr(x, y);
|
||||
byte s = spriteData[i][fromhere++];
|
||||
if (s) {
|
||||
target[0] = (byte)255;
|
||||
target[1] = (byte)loadhere.myPalette.b[s];
|
||||
target[2] = (byte)loadhere.myPalette.g[s];
|
||||
target[3] = (byte)loadhere.myPalette.r[s];
|
||||
transColour = s;
|
||||
} else if (transColour >= 0) {
|
||||
target[0] = (byte)0;
|
||||
target[1] = (byte)loadhere.myPalette.b[transColour];
|
||||
target[2] = (byte)loadhere.myPalette.g[transColour];
|
||||
target[3] = (byte)loadhere.myPalette.r[transColour];
|
||||
}
|
||||
if (isFont) {
|
||||
target = (byte *)loadhere.sprites[i].burnSurface.getBasePtr(x, y);
|
||||
if (s)
|
||||
target[0] = loadhere.myPalette.r[s];
|
||||
target[1] = (byte)255;
|
||||
target[2] = (byte)255;
|
||||
target[3] = (byte)255;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] spriteData[i];
|
||||
}
|
||||
delete[] spriteData;
|
||||
spriteData = NULL;
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
|
||||
setResourceForFatal(-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// pasteSpriteToBackDrop uses the colour specified by the setPasteColour (or setPasteColor)
|
||||
void GraphicsManager::pasteSpriteToBackDrop(int x1, int y1, Sprite &single, const SpritePalette &fontPal) {
|
||||
if (!single.surface.w || !single.surface.h) {
|
||||
// Skip surfaces with a 0 width/height (e.g. the space character on Out of Order) to avoid crashes in the blitting code.
|
||||
return;
|
||||
}
|
||||
|
||||
// kill zBuffer
|
||||
if (_zBuffer->originalNum >= 0 && _zBuffer->tex) {
|
||||
int num = _zBuffer->originalNum;
|
||||
killZBuffer();
|
||||
_zBuffer->originalNum = num;
|
||||
}
|
||||
|
||||
x1 -= single.xhot;
|
||||
y1 -= single.yhot;
|
||||
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(single.surface);
|
||||
tmp.blendBlitTo(_backdropSurface, x1, y1, Graphics::FLIP_NONE, nullptr, MS_RGB(fontPal.originalRed, fontPal.originalGreen, fontPal.originalBlue));
|
||||
|
||||
}
|
||||
|
||||
// burnSpriteToBackDrop adds text in the colour specified by setBurnColour
|
||||
// using the differing brightness levels of the font to achieve an anti-aliasing effect.
|
||||
void GraphicsManager::burnSpriteToBackDrop(int x1, int y1, Sprite &single, const SpritePalette &fontPal) {
|
||||
if (!single.burnSurface.w || !single.burnSurface.h) {
|
||||
// Skip surfaces with a 0 width/height (e.g. the space character on Out of Order) to avoid crashes in the blitting code.
|
||||
return;
|
||||
}
|
||||
|
||||
// kill zBuffer
|
||||
if (_zBuffer->originalNum >= 0 && _zBuffer->tex) {
|
||||
int num = _zBuffer->originalNum;
|
||||
killZBuffer();
|
||||
_zBuffer->originalNum = num;
|
||||
}
|
||||
|
||||
x1 -= single.xhot;
|
||||
y1 -= single.yhot - 1;
|
||||
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(single.burnSurface);
|
||||
tmp.blendBlitTo(_backdropSurface, x1, y1, Graphics::FLIP_NONE, nullptr,
|
||||
MS_RGB(_currentBurnR, _currentBurnG, _currentBurnB));
|
||||
}
|
||||
|
||||
void GraphicsManager::fontSprite(bool flip, int x, int y, Sprite &single, const SpritePalette &fontPal) {
|
||||
if (!single.surface.w || !single.surface.h) {
|
||||
// Skip surfaces with a 0 width/height (e.g. the space character on Out of Order) to avoid crashes in the blitting code.
|
||||
return;
|
||||
}
|
||||
|
||||
float x1 = (float)x - (float)single.xhot / _cameraZoom;
|
||||
float y1 = (float)y - (float)single.yhot / _cameraZoom;
|
||||
|
||||
// Use Managed surface to scale and blit
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(single.surface);
|
||||
tmp.blendBlitTo(_renderSurface, x1, y1, (flip ? Graphics::FLIP_H : Graphics::FLIP_NONE), 0, MS_RGB(fontPal.originalRed, fontPal.originalGreen, fontPal.originalBlue));
|
||||
|
||||
if (single.burnSurface.getPixels() != nullptr) {
|
||||
Graphics::ManagedSurface tmp2;
|
||||
tmp2.copyFrom(single.burnSurface);
|
||||
tmp2.blendBlitTo(_renderSurface, x1, y1, (flip ? Graphics::FLIP_H : Graphics::FLIP_NONE), 0, MS_RGB(fontPal.originalRed, fontPal.originalGreen, fontPal.originalBlue));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsManager::fontSprite(int x, int y, Sprite &single, const SpritePalette &fontPal) {
|
||||
fontSprite(false, x, y, single, fontPal);
|
||||
}
|
||||
|
||||
void GraphicsManager::flipFontSprite(int x, int y, Sprite &single, const SpritePalette &fontPal) {
|
||||
fontSprite(true, x, y, single, fontPal);
|
||||
}
|
||||
|
||||
Graphics::Surface *GraphicsManager::duplicateSurface(Graphics::Surface *surface) {
|
||||
Graphics::Surface *res = new Graphics::Surface();
|
||||
res->copyFrom(*surface);
|
||||
return res;
|
||||
}
|
||||
|
||||
void GraphicsManager::blendColor(Graphics::Surface *blitted, uint32 color, Graphics::TSpriteBlendMode mode) {
|
||||
Graphics::ManagedSurface tmp(blitted->w, blitted->h, blitted->format);
|
||||
tmp.fillRect(Common::Rect(0, 0, tmp.w, tmp.h), color);
|
||||
tmp.blendBlitTo(*blitted, 0, 0, Graphics::FLIP_NONE, nullptr, MS_ARGB((uint)255, (uint)255, (uint)255, (uint)255), (int)blitted->w, (int)blitted->h, mode);
|
||||
tmp.free();
|
||||
}
|
||||
|
||||
Graphics::Surface *GraphicsManager::applyLightmapToSprite(Graphics::Surface *&blitted, OnScreenPerson *thisPerson, bool mirror, int x, int y, int x1, int y1, int diffX, int diffY) {
|
||||
Graphics::Surface * toDetele = nullptr;
|
||||
|
||||
// if light map is used
|
||||
bool light = !(thisPerson->extra & EXTRA_NOLITE);
|
||||
|
||||
// apply light map and set light map color
|
||||
byte curLight[3];
|
||||
if (light && _lightMap.getPixels()) {
|
||||
if (_lightMapMode == LIGHTMAPMODE_HOTSPOT) {
|
||||
int lx = x + _cameraX;
|
||||
int ly = y + _cameraY;
|
||||
if (lx < 0 || ly < 0 || lx >= (int)_sceneWidth || ly >= (int)_sceneHeight) {
|
||||
curLight[0] = curLight[1] = curLight[2] = 255;
|
||||
} else {
|
||||
byte *target = (byte *)_lightMap.getBasePtr(lx, ly);
|
||||
curLight[0] = target[3];
|
||||
curLight[1] = target[2];
|
||||
curLight[2] = target[1];
|
||||
}
|
||||
} else if (_lightMapMode == LIGHTMAPMODE_PIXEL) {
|
||||
curLight[0] = curLight[1] = curLight[2] = 255;
|
||||
|
||||
toDetele = blitted = duplicateSurface(blitted);
|
||||
|
||||
// apply light map texture
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(_lightMap);
|
||||
Common::Rect rect_h(_sceneWidth - x1 - diffX, y1, _sceneWidth - x1, y1 + diffY);
|
||||
Common::Rect rect_none(x1, y1, x1 + diffX, y1 + diffY);
|
||||
tmp.blendBlitTo(*blitted, 0, 0,
|
||||
(mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE),
|
||||
(mirror ? &rect_h : &rect_none),
|
||||
MS_ARGB((uint)255, (uint)255, (uint)255, (uint)255),
|
||||
(int)blitted->w, (int)blitted->h, Graphics::BLEND_MULTIPLY);
|
||||
|
||||
} else {
|
||||
curLight[0] = curLight[1] = curLight[2] = 255;
|
||||
}
|
||||
} else {
|
||||
curLight[0] = curLight[1] = curLight[2] = 255;
|
||||
}
|
||||
|
||||
// calculate light map color
|
||||
float fr, fg, fb;
|
||||
fr = fg = fb = 0.0F;
|
||||
if (thisPerson->colourmix) {
|
||||
fr = curLight[0]*thisPerson->r * thisPerson->colourmix / 65025 / 255.0F;
|
||||
fg = curLight[1]*thisPerson->g * thisPerson->colourmix / 65025 / 255.0F;
|
||||
fb = curLight[2]*thisPerson->b * thisPerson->colourmix / 65025 / 255.0F;
|
||||
}
|
||||
|
||||
uint32 primaryColor = MS_ARGB(255,
|
||||
(uint8)(fr + curLight[0] * (255 - thisPerson->colourmix) / 255.f),
|
||||
(uint8)(fg + curLight[1] * (255 - thisPerson->colourmix) / 255.f),
|
||||
(uint8)(fb + curLight[2] * (255 - thisPerson->colourmix) / 255.f));
|
||||
|
||||
uint32 secondaryColor = MS_ARGB(0xff, (uint8)(fr * 255), (uint8)(fg * 255), (uint8)(fb * 255));
|
||||
|
||||
// apply primary color
|
||||
if (primaryColor != (uint32)MS_ARGB(255, 255, 255, 255)) {
|
||||
if (!toDetele) {
|
||||
toDetele = blitted = duplicateSurface(blitted);
|
||||
blendColor(blitted, primaryColor, Graphics::BLEND_MULTIPLY);
|
||||
}
|
||||
}
|
||||
|
||||
// apply secondary light map color
|
||||
if (secondaryColor != 0x0) {
|
||||
if (!toDetele) {
|
||||
toDetele = blitted = duplicateSurface(blitted);
|
||||
}
|
||||
blendColor(blitted, secondaryColor, Graphics::BLEND_ADDITIVE);
|
||||
}
|
||||
return toDetele;
|
||||
}
|
||||
|
||||
bool GraphicsManager::scaleSprite(Sprite &single, const SpritePalette &fontPal, OnScreenPerson *thisPerson, bool mirror) {
|
||||
float x = thisPerson->x;
|
||||
float y = thisPerson->y;
|
||||
|
||||
float scale = thisPerson->scale;
|
||||
bool useZB = !(thisPerson->extra & EXTRA_NOZB);
|
||||
|
||||
if (scale <= 0.05)
|
||||
return false;
|
||||
|
||||
int diffX = (int)(((float)single.surface.w) * scale);
|
||||
int diffY = (int)(((float)single.surface.h) * scale);
|
||||
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
if (thisPerson->extra & EXTRA_FIXTOSCREEN) {
|
||||
x = x / _cameraZoom;
|
||||
y = y / _cameraZoom;
|
||||
if (single.xhot < 0)
|
||||
x1 = x - (int)((mirror ? (float)(single.surface.w - single.xhot) : (float)(single.xhot + 1)) * scale / _cameraZoom);
|
||||
else
|
||||
x1 = x - (int)((mirror ? (float)(single.surface.w - (single.xhot + 1)) : (float)single.xhot) * scale / _cameraZoom);
|
||||
y1 = y - (int)((single.yhot - thisPerson->floaty) * scale / _cameraZoom);
|
||||
x2 = x1 + (int)(diffX / _cameraZoom);
|
||||
y2 = y1 + (int)(diffY / _cameraZoom);
|
||||
} else {
|
||||
x -= _cameraX;
|
||||
y -= _cameraY;
|
||||
if (single.xhot < 0)
|
||||
x1 = x - (int)((mirror ? (float)(single.surface.w - single.xhot) : (float)(single.xhot + 1)) * scale);
|
||||
else
|
||||
x1 = x - (int)((mirror ? (float)(single.surface.w - (single.xhot + 1)) : (float)single.xhot) * scale);
|
||||
y1 = y - (int)((single.yhot - thisPerson->floaty) * scale);
|
||||
x2 = x1 + diffX;
|
||||
y2 = y1 + diffY;
|
||||
}
|
||||
|
||||
uint8 z;
|
||||
|
||||
if (useZB && _zBuffer->numPanels) {
|
||||
int i;
|
||||
for (i = 1; i < _zBuffer->numPanels; i++) {
|
||||
if (_zBuffer->panel[i] >= y + _cameraY) {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
z = ((i + 1) * 2) + 1;
|
||||
} else {
|
||||
z = 0xFF;
|
||||
}
|
||||
|
||||
Graphics::Surface *blitted = &single.surface;
|
||||
Graphics::Surface *toDelete = applyLightmapToSprite(blitted, thisPerson, mirror, x, y, x1, y1, diffX, diffY);
|
||||
|
||||
// Use Managed surface to scale and blit
|
||||
if (!_zBuffer->numPanels) {
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(*blitted);
|
||||
tmp.blendBlitTo(_renderSurface, x1, y1, (mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE), nullptr, MS_ARGB(255 - thisPerson->transparency, 255, 255, 255), diffX, diffY);
|
||||
} else {
|
||||
// TODO: you dont need to copy the whole render surface, just the part to which the sprite may be drawn
|
||||
Graphics::ManagedSurface scaled;
|
||||
scaled.copyFrom(_renderSurface);
|
||||
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(*blitted);
|
||||
tmp.blendBlitTo(scaled, x1, y1, (mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE), nullptr, MS_ARGB(255 - thisPerson->transparency, 255, 255, 255), diffX, diffY);
|
||||
|
||||
drawSpriteToZBuffer(0, 0, z, scaled.rawSurface());
|
||||
}
|
||||
|
||||
if (toDelete) {
|
||||
toDelete->free();
|
||||
delete toDelete;
|
||||
toDelete = nullptr;
|
||||
}
|
||||
|
||||
// Are we pointing at the sprite?
|
||||
if (_vm->_evtMan->mouseX() >= x1 && _vm->_evtMan->mouseX() < x2
|
||||
&& _vm->_evtMan->mouseY() >= y1 && _vm->_evtMan->mouseY() < y2) {
|
||||
if (thisPerson->extra & EXTRA_RECTANGULAR)
|
||||
return true;
|
||||
|
||||
// check if point to non transparent part
|
||||
int pixelx = (int)(single.surface.w * (_vm->_evtMan->mouseX() - x1) / (x2 - x1));
|
||||
int pixely = (int)(single.surface.h * (_vm->_evtMan->mouseY() - y1) / (y2 - y1));
|
||||
uint32 *colorPtr = (uint32 *)single.surface.getBasePtr(pixelx, pixely);
|
||||
|
||||
uint8 a, r, g, b;
|
||||
g_sludge->getScreenPixelFormat()->colorToARGB(*colorPtr, a, r, g, b);
|
||||
return a != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Paste a scaled sprite onto the backdrop
|
||||
void GraphicsManager::fixScaleSprite(int x, int y, Sprite &single, const SpritePalette &fontPal, OnScreenPerson *thisPerson, int camX, int camY, bool mirror) {
|
||||
|
||||
float scale = thisPerson->scale;
|
||||
bool useZB = !(thisPerson->extra & EXTRA_NOZB);
|
||||
|
||||
if (scale <= 0.05)
|
||||
return;
|
||||
|
||||
int diffX = (int)(((float)single.surface.w) * scale);
|
||||
int diffY = (int)(((float)single.surface.h) * scale);
|
||||
int x1;
|
||||
if (single.xhot < 0)
|
||||
x1 = x - (int)((mirror ? (float)(single.surface.w - single.xhot) : (float)(single.xhot + 1)) * scale);
|
||||
else
|
||||
x1 = x - (int)((mirror ? (float)(single.surface.w - (single.xhot + 1)) : (float)single.xhot) * scale);
|
||||
int y1 = y - (int)((single.yhot - thisPerson->floaty) * scale);
|
||||
|
||||
uint8 z;
|
||||
|
||||
if (useZB && _zBuffer->numPanels) {
|
||||
int i;
|
||||
for (i = 1; i < _zBuffer->numPanels; i++) {
|
||||
if (_zBuffer->panel[i] >= y + _cameraY) {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
z = ((i + 1) * 2) + 1;
|
||||
} else {
|
||||
z = 0xFF;
|
||||
}
|
||||
|
||||
Graphics::Surface *blitted = &single.surface;
|
||||
Graphics::Surface *toDelete = applyLightmapToSprite(blitted, thisPerson, mirror, x, y, x1, y1, diffX, diffY);
|
||||
|
||||
// draw backdrop
|
||||
drawBackDrop();
|
||||
|
||||
// draw zBuffer
|
||||
if (_zBuffer->numPanels) {
|
||||
drawZBuffer((int)(x1 + camX), (int)(y1 + camY), false);
|
||||
}
|
||||
|
||||
// draw sprite
|
||||
if (!_zBuffer->numPanels) {
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(single.surface);
|
||||
tmp.blendBlitTo(_renderSurface, x1, y1, (mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE), nullptr, MS_ARGB((uint)255, (uint)255, (uint)255, (uint)255), diffX, diffY);
|
||||
} else {
|
||||
Graphics::ManagedSurface scaled;
|
||||
scaled.copyFrom(_renderSurface);
|
||||
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(*blitted);
|
||||
tmp.blendBlitTo(scaled, x1, y1, (mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE), nullptr, MS_ARGB(255 - thisPerson->transparency, 255, 255, 255), diffX, diffY);
|
||||
|
||||
drawSpriteToZBuffer(0, 0, z, scaled.rawSurface());
|
||||
}
|
||||
|
||||
if (toDelete) {
|
||||
toDelete->free();
|
||||
delete toDelete;
|
||||
toDelete = nullptr;
|
||||
}
|
||||
|
||||
// copy screen to backdrop
|
||||
_backdropSurface.copyFrom(_renderSurface);
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
102
engines/sludge/sprites.h
Normal file
102
engines/sludge/sprites.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_SPRITES_H
|
||||
#define SLUDGE_SPRITES_H
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct Sprite {
|
||||
int xhot, yhot;
|
||||
Graphics::Surface surface;
|
||||
Graphics::Surface burnSurface;
|
||||
};
|
||||
|
||||
class SpritePalette {
|
||||
public:
|
||||
uint16 *pal;
|
||||
byte *r;
|
||||
byte *g;
|
||||
byte *b;
|
||||
byte originalRed, originalGreen, originalBlue, total;
|
||||
|
||||
SpritePalette() { init(); }
|
||||
~SpritePalette() { kill(); }
|
||||
|
||||
void init() {
|
||||
pal = nullptr;
|
||||
r = g = b = nullptr;
|
||||
total = 0;
|
||||
originalRed = originalGreen = originalBlue = 255;
|
||||
}
|
||||
|
||||
void kill() {
|
||||
if (pal) {
|
||||
delete[] pal;
|
||||
pal = nullptr;
|
||||
}
|
||||
if (r) {
|
||||
delete[] r;
|
||||
r = nullptr;
|
||||
}
|
||||
if (g) {
|
||||
delete[] g;
|
||||
g = nullptr;
|
||||
}
|
||||
if (b) {
|
||||
delete[] b;
|
||||
b = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void setColor(byte red, byte green, byte blue) {
|
||||
originalRed = red;
|
||||
originalGreen = green;
|
||||
originalBlue = blue;
|
||||
}
|
||||
};
|
||||
|
||||
struct SpriteBank {
|
||||
int total;
|
||||
int type;
|
||||
Sprite *sprites;
|
||||
SpritePalette myPalette;
|
||||
bool isFont;
|
||||
};
|
||||
|
||||
// Sprite display informations
|
||||
struct SpriteDisplay {
|
||||
int x, y;
|
||||
int width, height;
|
||||
bool freeAfterUse;
|
||||
Graphics::FLIP_FLAGS flip;
|
||||
Graphics::Surface *surface;
|
||||
byte transparency;
|
||||
|
||||
SpriteDisplay(int xpos, int ypos, Graphics::FLIP_FLAGS f, Graphics::Surface *ptr, int w = -1, int h = 1, bool free = false, byte trans = 255) :
|
||||
x(xpos), y(ypos), flip(f), surface(ptr), width(w), height(h), freeAfterUse(free), transparency(trans) {
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
231
engines/sludge/statusba.cpp
Normal file
231
engines/sludge/statusba.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "sludge/fonttext.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/moreio.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/statusba.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
StatusBarManager::StatusBarManager(SludgeEngine *sludge) {
|
||||
_nowStatus = &_mainStatus;
|
||||
_sludge = sludge;
|
||||
}
|
||||
|
||||
void StatusBarManager::init() {
|
||||
_mainStatus.firstStatusBar = NULL;
|
||||
_mainStatus.alignStatus = IN_THE_CENTRE;
|
||||
_mainStatus.litStatus = -1;
|
||||
_mainStatus.statusX = 10;
|
||||
_mainStatus.statusY = g_system->getHeight() - 15;
|
||||
statusBarColour(255, 255, 255);
|
||||
statusBarLitColour(255, 255, 128);
|
||||
}
|
||||
|
||||
void StatusBarManager::setLitStatus(int i) {
|
||||
_nowStatus->litStatus = i;
|
||||
}
|
||||
|
||||
void StatusBarManager::killLastStatus() {
|
||||
if (_nowStatus->firstStatusBar) {
|
||||
StatusBar *kill = _nowStatus->firstStatusBar;
|
||||
_nowStatus->firstStatusBar = kill->next;
|
||||
delete kill;
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBarManager::clear() {
|
||||
StatusBar *stat = _nowStatus->firstStatusBar;
|
||||
StatusBar *kill;
|
||||
_nowStatus->litStatus = -1;
|
||||
while (stat) {
|
||||
kill = stat;
|
||||
stat = stat->next;
|
||||
delete kill;
|
||||
}
|
||||
_nowStatus->firstStatusBar = NULL;
|
||||
}
|
||||
|
||||
void StatusBarManager::addStatusBar() {
|
||||
StatusBar *newStat = new StatusBar;
|
||||
if (checkNew(newStat)) {
|
||||
newStat->next = _nowStatus->firstStatusBar;
|
||||
newStat->text.clear();
|
||||
_nowStatus->firstStatusBar = newStat;
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBarManager::set(Common::String &txt) {
|
||||
if (_nowStatus->firstStatusBar) {
|
||||
_nowStatus->firstStatusBar->text.clear();
|
||||
_nowStatus->firstStatusBar->text = txt;
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBarManager::positionStatus(int x, int y) {
|
||||
_nowStatus->statusX = x;
|
||||
_nowStatus->statusY = y;
|
||||
}
|
||||
|
||||
void StatusBarManager::draw() {
|
||||
float cameraZoom = _sludge->_gfxMan->getCamZoom();
|
||||
int y = _nowStatus->statusY, n = 0;
|
||||
StatusBar *stat = _nowStatus->firstStatusBar;
|
||||
while (stat) {
|
||||
switch (_nowStatus->alignStatus) {
|
||||
case IN_THE_CENTRE:
|
||||
_sludge->_txtMan->pasteString(stat->text,
|
||||
((g_system->getWidth() - _sludge->_txtMan->stringWidth(stat->text)) >> 1) / cameraZoom, y / cameraZoom,
|
||||
(n++ == _nowStatus->litStatus) ? _litVerbLinePalette : _verbLinePalette);
|
||||
break;
|
||||
|
||||
case 1001:
|
||||
_sludge->_txtMan->pasteString(stat->text,
|
||||
(g_system->getWidth() - _sludge->_txtMan->stringWidth(stat->text)) - _nowStatus->statusX / cameraZoom, y / cameraZoom,
|
||||
(n ++ == _nowStatus->litStatus) ? _litVerbLinePalette : _verbLinePalette);
|
||||
break;
|
||||
|
||||
default:
|
||||
_sludge->_txtMan->pasteString(stat->text,
|
||||
_nowStatus->statusX / cameraZoom, y / cameraZoom,
|
||||
(n ++ == _nowStatus->litStatus) ? _litVerbLinePalette : _verbLinePalette);
|
||||
}
|
||||
stat = stat->next;
|
||||
y -= _sludge->_txtMan->getFontHeight();
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBarManager::statusBarColour(byte r, byte g, byte b) {
|
||||
_verbLinePalette.setColor(r, g, b);
|
||||
_nowStatus->statusR = r;
|
||||
_nowStatus->statusG = g;
|
||||
_nowStatus->statusB = b;
|
||||
}
|
||||
|
||||
void StatusBarManager::statusBarLitColour(byte r, byte g, byte b) {
|
||||
_litVerbLinePalette.setColor(r, g, b);
|
||||
_nowStatus->statusLR = r;
|
||||
_nowStatus->statusLG = g;
|
||||
_nowStatus->statusLB = b;
|
||||
}
|
||||
|
||||
StatusStuff *StatusBarManager::copyStatusBarStuff(StatusStuff *here) {
|
||||
|
||||
// Things we want to keep
|
||||
here->statusLR = _nowStatus->statusLR;
|
||||
here->statusLG = _nowStatus->statusLG;
|
||||
here->statusLB = _nowStatus->statusLB;
|
||||
here->statusR = _nowStatus->statusR;
|
||||
here->statusG = _nowStatus->statusG;
|
||||
here->statusB = _nowStatus->statusB;
|
||||
here->alignStatus = _nowStatus->alignStatus;
|
||||
here->statusX = _nowStatus->statusX;
|
||||
here->statusY = _nowStatus->statusY;
|
||||
|
||||
// Things we want to clear
|
||||
here->litStatus = -1;
|
||||
here->firstStatusBar = NULL;
|
||||
|
||||
StatusStuff *old = _nowStatus;
|
||||
_nowStatus = here;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
void StatusBarManager::restoreBarStuff(StatusStuff *here) {
|
||||
delete _nowStatus;
|
||||
_verbLinePalette.setColor((byte)here->statusR, (byte)here->statusG, (byte)here->statusB);
|
||||
_litVerbLinePalette.setColor((byte)here->statusLR, (byte)here->statusLG, (byte)here->statusLB);
|
||||
_nowStatus = here;
|
||||
}
|
||||
|
||||
|
||||
const Common::String StatusBarManager::statusBarText() {
|
||||
if (_nowStatus->firstStatusBar) {
|
||||
return _nowStatus->firstStatusBar->text;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void StatusBarManager::saveStatusBars(Common::WriteStream *stream) {
|
||||
StatusBar *viewLine = _nowStatus->firstStatusBar;
|
||||
|
||||
stream->writeUint16BE(_nowStatus->alignStatus);
|
||||
stream->writeSint16LE(_nowStatus->litStatus);
|
||||
stream->writeUint16BE(_nowStatus->statusX);
|
||||
stream->writeUint16BE(_nowStatus->statusY);
|
||||
|
||||
stream->writeByte(_nowStatus->statusR);
|
||||
stream->writeByte(_nowStatus->statusG);
|
||||
stream->writeByte(_nowStatus->statusB);
|
||||
stream->writeByte(_nowStatus->statusLR);
|
||||
stream->writeByte(_nowStatus->statusLG);
|
||||
stream->writeByte(_nowStatus->statusLB);
|
||||
|
||||
// Write what's being said
|
||||
while (viewLine) {
|
||||
stream->writeByte(1);
|
||||
writeString(viewLine->text, stream);
|
||||
viewLine = viewLine->next;
|
||||
}
|
||||
stream->writeByte(0);
|
||||
}
|
||||
|
||||
bool StatusBarManager::loadStatusBars(Common::SeekableReadStream *stream) {
|
||||
clear();
|
||||
|
||||
_nowStatus->alignStatus = stream->readUint16BE();
|
||||
_nowStatus->litStatus = stream->readSint16LE();
|
||||
_nowStatus->statusX = stream->readUint16BE();
|
||||
_nowStatus->statusY = stream->readUint16BE();
|
||||
|
||||
_nowStatus->statusR = stream->readByte();
|
||||
_nowStatus->statusG = stream->readByte();
|
||||
_nowStatus->statusB = stream->readByte();
|
||||
_nowStatus->statusLR = stream->readByte();
|
||||
_nowStatus->statusLG = stream->readByte();
|
||||
_nowStatus->statusLB = stream->readByte();
|
||||
|
||||
_verbLinePalette.setColor((byte)_nowStatus->statusR, (byte)_nowStatus->statusG, (byte)_nowStatus->statusB);
|
||||
_litVerbLinePalette.setColor((byte)_nowStatus->statusLR, (byte)_nowStatus->statusLG, (byte)_nowStatus->statusLB);
|
||||
// Read what's being said
|
||||
StatusBar **viewLine = &(_nowStatus->firstStatusBar);
|
||||
StatusBar *newOne;
|
||||
while (stream->readByte()) {
|
||||
newOne = new StatusBar;
|
||||
if (!checkNew(newOne))
|
||||
return false;
|
||||
newOne->text = readString(stream);
|
||||
newOne->next = NULL;
|
||||
(*viewLine) = newOne;
|
||||
viewLine = &(newOne->next);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
78
engines/sludge/statusba.h
Normal file
78
engines/sludge/statusba.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_STATUSBA_H
|
||||
#define SLUDGE_STATUSBA_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct StatusBar {
|
||||
Common::String text;
|
||||
StatusBar *next;
|
||||
};
|
||||
|
||||
struct StatusStuff {
|
||||
StatusBar *firstStatusBar;
|
||||
uint16 alignStatus;
|
||||
int litStatus;
|
||||
int statusX, statusY;
|
||||
int statusR, statusG, statusB;
|
||||
int statusLR, statusLG, statusLB;
|
||||
};
|
||||
|
||||
class StatusBarManager {
|
||||
public:
|
||||
StatusBarManager(SludgeEngine *sludge);
|
||||
|
||||
void init();
|
||||
void set(Common::String &txt);
|
||||
void clear();
|
||||
void addStatusBar();
|
||||
void killLastStatus();
|
||||
void statusBarColour(byte r, byte g, byte b);
|
||||
void statusBarLitColour(byte r, byte g, byte b);
|
||||
void setLitStatus(int i);
|
||||
const Common::String statusBarText();
|
||||
void positionStatus(int, int);
|
||||
void draw();
|
||||
|
||||
// Load and save
|
||||
bool loadStatusBars(Common::SeekableReadStream *stream);
|
||||
void saveStatusBars(Common::WriteStream *stream);
|
||||
|
||||
// For freezing
|
||||
void restoreBarStuff(StatusStuff *here);
|
||||
StatusStuff *copyStatusBarStuff(StatusStuff *here);
|
||||
|
||||
void setAlignStatus(uint16 val) { _nowStatus->alignStatus = val; }
|
||||
|
||||
private:
|
||||
SpritePalette _verbLinePalette;
|
||||
SpritePalette _litVerbLinePalette;
|
||||
|
||||
StatusStuff _mainStatus;
|
||||
StatusStuff *_nowStatus;
|
||||
|
||||
SludgeEngine *_sludge;
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
141
engines/sludge/thumbnail.cpp
Normal file
141
engines/sludge/thumbnail.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "image/png.h"
|
||||
|
||||
#include "sludge/errors.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/imgloader.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/version.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
bool GraphicsManager::setThumbnailSize(int thumbWidth, int thumbHeight) {
|
||||
if (checkSizeValide(thumbWidth, thumbHeight))
|
||||
{
|
||||
_thumbWidth = thumbWidth;
|
||||
_thumbHeight = thumbHeight;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GraphicsManager::saveThumbnail(Common::WriteStream *stream) {
|
||||
stream->writeUint32LE(_thumbWidth);
|
||||
stream->writeUint32LE(_thumbHeight);
|
||||
|
||||
if (_thumbWidth && _thumbHeight) {
|
||||
if (!freeze())
|
||||
return false;
|
||||
|
||||
if(!Image::writePNG(*stream, _renderSurface))
|
||||
return false;
|
||||
|
||||
unfreeze(true);
|
||||
}
|
||||
stream->writeByte('!');
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsManager::showThumbnail(const Common::String &filename, int atX, int atY) {
|
||||
Common::InSaveFile *fp = g_system->getSavefileManager()->openForLoading(filename);
|
||||
|
||||
if (fp == nullptr)
|
||||
return;
|
||||
|
||||
bool headerBad = false;
|
||||
if (fp->readByte() != 'S')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'L')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'U')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'D')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'S')
|
||||
headerBad = true;
|
||||
if (fp->readByte() != 'A')
|
||||
headerBad = true;
|
||||
if (headerBad) {
|
||||
fatal(ERROR_GAME_LOAD_NO, filename);
|
||||
return;
|
||||
}
|
||||
char c = fp->readByte();
|
||||
while ((c = fp->readByte()))
|
||||
;
|
||||
|
||||
int majVersion = fp->readByte();
|
||||
int minVersion = fp->readByte();
|
||||
int ssgVersion = VERSION(majVersion, minVersion);
|
||||
|
||||
if (ssgVersion >= VERSION(1, 4)) {
|
||||
int fileWidth = fp->readUint32LE();
|
||||
int fileHeight = fp->readUint32LE();
|
||||
|
||||
Graphics::ManagedSurface thumbnail;
|
||||
if (!ImgLoader::loadPNGImage(fp, thumbnail.surfacePtr()))
|
||||
return;
|
||||
|
||||
delete fp;
|
||||
fp = nullptr;
|
||||
|
||||
|
||||
if (atX < 0) {
|
||||
fileWidth += atX;
|
||||
atX = 0;
|
||||
}
|
||||
if (atY < 0) {
|
||||
fileHeight += atY;
|
||||
atY = 0;
|
||||
}
|
||||
if (fileWidth + atX > (int)_sceneWidth)
|
||||
fileWidth = _sceneWidth - atX;
|
||||
if (fileHeight + atY > (int)_sceneHeight)
|
||||
fileHeight = _sceneHeight - atY;
|
||||
|
||||
thumbnail.blendBlitTo(_backdropSurface, atX, atY, Graphics::FLIP_NONE, nullptr, MS_ARGB((uint)255, (uint)255, (uint)255, (uint)255), fileWidth, fileHeight);
|
||||
thumbnail.free();
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsManager::skipThumbnail(Common::SeekableReadStream *stream) {
|
||||
_thumbWidth = stream->readUint32LE();
|
||||
_thumbHeight = stream->readUint32LE();
|
||||
|
||||
// Load image
|
||||
Graphics::Surface tmp;
|
||||
if (_thumbWidth && _thumbHeight) {
|
||||
if (!ImgLoader::loadPNGImage(stream, &tmp))
|
||||
return false;
|
||||
else
|
||||
tmp.free();
|
||||
}
|
||||
|
||||
// Check flag
|
||||
return (stream->readByte() == '!');
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
87
engines/sludge/timing.cpp
Normal file
87
engines/sludge/timing.cpp
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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
#include "sludge/timing.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
Timer::Timer(){
|
||||
reset();
|
||||
}
|
||||
|
||||
void Timer::reset(void) {
|
||||
_desiredFPS = 300;
|
||||
_startTime = 0;
|
||||
_endTime = 0;
|
||||
_desiredFrameTime = 0;
|
||||
_addNextTime = 0;
|
||||
|
||||
// FPS stats
|
||||
_lastFPS = -1;
|
||||
_thisFPS = -1;
|
||||
_lastSeconds = 0;
|
||||
}
|
||||
|
||||
void Timer::init(void) {
|
||||
_desiredFrameTime = 1000 / _desiredFPS;
|
||||
_startTime = g_system->getMillis();
|
||||
}
|
||||
|
||||
void Timer::initSpecial(int t) {
|
||||
_desiredFrameTime = 1000 / t;
|
||||
_startTime = g_system->getMillis();
|
||||
}
|
||||
|
||||
void Timer::updateFpsStats() {
|
||||
uint32 currentSeconds = g_system->getMillis() / 1000;
|
||||
if (_lastSeconds != currentSeconds) {
|
||||
_lastSeconds = currentSeconds;
|
||||
_lastFPS = _thisFPS;
|
||||
_thisFPS = 1;
|
||||
} else {
|
||||
++_thisFPS;
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::waitFrame(void) {
|
||||
uint32 timetaken;
|
||||
|
||||
for (;;) {
|
||||
_endTime = g_system->getMillis();
|
||||
timetaken = _addNextTime + _endTime - _startTime;
|
||||
if (timetaken >= _desiredFrameTime)
|
||||
break;
|
||||
g_system->delayMillis(1);
|
||||
}
|
||||
|
||||
_addNextTime = timetaken - _desiredFrameTime;
|
||||
if (_addNextTime > _desiredFrameTime)
|
||||
_addNextTime = _desiredFrameTime;
|
||||
|
||||
_startTime = _endTime;
|
||||
|
||||
// Stats
|
||||
updateFpsStats();
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
53
engines/sludge/timing.h
Normal file
53
engines/sludge/timing.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_TIMING_H
|
||||
#define SLUDGE_TIMING_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
class Timer {
|
||||
public:
|
||||
Timer();
|
||||
|
||||
void setDesiredFPS(int t) { _desiredFPS = t; }
|
||||
void reset(void);
|
||||
void init(void);
|
||||
void initSpecial(int t);
|
||||
void waitFrame(void);
|
||||
|
||||
int getLastFps() const { return _lastFPS; }
|
||||
|
||||
private:
|
||||
int _desiredFPS; // desired frames per second
|
||||
uint32 _startTime, _endTime;
|
||||
uint32 _desiredFrameTime;
|
||||
uint32 _addNextTime;
|
||||
|
||||
// FPS stats
|
||||
void updateFpsStats();
|
||||
int _lastFPS;
|
||||
int _thisFPS;
|
||||
uint32 _lastSeconds;
|
||||
};
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
234
engines/sludge/transition.cpp
Normal file
234
engines/sludge/transition.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/textconsole.h"
|
||||
#include "sludge/graphics.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
extern float snapTexW, snapTexH;
|
||||
|
||||
void GraphicsManager::setBrightnessLevel(int brightnessLevel) {
|
||||
_brightnessLevel = CLIP(brightnessLevel, 0, 255);
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
// PROPER BRIGHTNESS FADING
|
||||
//----------------------------------------------------
|
||||
|
||||
unsigned lastFrom, lastTo;
|
||||
|
||||
void GraphicsManager::transitionFader() {
|
||||
blendColor(&_renderSurface, MS_ARGB(255 - _brightnessLevel, 0, 0, 0), Graphics::BLEND_NORMAL);
|
||||
}
|
||||
|
||||
void GraphicsManager::transitionCrossFader() {
|
||||
if (!_snapshotSurface.getPixels())
|
||||
return;
|
||||
|
||||
if (_brightnessLevel == 255)
|
||||
return;
|
||||
|
||||
Graphics::ManagedSurface tmp;
|
||||
tmp.copyFrom(_snapshotSurface);
|
||||
tmp.blendBlitTo(_renderSurface, 0, 0, Graphics::FLIP_NONE, nullptr, MS_ARGB(255 - _brightnessLevel, 0xff, 0xff, 0xff));
|
||||
}
|
||||
|
||||
void GraphicsManager::transitionSnapshotBox() {
|
||||
if (!_snapshotSurface.getPixels())
|
||||
return;
|
||||
|
||||
if (_brightnessLevel == 255)
|
||||
return;
|
||||
|
||||
uint32 xScale = (255 - _brightnessLevel) * _winWidth / 255;
|
||||
uint32 yScale = (255 - _brightnessLevel) * _winHeight / 255;
|
||||
|
||||
Graphics::Surface *surf = _snapshotSurface.scale(xScale, yScale);
|
||||
|
||||
_renderSurface.copyRectToSurface(surf->getPixels(), surf->pitch, (_winWidth - xScale) / 2, (_winHeight - yScale) / 2, xScale, yScale);
|
||||
|
||||
delete surf;
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
// FAST PSEUDO-RANDOM NUMBER STUFF FOR DISOLVE EFFECT
|
||||
//----------------------------------------------------
|
||||
|
||||
void GraphicsManager::resetRandW() {
|
||||
int32 seed = 12345;
|
||||
|
||||
for (int i = 0; i < RANDKK; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
seed = seed * 2891336453u + 1;
|
||||
_randbuffer[i][j] = seed;
|
||||
}
|
||||
}
|
||||
|
||||
_randp1 = 0;
|
||||
_randp2 = 10;
|
||||
}
|
||||
|
||||
void GraphicsManager::reserveTransitionTexture() {
|
||||
_transitionTexture = new Graphics::ManagedSurface;
|
||||
|
||||
_transitionTexture->create(256, 256, Graphics::BlendBlit::getSupportedPixelFormat());
|
||||
}
|
||||
|
||||
void GraphicsManager::transitionDisolve() {
|
||||
if (!_transitionTexture)
|
||||
reserveTransitionTexture();
|
||||
|
||||
if (!_brightnessLevel) {
|
||||
transitionFader();
|
||||
return;
|
||||
}
|
||||
|
||||
byte *toScreen = (byte *)_transitionTexture->getPixels();
|
||||
byte *end = (byte *)_transitionTexture->getBasePtr(255, 255);
|
||||
|
||||
do {
|
||||
// generate next number
|
||||
uint32 n = _randbuffer[_randp1][1];
|
||||
uint32 y = (n << 27) | ((n >> (32 - 27)) + _randbuffer[_randp2][1]);
|
||||
|
||||
n = _randbuffer[_randp1][0];
|
||||
_randbuffer[_randp1][1] = (n << 19) | ((n >> (32 - 19)) + _randbuffer[_randp2][0]);
|
||||
_randbuffer[_randp1][0] = y;
|
||||
|
||||
// rotate list pointers
|
||||
if (!_randp1--)
|
||||
_randp1 = RANDKK - 1;
|
||||
if (!_randp2--)
|
||||
_randp2 = RANDKK - 1;
|
||||
|
||||
if ((y & 0xff) > _brightnessLevel) {
|
||||
toScreen[0] = 255;
|
||||
toScreen[1] = toScreen[2] = toScreen[3] = 0;
|
||||
} else {
|
||||
toScreen[0] = toScreen[1] = toScreen[2] = toScreen[3] = 0;
|
||||
}
|
||||
toScreen += 4;
|
||||
} while (toScreen < end);
|
||||
|
||||
// The original stretched the texture, we just tile it
|
||||
for (uint y = 0; y < _sceneHeight; y += _transitionTexture->h)
|
||||
for (uint x = 0; x < _sceneWidth; x += _transitionTexture->w)
|
||||
_transitionTexture->blendBlitTo(_renderSurface, x, y);
|
||||
}
|
||||
|
||||
void GraphicsManager::transitionTV() {
|
||||
if (!_transitionTexture)
|
||||
reserveTransitionTexture();
|
||||
|
||||
byte *toScreen = (byte *)_transitionTexture->getPixels();
|
||||
byte *end = (byte *)_transitionTexture->getBasePtr(255, 255);
|
||||
|
||||
do {
|
||||
// generate next number
|
||||
uint32 n = _randbuffer[_randp1][1];
|
||||
uint32 y = (n << 27) | ((n >> (32 - 27)) + _randbuffer[_randp2][1]);
|
||||
|
||||
n = _randbuffer[_randp1][0];
|
||||
_randbuffer[_randp1][1] = (n << 19) | ((n >> (32 - 19)) + _randbuffer[_randp2][0]);
|
||||
_randbuffer[_randp1][0] = y;
|
||||
|
||||
// rotate list pointers
|
||||
if (!_randp1--)
|
||||
_randp1 = RANDKK - 1;
|
||||
if (!_randp2--)
|
||||
_randp2 = RANDKK - 1;
|
||||
|
||||
if ((y & 255u) > _brightnessLevel) {
|
||||
toScreen[0] = (n & 255);
|
||||
toScreen[1] = toScreen[2] = toScreen[3] = (n & 255);
|
||||
} else {
|
||||
toScreen[0] = toScreen[1] = toScreen[2] = toScreen[3] = 0;
|
||||
}
|
||||
toScreen += 4;
|
||||
} while (toScreen < end);
|
||||
|
||||
// The original stretched the texture, we just tile it
|
||||
for (uint y = 0; y < _sceneHeight; y += _transitionTexture->h)
|
||||
for (uint x = 0; x < _sceneWidth; x += _transitionTexture->w)
|
||||
_transitionTexture->blendBlitTo(_renderSurface, x, y);
|
||||
}
|
||||
|
||||
void GraphicsManager::transitionBlinds() {
|
||||
if (!_transitionTexture)
|
||||
reserveTransitionTexture();
|
||||
|
||||
int level = _brightnessLevel / 16;
|
||||
|
||||
for (int b = 0; b < 16; b++) {
|
||||
byte *toScreen = (byte *)_transitionTexture->getBasePtr(0, b * 16);
|
||||
|
||||
if (level)
|
||||
memset(toScreen, 0, 256 * 4 * level);
|
||||
if (level < 32) {
|
||||
for (int y = 0; y < 16 - level; y++) {
|
||||
toScreen = (byte *)_transitionTexture->getBasePtr(0, b * 16 + y);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
toScreen[0] = 0xff;
|
||||
toScreen[1] = toScreen[2] = toScreen[3] = 0;
|
||||
toScreen += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The original stretched the texture, we just tile it
|
||||
for (uint y = 0; y < _sceneHeight; y += _transitionTexture->h)
|
||||
for (uint x = 0; x < _sceneWidth; x += _transitionTexture->w)
|
||||
_transitionTexture->blendBlitTo(_renderSurface, x, y);
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
void GraphicsManager::fixBrightness() {
|
||||
switch (_fadeMode) {
|
||||
case 0:
|
||||
transitionFader();
|
||||
break;
|
||||
case 1:
|
||||
resetRandW();
|
||||
// Fall through!
|
||||
case 2:
|
||||
transitionDisolve();
|
||||
break;
|
||||
case 3:
|
||||
transitionTV();
|
||||
break;
|
||||
case 4:
|
||||
transitionBlinds();
|
||||
break;
|
||||
case 5:
|
||||
transitionCrossFader();
|
||||
break;
|
||||
case 6:
|
||||
transitionSnapshotBox();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
813
engines/sludge/variable.cpp
Normal file
813
engines/sludge/variable.cpp
Normal file
@@ -0,0 +1,813 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "engines/metaengine.h"
|
||||
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/moreio.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/objtypes.h"
|
||||
#include "sludge/people.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/sprbanks.h"
|
||||
#include "sludge/variable.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
const char *typeName[] = { "undefined", "number", "user function", "string",
|
||||
"built-in function", "file", "stack", "object type", "animation",
|
||||
"costume", "fast array" };
|
||||
|
||||
void Variable::unlinkVar() {
|
||||
switch (varType) {
|
||||
case SVT_STRING:
|
||||
delete []varData.theString;
|
||||
varData.theString = NULL;
|
||||
break;
|
||||
|
||||
case SVT_STACK:
|
||||
varData.theStack->timesUsed--;
|
||||
if (varData.theStack->timesUsed <= 0) {
|
||||
while (varData.theStack->first)
|
||||
trimStack(varData.theStack->first);
|
||||
delete varData.theStack;
|
||||
varData.theStack = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case SVT_FASTARRAY:
|
||||
varData.fastArray->timesUsed--;
|
||||
if (varData.theStack->timesUsed <= 0) {
|
||||
delete varData.fastArray->fastVariables;
|
||||
delete[] varData.fastArray;
|
||||
varData.fastArray = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case SVT_ANIM:
|
||||
if (varData.animHandler) {
|
||||
delete varData.animHandler;
|
||||
varData.animHandler = nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Variable::setVariable(VariableType vT, int value) {
|
||||
unlinkVar();
|
||||
varType = vT;
|
||||
varData.intValue = value;
|
||||
}
|
||||
|
||||
void Variable::makeAnimationVariable(PersonaAnimation *i) {
|
||||
unlinkVar();
|
||||
varType = SVT_ANIM;
|
||||
varData.animHandler = i;
|
||||
}
|
||||
|
||||
PersonaAnimation *Variable::getAnimationFromVar() {
|
||||
if (varType == SVT_ANIM)
|
||||
return new PersonaAnimation(varData.animHandler);
|
||||
|
||||
if (varType == SVT_INT && varData.intValue == 0)
|
||||
return new PersonaAnimation();
|
||||
|
||||
fatal("Expecting an animation variable; found Variable of type", typeName[varType]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Variable::makeCostumeVariable(Persona *i) {
|
||||
unlinkVar();
|
||||
varType = SVT_COSTUME;
|
||||
varData.costumeHandler = i;
|
||||
}
|
||||
|
||||
Persona *Variable::getCostumeFromVar() {
|
||||
Persona *p = NULL;
|
||||
|
||||
switch (varType) {
|
||||
case SVT_ANIM:
|
||||
p = new Persona;
|
||||
if (!checkNew(p))
|
||||
return NULL;
|
||||
p->numDirections = 1;
|
||||
p->animation = new PersonaAnimation *[3];
|
||||
if (!checkNew(p->animation))
|
||||
return NULL;
|
||||
|
||||
for (int iii = 0; iii < 3; iii++)
|
||||
p->animation[iii] = new PersonaAnimation(varData.animHandler);
|
||||
|
||||
break;
|
||||
|
||||
case SVT_COSTUME:
|
||||
return varData.costumeHandler;
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Expecting an animation variable; found Variable of type", typeName[varType]);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void Variable::debugPrint() {
|
||||
switch (varType) {
|
||||
case SVT_NULL:
|
||||
debugN("SVT_NULL() ");
|
||||
break;
|
||||
case SVT_INT:
|
||||
debugN("SVT_INT(%d) ", varData.intValue);
|
||||
break;
|
||||
case SVT_STRING:
|
||||
debugN("SVT_STRING(\"%s\") ", Common::toPrintable(varData.theString).c_str());
|
||||
break;
|
||||
case SVT_BUILT:
|
||||
debugN("SVT_BUILT(%d) ", varData.intValue);
|
||||
break;
|
||||
case SVT_STACK:
|
||||
debugN("SVT_STACK(");
|
||||
varData.theStack->debugPrint();
|
||||
debugN(") ");
|
||||
break;
|
||||
case SVT_FUNC:
|
||||
debugN("SVT_FUNC(%d) ", varData.intValue);
|
||||
break;
|
||||
case SVT_FILE:
|
||||
debugN("SVT_FILE(\"%s\") ", g_sludge->_resMan->resourceNameFromNum(varData.intValue).c_str());
|
||||
break;
|
||||
case SVT_ANIM:
|
||||
debugN("SVT_ANIM(Frames: %d, ID: %d) ", varData.animHandler->numFrames, varData.animHandler->numFrames ? varData.animHandler->theSprites->ID : -1337);
|
||||
break;
|
||||
case SVT_OBJTYPE:
|
||||
debugN("SVT_OBJTYPE(%d) ", varData.intValue);
|
||||
break;
|
||||
case SVT_COSTUME:
|
||||
debugN("SVT_COSTUME(numDirections: %d) ", varData.costumeHandler->numDirections);
|
||||
break;
|
||||
case SVT_FASTARRAY:
|
||||
debugN("FASTARRAY(");
|
||||
varData.fastArray->debugPrint();
|
||||
debugN(") ");
|
||||
break;
|
||||
default :
|
||||
debugN("<UNK %d> ", varType);
|
||||
}
|
||||
}
|
||||
|
||||
int StackHandler::getStackSize() const {
|
||||
int r = 0;
|
||||
VariableStack *a = first;
|
||||
while (a) {
|
||||
r++;
|
||||
a = a->next;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int stringCompareToIgnoreCase(const Common::String &s1, const Common::String &s2) {
|
||||
return s1.compareToIgnoreCase(s2) > 0;
|
||||
}
|
||||
|
||||
bool StackHandler::getSavedGamesStack(const Common::String &ext) {
|
||||
// Make pattern
|
||||
//uint len = realExtension.size();
|
||||
|
||||
// Get all saved files
|
||||
SaveStateList sa = g_sludge->getMetaEngine()->listSaves(g_sludge->getTargetName().c_str());
|
||||
Common::StringArray realNames;
|
||||
|
||||
g_sludge->_saveNameToSlot.clear();
|
||||
|
||||
for (auto &savestate : sa) {
|
||||
Common::String name = savestate.getDescription();
|
||||
realNames.push_back(name);
|
||||
g_sludge->_saveNameToSlot[name] = savestate.getSaveSlot();
|
||||
}
|
||||
|
||||
Common::sort(realNames.begin(), realNames.end(), stringCompareToIgnoreCase);
|
||||
|
||||
|
||||
// Save file names to stacks
|
||||
Variable newName;
|
||||
newName.varType = SVT_NULL;
|
||||
|
||||
for (Common::StringArray::iterator it = realNames.begin(); it != realNames.end(); ++it) {
|
||||
newName.makeTextVar((*it));
|
||||
if (!addVarToStack(newName, first))
|
||||
return false;
|
||||
if (last == NULL)
|
||||
last = first;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StackHandler::debugPrint() {
|
||||
VariableStack *a = first;
|
||||
|
||||
debugN("{");
|
||||
|
||||
while (a) {
|
||||
a->thisVar.debugPrint();
|
||||
a = a->next;
|
||||
}
|
||||
|
||||
debugN("}");
|
||||
}
|
||||
|
||||
bool Variable::copyStack(const Variable &from) {
|
||||
varType = SVT_STACK;
|
||||
varData.theStack = new StackHandler;
|
||||
if (!checkNew(varData.theStack))
|
||||
return false;
|
||||
varData.theStack->first = NULL;
|
||||
varData.theStack->last = NULL;
|
||||
varData.theStack->timesUsed = 1;
|
||||
VariableStack *a = from.varData.theStack->first;
|
||||
|
||||
while (a) {
|
||||
addVarToStack(a->thisVar, varData.theStack->first);
|
||||
if (varData.theStack->last == NULL) {
|
||||
varData.theStack->last = varData.theStack->first;
|
||||
}
|
||||
a = a->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Variable::addVariablesInSecond(const Variable &other) {
|
||||
if (other.varType == SVT_INT && varType == SVT_INT) {
|
||||
varData.intValue += other.varData.intValue;
|
||||
} else {
|
||||
Common::String string1 = other.getTextFromAnyVar();
|
||||
Common::String string2 = getTextFromAnyVar();
|
||||
|
||||
unlinkVar();
|
||||
varData.theString = createCString(string1 + string2);
|
||||
varType = SVT_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
int Variable::compareVars(const Variable &other) const {
|
||||
int re = 0;
|
||||
if (other.varType == varType) {
|
||||
switch (other.varType) {
|
||||
case SVT_NULL:
|
||||
re = 1;
|
||||
break;
|
||||
|
||||
case SVT_COSTUME:
|
||||
re = (other.varData.costumeHandler == varData.costumeHandler);
|
||||
break;
|
||||
|
||||
case SVT_ANIM:
|
||||
re = (other.varData.animHandler == varData.animHandler);
|
||||
break;
|
||||
|
||||
case SVT_STRING:
|
||||
re = (strcmp(other.varData.theString, varData.theString) == 0);
|
||||
break;
|
||||
|
||||
case SVT_STACK:
|
||||
re = (other.varData.theStack == varData.theStack);
|
||||
break;
|
||||
|
||||
default:
|
||||
re = (other.varData.intValue == varData.intValue);
|
||||
}
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
void Variable::compareVariablesInSecond(const Variable &other) {
|
||||
setVariable(SVT_INT, compareVars(other));
|
||||
}
|
||||
|
||||
void Variable::makeTextVar(const Common::String &txt) {
|
||||
unlinkVar();
|
||||
varType = SVT_STRING;
|
||||
varData.theString = createCString(txt);
|
||||
}
|
||||
|
||||
bool Variable::loadStringToVar(int value) {
|
||||
makeTextVar(g_sludge->_resMan->getNumberedString(value));
|
||||
return (bool)(varData.theString != NULL);
|
||||
}
|
||||
|
||||
Common::String Variable::getTextFromAnyVar(bool skipLoad) const {
|
||||
switch (varType) {
|
||||
case SVT_STRING:
|
||||
return varData.theString;
|
||||
|
||||
case SVT_FASTARRAY: {
|
||||
Common::String builder = "FAST:";
|
||||
Common::String builder2 = "";
|
||||
Common::String grabText = "";
|
||||
|
||||
for (int i = 0; i < varData.fastArray->size; i++) {
|
||||
builder2 = builder + " ";
|
||||
grabText = varData.fastArray->fastVariables[i].getTextFromAnyVar(skipLoad);
|
||||
builder.clear();
|
||||
builder = builder2 + grabText;
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
case SVT_STACK: {
|
||||
Common::String builder = "ARRAY:";
|
||||
Common::String builder2 = "";
|
||||
Common::String grabText = "";
|
||||
|
||||
VariableStack *stacky = varData.theStack->first;
|
||||
|
||||
while (stacky) {
|
||||
builder2 = builder + " ";
|
||||
grabText = stacky->thisVar.getTextFromAnyVar(skipLoad);
|
||||
builder.clear();
|
||||
builder = builder2 + grabText;
|
||||
stacky = stacky->next;
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
case SVT_INT: {
|
||||
Common::String buff = Common::String::format("%i", varData.intValue);
|
||||
return buff;
|
||||
}
|
||||
|
||||
case SVT_FILE: {
|
||||
return g_sludge->_resMan->resourceNameFromNum(varData.intValue);
|
||||
}
|
||||
|
||||
case SVT_OBJTYPE: {
|
||||
ObjectType *thisType = g_sludge->_objMan->findObjectType(varData.intValue, skipLoad);
|
||||
if (thisType)
|
||||
return thisType->screenName;
|
||||
else
|
||||
return Common::String::format("<unloaded id %d>", varData.intValue);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return typeName[varType];
|
||||
}
|
||||
|
||||
bool Variable::getBoolean() const {
|
||||
switch (varType) {
|
||||
case SVT_NULL:
|
||||
return false;
|
||||
|
||||
case SVT_INT:
|
||||
return (bool)(varData.intValue != 0);
|
||||
|
||||
case SVT_STACK:
|
||||
return (bool)(varData.theStack->first != NULL);
|
||||
|
||||
case SVT_STRING:
|
||||
return (bool)(varData.theString[0] != 0);
|
||||
|
||||
case SVT_FASTARRAY:
|
||||
return (bool)(varData.fastArray->size != 0);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Variable::copyMain(const Variable &from) {
|
||||
varType = from.varType;
|
||||
switch (varType) {
|
||||
case SVT_INT:
|
||||
case SVT_FUNC:
|
||||
case SVT_BUILT:
|
||||
case SVT_FILE:
|
||||
case SVT_OBJTYPE:
|
||||
varData.intValue = from.varData.intValue;
|
||||
return true;
|
||||
|
||||
case SVT_FASTARRAY:
|
||||
varData.fastArray = from.varData.fastArray;
|
||||
varData.fastArray->timesUsed++;
|
||||
return true;
|
||||
|
||||
case SVT_STRING:
|
||||
varData.theString = createCString(from.varData.theString);
|
||||
return varData.theString ? true : false;
|
||||
|
||||
case SVT_STACK:
|
||||
varData.theStack = from.varData.theStack;
|
||||
varData.theStack->timesUsed++;
|
||||
return true;
|
||||
|
||||
case SVT_COSTUME:
|
||||
varData.costumeHandler = from.varData.costumeHandler;
|
||||
return true;
|
||||
|
||||
case SVT_ANIM:
|
||||
varData.animHandler = new PersonaAnimation(from.varData.animHandler);
|
||||
return true;
|
||||
|
||||
case SVT_NULL:
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fatal("Unknown value type");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Variable::copyFrom(const Variable &from) {
|
||||
unlinkVar();
|
||||
return copyMain(from);
|
||||
}
|
||||
|
||||
Variable *FastArrayHandler::fastArrayGetByIndex(uint theIndex) {
|
||||
if ((int)theIndex >= size)
|
||||
return NULL;
|
||||
return &fastVariables[theIndex];
|
||||
}
|
||||
|
||||
void FastArrayHandler::debugPrint() {
|
||||
debugN("[");
|
||||
for (int i = 0; i < size; i++)
|
||||
fastVariables[i].debugPrint();
|
||||
|
||||
debugN("]");
|
||||
}
|
||||
|
||||
bool Variable::makeFastArraySize(int size) {
|
||||
if (size < 0)
|
||||
return fatal("Can't create a fast array with a negative number of elements!");
|
||||
unlinkVar();
|
||||
varType = SVT_FASTARRAY;
|
||||
varData.fastArray = new FastArrayHandler;
|
||||
if (!checkNew(varData.fastArray))
|
||||
return false;
|
||||
varData.fastArray->fastVariables = new Variable[size];
|
||||
if (!checkNew(varData.fastArray->fastVariables))
|
||||
return false;
|
||||
varData.fastArray->size = size;
|
||||
varData.fastArray->timesUsed = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Variable::makeFastArrayFromStack(const StackHandler *stacky) {
|
||||
int size = stacky->getStackSize();
|
||||
if (!makeFastArraySize(size))
|
||||
return false;
|
||||
|
||||
// Now let's fill up the new array
|
||||
|
||||
VariableStack *allV = stacky->first;
|
||||
size = 0;
|
||||
while (allV) {
|
||||
varData.fastArray->fastVariables[size].copyMain(allV->thisVar);
|
||||
size++;
|
||||
allV = allV->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addVarToStack(const Variable &va, VariableStack *&thisStack) {
|
||||
VariableStack *newStack = new VariableStack;
|
||||
if (!checkNew(newStack))
|
||||
return false;
|
||||
|
||||
if (!newStack->thisVar.copyMain(va))
|
||||
return false;
|
||||
newStack->next = thisStack;
|
||||
thisStack = newStack;
|
||||
debugC(2, kSludgeDebugStackMachine, "Variable %s was added to stack", va.getTextFromAnyVar(true).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addVarToStackQuick(Variable &va, VariableStack *&thisStack) {
|
||||
VariableStack *newStack = new VariableStack;
|
||||
if (!checkNew(newStack))
|
||||
return false;
|
||||
|
||||
// if (! copyMain (va, newStack -> thisVar)) return false;
|
||||
|
||||
memcpy(&(newStack->thisVar), &va, sizeof(Variable));
|
||||
va.varType = SVT_NULL;
|
||||
|
||||
newStack->next = thisStack;
|
||||
thisStack = newStack;
|
||||
debugC(2, kSludgeDebugStackMachine, "Variable %s was added to stack quick", va.getTextFromAnyVar(true).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VariableStack::stackSetByIndex(uint theIndex, const Variable &va) {
|
||||
VariableStack *vS = this;
|
||||
while (theIndex--) {
|
||||
vS = vS->next;
|
||||
if (!vS)
|
||||
return fatal("Index past end of stack.");
|
||||
}
|
||||
return vS->thisVar.copyFrom(va);
|
||||
}
|
||||
|
||||
Variable *VariableStack::stackGetByIndex(uint theIndex) {
|
||||
VariableStack *vS = this;
|
||||
while (theIndex--) {
|
||||
vS = vS->next;
|
||||
if (!vS) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return &(vS->thisVar);
|
||||
}
|
||||
|
||||
int deleteVarFromStack(const Variable &va, VariableStack *&thisStack, bool allOfEm) {
|
||||
VariableStack **huntVar = &thisStack;
|
||||
VariableStack *killMe;
|
||||
int reply = 0;
|
||||
|
||||
while (*huntVar) {
|
||||
if (va.compareVars((*huntVar)->thisVar)) {
|
||||
killMe = *huntVar;
|
||||
*huntVar = killMe->next;
|
||||
killMe->thisVar.unlinkVar();
|
||||
delete killMe;
|
||||
if (!allOfEm)
|
||||
return 1;
|
||||
reply++;
|
||||
} else {
|
||||
huntVar = &((*huntVar)->next);
|
||||
}
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
// Would be a LOT better just to keep this up to date in the above function... ah well
|
||||
VariableStack *VariableStack::stackFindLast() {
|
||||
VariableStack *hunt = this;
|
||||
while (hunt->next)
|
||||
hunt = hunt->next;
|
||||
|
||||
return hunt;
|
||||
}
|
||||
|
||||
bool Variable::getValueType(int &toHere, VariableType vT) const {
|
||||
if (varType != vT) {
|
||||
Common::String e1 = "Can only perform specified operation on a value which is of type ";
|
||||
e1 += typeName[vT];
|
||||
Common::String e2 = "... value supplied was of type ";
|
||||
e2 += typeName[varType];
|
||||
fatal(e1, e2);
|
||||
|
||||
return false;
|
||||
}
|
||||
toHere = varData.intValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
void trimStack(VariableStack *&stack) {
|
||||
VariableStack *killMe = stack;
|
||||
stack = stack->next;
|
||||
|
||||
debugC(2, kSludgeDebugStackMachine, "Variable %s was removed from stack", killMe->thisVar.getTextFromAnyVar(true).c_str());
|
||||
|
||||
// When calling this, we've ALWAYS checked that stack != NULL
|
||||
killMe->thisVar.unlinkVar();
|
||||
delete killMe;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Globals (so we know what's saved already and what's a reference
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
struct stackLibrary {
|
||||
StackHandler *stack;
|
||||
stackLibrary *next;
|
||||
};
|
||||
|
||||
int stackLibTotal = 0;
|
||||
stackLibrary *stackLib = NULL;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// For saving and loading stacks...
|
||||
//----------------------------------------------------------------------
|
||||
void saveStack(VariableStack *vs, Common::WriteStream *stream) {
|
||||
int elements = 0;
|
||||
int a;
|
||||
|
||||
VariableStack *search = vs;
|
||||
while (search) {
|
||||
elements++;
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
stream->writeUint16BE(elements);
|
||||
search = vs;
|
||||
for (a = 0; a < elements; a++) {
|
||||
search->thisVar.save(stream);
|
||||
search = search->next;
|
||||
}
|
||||
}
|
||||
|
||||
VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last) {
|
||||
int elements = stream->readUint16BE();
|
||||
int a;
|
||||
VariableStack *first = NULL;
|
||||
VariableStack **changeMe = &first;
|
||||
|
||||
for (a = 0; a < elements; a++) {
|
||||
VariableStack *nS = new VariableStack;
|
||||
if (!checkNew(nS))
|
||||
return NULL;
|
||||
nS->thisVar.load(stream);
|
||||
if (last && a == elements - 1) {
|
||||
*last = nS;
|
||||
}
|
||||
nS->next = NULL;
|
||||
(*changeMe) = nS;
|
||||
changeMe = &(nS->next);
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
bool saveStackRef(StackHandler *vs, Common::WriteStream *stream) {
|
||||
stackLibrary *s = stackLib;
|
||||
int a = 0;
|
||||
while (s) {
|
||||
if (s->stack == vs) {
|
||||
stream->writeByte(1);
|
||||
stream->writeUint16BE(stackLibTotal - a);
|
||||
return true;
|
||||
}
|
||||
s = s->next;
|
||||
a++;
|
||||
}
|
||||
stream->writeByte(0);
|
||||
saveStack(vs->first, stream);
|
||||
s = new stackLibrary;
|
||||
stackLibTotal++;
|
||||
if (!checkNew(s))
|
||||
return false;
|
||||
s->next = stackLib;
|
||||
s->stack = vs;
|
||||
stackLib = s;
|
||||
return true;
|
||||
}
|
||||
|
||||
void clearStackLib() {
|
||||
stackLibrary *k;
|
||||
while (stackLib) {
|
||||
k = stackLib;
|
||||
stackLib = stackLib->next;
|
||||
delete k;
|
||||
}
|
||||
stackLibTotal = 0;
|
||||
}
|
||||
|
||||
StackHandler *getStackFromLibrary(int n) {
|
||||
n = stackLibTotal - n;
|
||||
while (n) {
|
||||
stackLib = stackLib->next;
|
||||
n--;
|
||||
}
|
||||
return stackLib->stack;
|
||||
}
|
||||
|
||||
StackHandler *loadStackRef(Common::SeekableReadStream *stream) {
|
||||
StackHandler *nsh;
|
||||
|
||||
if (stream->readByte()) { // It's one we've loaded already...
|
||||
nsh = getStackFromLibrary(stream->readUint16BE());
|
||||
nsh->timesUsed++;
|
||||
} else {
|
||||
// Load the new stack
|
||||
|
||||
nsh = new StackHandler;
|
||||
if (!checkNew(nsh))
|
||||
return NULL;
|
||||
nsh->last = NULL;
|
||||
nsh->first = loadStack(stream, &nsh->last);
|
||||
nsh->timesUsed = 1;
|
||||
|
||||
// Add it to the library of loaded stacks
|
||||
|
||||
stackLibrary *s = new stackLibrary;
|
||||
if (!checkNew(s))
|
||||
return NULL;
|
||||
s->stack = nsh;
|
||||
s->next = stackLib;
|
||||
stackLib = s;
|
||||
stackLibTotal++;
|
||||
}
|
||||
return nsh;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// For saving and loading variables...
|
||||
//----------------------------------------------------------------------
|
||||
bool Variable::save(Common::WriteStream *stream) {
|
||||
stream->writeByte(varType);
|
||||
switch (varType) {
|
||||
case SVT_INT:
|
||||
case SVT_FUNC:
|
||||
case SVT_BUILT:
|
||||
case SVT_FILE:
|
||||
case SVT_OBJTYPE:
|
||||
stream->writeUint32LE(varData.intValue);
|
||||
return true;
|
||||
|
||||
case SVT_STRING:
|
||||
writeString(varData.theString, stream);
|
||||
return true;
|
||||
|
||||
case SVT_STACK:
|
||||
return saveStackRef(varData.theStack, stream);
|
||||
|
||||
case SVT_COSTUME:
|
||||
varData.costumeHandler->save(stream);
|
||||
return false;
|
||||
|
||||
case SVT_ANIM:
|
||||
varData.animHandler->save(stream);
|
||||
return false;
|
||||
|
||||
case SVT_NULL:
|
||||
return false;
|
||||
|
||||
default:
|
||||
fatal("Can't save variables of this type:", (varType < SVT_NUM_TYPES - 1) ? typeName[varType] : "bad ID");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Variable::load(Common::SeekableReadStream *stream) {
|
||||
varType = (VariableType)stream->readByte();
|
||||
switch (varType) {
|
||||
case SVT_INT:
|
||||
case SVT_FUNC:
|
||||
case SVT_BUILT:
|
||||
case SVT_FILE:
|
||||
case SVT_OBJTYPE:
|
||||
varData.intValue = stream->readUint32LE();
|
||||
return true;
|
||||
|
||||
case SVT_STRING:
|
||||
varData.theString = createCString(readString(stream));
|
||||
return true;
|
||||
|
||||
case SVT_STACK:
|
||||
varData.theStack = loadStackRef(stream);
|
||||
return true;
|
||||
|
||||
case SVT_COSTUME:
|
||||
varData.costumeHandler = new Persona;
|
||||
if (!checkNew(varData.costumeHandler))
|
||||
return false;
|
||||
varData.costumeHandler->load(stream);
|
||||
return true;
|
||||
|
||||
case SVT_ANIM:
|
||||
varData.animHandler = new PersonaAnimation;
|
||||
if (!checkNew(varData.animHandler))
|
||||
return false;
|
||||
varData.animHandler->load(stream);
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
160
engines/sludge/variable.h
Normal file
160
engines/sludge/variable.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_VARIABLE_H
|
||||
#define SLUDGE_VARIABLE_H
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
class WriteStream;
|
||||
}
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct Persona;
|
||||
struct PersonaAnimation;
|
||||
struct Variable;
|
||||
struct VariableStack;
|
||||
|
||||
enum VariableType {
|
||||
SVT_NULL,
|
||||
SVT_INT,
|
||||
SVT_FUNC,
|
||||
SVT_STRING,
|
||||
SVT_BUILT,
|
||||
SVT_FILE,
|
||||
SVT_STACK,
|
||||
SVT_OBJTYPE,
|
||||
SVT_ANIM,
|
||||
SVT_COSTUME,
|
||||
SVT_FASTARRAY,
|
||||
SVT_NUM_TYPES
|
||||
};
|
||||
|
||||
struct FastArrayHandler {
|
||||
struct Variable *fastVariables;
|
||||
int size;
|
||||
int timesUsed;
|
||||
|
||||
Variable *fastArrayGetByIndex(uint theIndex);
|
||||
void debugPrint();
|
||||
};
|
||||
|
||||
struct StackHandler {
|
||||
struct VariableStack *first;
|
||||
struct VariableStack *last;
|
||||
int timesUsed;
|
||||
|
||||
int getStackSize() const;
|
||||
bool getSavedGamesStack(const Common::String &ext);
|
||||
|
||||
void debugPrint();
|
||||
};
|
||||
|
||||
union VariableData {
|
||||
signed int intValue;
|
||||
const char *theString;
|
||||
StackHandler *theStack;
|
||||
PersonaAnimation *animHandler;
|
||||
Persona *costumeHandler;
|
||||
FastArrayHandler *fastArray;
|
||||
};
|
||||
|
||||
struct Variable {
|
||||
VariableType varType;
|
||||
VariableData varData;
|
||||
|
||||
Variable() {
|
||||
varType = SVT_NULL;
|
||||
varData.intValue = 0;
|
||||
}
|
||||
|
||||
void unlinkVar();
|
||||
void setVariable(VariableType vT, int value);
|
||||
|
||||
// Copy from another variable
|
||||
bool copyFrom(const Variable &from);
|
||||
bool copyMain(const Variable &from); // without variable unlink
|
||||
|
||||
// Load & save
|
||||
bool save(Common::WriteStream *stream);
|
||||
bool load(Common::SeekableReadStream *stream);
|
||||
|
||||
// Text variable
|
||||
void makeTextVar(const Common::String &txt);
|
||||
bool loadStringToVar(int value);
|
||||
|
||||
// Animation variable
|
||||
void makeAnimationVariable(PersonaAnimation *i);
|
||||
struct PersonaAnimation *getAnimationFromVar();
|
||||
|
||||
// Custome variable
|
||||
void makeCostumeVariable(Persona *i);
|
||||
struct Persona *getCostumeFromVar();
|
||||
|
||||
// Fast array variable
|
||||
bool makeFastArrayFromStack(const StackHandler *stacky);
|
||||
bool makeFastArraySize(int size);
|
||||
|
||||
// Stack variable
|
||||
bool copyStack(const Variable &from);
|
||||
|
||||
// Add variables
|
||||
void addVariablesInSecond(const Variable &other);
|
||||
void compareVariablesInSecond(const Variable &other);
|
||||
int compareVars(const Variable &other) const;
|
||||
|
||||
// General getters
|
||||
Common::String getTextFromAnyVar(bool skipLoad = false) const;
|
||||
bool getBoolean() const;
|
||||
bool getValueType(int &toHere, VariableType vT) const;
|
||||
|
||||
void debugPrint();
|
||||
};
|
||||
|
||||
struct VariableStack {
|
||||
Variable thisVar;
|
||||
VariableStack *next;
|
||||
|
||||
// Variable getter & setter
|
||||
bool stackSetByIndex(uint, const Variable &);
|
||||
Variable *stackGetByIndex(uint);
|
||||
|
||||
// Find last
|
||||
VariableStack *stackFindLast();
|
||||
};
|
||||
|
||||
// Stacky stuff
|
||||
|
||||
bool addVarToStack(const Variable &va, VariableStack *&thisStack);
|
||||
bool addVarToStackQuick(Variable &va, VariableStack *&thisStack);
|
||||
void trimStack(VariableStack *&stack);
|
||||
int deleteVarFromStack(const Variable &va, VariableStack *&thisStack, bool allOfEm = false);
|
||||
|
||||
// load & save
|
||||
void saveStack(VariableStack *vs, Common::WriteStream *stream);
|
||||
VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last);
|
||||
bool saveStackRef(StackHandler *vs, Common::WriteStream *stream);
|
||||
StackHandler *loadStackRef(Common::SeekableReadStream *stream);
|
||||
void clearStackLib();
|
||||
|
||||
} // End of namespace Sludge
|
||||
|
||||
#endif
|
||||
37
engines/sludge/version.h
Normal file
37
engines/sludge/version.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#define MAJOR_VERSION 2
|
||||
#define MINOR_VERSION 2
|
||||
#define RELEASE_VERSION 1
|
||||
#define BUILD_VERSION 208
|
||||
#define TEXT_VERSION "2.2.1"
|
||||
#define WHOLE_VERSION (MAJOR_VERSION * 256 + MINOR_VERSION) // This version
|
||||
#define MINIM_VERSION (1 * 256 + 2) // Earliest version of games the engine can run
|
||||
|
||||
#define COPYRIGHT_TEXT "\251 Hungry Software and contributors 2000-2014"
|
||||
|
||||
#define VERSION(a,b) (a * 256 + b)
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
extern int gameVersion;
|
||||
|
||||
} // End of namespace Sludge
|
||||
232
engines/sludge/zbuffer.cpp
Normal file
232
engines/sludge/zbuffer.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "image/png.h"
|
||||
|
||||
#include "sludge/fileset.h"
|
||||
#include "sludge/graphics.h"
|
||||
#include "sludge/newfatal.h"
|
||||
#include "sludge/sludge.h"
|
||||
#include "sludge/zbuffer.h"
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
void GraphicsManager::killZBuffer() {
|
||||
|
||||
if (_zBuffer->tex) {
|
||||
delete[] _zBuffer->tex;
|
||||
_zBuffer->tex = nullptr;
|
||||
}
|
||||
|
||||
_zBuffer->numPanels = 0;
|
||||
_zBuffer->originalNum = -1;
|
||||
}
|
||||
|
||||
void GraphicsManager::sortZPal(int *oldpal, int *newpal, int size) {
|
||||
int i, tmp;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
newpal[i] = i;
|
||||
}
|
||||
|
||||
if (size < 2)
|
||||
return;
|
||||
|
||||
for (i = 1; i < size; i++) {
|
||||
if (oldpal[newpal[i]] < oldpal[newpal[i - 1]]) {
|
||||
tmp = newpal[i];
|
||||
newpal[i] = newpal[i - 1];
|
||||
newpal[i - 1] = tmp;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsManager::setZBuffer(int num) {
|
||||
// if the backdrop has not been set yet
|
||||
// set zbuffer later
|
||||
if (!_backdropSurface.getPixels()) {
|
||||
_zBuffer->originalNum = num;
|
||||
return true;
|
||||
}
|
||||
|
||||
debug (kSludgeDebugGraphics, "Setting zBuffer");
|
||||
uint32 stillToGo = 0;
|
||||
int yPalette[16], sorted[16], sortback[16];
|
||||
|
||||
killZBuffer();
|
||||
|
||||
setResourceForFatal(num);
|
||||
|
||||
_zBuffer->originalNum = num;
|
||||
uint fsize = g_sludge->_resMan->openFileFromNum(num);
|
||||
if (!fsize)
|
||||
return false;
|
||||
|
||||
Common::SeekableReadStream *readStream = g_sludge->_resMan->getData();
|
||||
|
||||
g_sludge->_resMan->dumpFile(num, "zbuffer%04d.zbu");
|
||||
|
||||
if (readStream->readByte() != 'S')
|
||||
return fatal("Not a Z-buffer file");
|
||||
if (readStream->readByte() != 'z')
|
||||
return fatal("Not a Z-buffer file");
|
||||
if (readStream->readByte() != 'b')
|
||||
return fatal("Not a Z-buffer file");
|
||||
|
||||
switch (readStream->readByte()) {
|
||||
case 0:
|
||||
_zBuffer->width = 640;
|
||||
_zBuffer->height = 480;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_zBuffer->width = readStream->readUint16BE();
|
||||
_zBuffer->height = readStream->readUint16BE();
|
||||
break;
|
||||
|
||||
default:
|
||||
return fatal("Extended Z-buffer format not supported in this version of the SLUDGE engine");
|
||||
}
|
||||
if (_zBuffer->width != _sceneWidth || _zBuffer->height != _sceneHeight) {
|
||||
Common::String tmp = Common::String::format("Z-w: %d Z-h:%d w: %d, h:%d", _zBuffer->width, _zBuffer->height, _sceneWidth, _sceneHeight);
|
||||
return fatal("Z-buffer width and height don't match scene width and height", tmp);
|
||||
}
|
||||
|
||||
_zBuffer->numPanels = readStream->readByte();
|
||||
debugC(2, kSludgeDebugZBuffer, "Loading zBuffer : %i panels", _zBuffer->numPanels);
|
||||
for (int y = 0; y < _zBuffer->numPanels; y++) {
|
||||
yPalette[y] = readStream->readUint16BE();
|
||||
}
|
||||
sortZPal(yPalette, sorted, _zBuffer->numPanels);
|
||||
for (int y = 0; y < _zBuffer->numPanels; y++) {
|
||||
_zBuffer->panel[y] = yPalette[sorted[y]];
|
||||
sortback[sorted[y]] = y;
|
||||
debugC(2, kSludgeDebugZBuffer, "Y-value : %i", _zBuffer->panel[y]);
|
||||
}
|
||||
|
||||
int picWidth = _sceneWidth;
|
||||
int picHeight = _sceneHeight;
|
||||
|
||||
_zBuffer->tex = nullptr;
|
||||
_zBuffer->tex = new uint8[picHeight * picWidth];
|
||||
|
||||
int n = 0;
|
||||
|
||||
for (uint y = 0; y < _sceneHeight; y++) {
|
||||
for (uint x = 0; x < _sceneWidth; x++) {
|
||||
if (stillToGo == 0) {
|
||||
n = readStream->readByte();
|
||||
stillToGo = n >> 4;
|
||||
if (stillToGo == 15)
|
||||
stillToGo = readStream->readUint16BE() + 16l;
|
||||
else
|
||||
stillToGo++;
|
||||
n &= 15;
|
||||
}
|
||||
|
||||
_zBuffer->tex[y*picWidth + x] = sortback[n];
|
||||
|
||||
stillToGo--;
|
||||
}
|
||||
}
|
||||
|
||||
g_sludge->_resMan->finishAccess();
|
||||
setResourceForFatal(-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsManager::fillZBuffer(uint8 d) {
|
||||
memset(_zBufferSurface, d, _winHeight * _winWidth);
|
||||
}
|
||||
|
||||
void GraphicsManager::drawSpriteToZBuffer(int x, int y, uint8 depth, const Graphics::Surface &surface) {
|
||||
|
||||
for (uint y1 = 0; y1 < (uint)surface.h; y1++) {
|
||||
for (uint x1 = 0; x1 < (uint)surface.w; x1++) {
|
||||
if (x1 + x >= _sceneWidth || y1 + y >= _sceneHeight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte *target = (byte *)_renderSurface.getBasePtr(x1 + x, y1 + y);
|
||||
const byte *source = (const byte *)surface.getBasePtr(x1, y1);
|
||||
|
||||
if (depth > _zBufferSurface[(y1 + y) * _winWidth + (x1 + x)]) {
|
||||
|
||||
if (source[0] == 0xff) {
|
||||
// Completely opaque, so copy RGB values over
|
||||
target[0] = 0xff;
|
||||
target[1] = source[1];
|
||||
target[2] = source[2];
|
||||
target[3] = source[3];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsManager::drawZBuffer(int x, int y, bool upsidedown) {
|
||||
if (!_zBuffer->numPanels || !_zBuffer->tex)
|
||||
return;
|
||||
|
||||
fillZBuffer(0);
|
||||
|
||||
int w = MIN<uint>(_zBuffer->width, _winWidth + x);
|
||||
int h = MIN<uint>(_zBuffer->height, _winHeight + y);
|
||||
|
||||
for (int y1 = y; y1 < h; y1++) {
|
||||
for (int x1 = x; x1 < w; x1++) {
|
||||
uint8 z = 0;
|
||||
|
||||
if (upsidedown) {
|
||||
z = (_zBuffer->tex[(_zBuffer->height - y1) * _zBuffer->width + x1] + 1) * 2;
|
||||
} else {
|
||||
z = (_zBuffer->tex[y1 * _zBuffer->width + x1] + 1) * 2;
|
||||
}
|
||||
|
||||
if ( z > _zBufferSurface[(y1 - y) * _winWidth + (x1 - x)])
|
||||
_zBufferSurface[(y1 - y) * _winWidth + (x1 - x)] = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsManager::saveZBuffer(Common::WriteStream *stream) {
|
||||
if (_zBuffer->numPanels > 0) {
|
||||
stream->writeByte(1);
|
||||
stream->writeUint16BE(_zBuffer->originalNum);
|
||||
} else {
|
||||
stream->writeByte(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsManager::loadZBuffer(Common::SeekableReadStream *stream) {
|
||||
if (stream->readByte()) {
|
||||
if (!setZBuffer(stream->readUint16BE()))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sludge
|
||||
39
engines/sludge/zbuffer.h
Normal file
39
engines/sludge/zbuffer.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef SLUDGE_ZBUFFER_H
|
||||
#define SLUDGE_ZBUFFER_H
|
||||
|
||||
namespace Sludge {
|
||||
|
||||
struct ZBufferData {
|
||||
// bool loaded;
|
||||
uint width, height;
|
||||
int numPanels;
|
||||
int panel[16];
|
||||
int originalNum;
|
||||
|
||||
uint8 *tex;
|
||||
Graphics::Surface *sprites;
|
||||
};
|
||||
|
||||
} // End of namespace Sludges
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user