Initial import of the work in progress MADE engine

svn-id: r31599
This commit is contained in:
Filippos Karapetis 2008-04-20 14:43:56 +00:00
parent d484c7ed43
commit d0590a09ea
20 changed files with 4397 additions and 0 deletions

393
engines/made/database.cpp Normal file
View file

@ -0,0 +1,393 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/endian.h"
#include "common/util.h"
#include "made/database.h"
namespace Made {
/*
Class types:
0x7FFF byte array
0x7FFE word array
< 0x7FFE object
*/
Object::Object() {
}
Object::~Object() {
if (_freeData && _objData)
delete[] _objData;
}
void Object::load(Common::SeekableReadStream &source) {
_freeData = true;
source.readUint16LE(); // skip flags
uint16 type = source.readUint16LE();
/*
if (type < 0x7FFE) {
byte count1 = source.readByte();
byte count2 = source.readByte();
_objSize = (count1 + count2) * 2;
} else {
_objSize = source.readUint16LE();
}
*/
if (type == 0x7FFF) {
_objSize = source.readUint16LE();
} else if (type == 0x7FFE) {
_objSize = source.readUint16LE() * 2;
} else if (type < 0x7FFE) {
byte count1 = source.readByte();
byte count2 = source.readByte();
_objSize = (count1 + count2) * 2;
}
source.seek(-6, SEEK_CUR);
_objSize += 6;
_objData = new byte[_objSize];
source.read(_objData, _objSize);
/*
debug(2, "Object::load(con): flags = %04X; type = %04X; _objSize = %04X\n", getFlags(), getClass(), _objSize);
fflush(stdout);
*/
}
void Object::load(byte *source) {
_objData = source;
_freeData = false;
if (getClass() < 0x7FFE) {
_objSize = (getCount1() + getCount2()) * 2;
} else {
_objSize = getSize();
}
_objSize += 6;
/*
debug(2, "Object::load(var): flags = %04X; type = %04X; _objSize = %04X\n", getFlags(), getClass(), _objSize);
fflush(stdout);
*/
}
uint16 Object::getFlags() const {
return READ_LE_UINT16(_objData);
}
uint16 Object::getClass() const {
return READ_LE_UINT16(_objData + 2);
}
uint16 Object::getSize() const {
return READ_LE_UINT16(_objData + 4);
}
byte Object::getCount1() const {
return _objData[4];
}
byte Object::getCount2() const {
return _objData[5];
}
byte *Object::getData() {
return _objData + 6;
}
const char *Object::getString() {
if (getClass() == 0x7FFF)
return (const char*)getData();
else
return NULL;
}
bool Object::isObject() {
return getClass() < 0x7FFE;
}
bool Object::isVector() {
return getClass() == 0x7FFF;
}
int16 Object::getVectorSize() {
if (getClass() == 0x7FFF || getClass() == 0x7FFE) {
return getSize();
} else if (getClass() < 0x7FFE) {
return getCount1() + getCount2();
} else {
return 0; // FIXME
}
}
int16 Object::getVectorItem(int16 index) {
if (getClass() == 0x7FFF) {
byte *vector = (byte*)getData();
return vector[index];
} else if (getClass() == 0x7FFE) {
int16 *vector = (int16*)getData();
return vector[index];
} else if (getClass() < 0x7FFE) {
int16 *vector = (int16*)getData();
return vector[index];
} else {
return 0; // FIXME
}
}
void Object::setVectorItem(int16 index, int16 value) {
if (getClass() == 0x7FFF) {
byte *vector = (byte*)getData();
vector[index] = value;
} else if (getClass() <= 0x7FFE) {
int16 *vector = (int16*)getData();
vector[index] = value;
}
}
void Object::dump(const char *filename) {
/*
FILE *o = fopen(filename, "wb");
fwrite(_objData, _objSize, 1, o);
fclose(o);
*/
}
GameDatabase::GameDatabase() {
}
GameDatabase::~GameDatabase() {
if (_gameState)
delete[] _gameState;
}
void GameDatabase::open(const char *filename) {
_fd.open(filename);
// TODO: Read/verifiy header
_fd.seek(0x1E);
uint32 objectIndexOffs = _fd.readUint32LE();
uint16 objectCount = _fd.readUint16LE();
uint32 gameStateOffs = _fd.readUint32LE();
_gameStateSize = _fd.readUint32LE();
uint32 objectsOffs = _fd.readUint32LE();
uint32 objectsSize = _fd.readUint32LE();
_mainCodeObjectIndex = _fd.readUint16LE();
debug(2, "objectIndexOffs = %08X; objectCount = %d; gameStateOffs = %08X; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n",
objectIndexOffs, objectCount, gameStateOffs, _gameStateSize, objectsOffs, objectsSize);
_gameState = new byte[_gameStateSize];
_fd.seek(gameStateOffs);
_fd.read(_gameState, _gameStateSize);
Common::Array<uint32> objectOffsets;
_fd.seek(objectIndexOffs);
for (uint32 i = 0; i < objectCount; i++)
objectOffsets.push_back(_fd.readUint32LE());
for (uint32 i = 0; i < objectCount; i++) {
Object *obj = new Object();
// The LSB indicates if it's a constant or variable object
debug(2, "obj(%04X) ofs = %08X\n", i, objectOffsets[i]);
if (objectOffsets[i] & 1) {
debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1);
_fd.seek(objectsOffs + objectOffsets[i] - 1);
obj->load(_fd);
} else {
debug(2, "-> var\n");
obj->load(_gameState + objectOffsets[i]);
}
_objects.push_back(obj);
}
}
int16 GameDatabase::getVar(int16 index) {
return (int16)READ_LE_UINT16(_gameState + index * 2);
}
void GameDatabase::setVar(int16 index, int16 value) {
WRITE_LE_UINT16(_gameState + index * 2, value);
}
int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag) {
Object *obj = getObject(objectIndex);
//dumpObject(objectIndex);
int16 *prop = (int16*)obj->getData();
byte count1 = obj->getCount1();
byte count2 = obj->getCount2();
int16 *propPtr1 = prop + count1;
int16 *propPtr2 = prop + count2;
debug(2, "# propertyId = %04X\n", propertyId);
// First see if the property exists in the given object
while (count2-- > 0) {
if ((*prop & 0x3FFF) == propertyId) {
if (*prop & 0x4000) {
debug(2, "! L1.1\n");
propertyFlag = 1;
return (int16*)_gameState + *propPtr1;
} else {
debug(2, "! L1.2\n");
propertyFlag = obj->getFlags() & 1;
return propPtr1;
}
}
prop++;
propPtr1++;
}
// Now check in the object hierarchy of the given object
int16 parentObjectIndex = obj->getClass();
if (parentObjectIndex == 0) {
debug(2, "! NULL(np)\n");
return NULL;
}
while (parentObjectIndex != 0) {
debug(2, "parentObjectIndex = %04X\n", parentObjectIndex);
//dumpObject(parentObjectIndex);
obj = getObject(parentObjectIndex);
prop = (int16*)obj->getData();
count1 = obj->getCount1();
count2 = obj->getCount2();
propPtr1 = propPtr2 + count1 - count2;
int16 *propertyPtr = prop + count1;
while (count2-- > 0) {
if (!(*prop & 0x8000)) {
if ((*prop & 0x3FFF) == propertyId) {
if (*prop & 0x4000) {
debug(2, "! L2.1\n");
propertyFlag = 1;
return (int16*)_gameState + *propPtr1;
} else {
debug(2, "! L2.2\n");
propertyFlag = obj->getFlags() & 1;
return propPtr1;
}
} else {
propPtr1++;
}
} else {
if ((*prop & 0x3FFF) == propertyId) {
if (*prop & 0x4000) {
debug(2, "! L3.1\n");
propertyFlag = 1;
return (int16*)_gameState + *propertyPtr;
} else {
debug(2, "! L3.2\n");
propertyFlag = obj->getFlags() & 1;
return propertyPtr;
}
}
}
prop++;
propertyPtr++;
}
parentObjectIndex = obj->getClass();
}
debug(2, "! NULL(nf)\n");
return NULL;
fflush(stdout);
}
int16 GameDatabase::getObjectProperty(int16 objectIndex, int16 propertyId) {
if (objectIndex == 0)
return 0;
int16 propertyFlag;
int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag);
if (property) {
return *property;
} else {
return 0;
}
}
int16 GameDatabase::setObjectProperty(int16 objectIndex, int16 propertyId, int16 value) {
if (objectIndex == 0)
return 0;
int16 propertyFlag;
int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag);
if (property) {
if (propertyFlag == 1) {
*property = value;
} else {
debug(2, "GameDatabase::setObjectProperty(%04X, %04X, %04X) Trying to set constant property\n",
objectIndex, propertyId, value);
}
return value;
} else {
return 0;
}
}
void GameDatabase::dumpObject(int16 index) {
Object *obj = getObject(index);
char fn[512];
sprintf(fn, "obj%04X.0", index);
obj->dump(fn);
}
} // End of namespace Made

105
engines/made/database.h Normal file
View file

@ -0,0 +1,105 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MADE_DATABASE_H
#define MADE_DATABASE_H
#include "common/array.h"
#include "common/util.h"
#include "common/file.h"
#include "common/stream.h"
namespace Made {
class Object {
public:
Object();
~Object();
void load(Common::SeekableReadStream &source);
void load(byte *source);
uint16 getFlags() const;
uint16 getClass() const;
uint16 getSize() const;
byte getCount1() const;
byte getCount2() const;
byte *getData();
const char *getString();
bool isObject();
bool isVector();
bool isConstant() const { return !(getFlags() & 1); }
int16 getVectorSize();
int16 getVectorItem(int16 index);
void setVectorItem(int16 index, int16 value);
void dump(const char *filename);
protected:
bool _freeData;
uint16 _objSize;
byte *_objData;
};
class GameDatabase {
public:
GameDatabase();
~GameDatabase();
void open(const char *filename);
Object *getObject(int16 index) const {
if (index >= 1)
return _objects[index - 1];
else
return NULL;
}
int16 getMainCodeObjectIndex() const { return _mainCodeObjectIndex; }
int16 getVar(int16 index);
void setVar(int16 index, int16 value);
int16 *getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag);
int16 getObjectProperty(int16 objectIndex, int16 propertyId);
int16 setObjectProperty(int16 objectIndex, int16 propertyId, int16 value);
void dumpObject(int16 index);
protected:
Common::File _fd;
Common::Array<Object*> _objects;
byte *_gameState;
uint32 _gameStateSize;
int16 _mainCodeObjectIndex;
};
} // End of namespace Made
#endif /* MADE_H */

172
engines/made/detection.cpp Normal file
View file

@ -0,0 +1,172 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "base/plugins.h"
#include "common/advancedDetector.h"
#include "common/file.h"
#include "made/made.h"
namespace Made {
struct MadeGameDescription {
Common::ADGameDescription desc;
int gameID;
int gameType;
uint32 features;
uint16 version;
};
uint32 MadeEngine::getGameID() const {
return _gameDescription->gameID;
}
uint32 MadeEngine::getFeatures() const {
return _gameDescription->features;
}
Common::Platform MadeEngine::getPlatform() const {
return _gameDescription->desc.platform;
}
uint16 MadeEngine::getVersion() const {
return _gameDescription->version;
}
}
static const PlainGameDescriptor madeGames[] = {
{"made", "Return to Zork"},
{0, 0}
};
namespace Made {
static const MadeGameDescription gameDescriptions[] = {
{
// Made English version
{
"made",
"CD",
AD_ENTRY1("rtzcd.dat", "a1db8c97a78dae10f91d356f16ad07b8"),
Common::EN_ANY,
Common::kPlatformPC,
Common::ADGF_NO_FLAGS
},
0,
0,
0,
0,
},
{ AD_TABLE_END_MARKER, 0, 0, 0, 0 }
};
/**
* The fallback game descriptor used by the Made engine's fallbackDetector.
* Contents of this struct are to be overwritten by the fallbackDetector.
*/
static MadeGameDescription g_fallbackDesc = {
{
"",
"",
AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
Common::UNK_LANG,
Common::kPlatformPC,
Common::ADGF_NO_FLAGS
},
0,
0,
0,
0,
};
} // End of namespace Made
static const Common::ADParams detectionParams = {
// Pointer to ADGameDescription or its superset structure
(const byte *)Made::gameDescriptions,
// Size of that superset structure
sizeof(Made::MadeGameDescription),
// Number of bytes to compute MD5 sum for
5000,
// List of all engine targets
madeGames,
// Structure for autoupgrading obsolete targets
0,
// Name of single gameid (optional)
"made",
// List of files for file-based fallback detection (optional)
0,
// Flags
0
};
class MadeMetaEngine : public Common::AdvancedMetaEngine {
public:
MadeMetaEngine() : Common::AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
return "MADE Engine";
}
virtual const char *getCopyright() const {
return "MADE Engine";
}
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
const Common::ADGameDescription *fallbackDetect(const FSList *fslist) const;
};
bool MadeMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Made::MadeGameDescription *gd = (const Made::MadeGameDescription *)desc;
if (gd) {
*engine = new Made::MadeEngine(syst, gd);
}
return gd != 0;
}
const Common::ADGameDescription *MadeMetaEngine::fallbackDetect(const FSList *fslist) const {
// Set the default values for the fallback descriptor's ADGameDescription part.
Made::g_fallbackDesc.desc.language = Common::UNK_LANG;
Made::g_fallbackDesc.desc.platform = Common::kPlatformPC;
Made::g_fallbackDesc.desc.flags = Common::ADGF_NO_FLAGS;
// Set default values for the fallback descriptor's MadeGameDescription part.
Made::g_fallbackDesc.gameID = 0;
Made::g_fallbackDesc.features = 0;
Made::g_fallbackDesc.version = 0;
return (const Common::ADGameDescription *)&Made::g_fallbackDesc;
}
REGISTER_PLUGIN(MADE, PLUGIN_TYPE_ENGINE, MadeMetaEngine);

152
engines/made/graphics.cpp Normal file
View file

@ -0,0 +1,152 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/endian.h"
#include "made/graphics.h"
namespace Made {
void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, bool deltaFrame) {
const int offsets[] = {
0, 1, 2, 3,
320, 321, 322, 323,
640, 641, 642, 643,
960, 961, 962, 963
};
uint16 width = surface.w;
uint16 height = surface.h;
byte *cmdBuffer = source + cmdOffs;
byte *maskBuffer = source + maskOffs;
byte *pixelBuffer = source + pixelOffs;
byte *destPtr = (byte*)surface.getBasePtr(0, 0);
//byte lineBuf[320 * 4];
byte lineBuf[640 * 4];
byte bitBuf[40];
int bitBufLastOfs = (((lineSize + 1) >> 1) << 1) - 2;
int bitBufLastCount = ((width + 3) >> 2) & 7;
if (bitBufLastCount == 0)
bitBufLastCount = 8;
while (height > 0) {
int drawDestOfs = 0;
memset(lineBuf, 0, sizeof(lineBuf));
memcpy(bitBuf, cmdBuffer, lineSize);
cmdBuffer += lineSize;
for (uint16 bitBufOfs = 0; bitBufOfs < lineSize; bitBufOfs += 2) {
uint16 bits = READ_LE_UINT16(&bitBuf[bitBufOfs]);
int bitCount;
if (bitBufOfs == bitBufLastOfs)
bitCount = bitBufLastCount;
else
bitCount = 8;
for (int curCmd = 0; curCmd < bitCount; curCmd++) {
int cmd = bits & 3;
bits >>= 2;
byte pixels[4];
uint32 mask;
switch (cmd) {
case 0:
pixels[0] = *pixelBuffer++;
for (int i = 0; i < 16; i++)
lineBuf[drawDestOfs + offsets[i]] = pixels[0];
break;
case 1:
pixels[0] = *pixelBuffer++;
pixels[1] = *pixelBuffer++;
mask = READ_LE_UINT16(maskBuffer);
maskBuffer += 2;
for (int i = 0; i < 16; i++) {
lineBuf[drawDestOfs + offsets[i]] = pixels[mask & 1];
mask >>= 1;
}
break;
case 2:
pixels[0] = *pixelBuffer++;
pixels[1] = *pixelBuffer++;
pixels[2] = *pixelBuffer++;
pixels[3] = *pixelBuffer++;
mask = READ_LE_UINT32(maskBuffer);
maskBuffer += 4;
for (int i = 0; i < 16; i++) {
lineBuf[drawDestOfs + offsets[i]] = pixels[mask & 3];
mask >>= 2;
}
break;
case 3:
if (!deltaFrame) {
// Yes, it reads from maskBuffer here
for (int i = 0; i < 16; i++)
lineBuf[drawDestOfs + offsets[i]] = *maskBuffer++;
}
break;
}
drawDestOfs += 4;
}
}
if (deltaFrame) {
for (int y = 0; y < 4 && height > 0; y++, height--) {
for (int x = 0; x < width; x++) {
if (lineBuf[x + y * 320] != 0)
*destPtr = lineBuf[x + y * 320];
destPtr++;
}
}
} else {
for (int y = 0; y < 4 && height > 0; y++, height--) {
memcpy(destPtr, &lineBuf[y * 320], width);
destPtr += width;
}
}
}
}
} // End of namespace Made

40
engines/made/graphics.h Normal file
View file

@ -0,0 +1,40 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MADE_GRAPHICS_H
#define MADE_GRAPHICS_H
#include "common/util.h"
#include "common/file.h"
#include "common/stream.h"
#include "graphics/surface.h"
namespace Made {
void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, bool deltaFrame = false);
} // End of namespace Made
#endif /* MADE_H */

155
engines/made/made.cpp Normal file
View file

@ -0,0 +1,155 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/events.h"
#include "common/keyboard.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/config-manager.h"
#include "graphics/cursorman.h"
#include "base/plugins.h"
#include "base/version.h"
#include "sound/mixer.h"
#include "made/made.h"
#include "made/database.h"
#include "made/pmvplayer.h"
#include "made/resource.h"
#include "made/screen.h"
#include "made/script.h"
#include "made/sound.h"
namespace Made {
struct GameSettings {
const char *gameid;
const char *description;
byte id;
uint32 features;
const char *detectname;
};
static const GameSettings madeSettings[] = {
{"made", "Made game", 0, 0, 0},
{NULL, NULL, 0, 0, NULL}
};
MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
// Setup mixer
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
const GameSettings *g;
const char *gameid = ConfMan.get("gameid").c_str();
for (g = madeSettings; g->gameid; ++g)
if (!scumm_stricmp(g->gameid, gameid))
_gameId = g->id;
_rnd = new Common::RandomSource();
syst->getEventManager()->registerRandomSource(*_rnd, "made");
int cd_num = ConfMan.getInt("cdrom");
if (cd_num >= 0)
_system->openCD(cd_num);
_pmvPlayer = new PmvPlayer(_system, _mixer);
_res = new ProjectReader();
_screen = new Screen(this);
_dat = new GameDatabase();
_script = new ScriptInterpreter(this);
}
MadeEngine::~MadeEngine() {
delete _rnd;
delete _pmvPlayer;
delete _res;
delete _screen;
delete _dat;
delete _script;
}
int MadeEngine::init() {
// Initialize backend
_system->beginGFXTransaction();
initCommonGFX(false);
_system->initSize(320, 200);
_system->endGFXTransaction();
return 0;
}
int16 MadeEngine::getTimer(int16 timerNum) {
return (_system->getMillis() - _timers[timerNum]) / 60;
}
void MadeEngine::setTimer(int16 timerNum, int16 value) {
_timers[timerNum] = value * 60;
}
void MadeEngine::resetTimer(int16 timerNum) {
_timers[timerNum] = _system->getMillis();
}
int16 MadeEngine::allocTimer() {
for (int i = 0; i < ARRAYSIZE(_timers); i++) {
if (_timers[i] == -1) {
resetTimer(i);
return i + 1;
}
}
return 0;
}
void MadeEngine::freeTimer(int16 timerNum) {
_timers[timerNum] = -1;
}
int MadeEngine::go() {
for (int i = 0; i < ARRAYSIZE(_timers); i++)
_timers[i] = -1;
_dat->open("rtzcd.dat");
_res->open("rtzcd.prj");
PictureResource *flex1 = _res->getPicture(78);
Graphics::Surface *surf = flex1->getPicture();
CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, 0, 0, 0);
CursorMan.showMouse(true);
_res->freeResource(flex1);
_eventMouseX = _eventMouseY = 0;
_script->runScript(_dat->getMainCodeObjectIndex());
return 0;
}
} // End of namespace Made

106
engines/made/made.h Normal file
View file

@ -0,0 +1,106 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MADE_H
#define MADE_H
#include "common/scummsys.h"
#include "common/endian.h"
#include "common/util.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/system.h"
#include "common/hash-str.h"
#include "common/events.h"
#include "common/keyboard.h"
#include "graphics/surface.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
#include "sound/voc.h"
#include "sound/audiocd.h"
#include "engines/engine.h"
namespace Made {
enum MadeGameFeatures {
};
struct MadeGameDescription;
class ProjectReader;
class PmvPlayer;
class Screen;
class ScriptInterpreter;
class GameDatabase;
class MadeEngine : public ::Engine {
int _gameId;
Common::KeyState _keyPressed;
protected:
int init();
int go();
public:
MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc);
virtual ~MadeEngine();
int getGameId() {
return _gameId;
}
Common::RandomSource *_rnd;
const MadeGameDescription *_gameDescription;
uint32 getGameID() const;
uint32 getFeatures() const;
uint16 getVersion() const;
Common::Platform getPlatform() const;
void update_events();
private:
public:
PmvPlayer *_pmvPlayer;
ProjectReader *_res;
Screen *_screen;
GameDatabase *_dat;
ScriptInterpreter *_script;
int _eventMouseX, _eventMouseY;
int32 _timers[50];
int16 getTimer(int16 timerNum);
void setTimer(int16 timerNum, int16 value);
void resetTimer(int16 timerNum);
int16 allocTimer();
void freeTimer(int16 timerNum);
};
} // End of namespace Made
#endif /* MADE_H */

22
engines/made/module.mk Normal file
View file

@ -0,0 +1,22 @@
MODULE := engines/made
MODULE_OBJS = \
database.o \
detection.o \
graphics.o \
made.o \
pmvplayer.o \
resource.o \
screen.o \
script.o \
scriptfuncs.o \
sound.o
# This module can be built as a plugin
ifdef BUILD_PLUGINS
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk

152
engines/made/pmvplayer.cpp Normal file
View file

@ -0,0 +1,152 @@
#include "made/pmvplayer.h"
namespace Made {
PmvPlayer::PmvPlayer(OSystem *system, Audio::Mixer *mixer) : _fd(NULL), _system(system), _mixer(mixer) {
}
PmvPlayer::~PmvPlayer() {
}
void PmvPlayer::play(const char *filename) {
_abort = false;
_surface = NULL;
_fd = new Common::File();
_fd->open(filename);
uint32 chunkType, chunkSize;
readChunk(chunkType, chunkSize); // "MOVE"
readChunk(chunkType, chunkSize); // "MHED"
// TODO: Evaluate header
//_fd->skip(0x3A);
uint frameDelay = _fd->readUint16LE();
_fd->skip(10);
uint soundFreq = _fd->readUint16LE();
// FIXME: weird frequencies... (11127 or 22254)
//if (soundFreq == 11127) soundFreq = 11025;
//if (soundFreq == 22254) soundFreq = 22050;
int unk;
for (int i = 0; i < 22; i++) {
unk = _fd->readUint16LE();
debug(2, "%i ", unk);
}
debug(2, "\n");
_mixer->stopAll();
_audioStream = Audio::makeAppendableAudioStream(soundFreq, Audio::Mixer::FLAG_UNSIGNED);
_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream);
// Read palette
_fd->read(_palette, 768);
updatePalette();
//FILE *raw = fopen("track.raw", "wb");
while (!_abort && !_fd->eof()) {
readChunk(chunkType, chunkSize);
if (_fd->eof())
break;
byte *frameData = new byte[chunkSize];
_fd->read(frameData, chunkSize);
byte *audioData = frameData + READ_LE_UINT32(frameData + 8) - 8;
uint16 chunkSize = READ_LE_UINT16(audioData + 4);
uint16 chunkCount = READ_LE_UINT16(audioData + 6);
if (chunkCount > 50) break; // FIXME: this is a hack
debug(2, "chunkCount = %d; chunkSize = %d\n", chunkCount, chunkSize);
uint32 soundSize = chunkCount * chunkSize;
byte *soundData = new byte[soundSize];
decompressSound(audioData + 8, soundData, chunkSize, chunkCount);
_audioStream->queueBuffer(soundData, soundSize);
//fwrite(soundData, soundSize, 1, raw);
byte *imageData = frameData + READ_LE_UINT32(frameData + 12) - 8;
uint32 frameNum = READ_LE_UINT32(frameData);
uint16 width = READ_LE_UINT16(imageData + 8);
uint16 height = READ_LE_UINT16(imageData + 10);
uint16 cmdOffs = READ_LE_UINT16(imageData + 12);
uint16 pixelOffs = READ_LE_UINT16(imageData + 16);
uint16 maskOffs = READ_LE_UINT16(imageData + 20);
uint16 lineSize = READ_LE_UINT16(imageData + 24);
debug(2, "width = %d; height = %d; cmdOffs = %04X; pixelOffs = %04X; maskOffs = %04X; lineSize = %d\n",
width, height, cmdOffs, pixelOffs, maskOffs, lineSize);
if (!_surface) {
_surface = new Graphics::Surface();
_surface->create(width, height, 1);
}
decompressImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize, frameNum > 0);
handleEvents();
updateScreen();
delete[] frameData;
_system->delayMillis(frameDelay);
}
_audioStream->finish();
_mixer->stopAll();
//delete _audioStream;
delete _fd;
delete _surface;
//fclose(raw);
}
void PmvPlayer::readChunk(uint32 &chunkType, uint32 &chunkSize) {
chunkType = _fd->readUint32BE();
chunkSize = _fd->readUint32LE();
debug(2, "chunkType = %c%c%c%c; chunkSize = %d\n",
(chunkType >> 24) & 0xFF, (chunkType >> 16) & 0xFF, (chunkType >> 8) & 0xFF, chunkType & 0xFF,
chunkSize);
}
void PmvPlayer::handleEvents() {
Common::Event event;
while (_system->getEventManager()->pollEvent(event)) {
if (event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) {
_abort = true;
}
}
}
void PmvPlayer::updatePalette() {
byte colors[1024];
for (int i = 0; i < 256; i++) {
colors[i * 4 + 0] = _palette[i * 3 + 0];
colors[i * 4 + 1] = _palette[i * 3 + 1];
colors[i * 4 + 2] = _palette[i * 3 + 2];
colors[i * 4 + 3] = 0;
}
_system->setPalette(colors, 0, 256);
}
void PmvPlayer::updateScreen() {
_system->copyRectToScreen((const byte*)_surface->pixels, _surface->pitch, 0, 0, _surface->w, _surface->h);
_system->updateScreen();
}
}

39
engines/made/pmvplayer.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef MADE_PMVPLAYER_H
#define MADE_PMVPLAYER_H
#include "common/system.h"
#include "common/events.h"
#include "common/file.h"
#include "common/endian.h"
#include "graphics/surface.h"
#include "sound/mixer.h"
#include "sound/audiostream.h"
#include "made/graphics.h"
#include "made/sound.h"
namespace Made {
class PmvPlayer {
public:
PmvPlayer(OSystem *system, Audio::Mixer *mixer);
~PmvPlayer();
void play(const char *filename);
protected:
OSystem *_system;
Audio::Mixer *_mixer;
Common::File *_fd;
Audio::AppendableAudioStream *_audioStream;
Audio::SoundHandle _audioStreamHandle;
byte _palette[768];
Graphics::Surface *_surface;
bool _abort;
void readChunk(uint32 &chunkType, uint32 &chunkSize);
void handleEvents();
void updatePalette();
void updateScreen();
};
}
#endif

333
engines/made/resource.cpp Normal file
View file

@ -0,0 +1,333 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/endian.h"
#include "made/resource.h"
#include "made/graphics.h"
#include "made/sound.h"
namespace Made {
/* Resource */
Resource::~Resource() {
}
/* PictureResource */
PictureResource::PictureResource() : _picture(NULL), _palette(NULL) {
}
PictureResource::~PictureResource() {
if (_picture)
delete _picture;
if (_palette)
delete[] _palette;
}
void PictureResource::load(byte *source, int size) {
Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size);
bool hasPalette = sourceS->readByte() == 1;
sourceS->readByte();
sourceS->readByte();
sourceS->readByte();
uint16 cmdOffs = sourceS->readUint16LE();
uint16 pixelOffs = sourceS->readUint16LE();
uint16 maskOffs = sourceS->readUint16LE();
uint16 lineSize = sourceS->readUint16LE();
uint16 u = sourceS->readUint16LE();
uint16 width = sourceS->readUint16LE();
uint16 height = sourceS->readUint16LE();
debug(2, "width = %d; height = %d\n", width, height);
if (hasPalette) {
_palette = new byte[768];
sourceS->read(_palette, 768);
}
_picture = new Graphics::Surface();
_picture->create(width, height, 1);
decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize);
delete sourceS;
}
/* AnimationResource */
AnimationResource::AnimationResource() {
}
AnimationResource::~AnimationResource() {
// TODO: Free anim frames
}
void AnimationResource::load(byte *source, int size) {
Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size);
sourceS->readUint32LE();
sourceS->readUint32LE();
sourceS->readUint16LE();
_flags = sourceS->readUint16LE();
_width = sourceS->readUint16LE();
_height = sourceS->readUint16LE();
sourceS->readUint32LE();
uint16 frameCount = sourceS->readUint16LE();
sourceS->readUint16LE();
sourceS->readUint16LE();
for (uint16 i = 0; i < frameCount; i++) {
sourceS->seek(26 + i * 4);
uint32 frameOffs = sourceS->readUint32LE();
sourceS->seek(frameOffs);
sourceS->readUint32LE();
sourceS->readUint32LE();
uint16 frameWidth = sourceS->readUint16LE();
uint16 frameHeight = sourceS->readUint16LE();
uint16 cmdOffs = sourceS->readUint16LE();
sourceS->readUint16LE();
uint16 pixelOffs = sourceS->readUint16LE();
sourceS->readUint16LE();
uint16 maskOffs = sourceS->readUint16LE();
sourceS->readUint16LE();
uint16 lineSize = sourceS->readUint16LE();
Graphics::Surface *frame = new Graphics::Surface();
frame->create(frameWidth, frameHeight, 1);
decompressImage(source + frameOffs, *frame, cmdOffs, pixelOffs, maskOffs, lineSize, _flags & 1);
_frames.push_back(frame);
}
delete sourceS;
}
/* SoundResource */
SoundResource::SoundResource() : _soundSize(0), _soundData(NULL) {
}
SoundResource::~SoundResource() {
if (_soundData)
delete[] _soundData;
}
void SoundResource::load(byte *source, int size) {
uint16 chunkCount = READ_LE_UINT16(source + 8);
uint16 chunkSize = READ_LE_UINT16(source + 12);
_soundSize = chunkCount * chunkSize;
_soundData = new byte[_soundSize];
decompressSound(source + 14, _soundData, chunkSize, chunkCount);
}
Audio::AudioStream *SoundResource::getAudioStream() {
return Audio::makeLinearInputStream(_soundData, _soundSize, 22050, 0, 0, 0);
}
/* MenuResource */
MenuResource::MenuResource() {
}
MenuResource::~MenuResource() {
}
void MenuResource::load(byte *source, int size) {
_strings.clear();
Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size);
sourceS->skip(4); // skip "MENU"
uint16 count = sourceS->readUint16LE();
for (uint16 i = 0; i < count; i++) {
uint16 offs = sourceS->readUint16LE();
const char *string = (const char*)(source + offs);
_strings.push_back(string);
debug(2, "%02d: %s\n", i, string);
}
fflush(stdout);
delete sourceS;
}
/* ProjectReader */
ProjectReader::ProjectReader() {
}
ProjectReader::~ProjectReader() {
}
void ProjectReader::open(const char *filename) {
_fd = new Common::File();
_fd->open(filename);
_fd->skip(0x18); // skip header for now
uint16 indexCount = _fd->readUint16LE();
for (uint16 i = 0; i < indexCount; i++) {
uint32 resType = _fd->readUint32BE();
uint32 indexOffs = _fd->readUint32LE();
_fd->readUint32LE();
_fd->readUint32LE();
_fd->readUint32LE();
_fd->readUint16LE();
_fd->readUint16LE();
// We don't need ARCH, FREE and OMNI resources
if (resType == kResARCH || resType == kResFREE || resType == kResOMNI)
continue;
//debug(2, "resType = %08X; indexOffs = %d\n", resType, indexOffs);
uint32 oldOffs = _fd->pos();
ResourceSlots *resSlots = new ResourceSlots();
_fd->seek(indexOffs);
loadIndex(resSlots);
_resSlots[resType] = resSlots;
_fd->seek(oldOffs);
}
_cacheCount = 0;
}
PictureResource *ProjectReader::getPicture(int index) {
return createResource<PictureResource>(kResFLEX, index);
}
AnimationResource *ProjectReader::getAnimation(int index) {
return createResource<AnimationResource>(kResANIM, index);
}
SoundResource *ProjectReader::getSound(int index) {
return createResource<SoundResource>(kResSNDS, index);
}
MenuResource *ProjectReader::getMenu(int index) {
return createResource<MenuResource>(kResMENU, index);
}
void ProjectReader::loadIndex(ResourceSlots *slots) {
_fd->readUint32LE(); // skip INDX
_fd->readUint32LE(); // skip index size
_fd->readUint32LE(); // skip unknown
_fd->readUint32LE(); // skip res type
uint16 count = _fd->readUint16LE();
_fd->readUint16LE(); // skip unknown count
_fd->readUint16LE(); // skip unknown count
for (uint16 i = 0; i < count; i++) {
uint32 offs = _fd->readUint32LE();
uint32 size = _fd->readUint32LE();
slots->push_back(ResourceSlot(offs, size));
}
}
void ProjectReader::freeResource(Resource *resource) {
tossResourceFromCache(resource->slot);
}
bool ProjectReader::loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size) {
if (slot && slot->size > 0) {
size = slot->size - 62;
buffer = new byte[size];
debug(2, "ProjectReader::loadResource() %08X\n", slot->offs + 62); fflush(stdout);
_fd->seek(slot->offs + 62);
_fd->read(buffer, size);
return true;
} else {
return false;
}
}
ResourceSlot *ProjectReader::getResourceSlot(uint32 resType, uint index) {
ResourceSlots *slots = _resSlots[resType];
if (index >= 1 && index < slots->size()) {
ResourceSlot *slot = &slots->operator[](index);
return slot;
} else {
return NULL;
}
}
Resource *ProjectReader::getResourceFromCache(ResourceSlot *slot) {
if (slot->res)
slot->refCount++;
return slot->res;
}
void ProjectReader::addResourceToCache(ResourceSlot *slot, Resource *res) {
if (_cacheCount >= kMaxResourceCacheCount) {
purgeCache();
}
slot->res = res;
slot->refCount = 0;
_cacheCount++;
}
void ProjectReader::tossResourceFromCache(ResourceSlot *slot) {
if (slot->res) {
slot->refCount--;
}
}
void ProjectReader::purgeCache() {
printf("ProjectReader::purgeCache()\n");
for (ResMap::const_iterator resTypeIter = _resSlots.begin(); resTypeIter != _resSlots.end(); ++resTypeIter) {
ResourceSlots *slots = (*resTypeIter)._value;
for (ResourceSlots::iterator slotIter = slots->begin(); slotIter != slots->end(); ++slotIter) {
ResourceSlot *slot = &(*slotIter);
if (slot->refCount <= 0 && slot->res) {
delete slot->res;
slot->res = NULL;
slot->refCount = 0;
_cacheCount--;
}
}
}
}
} // End of namespace Made

178
engines/made/resource.h Normal file
View file

@ -0,0 +1,178 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MADE_RESOURCE_H
#define MADE_RESOURCE_H
#include "common/util.h"
#include "common/file.h"
#include "common/stream.h"
#include "common/hashmap.h"
#include "graphics/surface.h"
#include "sound/audiostream.h"
namespace Made {
const int kMaxResourceCacheCount = 100;
enum ResourceType {
kResARCH = MKID_BE('ARCH'),
kResFREE = MKID_BE('FREE'),
kResOMNI = MKID_BE('OMNI'),
kResFLEX = MKID_BE('FLEX'),
kResSNDS = MKID_BE('SNDS'),
kResANIM = MKID_BE('ANIM'),
kResMENU = MKID_BE('MENU')
};
struct ResourceSlot;
class Resource {
public:
ResourceSlot *slot;
virtual ~Resource();
virtual void load(byte *buffer, int size) = 0;
};
class PictureResource : public Resource {
public:
PictureResource();
~PictureResource();
void load(byte *source, int size);
Graphics::Surface *getPicture() const { return _picture; }
byte *getPalette() const { return _palette; }
protected:
Graphics::Surface *_picture;
byte *_palette;
};
class AnimationResource : public Resource {
public:
AnimationResource();
~AnimationResource();
void load(byte *source, int size);
int getCount() const { return _frames.size(); }
Graphics::Surface *getFrame(int index) const { return _frames[index]; }
uint16 getFlags() const { return _flags; }
int16 getWidth() const { return _width; }
int16 getHeight() const { return _height; }
protected:
Common::Array<Graphics::Surface*> _frames;
uint16 _flags;
int16 _width, _height;
};
class SoundResource : public Resource {
public:
SoundResource();
~SoundResource();
void load(byte *source, int size);
Audio::AudioStream *getAudioStream();
protected:
byte *_soundData;
int _soundSize;
};
class MenuResource : public Resource {
public:
MenuResource();
~MenuResource();
void load(byte *source, int size);
int getCount() const { return _strings.size(); }
Common::String getString(int index) const { return _strings[index]; }
protected:
Common::Array<Common::String> _strings;
};
struct ResourceSlot {
uint32 offs;
uint32 size;
Resource *res;
int refCount;
ResourceSlot() : offs(0), size(0), res(NULL), refCount(0) {
}
ResourceSlot(uint32 roffs, uint32 rsize) : offs(roffs), size(rsize), res(NULL), refCount(0) {
}
};
class ProjectReader {
public:
ProjectReader();
~ProjectReader();
void open(const char *filename);
PictureResource *getPicture(int index);
AnimationResource *getAnimation(int index);
SoundResource *getSound(int index);
MenuResource *getMenu(int index);
void freeResource(Resource *resource);
protected:
Common::File *_fd;
typedef Common::Array<ResourceSlot> ResourceSlots;
typedef Common::HashMap<uint32, ResourceSlots*> ResMap;
ResMap _resSlots;
int _cacheCount;
void loadIndex(ResourceSlots *slots);
template <class T>
T *createResource(uint32 resType, int index) {
ResourceSlot *slot = getResourceSlot(resType, index);
if (!slot)
return NULL;
T *res = (T*)getResourceFromCache(slot);
if (!res) {
byte *buffer;
uint32 size;
if (loadResource(slot, buffer, size)) {
res = new T();
res->slot = slot;
res->load(buffer, size);
addResourceToCache(slot, res);
delete[] buffer;
}
}
return res;
}
bool loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size);
ResourceSlot *getResourceSlot(uint32 resType, uint index);
Resource *getResourceFromCache(ResourceSlot *slot);
void addResourceToCache(ResourceSlot *slot, Resource *res);
void tossResourceFromCache(ResourceSlot *slot);
void purgeCache();
};
} // End of namespace Made
#endif /* MADE_H */

459
engines/made/screen.cpp Normal file
View file

@ -0,0 +1,459 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "made/made.h"
#include "made/screen.h"
#include "made/resource.h"
namespace Made {
Screen::Screen(MadeEngine *vm) : _vm(vm) {
_screen1 = new Graphics::Surface();
_screen1->create(320, 200, 1);
_clipInfo1.x = 0;
_clipInfo1.y = 0;
_clipInfo1.w = 320;
_clipInfo1.h = 200;
_clipInfo1.destSurface = _screen1;
_screen2 = new Graphics::Surface();
_screen2->create(320, 200, 1);
_clipInfo2.x = 0;
_clipInfo2.y = 0;
_clipInfo2.w = 320;
_clipInfo2.h = 200;
_clipInfo2.destSurface = _screen2;
_clipArea.destSurface = _screen2;
_excludeClipAreaEnabled[0] = false;
_excludeClipAreaEnabled[1] = false;
_excludeClipAreaEnabled[2] = false;
_excludeClipAreaEnabled[3] = false;
clearChannels();
}
Screen::~Screen() {
delete _screen1;
delete _screen2;
}
void Screen::clearScreen() {
_screen1->fillRect(Common::Rect(0, 0, 320, 200), 0);
_screen2->fillRect(Common::Rect(0, 0, 320, 200), 0);
//_vm->_system->clearScreen();
}
void Screen::drawSurface(Graphics::Surface *source, int x, int y) {
}
void Screen::setPalette(byte *palette, int start, int count) {
}
uint16 Screen::updateChannel(uint16 channelIndex) {
return 0;
}
void Screen::deleteChannel(uint16 channelIndex) {
if (channelIndex < 1 || channelIndex >= 100)
return;
_channels[channelIndex - 1].type = 0;
_channels[channelIndex - 1].state = 0;
_channels[channelIndex - 1].index = 0;
}
int16 Screen::getChannelType(uint16 channelIndex) {
if (channelIndex < 1 || channelIndex >= 100)
return -1;
return _channels[channelIndex - 1].type;
}
int16 Screen::getChannelState(uint16 channelIndex) {
if (channelIndex < 1 || channelIndex >= 100)
return -1;
return _channels[channelIndex - 1].state;
}
void Screen::setChannelState(uint16 channelIndex, int16 state) {
if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
return;
_channels[channelIndex - 1].state = state;
}
uint16 Screen::setChannelLocation(uint16 channelIndex, int16 x, int16 y) {
if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
return 0;
_channels[channelIndex - 1].x = x;
_channels[channelIndex - 1].y = y;
return updateChannel(channelIndex - 1) + 1;
}
uint16 Screen::setChannelContent(uint16 channelIndex, uint16 index) {
if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
return 0;
//debug(2, "setChannelContent(%d, %04X)\n", channelIndex, index); fflush(stdout); g_system->delayMillis(5000);
_channels[channelIndex - 1].index = index;
return updateChannel(channelIndex - 1) + 1;
}
void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask, int16 excludeStateMask) {
_excludeClipArea[0].destSurface = clipInfo.destSurface;
_excludeClipArea[1].destSurface = clipInfo.destSurface;
_excludeClipArea[2].destSurface = clipInfo.destSurface;
_excludeClipArea[3].destSurface = clipInfo.destSurface;
_clipArea.destSurface = clipInfo.destSurface;
for (uint16 i = 0; i < _channelsUsedCount; i++) {
debug(2, "drawSpriteChannels() i = %d\n", i);
if (((_channels[i].state & includeStateMask) == includeStateMask) && (_channels[i].state & excludeStateMask) == 0)
{
uint16 flag1 = _channels[i].state & 0x10;
uint16 flag2 = _channels[i].state & 0x20;
debug(2, "drawSpriteChannels() type = %d; index = %04X\n", _channels[i].type, _channels[i].index);
switch (_channels[i].type) {
case 1: // drawFlex
if (_channels[i].state & 4) {
drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, _clipArea);
} else if (_channels[i].state & 8) {
for (int excludeIndex = 0; excludeIndex < 4; excludeIndex++) {
if (_excludeClipAreaEnabled[excludeIndex]) {
drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, _excludeClipArea[excludeIndex]);
}
}
} else {
drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, clipInfo);
}
break;
case 2: // drawObjectText
// TODO
break;
case 3: // drawAnimFrame
if (_channels[i].state & 4) {
drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, _clipArea);
} else if (_channels[i].state & 8) {
for (int excludeIndex = 0; excludeIndex < 4; excludeIndex++) {
if (_excludeClipAreaEnabled[excludeIndex]) {
drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, _excludeClipArea[excludeIndex]);
}
}
} else {
drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, clipInfo);
}
break;
case 4: // drawMenuText
// TODO
break;
default:
break;
}
}
}
}
void Screen::updateSprites() {
// TODO: This needs some more work, I don't use dirty rectangles for now
memcpy(_screen2->pixels, _screen1->pixels, 64000);
//drawSpriteChannels(_clipInfo1, 3, 0x40);//CHECKME
drawSpriteChannels(_clipInfo1, 3, 0);//CHECKME
drawSpriteChannels(_clipInfo2, 1, 2);//CHECKME
_vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h);
}
void Screen::clearChannels() {
for (uint16 i = 0; i < ARRAYSIZE(_channels); i++) {
_channels[i].type = 0;
_channels[i].index = 0;
}
_channelsUsedCount = 0;
}
uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) {
if (flexIndex == 0)
return 0;
PictureResource *flex = _vm->_res->getPicture(flexIndex);
Graphics::Surface *sourceSurface = flex->getPicture();
byte *source = (byte*)sourceSurface->getBasePtr(0, 0);
byte *dest = (byte*)clipInfo.destSurface->getBasePtr(x, y);
if (x + sourceSurface->w > clipInfo.destSurface->w || y + sourceSurface->h > clipInfo.destSurface->h) {
debug(2, "CLIPPING PROBLEM: x = %d; y = %d; w = %d; h = %d; x+w = %d; y+h = %d\n",
x, y, sourceSurface->w, sourceSurface->h, x + sourceSurface->w, y + sourceSurface->h);
//fflush(stdout); g_system->delayMillis(5000);
return 0;
}
for (int16 yc = 0; yc < sourceSurface->h; yc++) {
for (int16 xc = 0; xc < sourceSurface->w; xc++) {
if (source[xc])
dest[xc] = source[xc];
}
source += sourceSurface->pitch;
dest += clipInfo.destSurface->pitch;
}
// TODO: Palette stuff; palette should be set in showPage
byte *pal = flex->getPalette();
if (pal) {
for (int i = 0; i < 256; i++) {
_palette[i * 4 + 0] = pal[i * 3 + 0];
_palette[i * 4 + 1] = pal[i * 3 + 1];
_palette[i * 4 + 2] = pal[i * 3 + 2];
}
_vm->_system->setPalette(_palette, 0, 256);
}
_vm->_res->freeResource(flex);
return 0;
}
void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) {
AnimationResource *anim = _vm->_res->getAnimation(animIndex);
Graphics::Surface *sourceSurface = anim->getFrame(frameNum);
byte *source = (byte*)sourceSurface->getBasePtr(0, 0);
byte *dest = (byte*)clipInfo.destSurface->getBasePtr(x, y);
for (int16 yc = 0; yc < sourceSurface->h; yc++) {
for (int16 xc = 0; xc < sourceSurface->w; xc++) {
if (source[xc])
dest[xc] = source[xc];
}
source += sourceSurface->pitch;
dest += clipInfo.destSurface->pitch;
}
_vm->_res->freeResource(anim);
}
uint16 Screen::drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2) {
//DEBUG
if (y > 200) y = 0;
drawFlex(index, x, y, flag1, flag2, _clipInfo1);
return 0;
}
uint16 Screen::drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2) {
drawAnimFrame(animIndex, x, y, frameNum, flag1, flag2, _clipInfo1);
return 0;
}
uint16 Screen::addSprite(uint16 spriteIndex) {
bool oldScreenLock = _screenLock;
drawFlex(spriteIndex, 0, 0, 0, 0, _clipInfo1);
_screenLock = oldScreenLock;
return 0;
}
uint16 Screen::drawSprite(uint16 flexIndex, int16 x, int16 y) {
return placeSprite(_channelsUsedCount + 1, flexIndex, x, y);
}
uint16 Screen::placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 y) {
debug(2, "placeSprite(%d, %04X, %d, %d)\n", channelIndex, flexIndex, x, y); fflush(stdout);
//g_system->delayMillis(5000);
if (channelIndex < 1 || channelIndex >= 100)
return 0;
channelIndex--;
PictureResource *flex = _vm->_res->getPicture(flexIndex);
if (flex) {
Graphics::Surface *surf = flex->getPicture();
int16 state = 1;
int16 x1, y1, x2, y2;
x1 = x;
y1 = y;
x2 = x + surf->w + 1;
y2 = y + surf->h + 1;
//TODO: clipRect(x1, y1, x2, y2);
if (_ground == 0)
state |= 2;
if (_clip != 0)
state |= 4;
if (_exclude != 0)
state |= 8;
_channels[channelIndex].state = state;
_channels[channelIndex].type = 1;
_channels[channelIndex].index = flexIndex;
_channels[channelIndex].x = x;
_channels[channelIndex].y = y;
_channels[channelIndex].x1 = x1;
_channels[channelIndex].y1 = y1;
_channels[channelIndex].x2 = x2;
_channels[channelIndex].y2 = y2;
_channels[channelIndex].area = (x2 - x2) * (y2 - y1);
if (_channelsUsedCount <= channelIndex)
_channelsUsedCount = channelIndex + 1;
_vm->_res->freeResource(flex);
} else {
_channels[channelIndex].type = 0;
_channels[channelIndex].state = 0;
}
return channelIndex + 1;
}
uint16 Screen::placeAnim(uint16 channelIndex, uint16 animIndex, int16 x, int16 y, int16 frameNum) {
if (channelIndex < 1 || channelIndex >= 100)
return 0;
channelIndex--;
AnimationResource *anim = _vm->_res->getAnimation(animIndex);
if (anim) {
int16 state = 1;
int16 x1, y1, x2, y2;
x1 = x;
y1 = y;
x2 = x + anim->getWidth();
y2 = y + anim->getHeight();
//TODO: clipRect(x1, y1, x2, y2);
if (anim->getFlags() == 1 || _ground == 0)
state |= 2;
if (_clip != 0)
state |= 4;
if (_exclude != 0)
state |= 8;
_channels[channelIndex].state = state;
_channels[channelIndex].type = 3;
_channels[channelIndex].index = animIndex;
_channels[channelIndex].frameNum = frameNum;
_channels[channelIndex].needRefresh = 1;
_channels[channelIndex].x = x;
_channels[channelIndex].y = y;
_channels[channelIndex].x1 = x1;
_channels[channelIndex].y1 = y1;
_channels[channelIndex].x2 = x2;
_channels[channelIndex].y2 = y2;
_channels[channelIndex].area = (x2 - x2) * (y2 - y1);
if (_channelsUsedCount <= channelIndex)
_channelsUsedCount = channelIndex + 1;
_vm->_res->freeResource(anim);
} else {
_channels[channelIndex].type = 0;
_channels[channelIndex].state = 0;
}
return channelIndex + 1;
}
int16 Screen::setAnimFrame(uint16 channelIndex, int16 frameNum) {
if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
return 0;
channelIndex--;
_channels[channelIndex].frameNum = frameNum;
_channels[channelIndex].needRefresh = 1;
return updateChannel(channelIndex) + 1;
}
int16 Screen::getAnimFrame(uint16 channelIndex) {
if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
return -1;
return _channels[channelIndex - 1].frameNum;
}
int16 Screen::getAnimFrameCount(uint16 animIndex) {
int16 frameCount = 0;
AnimationResource *anim = _vm->_res->getAnimation(animIndex);
if (anim) {
frameCount = anim->getCount();
_vm->_res->freeResource(anim);
}
return frameCount;
}
uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, int16 y, uint16 fontNum, int16 textColor, int16 outlineColor) {
return 0;
}
void Screen::show() {
// TODO
memcpy(_screen2->pixels, _screen1->pixels, 64000);
drawSpriteChannels(_clipInfo2, 0, 0);
//drawSpriteChannels(_clipInfo2, 3, 0);//CHECKME
//drawSpriteChannels(_clipInfo2, 1, 2);//CHECKME
//_vm->_system->copyRectToScreen((const byte*)_screen1->pixels, _screen1->pitch, 0, 0, _screen1->w, _screen1->h);
_vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h);
}
} // End of namespace Made

123
engines/made/screen.h Normal file
View file

@ -0,0 +1,123 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MADE_SCREEN_H
#define MADE_SCREEN_H
#include "common/endian.h"
#include "common/util.h"
#include "graphics/surface.h"
namespace Made {
struct SpriteChannel {
int16 type;
int16 state;
int16 needRefresh;
uint16 index;
int16 x, y;
int16 x1, y1, x2, y2;
uint32 area;
uint16 fontNum;
int16 textColor, outlineColor;
int16 frameNum;
};
struct ClipInfo {
uint16 x, y, w, h;
Graphics::Surface *destSurface;
};
class MadeEngine;
class Screen {
public:
Screen(MadeEngine *vm);
~Screen();
void clearScreen();
void drawSurface(Graphics::Surface *source, int x, int y);
void setPalette(byte *palette, int start, int count);
uint16 updateChannel(uint16 channelIndex);
void deleteChannel(uint16 channelIndex);
int16 getChannelType(uint16 channelIndex);
int16 getChannelState(uint16 channelIndex);
void setChannelState(uint16 channelIndex, int16 state);
uint16 setChannelLocation(uint16 channelIndex, int16 x, int16 y);
uint16 setChannelContent(uint16 channelIndex, uint16 index);
void drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask, int16 excludeStateMask);
void updateSprites();
void clearChannels();
uint16 drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo);
void drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo);
uint16 drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2);
uint16 drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2);
uint16 addSprite(uint16 spriteIndex);
uint16 drawSprite(uint16 flexIndex, int16 x, int16 y);
uint16 placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 y);
uint16 placeAnim(uint16 channelIndex, uint16 animIndex, int16 x, int16 y, int16 frameNum);
int16 setAnimFrame(uint16 channelIndex, int16 frameNum);
int16 getAnimFrame(uint16 channelIndex);
// TODO: Move to script function
int16 getAnimFrameCount(uint16 animIndex);
uint16 placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, int16 y, uint16 fontNum, int16 textColor, int16 outlineColor);
void show();
void setClip(uint16 clip);
void setExclude(uint16 exclude);
void setGround(uint16 ground);
byte _palette[256 * 4];
protected:
MadeEngine *_vm;
bool _screenLock;
uint16 _clip, _exclude, _ground;
Graphics::Surface *_screen1, *_screen2;
ClipInfo _clipArea, _clipInfo1, _clipInfo2;
ClipInfo _excludeClipArea[4];
bool _excludeClipAreaEnabled[4];
uint16 _channelsUsedCount;
SpriteChannel _channels[100];
};
} // End of namespace Made
#endif /* MADE_H */

738
engines/made/script.cpp Normal file
View file

@ -0,0 +1,738 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/endian.h"
#include "common/util.h"
#include "made/made.h"
#include "made/script.h"
#include "made/database.h"
#include "made/scriptfuncs.h"
namespace Made {
const char *extendFuncNames[] = {
"SYSTEM",
"INITGRAF",
"RESTOREGRAF",
"DRAWPIC",
"CLS",
"SHOWPAGE",
"EVENT",
"EVENTX",
"EVENTY",
"EVENTKEY",
"VISUALFX",
"PLAYSND",
"PLAYMUS",
"STOPMUS",
"ISMUS",
"TEXTPOS",
"FLASH",
"PLAYNOTE",
"STOPNOTE",
"PLAYTELE",
"STOPTELE",
"HIDECURS",
"SHOWCURS",
"MUSICBEAT",
"SCREENLOCK",
"ADDSPRITE",
"FREEANIM",
"DRAWSPRITE",
"ERASESPRITES",
"UPDATESPRITES",
"GETTIMER",
"SETTIMER",
"RESETTIMER",
"ALLOCTIMER",
"FREETIMER",
"PALETTELOCK",
"FONT",
"DRAWTEXT",
"HOMETEXT",
"TEXTRECT",
"TEXTXY",
"DROPSHADOW",
"TEXTCOLOR",
"OUTLINE",
"LOADCURSOR",
"SETGROUND",
"RESTEXT",
"CLIPAREA",
"SETCLIP",
"ISSND",
"STOPSND",
"PLAYVOICE",
"CDPLAY",
"STOPCD",
"CDSTATUS",
"CDTIME",
"CDPLAYSEG",
"PRINTF",
"MONOCLS",
"SNDENERGY",
"CLEARTEXT",
"ANIMTEXT",
"TEXTWIDTH",
"PLAYMOVIE",
"LOADSND",
"LOADMUS",
"LOADPIC",
"MUSICVOL",
"RESTARTEVENTS",
"PLACESPRITE",
"PLACETEXT",
"DELETECHANNEL",
"CHANNELTYPE",
"SETSTATE",
"SETLOCATION",
"SETCONTENT",
"EXCLUDEAREA",
"SETEXCLUDE",
"GETSTATE",
"PLACEANIM",
"SETFRAME",
"GETFRAME",
"GETFRAMECOUNT",
"PICWIDTH",
"PICHEIGHT",
"SOUNDRATE",
"DRAWANIMPIC",
"LOADANIM",
"READTEXT",
"READMENU",
"DRAWMENU",
"MENUCOUNT",
"SAVEGAME",
"LOADGAME",
"GAMENAME",
"SHAKESCREEN",
"PLACEMENU",
"SETVOLUME",
"WHATSYNTH",
"SLOWSYSTEM"
};
/* ScriptStack */
ScriptStack::ScriptStack() {
for (int16 i = 0; i < kScriptStackSize; i++)
_stack[i] = 0;
_stackPos = kScriptStackSize;
}
ScriptStack::~ScriptStack() {
}
int16 ScriptStack::top() {
return _stack[_stackPos];
}
int16 ScriptStack::pop() {
if (_stackPos == kScriptStackSize)
error("ScriptStack::pop() Stack underflow");
return _stack[_stackPos++];
}
void ScriptStack::push(int16 value) {
if (_stackPos == 0)
error("ScriptStack::push() Stack overflow");
_stack[--_stackPos] = value;
}
void ScriptStack::setTop(int16 value) {
_stack[_stackPos] = value;
}
int16 ScriptStack::peek(int16 index) {
return _stack[index];
}
void ScriptStack::poke(int16 index, int16 value) {
_stack[index] = value;
}
void ScriptStack::alloc(int16 count) {
_stackPos -= count;
}
void ScriptStack::free(int16 count) {
_stackPos += count;
}
void ScriptStack::setStackPos(int16 stackPtr) {
_stackPos = stackPtr;
}
int16 *ScriptStack::getStackPtr() {
return &_stack[_stackPos];
}
/* ScriptInterpreter */
ScriptInterpreter::ScriptInterpreter(MadeEngine *vm) : _vm(vm) {
#define COMMAND(x) { &ScriptInterpreter::x, #x }
static CommandEntry commandProcs[] = {
/* 01 */
COMMAND(cmd_branchTrue),
COMMAND(cmd_branchFalse),
COMMAND(cmd_branch),
COMMAND(cmd_true),
/* 05 */
COMMAND(cmd_false),
COMMAND(cmd_push),
COMMAND(cmd_not),
COMMAND(cmd_add),
/* 09 */
COMMAND(cmd_sub),
COMMAND(cmd_mul),
COMMAND(cmd_div),
COMMAND(cmd_mod),
/* 13 */
COMMAND(cmd_band),
COMMAND(cmd_bor),
COMMAND(cmd_bnot),
COMMAND(cmd_lt),
/* 17 */
COMMAND(cmd_eq),
COMMAND(cmd_gt),
COMMAND(cmd_loadConstant),
COMMAND(cmd_loadVariable),
/* 21 */
COMMAND(cmd_getObjectProperty),
COMMAND(cmd_setObjectProperty),
COMMAND(cmd_set),
COMMAND(cmd_print),
/* 25 */
COMMAND(cmd_terpri),
COMMAND(cmd_printNumber),
COMMAND(cmd_vref),
COMMAND(cmd_vset),
/* 29 */
COMMAND(cmd_vsize),
COMMAND(cmd_exit),
COMMAND(cmd_return),
COMMAND(cmd_call),
/* 33 */
COMMAND(cmd_svar),
COMMAND(cmd_sset),
COMMAND(cmd_split),
COMMAND(cmd_snlit),
/* 37 */
COMMAND(cmd_yorn),
COMMAND(cmd_save),
COMMAND(cmd_restore),
COMMAND(cmd_arg),
/* 41 */
COMMAND(cmd_aset),
COMMAND(cmd_tmp),
COMMAND(cmd_tset),
COMMAND(cmd_tspace),
/* 45 */
COMMAND(cmd_class),
COMMAND(cmd_objectp),
COMMAND(cmd_vectorp),
COMMAND(cmd_restart),
/* 49 */
COMMAND(cmd_rand),
COMMAND(cmd_randomize),
COMMAND(cmd_send),
COMMAND(cmd_extend),
/* 53 */
COMMAND(cmd_catch),
COMMAND(cmd_cdone),
COMMAND(cmd_throw),
COMMAND(cmd_functionp),
/* 57 */
COMMAND(cmd_le),
COMMAND(cmd_ge),
COMMAND(cmd_varx),
COMMAND(cmd_setx)
};
_commands = commandProcs;
_commandsMax = ARRAYSIZE(commandProcs) + 1;
_functions = new ScriptFunctionsRtz(_vm);
_functions->setupExternalsTable();
#undef COMMAND
}
ScriptInterpreter::~ScriptInterpreter() {
delete _functions;
}
void ScriptInterpreter::runScript(int16 scriptObjectIndex) {
_terminated = false;
_runningScriptObjectIndex = scriptObjectIndex;
_localStackPos = _stack.getStackPos();
_codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData();
_codeIp = _codeBase;
while (!_terminated) {
byte opcode = readByte();
if (opcode >= 1 && opcode <= _commandsMax) {
debug(4, "opcode = %s\n", _commands[opcode - 1].desc);
(this->*_commands[opcode - 1].proc)();
} else {
printf("ScriptInterpreter::runScript(%d) Unknown opcode %02X\n", _runningScriptObjectIndex, opcode);
}
}
}
byte ScriptInterpreter::readByte() {
return *_codeIp++;
}
int16 ScriptInterpreter::readInt16() {
int16 temp = (int16)READ_LE_UINT16(_codeIp);
_codeIp += 2;
debug(4, "readInt16() value = %04X\n", temp);
return temp;
}
void ScriptInterpreter::cmd_branchTrue() {
int16 ofs = readInt16();
if (_stack.top() != 0)
_codeIp = _codeBase + ofs;
}
void ScriptInterpreter::cmd_branchFalse() {
int16 ofs = readInt16();
if (_stack.top() == 0)
_codeIp = _codeBase + ofs;
}
void ScriptInterpreter::cmd_branch() {
int16 ofs = readInt16();
_codeIp = _codeBase + ofs;
}
void ScriptInterpreter::cmd_true() {
_stack.setTop(-1);
}
void ScriptInterpreter::cmd_false() {
_stack.setTop(0);
}
void ScriptInterpreter::cmd_push() {
_stack.push();
}
void ScriptInterpreter::cmd_not() {
if (_stack.top() == 0)
_stack.setTop(-1);
else
_stack.setTop(0);
}
void ScriptInterpreter::cmd_add() {
int16 value = _stack.pop();
_stack.setTop(_stack.top() + value);
}
void ScriptInterpreter::cmd_sub() {
int16 value = _stack.pop();
_stack.setTop(_stack.top() - value);
}
void ScriptInterpreter::cmd_mul() {
int16 value = _stack.pop();
_stack.setTop(_stack.top() * value);
}
void ScriptInterpreter::cmd_div() {
int16 value = _stack.pop();
if (value == 0)
_stack.setTop(0);
else
_stack.setTop(_stack.top() / value);
}
void ScriptInterpreter::cmd_mod() {
int16 value = _stack.pop();
if (value == 0)
_stack.setTop(0);
else
_stack.setTop(_stack.top() % value);
}
void ScriptInterpreter::cmd_band() {
int16 value = _stack.pop();
_stack.setTop(_stack.top() & value);
}
void ScriptInterpreter::cmd_bor() {
int16 value = _stack.pop();
_stack.setTop(_stack.top() | value);
}
void ScriptInterpreter::cmd_bnot() {
_stack.setTop(~_stack.top());
}
void ScriptInterpreter::cmd_lt() {
int16 value = _stack.pop();
if (_stack.top() < value)
_stack.setTop(-1);
else
_stack.setTop(0);
}
void ScriptInterpreter::cmd_eq() {
int16 value = _stack.pop();
if (_stack.top() == value)
_stack.setTop(-1);
else
_stack.setTop(0);
}
void ScriptInterpreter::cmd_gt() {
int16 value = _stack.pop();
if (_stack.top() > value)
_stack.setTop(-1);
else
_stack.setTop(0);
}
void ScriptInterpreter::cmd_loadConstant() {
int16 value = readInt16();
debug(4, "value = %04X (%d)\n", value, value);
_stack.setTop(value);
}
void ScriptInterpreter::cmd_loadVariable() {
int16 variable = readInt16();
int16 value = _vm->_dat->getVar(variable);
debug(4, "variable = %d; value = %d (%04X)\n", variable, value, value); fflush(stdout);
_stack.setTop(value);
}
void ScriptInterpreter::cmd_getObjectProperty() {
int16 propertyId = _stack.pop();
int16 objectIndex = _stack.top();
int16 value = _vm->_dat->getObjectProperty(objectIndex, propertyId);
debug(4, "value = %04X(%d)\n", value, value);
//fflush(stdout); g_system->delayMillis(5000);
_stack.setTop(value);
}
void ScriptInterpreter::cmd_setObjectProperty() {
int16 value = _stack.pop();
int16 propertyId = _stack.pop();
int16 objectIndex = _stack.top();
value = _vm->_dat->setObjectProperty(objectIndex, propertyId, value);
//fflush(stdout); g_system->delayMillis(5000);
_stack.setTop(value);
}
void ScriptInterpreter::cmd_set() {
int16 variable = readInt16();
debug(4, "var(%d) = %04d (%d)\n", variable, _stack.top(), _stack.top());
_vm->_dat->setVar(variable, _stack.top());
}
void ScriptInterpreter::cmd_print() {
// TODO: This opcode was used for printing debug messages
Object *obj = _vm->_dat->getObject(_stack.top());
const char *text = obj->getString();
debug(4, "%s", text); fflush(stdout);
_stack.setTop(0);
}
void ScriptInterpreter::cmd_terpri() {
// TODO: This opcode was used for printing debug messages
debug(4, "\n");
_stack.setTop(0);
}
void ScriptInterpreter::cmd_printNumber() {
// TODO: This opcode was used for printing debug messages
debug(4, "%d", _stack.top());
}
void ScriptInterpreter::cmd_vref() {
int16 index = _stack.pop();
int16 objectIndex = _stack.top();
int16 value = 0;
debug(4, "index = %d; objectIndex = %d\n", index, objectIndex); fflush(stdout);
if (objectIndex > 0) {
Object *obj = _vm->_dat->getObject(objectIndex);
value = obj->getVectorItem(index);
}
_stack.setTop(value);
debug(4, "--> value = %d\n", value); fflush(stdout);
}
void ScriptInterpreter::cmd_vset() {
int16 value = _stack.pop();
int16 index = _stack.pop();
int16 objectIndex = _stack.top();
debug(4, "index = %d; objectIndex = %d; value = %d\n", index, objectIndex, value); fflush(stdout);
if (objectIndex > 0) {
Object *obj = _vm->_dat->getObject(objectIndex);
obj->setVectorItem(index, value);
}
_stack.setTop(value);
}
void ScriptInterpreter::cmd_vsize() {
int16 objectIndex = _stack.top();
if (objectIndex < 1) objectIndex = 1; // HACK
Object *obj = _vm->_dat->getObject(objectIndex);
int16 size = obj->getVectorSize();
_stack.setTop(size);
}
void ScriptInterpreter::cmd_exit() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_return() {
// TODO: Check if returning from main function
int16 funcResult = _stack.top();
_stack.setStackPos(_localStackPos);
_localStackPos = kScriptStackLimit - _stack.pop();
//_localStackPos = _stack.pop();
_runningScriptObjectIndex = _stack.pop();
_codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData();
_codeIp = _codeBase + _stack.pop();
byte argc = _stack.pop();
_stack.free(argc);
_stack.setTop(funcResult);
debug(4, "LEAVE: stackPtr = %d; _localStackPos = %d\n\n\n", _stack.getStackPos(), _localStackPos);
}
void ScriptInterpreter::cmd_call() {
debug(4, "\n\n\nENTER: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos);
byte argc = readByte();
_stack.push(argc);
_stack.push(_codeIp - _codeBase);
_stack.push(_runningScriptObjectIndex);
_stack.push(kScriptStackLimit - _localStackPos);
_localStackPos = _stack.getStackPos();
_runningScriptObjectIndex = _stack.peek(_localStackPos + argc + 4);
debug(4, "argc = %d; _runningScriptObjectIndex = %04X\n", argc, _runningScriptObjectIndex); fflush(stdout);
_codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData();
_codeIp = _codeBase;
//_vm->_dat->dumpObject(_runningScriptObjectIndex);
}
void ScriptInterpreter::cmd_svar() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_sset() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_split() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_snlit() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_yorn() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_save() {
//fflush(stdout); g_system->delayMillis(5000);
// TODO
_stack.setTop(0);
}
void ScriptInterpreter::cmd_restore() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_arg() {
int16 argIndex = readByte();
debug(4, "argIndex = %d; value = %04X (%d)\n", argIndex, _stack.peek(_localStackPos + 4 + argIndex), _stack.peek(_localStackPos + 4 + argIndex));
_stack.setTop(_stack.peek(_localStackPos + 4 + argIndex));
}
void ScriptInterpreter::cmd_aset() {
int16 argIndex = readByte();
debug(4, "argIndex = %d; value = %d\n", argIndex, _stack.peek(_localStackPos + 4 + argIndex));
_stack.poke(_localStackPos + 4 + argIndex, _stack.top());
}
void ScriptInterpreter::cmd_tmp() {
int16 tempIndex = readByte();
debug(4, "tempIndex = %d; value = %d\n", tempIndex, _stack.peek(_localStackPos - tempIndex - 1));
_stack.setTop(_stack.peek(_localStackPos - tempIndex - 1));
}
void ScriptInterpreter::cmd_tset() {
int16 tempIndex = readByte();
debug(4, "tempIndex = %d; value = %d\n", tempIndex, _stack.top());
_stack.poke(_localStackPos - tempIndex - 1, _stack.top());
}
void ScriptInterpreter::cmd_tspace() {
int16 tempCount = readByte();
debug(4, "tempCount = %d\n", tempCount);
_stack.alloc(tempCount);
}
void ScriptInterpreter::cmd_class() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_objectp() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_vectorp() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_restart() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_rand() {
//fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_randomize() {
// TODO
_stack.setTop(0);
}
void ScriptInterpreter::cmd_send() {
debug(4, "\n\n\nENTER: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos);
byte argc = readByte();
debug(4, "argc = %d\n", argc);
_stack.push(argc);
_stack.push(_codeIp - _codeBase);
_stack.push(_runningScriptObjectIndex);
_stack.push(kScriptStackLimit - _localStackPos);
_localStackPos = _stack.getStackPos();
int16 propertyId = _stack.peek(_localStackPos + argc + 2);
int16 objectIndex = _stack.peek(_localStackPos + argc + 4);
debug(4, "objectIndex = %d (%04X); propertyId = %d(%04X)\n", objectIndex, objectIndex, propertyId, propertyId); fflush(stdout);
if (objectIndex != 0) {
objectIndex = _vm->_dat->getObject(objectIndex)->getClass();
} else {
objectIndex = _stack.peek(_localStackPos + argc + 3);
}
debug(4, "--> objectIndex = %d(%04X)\n", objectIndex, objectIndex); fflush(stdout);
if (objectIndex != 0) {
_runningScriptObjectIndex = _vm->_dat->getObjectProperty(objectIndex, propertyId);
if (_runningScriptObjectIndex != 0) {
_codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData();
_codeIp = _codeBase;
} else {
_stack.push(0);
cmd_return();
}
} else {
_stack.push(0);
cmd_return();
}
}
void ScriptInterpreter::cmd_extend() {
byte func = readByte();
byte argc = readByte();
int16 *argv = _stack.getStackPtr();
debug(4, "func = %d (%s); argc = %d\n", func, extendFuncNames[func], argc); fflush(stdout);
for (int i = 0; i < argc; i++)
debug(4, "argv[%02d] = %04X (%d)\n", i, argv[i], argv[i]);
int16 result = _functions->callFunction(func, argc, argv);
debug(4, "result = %04X (%d)\n", result, result);
_stack.free(argc);
_stack.setTop(result);
}
void ScriptInterpreter::cmd_catch() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_cdone() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_throw() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_functionp() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_le() {
int16 value = _stack.pop();
if (_stack.top() <= value)
_stack.setTop(-1);
else
_stack.setTop(0);
}
void ScriptInterpreter::cmd_ge() {
int16 value = _stack.pop();
if (_stack.top() >= value)
_stack.setTop(-1);
else
_stack.setTop(0);
}
void ScriptInterpreter::cmd_varx() {
fflush(stdout); g_system->delayMillis(5000);
}
void ScriptInterpreter::cmd_setx() {
fflush(stdout); g_system->delayMillis(5000);
}
} // End of namespace Made

154
engines/made/script.h Normal file
View file

@ -0,0 +1,154 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MADE_SCRIPT_H
#define MADE_SCRIPT_H
#include "common/util.h"
#include "common/file.h"
#include "common/stream.h"
namespace Made {
class MadeEngine;
class ScriptFunctions;
const int kScriptStackSize = 1000;
const int kScriptStackLimit = kScriptStackSize + 1;
class ScriptStack {
public:
ScriptStack();
~ScriptStack();
int16 top();
int16 pop();
void push(int16 value = 0);
void setTop(int16 value);
int16 peek(int16 index);
void poke(int16 index, int16 value);
void alloc(int16 count);
void free(int16 count);
int16 getStackPos() const { return _stackPos; }
void setStackPos(int16 stackPtr);
int16 *getStackPtr();
protected:
int16 _stack[kScriptStackSize];
int16 _stackPos;
};
class ScriptInterpreter {
public:
ScriptInterpreter(MadeEngine *vm);
~ScriptInterpreter();
void runScript(int16 scriptObjectIndex);
protected:
MadeEngine *_vm;
ScriptStack _stack;
int16 _localStackPos;
int16 _runningScriptObjectIndex;
byte *_codeBase, *_codeIp;
bool _terminated;
ScriptFunctions *_functions;
byte readByte();
int16 readInt16();
typedef void (ScriptInterpreter::*CommandProc)();
struct CommandEntry {
CommandProc proc;
const char *desc;
};
const CommandEntry *_commands;
int16 _commandsMax;
void cmd_branchTrue();
void cmd_branchFalse();
void cmd_branch();
void cmd_true();
void cmd_false();
void cmd_push();
void cmd_not();
void cmd_add();
void cmd_sub();
void cmd_mul();
void cmd_div();
void cmd_mod();
void cmd_band();
void cmd_bor();
void cmd_bnot();
void cmd_lt();
void cmd_eq();
void cmd_gt();
void cmd_loadConstant();
void cmd_loadVariable();
void cmd_getObjectProperty();
void cmd_setObjectProperty();
void cmd_set();
void cmd_print();
void cmd_terpri();
void cmd_printNumber();
void cmd_vref();
void cmd_vset();
void cmd_vsize();
void cmd_exit();
void cmd_return();
void cmd_call();
void cmd_svar();
void cmd_sset();
void cmd_split();
void cmd_snlit();
void cmd_yorn();
void cmd_save();
void cmd_restore();
void cmd_arg();
void cmd_aset();
void cmd_tmp();
void cmd_tset();
void cmd_tspace();
void cmd_class();
void cmd_objectp();
void cmd_vectorp();
void cmd_restart();
void cmd_rand();
void cmd_randomize();
void cmd_send();
void cmd_extend();
void cmd_catch();
void cmd_cdone();
void cmd_throw();
void cmd_functionp();
void cmd_le();
void cmd_ge();
void cmd_varx();
void cmd_setx();
};
} // End of namespace Made
#endif /* MADE_H */

View file

@ -0,0 +1,718 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/endian.h"
#include "common/util.h"
#include "common/events.h"
#include "graphics/cursorman.h"
#include "made/made.h"
#include "made/resource.h"
#include "made/database.h"
#include "made/screen.h"
#include "made/script.h"
#include "made/pmvplayer.h"
#include "made/scriptfuncs.h"
namespace Made {
int16 ScriptFunctions::callFunction(uint16 index, int16 argc, int16 *argv) {
if (index >= _externalFuncs.size()) {
// TODO: ERROR!
return 0;
}
fflush(stdout);
//g_system->delayMillis(2000);
return (*_externalFuncs[index])(argc, argv);
}
typedef Functor2Mem<int16, int16*, int16, ScriptFunctionsRtz> ExternalFuncRtz;
#define External(x) ExternalFuncRtz(this, &ScriptFunctionsRtz::x)
void ScriptFunctionsRtz::setupExternalsTable() {
static const ExternalFuncRtz externalsTable[] = {
External(o1_SYSTEM),
External(o1_INITGRAF),
External(o1_RESTOREGRAF),
External(o1_DRAWPIC),
External(o1_CLS),
External(o1_SHOWPAGE),
External(o1_EVENT),
External(o1_EVENTX),
External(o1_EVENTY),
External(o1_EVENTKEY),
External(o1_VISUALFX),
External(o1_PLAYSND),
External(o1_PLAYMUS),
External(o1_STOPMUS),
External(o1_ISMUS),
External(o1_TEXTPOS),
External(o1_FLASH),
External(o1_PLAYNOTE),
External(o1_STOPNOTE),
External(o1_PLAYTELE),
External(o1_STOPTELE),
External(o1_HIDECURS),
External(o1_SHOWCURS),
External(o1_MUSICBEAT),
External(o1_SCREENLOCK),
External(o1_ADDSPRITE),
External(o1_FREEANIM),
External(o1_DRAWSPRITE),
External(o1_ERASESPRITES),
External(o1_UPDATESPRITES),
External(o1_GETTIMER),
External(o1_SETTIMER),
External(o1_RESETTIMER),
External(o1_ALLOCTIMER),
External(o1_FREETIMER),
External(o1_PALETTELOCK),
External(o1_FONT),
External(o1_DRAWTEXT),
External(o1_HOMETEXT),
External(o1_TEXTRECT),
External(o1_TEXTXY),
External(o1_DROPSHADOW),
External(o1_TEXTCOLOR),
External(o1_OUTLINE),
External(o1_LOADCURSOR),
External(o1_SETGROUND),
External(o1_RESTEXT),
External(o1_CLIPAREA),
External(o1_SETCLIP),
External(o1_ISSND),
External(o1_STOPSND),
External(o1_PLAYVOICE),
External(o1_CDPLAY),
External(o1_STOPCD),
External(o1_CDSTATUS),
External(o1_CDTIME),
External(o1_CDPLAYSEG),
External(o1_PRINTF),
External(o1_MONOCLS),
External(o1_SNDENERGY),
External(o1_CLEARTEXT),
External(o1_ANIMTEXT),
External(o1_TEXTWIDTH),
External(o1_PLAYMOVIE),
External(o1_LOADSND),
External(o1_LOADMUS),
External(o1_LOADPIC),
External(o1_MUSICVOL),
External(o1_RESTARTEVENTS),
External(o1_PLACESPRITE),
External(o1_PLACETEXT),
External(o1_DELETECHANNEL),
External(o1_CHANNELTYPE),
External(o1_SETSTATE),
External(o1_SETLOCATION),
External(o1_SETCONTENT),
External(o1_EXCLUDEAREA),
External(o1_SETEXCLUDE),
External(o1_GETSTATE),
External(o1_PLACEANIM),
External(o1_SETFRAME),
External(o1_GETFRAME),
External(o1_GETFRAMECOUNT),
External(o1_PICWIDTH),
External(o1_PICHEIGHT),
External(o1_SOUNDRATE),
External(o1_DRAWANIMPIC),
External(o1_LOADANIM),
External(o1_READTEXT),
External(o1_READMENU),
External(o1_DRAWMENU),
External(o1_MENUCOUNT),
External(o1_SAVEGAME),
External(o1_LOADGAME),
External(o1_GAMENAME),
External(o1_SHAKESCREEN),
External(o1_PLACEMENU),
External(o1_SETVOLUME),
External(o1_WHATSYNTH),
External(o1_SLOWSYSTEM)
};
for (int i = 0; i < ARRAYSIZE(externalsTable); ++i)
_externalFuncs.push_back(&externalsTable[i]);
}
#undef External
int16 ScriptFunctionsRtz::o1_SYSTEM(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_INITGRAF(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_RESTOREGRAF(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_DRAWPIC(int16 argc, int16 *argv) {
fflush(stdout);
//g_system->delayMillis(5000);
int16 channel = _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]);
return channel;
}
int16 ScriptFunctionsRtz::o1_CLS(int16 argc, int16 *argv) {
//_vm->_screen->clearScreen();
return 0;
}
int16 ScriptFunctionsRtz::o1_SHOWPAGE(int16 argc, int16 *argv) {
//_vm->_system->setPalette(_vm->_screen->_palette, 0, 256);
_vm->_screen->show();
return 0;
}
int16 ScriptFunctionsRtz::o1_EVENT(int16 argc, int16 *argv) {
Common::Event event;
Common::EventManager *eventMan = g_system->getEventManager();
int16 eventNum = 0;
if (eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
_vm->_eventMouseX = event.mouse.x;
_vm->_eventMouseY = event.mouse.y;
break;
case Common::EVENT_LBUTTONDOWN:
eventNum = 1;
break;
case Common::EVENT_RBUTTONDOWN:
eventNum = 3;
break;
case Common::EVENT_KEYDOWN:
switch (event.kbd.ascii) {
case '1':
eventNum = 1;
break;
case '2':
eventNum = 2;
break;
case '3':
eventNum = 3;
break;
case '4':
eventNum = 4;
break;
case '5':
eventNum = 5;
break;
default:
break;
}
break;
default:
break;
}
}
_vm->_system->updateScreen();
//g_system->delayMillis(10);
return eventNum;
}
int16 ScriptFunctionsRtz::o1_EVENTX(int16 argc, int16 *argv) {
return _vm->_eventMouseX;
}
int16 ScriptFunctionsRtz::o1_EVENTY(int16 argc, int16 *argv) {
return _vm->_eventMouseY;
}
int16 ScriptFunctionsRtz::o1_EVENTKEY(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_VISUALFX(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_PLAYSND(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_PLAYMUS(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_STOPMUS(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_ISMUS(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_TEXTPOS(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_FLASH(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_PLAYNOTE(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_STOPNOTE(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_PLAYTELE(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_STOPTELE(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_HIDECURS(int16 argc, int16 *argv) {
_vm->_system->showMouse(false);
return 0;
}
int16 ScriptFunctionsRtz::o1_SHOWCURS(int16 argc, int16 *argv) {
_vm->_system->showMouse(true);
return 0;
}
int16 ScriptFunctionsRtz::o1_MUSICBEAT(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_SCREENLOCK(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_ADDSPRITE(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_FREEANIM(int16 argc, int16 *argv) {
_vm->_screen->clearChannels();
return 0;
}
int16 ScriptFunctionsRtz::o1_DRAWSPRITE(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_ERASESPRITES(int16 argc, int16 *argv) {
_vm->_screen->clearChannels();
return 0;
}
int16 ScriptFunctionsRtz::o1_UPDATESPRITES(int16 argc, int16 *argv) {
_vm->_screen->updateSprites();
return 0;
}
int16 ScriptFunctionsRtz::o1_GETTIMER(int16 argc, int16 *argv) {
return _vm->getTimer(argv[0]);
}
int16 ScriptFunctionsRtz::o1_SETTIMER(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_RESETTIMER(int16 argc, int16 *argv) {
_vm->resetTimer(argv[0]);
return 0;
}
int16 ScriptFunctionsRtz::o1_ALLOCTIMER(int16 argc, int16 *argv) {
int16 timerNum = _vm->allocTimer();
return timerNum;
}
int16 ScriptFunctionsRtz::o1_FREETIMER(int16 argc, int16 *argv) {
_vm->freeTimer(argv[0]);
return 0;
}
int16 ScriptFunctionsRtz::o1_PALETTELOCK(int16 argc, int16 *argv) {
//g_system->delayMillis(1000);
return 0;
}
int16 ScriptFunctionsRtz::o1_FONT(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_DRAWTEXT(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_HOMETEXT(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_TEXTXY(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_DROPSHADOW(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_TEXTCOLOR(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_OUTLINE(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_LOADCURSOR(int16 argc, int16 *argv) {
PictureResource *flex = _vm->_res->getPicture(argv[2]);
Graphics::Surface *surf = flex->getPicture();
CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, argv[1], argv[0], 0);
CursorMan.showMouse(true);
_vm->_res->freeResource(flex);
return 0;
}
int16 ScriptFunctionsRtz::o1_SETGROUND(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_RESTEXT(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_CLIPAREA(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_SETCLIP(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_ISSND(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_STOPSND(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_PLAYVOICE(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_CDPLAY(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_STOPCD(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_CDSTATUS(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_CDTIME(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_CDPLAYSEG(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_PRINTF(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_MONOCLS(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_SNDENERGY(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_CLEARTEXT(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_ANIMTEXT(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_TEXTWIDTH(int16 argc, int16 *argv) {
Object *obj = _vm->_dat->getObject(argv[1]);
const char *text = obj->getString();
debug(4, "text = %s\n", text); fflush(stdout);
//!!g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_PLAYMOVIE(int16 argc, int16 *argv) {
const char *movieName = _vm->_dat->getObject(argv[1])->getString();
printf("movieName = %s\n", movieName); fflush(stdout);
_vm->_pmvPlayer->play(movieName);
return 0;
}
int16 ScriptFunctionsRtz::o1_LOADSND(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_LOADMUS(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_LOADPIC(int16 argc, int16 *argv) {
PictureResource *flex = _vm->_res->getPicture(argv[0]);
if (flex) {
_vm->_res->freeResource(flex);
return 1;
}
return 0;
}
int16 ScriptFunctionsRtz::o1_MUSICVOL(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_RESTARTEVENTS(int16 argc, int16 *argv) {
return 0;
}
int16 ScriptFunctionsRtz::o1_PLACESPRITE(int16 argc, int16 *argv) {
return _vm->_screen->placeSprite(argv[3], argv[2], argv[1], argv[0]);
}
int16 ScriptFunctionsRtz::o1_PLACETEXT(int16 argc, int16 *argv) {
Object *obj = _vm->_dat->getObject(argv[5]);
_vm->_dat->dumpObject(argv[5]);
const char *text = obj->getString();
debug(4, "text = %s\n", text); fflush(stdout);
//!! g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_DELETECHANNEL(int16 argc, int16 *argv) {
_vm->_screen->deleteChannel(argv[0]);
return 0;
}
int16 ScriptFunctionsRtz::o1_CHANNELTYPE(int16 argc, int16 *argv) {
return _vm->_screen->getChannelType(argv[0]);
}
int16 ScriptFunctionsRtz::o1_SETSTATE(int16 argc, int16 *argv) {
_vm->_screen->setChannelState(argv[1], argv[0]);
return 0;
}
int16 ScriptFunctionsRtz::o1_SETLOCATION(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_SETCONTENT(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_EXCLUDEAREA(int16 argc, int16 *argv) {
//!! g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_SETEXCLUDE(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_GETSTATE(int16 argc, int16 *argv) {
//!! g_system->delayMillis(5000);
int16 state = _vm->_screen->getChannelState(argv[0]);
return state;
}
int16 ScriptFunctionsRtz::o1_PLACEANIM(int16 argc, int16 *argv) {
printf("anim = %04X\n", argv[3]); fflush(stdout);
int16 channel = _vm->_screen->placeAnim(argv[4], argv[3], argv[2], argv[1], argv[0]);
//g_system->delayMillis(5000);
return channel;
}
int16 ScriptFunctionsRtz::o1_SETFRAME(int16 argc, int16 *argv) {
_vm->_screen->setAnimFrame(argv[1], argv[0]);
return 0;
}
int16 ScriptFunctionsRtz::o1_GETFRAME(int16 argc, int16 *argv) {
return _vm->_screen->getAnimFrame(argv[0]);
}
int16 ScriptFunctionsRtz::o1_GETFRAMECOUNT(int16 argc, int16 *argv) {
debug(4, "anim = %04X\n", argv[0]);
int16 frameCount = _vm->_screen->getAnimFrameCount(argv[0]);
debug(4, "frameCount = %04X\n", frameCount);
//fflush(stdout);
//g_system->delayMillis(5000);
return frameCount;
}
int16 ScriptFunctionsRtz::o1_PICWIDTH(int16 argc, int16 *argv) {
int16 width = 0;
PictureResource *flex = _vm->_res->getPicture(argv[0]);
if (flex) {
width = flex->getPicture()->w;
_vm->_res->freeResource(flex);
}
return width;
}
int16 ScriptFunctionsRtz::o1_PICHEIGHT(int16 argc, int16 *argv) {
int16 height = 0;
PictureResource *flex = _vm->_res->getPicture(argv[0]);
if (flex) {
height = flex->getPicture()->h;
_vm->_res->freeResource(flex);
}
return height;
}
int16 ScriptFunctionsRtz::o1_SOUNDRATE(int16 argc, int16 *argv) {
//g_system->delayMillis(5000);
return 1;
}
int16 ScriptFunctionsRtz::o1_DRAWANIMPIC(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_LOADANIM(int16 argc, int16 *argv) {
//g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_READTEXT(int16 argc, int16 *argv) {
//g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) {
/*
int16 objectIndex = argv[2];
int16 menuIndex = argv[1];
int16 textIndex = argv[0];
MenuResource *menu = _vm->_res->getMenu(menuIndex);
if (menu) {
const char *text = menu->getString(textIndex).c_str();
debug(4, "text = %s\n", text); fflush(stdout);
_vm->_res->freeResource(menu);
}
g_system->delayMillis(5000);
*/
return 0;
}
int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_SHAKESCREEN(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_PLACEMENU(int16 argc, int16 *argv) {
g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_SETVOLUME(int16 argc, int16 *argv) {
//!! g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_WHATSYNTH(int16 argc, int16 *argv) {
//g_system->delayMillis(5000);
return 0;
}
int16 ScriptFunctionsRtz::o1_SLOWSYSTEM(int16 argc, int16 *argv) {
//!! g_system->delayMillis(5000);
return 0;
}
} // End of namespace Made

188
engines/made/scriptfuncs.h Normal file
View file

@ -0,0 +1,188 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MADE_SCRIPTFUNCS_H
#define MADE_SCRIPTFUNCS_H
#include "common/util.h"
#include "common/file.h"
#include "common/stream.h"
namespace Made {
class MadeEngine;
template<class Arg1, class Arg2, class Res>
struct Functor2 : public Common::BinaryFunction<Arg1, Arg2, Res> {
virtual ~Functor2() {}
virtual bool isValid() const = 0;
virtual Res operator()(Arg1, Arg2) const = 0;
};
template<class Arg1, class Arg2, class Res, class T>
class Functor2Mem : public Functor2<Arg1, Arg2, Res> {
public:
typedef Res (T::*FuncType)(Arg1, Arg2);
Functor2Mem(T *t, const FuncType &func) : _t(t), _func(func) {}
bool isValid() const { return _func != 0; }
Res operator()(Arg1 v1, Arg2 v2) const {
return (_t->*_func)(v1, v2);
}
private:
mutable T *_t;
Res (T::*_func)(Arg1, Arg2);
};
typedef Functor2<int16, int16*, int16> ExternalFunc;
class ScriptFunctions {
public:
ScriptFunctions(MadeEngine *vm) : _vm(vm) {}
virtual ~ScriptFunctions() {}
int16 callFunction(uint16 index, int16 argc, int16 *argv);
virtual void setupExternalsTable() = 0;
protected:
MadeEngine *_vm;
Common::Array<const ExternalFunc*> _externalFuncs;
};
class ScriptFunctionsRtz : public ScriptFunctions {
public:
ScriptFunctionsRtz(MadeEngine *vm) : ScriptFunctions(vm) {}
~ScriptFunctionsRtz() {}
void setupExternalsTable();
protected:
int16 o1_SYSTEM(int16 argc, int16 *argv);
int16 o1_INITGRAF(int16 argc, int16 *argv);
int16 o1_RESTOREGRAF(int16 argc, int16 *argv);
int16 o1_DRAWPIC(int16 argc, int16 *argv);
int16 o1_CLS(int16 argc, int16 *argv);
int16 o1_SHOWPAGE(int16 argc, int16 *argv);
int16 o1_EVENT(int16 argc, int16 *argv);
int16 o1_EVENTX(int16 argc, int16 *argv);
int16 o1_EVENTY(int16 argc, int16 *argv);
int16 o1_EVENTKEY(int16 argc, int16 *argv);
int16 o1_VISUALFX(int16 argc, int16 *argv);
int16 o1_PLAYSND(int16 argc, int16 *argv);
int16 o1_PLAYMUS(int16 argc, int16 *argv);
int16 o1_STOPMUS(int16 argc, int16 *argv);
int16 o1_ISMUS(int16 argc, int16 *argv);
int16 o1_TEXTPOS(int16 argc, int16 *argv);
int16 o1_FLASH(int16 argc, int16 *argv);
int16 o1_PLAYNOTE(int16 argc, int16 *argv);
int16 o1_STOPNOTE(int16 argc, int16 *argv);
int16 o1_PLAYTELE(int16 argc, int16 *argv);
int16 o1_STOPTELE(int16 argc, int16 *argv);
int16 o1_HIDECURS(int16 argc, int16 *argv);
int16 o1_SHOWCURS(int16 argc, int16 *argv);
int16 o1_MUSICBEAT(int16 argc, int16 *argv);
int16 o1_SCREENLOCK(int16 argc, int16 *argv);
int16 o1_ADDSPRITE(int16 argc, int16 *argv);
int16 o1_FREEANIM(int16 argc, int16 *argv);
int16 o1_DRAWSPRITE(int16 argc, int16 *argv);
int16 o1_ERASESPRITES(int16 argc, int16 *argv);
int16 o1_UPDATESPRITES(int16 argc, int16 *argv);
int16 o1_GETTIMER(int16 argc, int16 *argv);
int16 o1_SETTIMER(int16 argc, int16 *argv);
int16 o1_RESETTIMER(int16 argc, int16 *argv);
int16 o1_ALLOCTIMER(int16 argc, int16 *argv);
int16 o1_FREETIMER(int16 argc, int16 *argv);
int16 o1_PALETTELOCK(int16 argc, int16 *argv);
int16 o1_FONT(int16 argc, int16 *argv);
int16 o1_DRAWTEXT(int16 argc, int16 *argv);
int16 o1_HOMETEXT(int16 argc, int16 *argv);
int16 o1_TEXTRECT(int16 argc, int16 *argv);
int16 o1_TEXTXY(int16 argc, int16 *argv);
int16 o1_DROPSHADOW(int16 argc, int16 *argv);
int16 o1_TEXTCOLOR(int16 argc, int16 *argv);
int16 o1_OUTLINE(int16 argc, int16 *argv);
int16 o1_LOADCURSOR(int16 argc, int16 *argv);
int16 o1_SETGROUND(int16 argc, int16 *argv);
int16 o1_RESTEXT(int16 argc, int16 *argv);
int16 o1_CLIPAREA(int16 argc, int16 *argv);
int16 o1_SETCLIP(int16 argc, int16 *argv);
int16 o1_ISSND(int16 argc, int16 *argv);
int16 o1_STOPSND(int16 argc, int16 *argv);
int16 o1_PLAYVOICE(int16 argc, int16 *argv);
int16 o1_CDPLAY(int16 argc, int16 *argv);
int16 o1_STOPCD(int16 argc, int16 *argv);
int16 o1_CDSTATUS(int16 argc, int16 *argv);
int16 o1_CDTIME(int16 argc, int16 *argv);
int16 o1_CDPLAYSEG(int16 argc, int16 *argv);
int16 o1_PRINTF(int16 argc, int16 *argv);
int16 o1_MONOCLS(int16 argc, int16 *argv);
int16 o1_SNDENERGY(int16 argc, int16 *argv);
int16 o1_CLEARTEXT(int16 argc, int16 *argv);
int16 o1_ANIMTEXT(int16 argc, int16 *argv);
int16 o1_TEXTWIDTH(int16 argc, int16 *argv);
int16 o1_PLAYMOVIE(int16 argc, int16 *argv);
int16 o1_LOADSND(int16 argc, int16 *argv);
int16 o1_LOADMUS(int16 argc, int16 *argv);
int16 o1_LOADPIC(int16 argc, int16 *argv);
int16 o1_MUSICVOL(int16 argc, int16 *argv);
int16 o1_RESTARTEVENTS(int16 argc, int16 *argv);
int16 o1_PLACESPRITE(int16 argc, int16 *argv);
int16 o1_PLACETEXT(int16 argc, int16 *argv);
int16 o1_DELETECHANNEL(int16 argc, int16 *argv);
int16 o1_CHANNELTYPE(int16 argc, int16 *argv);
int16 o1_SETSTATE(int16 argc, int16 *argv);
int16 o1_SETLOCATION(int16 argc, int16 *argv);
int16 o1_SETCONTENT(int16 argc, int16 *argv);
int16 o1_EXCLUDEAREA(int16 argc, int16 *argv);
int16 o1_SETEXCLUDE(int16 argc, int16 *argv);
int16 o1_GETSTATE(int16 argc, int16 *argv);
int16 o1_PLACEANIM(int16 argc, int16 *argv);
int16 o1_SETFRAME(int16 argc, int16 *argv);
int16 o1_GETFRAME(int16 argc, int16 *argv);
int16 o1_GETFRAMECOUNT(int16 argc, int16 *argv);
int16 o1_PICWIDTH(int16 argc, int16 *argv);
int16 o1_PICHEIGHT(int16 argc, int16 *argv);
int16 o1_SOUNDRATE(int16 argc, int16 *argv);
int16 o1_DRAWANIMPIC(int16 argc, int16 *argv);
int16 o1_LOADANIM(int16 argc, int16 *argv);
int16 o1_READTEXT(int16 argc, int16 *argv);
int16 o1_READMENU(int16 argc, int16 *argv);
int16 o1_DRAWMENU(int16 argc, int16 *argv);
int16 o1_MENUCOUNT(int16 argc, int16 *argv);
int16 o1_SAVEGAME(int16 argc, int16 *argv);
int16 o1_LOADGAME(int16 argc, int16 *argv);
int16 o1_GAMENAME(int16 argc, int16 *argv);
int16 o1_SHAKESCREEN(int16 argc, int16 *argv);
int16 o1_PLACEMENU(int16 argc, int16 *argv);
int16 o1_SETVOLUME(int16 argc, int16 *argv);
int16 o1_WHATSYNTH(int16 argc, int16 *argv);
int16 o1_SLOWSYSTEM(int16 argc, int16 *argv);
};
} // End of namespace Made
#endif /* MADE_H */

131
engines/made/sound.cpp Normal file
View file

@ -0,0 +1,131 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/endian.h"
#include "common/util.h"
#include "made/sound.h"
namespace Made {
void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount) {
int16 prevSample = 0;
byte soundBuffer[1025];
byte soundBuffer3[1024];
int16 soundBuffer2[16];
while (chunkCount--) {
byte deltaType = (*source) >> 6;
uint16 workChunkSize = chunkSize;
if (deltaType == 1)
workChunkSize /= 2;
else if (deltaType == 2)
workChunkSize /= 4;
byte type = (*source++) & 0x0F;
int16 workSample = prevSample;
switch (type) {
case 0:
memset(soundBuffer, 0x80, workChunkSize);
workSample = 0;
break;
case 1:
break;
case 2:
case 3:
case 4:
{
const int modeValues[3][4] = {
{ 2, 8, 0x01, 1},
{ 4, 4, 0x03, 2},
{16, 2, 0x0F, 4}
};
uint16 byteCount = modeValues[type - 2][0];
uint16 bitCount = modeValues[type - 2][1];
byte bitMask = modeValues[type - 2][2];
byte bitShift = modeValues[type - 2][3];
uint16 ofs = 0;
for (uint16 i = 0; i < byteCount; i++)
soundBuffer2[i] = (*source++) * 2 - 128;
while (ofs < workChunkSize) {
byte val = *source++;
for (uint i = 0; i < bitCount; i++) {
workSample = CLIP<int16>(workSample + soundBuffer2[val & bitMask], -127, 127);
val >>= bitShift;
soundBuffer[ofs++] = workSample + 128;
}
}
break;
}
case 5:
{
for (uint16 i = 0; i < workChunkSize; i++)
soundBuffer[i] = *source++;
workSample = soundBuffer[workChunkSize - 1] - 128;
break;
}
default:
return;
}
if (deltaType == 1) {
for (uint16 i = 0; i < chunkSize - 1; i += 2) {
uint16 l = i / 2;
soundBuffer3[i] = soundBuffer[l];
soundBuffer3[i + 1] = (soundBuffer[l + 1] + soundBuffer[l]) / 2;
}
for (uint16 i = 0; i < chunkSize; i++) {
soundBuffer[i] = soundBuffer3[i];
}
} else if (deltaType == 2) {
debug(2, "****************************************");
}
prevSample = workSample;
memcpy(dest, soundBuffer, chunkSize);
dest += chunkSize;
}
}
} // End of namespace Made

39
engines/made/sound.h Normal file
View 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 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef MADE_SOUND_H
#define MADE_SOUND_H
#include "common/util.h"
#include "common/file.h"
#include "common/stream.h"
namespace Made {
void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount);
} // End of namespace Made
#endif /* MADE_H */