diff options
Diffstat (limited to 'engines/made')
-rw-r--r-- | engines/made/database.cpp | 608 | ||||
-rw-r--r-- | engines/made/database.h | 122 | ||||
-rw-r--r-- | engines/made/detection.cpp | 116 | ||||
-rw-r--r-- | engines/made/graphics.cpp | 144 | ||||
-rw-r--r-- | engines/made/graphics.h | 13 | ||||
-rw-r--r-- | engines/made/made.cpp | 121 | ||||
-rw-r--r-- | engines/made/made.h | 29 | ||||
-rw-r--r-- | engines/made/module.mk | 5 | ||||
-rw-r--r-- | engines/made/pmvplayer.cpp | 72 | ||||
-rw-r--r-- | engines/made/resource.cpp | 34 | ||||
-rw-r--r-- | engines/made/resource.h | 11 | ||||
-rw-r--r-- | engines/made/screen.cpp | 315 | ||||
-rw-r--r-- | engines/made/screen.h | 94 | ||||
-rw-r--r-- | engines/made/screenfx.cpp | 356 | ||||
-rw-r--r-- | engines/made/screenfx.h | 70 | ||||
-rw-r--r-- | engines/made/script.cpp | 366 | ||||
-rw-r--r-- | engines/made/script.h | 10 | ||||
-rw-r--r-- | engines/made/scriptfuncs.cpp | 770 | ||||
-rw-r--r-- | engines/made/scriptfuncs.h | 359 | ||||
-rw-r--r-- | engines/made/scriptfuncs_lgop2.cpp | 467 | ||||
-rw-r--r-- | engines/made/scriptfuncs_mhne.cpp | 494 | ||||
-rw-r--r-- | engines/made/scriptfuncs_rtz.cpp | 864 |
22 files changed, 2403 insertions, 3037 deletions
diff --git a/engines/made/database.cpp b/engines/made/database.cpp index a7970a2e27..55e0e90732 100644 --- a/engines/made/database.cpp +++ b/engines/made/database.cpp @@ -39,7 +39,7 @@ namespace Made { < 0x7FFE object */ -Object::Object() { +Object::Object() : _objData(NULL), _freeData(false) { } Object::~Object() { @@ -47,82 +47,6 @@ Object::~Object() { delete[] _objData; } -int Object::loadVersion2(Common::SeekableReadStream &source) { - _freeData = true; - uint16 type = 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(-4, SEEK_CUR); - _objSize += 6; - _objData = new byte[_objSize]; - WRITE_LE_UINT16(_objData, 1); - source.read(_objData + 2, _objSize - 2); - return _objSize - 2; -} - -int Object::loadVersion3(Common::SeekableReadStream &source) { - _freeData = true; - source.readUint16LE(); // skip flags - uint16 type = 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); - return _objSize; -} - -int Object::loadVersion3(byte *source) { - _objData = source; - _freeData = false; - if (getClass() < 0x7FFE) { - _objSize = (getCount1() + getCount2()) * 2; - } else { - _objSize = getSize(); - } - _objSize += 6; - return _objSize; -} - -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(); @@ -195,15 +119,140 @@ void Object::dump(const char *filename) { */ } +int ObjectV2::load(Common::SeekableReadStream &source) { + + if (_freeData && _objData) + delete[] _objData; + + _freeData = true; + + byte header[4]; + source.read(header, 4); + + uint16 type = READ_LE_UINT16(header); + if (type == 0x7FFF) { + _objSize = READ_LE_UINT16(header + 2); + } else if (type == 0x7FFE) { + _objSize = READ_LE_UINT16(header + 2) * 2; + } else if (type < 0x7FFE) { + byte count1 = header[2]; + byte count2 = header[3]; + _objSize = (count1 + count2) * 2; + } + _objSize += 4; + _objData = new byte[_objSize]; + memcpy(_objData, header, 4); + source.read(_objData + 4, _objSize - 4); + + return _objSize; + +} + +int ObjectV2::load(byte *source) { + // Not implemented/used for version 2 objects + return 0; +} + +int ObjectV2::save(Common::WriteStream &dest) { + dest.write(_objData, _objSize); + return 0; +} + +uint16 ObjectV2::getFlags() { + return 1; +} + +uint16 ObjectV2::getClass() { + return READ_LE_UINT16(_objData); +} + +uint16 ObjectV2::getSize() { + return READ_LE_UINT16(_objData + 2); +} + +byte ObjectV2::getCount1() { + return _objData[2]; +} + +byte ObjectV2::getCount2() { + return _objData[3]; +} + +byte *ObjectV2::getData() { + return _objData + 4; +} + +int ObjectV3::load(Common::SeekableReadStream &source) { + + _freeData = true; + source.readUint16LE(); // skip flags + uint16 type = 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); + return _objSize; + +} + +int ObjectV3::load(byte *source) { + _objData = source; + _freeData = false; + if (getClass() < 0x7FFE) { + _objSize = (getCount1() + getCount2()) * 2; + } else { + _objSize = getSize(); + } + _objSize += 6; + return _objSize; +} + +int ObjectV3::save(Common::WriteStream &dest) { + // Not implemented/used for version 3 objects + return 0; +} + +uint16 ObjectV3::getFlags() { + return READ_LE_UINT16(_objData); +} + +uint16 ObjectV3::getClass() { + return READ_LE_UINT16(_objData + 2); +} + +uint16 ObjectV3::getSize() { + return READ_LE_UINT16(_objData + 4); +} + +byte ObjectV3::getCount1() { + return _objData[4]; +} + +byte ObjectV3::getCount2() { + return _objData[5]; +} + +byte *ObjectV3::getData() { + return _objData + 6; +} + + + GameDatabase::GameDatabase(MadeEngine *vm) : _vm(vm) { - _gameText = NULL; } GameDatabase::~GameDatabase() { if (_gameState) delete[] _gameState; - if (_gameText) - delete[] _gameText; } void GameDatabase::open(const char *filename) { @@ -224,19 +273,85 @@ void GameDatabase::openFromRed(const char *redFilename, const char *filename) { delete fileS; } -void GameDatabase::load(Common::SeekableReadStream &sourceS) { +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); +} + +const char *GameDatabase::getObjectString(int16 index) { + Object *obj = getObject(index); + if (obj) + return obj->getString(); + else + return ""; +} - if (_vm->getGameID() == GID_MANHOLE || _vm->getGameID() == GID_LGOP2) { - debug(2, "loading version 2 dat"); - loadVersion2(sourceS); - } else if (_vm->getGameID() == GID_RTZ) { - debug(2, "loading version 3 dat"); - loadVersion3(sourceS); +void GameDatabase::setObjectString(int16 index, const char *str) { + Object *obj = getObject(index); + if (obj) + obj->setString(str); +} + +int16 GameDatabase::getObjectProperty(int16 objectIndex, int16 propertyId) { + + if (objectIndex == 0) + return 0; + + int16 propertyFlag; + int16 *property = findObjectProperty(objectIndex, propertyId, propertyFlag); + + if (property) { + return (int16)READ_LE_UINT16(property); + } else { + return 0; } } -void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) { +int16 GameDatabase::setObjectProperty(int16 objectIndex, int16 propertyId, int16 value) { + + if (objectIndex == 0) + return 0; + + int16 propertyFlag; + int16 *property = findObjectProperty(objectIndex, propertyId, propertyFlag); + + if (property) { + if (propertyFlag == 1) { + WRITE_LE_UINT16(property, value); + } else { + warning("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); +} + + +/* GameDatabaseV2 */ + +GameDatabaseV2::GameDatabaseV2(MadeEngine *vm) : GameDatabase(vm), _gameText(NULL) { +} + +GameDatabaseV2::~GameDatabaseV2() { + if (_gameText) + delete[] _gameText; +} + +void GameDatabaseV2::load(Common::SeekableReadStream &sourceS) { // TODO: Read/verifiy header @@ -256,8 +371,9 @@ void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) { debug(2, "textOffs = %08X; textSize = %08X; objectCount = %d; varObjectCount = %d; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", textOffs, textSize, objectCount, varObjectCount, _gameStateSize, objectsOffs, objectsSize); - _gameState = new byte[_gameStateSize]; + _gameState = new byte[_gameStateSize + 2]; memset(_gameState, 0, _gameStateSize); + setVar(1, objectCount); sourceS.seek(textOffs); _gameText = new char[textSize]; @@ -269,145 +385,52 @@ void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) { sourceS.seek(objectsOffs); for (uint32 i = 0; i < objectCount; i++) { - Object *obj = new Object(); - int objSize = obj->loadVersion2(sourceS); - objSize = objSize % 2; + Object *obj = new ObjectV2(); + int objSize = obj->load(sourceS); // objects are aligned on 2-byte-boundaries, skip unused bytes - sourceS.skip(objSize); + sourceS.skip(objSize % 2); _objects.push_back(obj); } } -void GameDatabase::loadVersion3(Common::SeekableReadStream &sourceS) { - - // TODO: Read/verifiy header - - sourceS.seek(0x1E); - - uint32 objectIndexOffs = sourceS.readUint32LE(); - uint16 objectCount = sourceS.readUint16LE(); - uint32 gameStateOffs = sourceS.readUint32LE(); - _gameStateSize = sourceS.readUint32LE(); - uint32 objectsOffs = sourceS.readUint32LE(); - uint32 objectsSize = sourceS.readUint32LE(); - _mainCodeObjectIndex = sourceS.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]; - sourceS.seek(gameStateOffs); - sourceS.read(_gameState, _gameStateSize); - - Common::Array<uint32> objectOffsets; - sourceS.seek(objectIndexOffs); - for (uint32 i = 0; i < objectCount; i++) - objectOffsets.push_back(sourceS.readUint32LE()); - - for (uint32 i = 0; i < objectCount; i++) { - Object *obj = new Object(); - - // The LSB indicates if it's a constant or variable object. - // Constant objects are loaded from disk, while variable objects exist - // in the _gameState buffer. - - debug(2, "obj(%04X) ofs = %08X\n", i, objectOffsets[i]); - - if (objectOffsets[i] & 1) { - debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1); - sourceS.seek(objectsOffs + objectOffsets[i] - 1); - obj->loadVersion3(sourceS); - } else { - debug(2, "-> var\n"); - obj->loadVersion3(_gameState + objectOffsets[i]); - } - _objects.push_back(obj); - } - -} - -bool GameDatabase::getSavegameDescription(const char *filename, Common::String &description) { - - Common::InSaveFile *in; - - if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { - return false; - } - - char desc[64]; - - in->skip(4); // TODO: Verify marker 'SGAM' - in->skip(4); // TODO: Verify size - in->skip(2); // TODO: Verify version - in->read(desc, 64); - description = desc; - - printf("description = %s\n", description.c_str()); fflush(stdout); - - delete in; - - return true; - +bool GameDatabaseV2::getSavegameDescription(const char *filename, Common::String &description) { + // Not used in version 2 games + return false; } -int16 GameDatabase::savegame(const char *filename, const char *description, int16 version) { - +int16 GameDatabaseV2::savegame(const char *filename, const char *description, int16 version) { Common::OutSaveFile *out; - + int16 result = 0; if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { warning("Can't create file '%s', game not saved", filename); return 6; } - - uint32 size = 4 + 4 + 2 + _gameStateSize; - char desc[64]; - - strncpy(desc, description, 64); - - out->writeUint32BE(MKID_BE('SGAM')); - out->writeUint32LE(size); - out->writeUint16LE(version); - out->write(desc, 64); - out->write(_gameState, _gameStateSize); - + // Variable 0 is not saved + out->write(_gameState + 2, _gameStateSize - 2); + for (uint i = 0; i < _objects.size(); i++) + _objects[i]->save(*out); delete out; - - return 0; - + return result; } -int16 GameDatabase::loadgame(const char *filename, int16 version) { - +int16 GameDatabaseV2::loadgame(const char *filename, int16 version) { Common::InSaveFile *in; - + int16 result = 0; if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { warning("Can't open file '%s', game not loaded", filename); return 1; } - - //uint32 expectedSize = 4 + 4 + 2 + _gameStateSize; - - in->skip(4); // TODO: Verify marker 'SGAM' - in->skip(4); // TODO: Verify size - in->skip(2); // TODO: Verify version - in->skip(64); // skip savegame description - in->read(_gameState, _gameStateSize); - + // Variable 0 is not loaded + in->read(_gameState + 2, _gameStateSize - 2); + for (uint i = 0; i < _objects.size(); i++) { + _objects[i]->load(*in); + } delete in; - - return 0; - + return result; } -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::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { +int16 *GameDatabaseV2::findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { Object *obj = getObject(objectIndex); int16 *prop = (int16*)obj->getData(); @@ -430,14 +453,11 @@ int16 *GameDatabase::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, // 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); - obj = getObject(parentObjectIndex); prop = (int16*)obj->getData(); @@ -469,12 +489,116 @@ int16 *GameDatabase::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, } - //debug(2, "! NULL(nf)\n"); + debug(1, "findObjectProperty(%04X, %04X) Property not found", objectIndex, propertyId); return NULL; } -int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { +const char *GameDatabaseV2::getString(uint16 offset) { + return (const char*)&_gameText[offset * 4]; +} + + +/* GameDatabaseV3 */ + +GameDatabaseV3::GameDatabaseV3(MadeEngine *vm) : GameDatabase(vm) { +} + +void GameDatabaseV3::load(Common::SeekableReadStream &sourceS) { + + // TODO: Read/verifiy header + + sourceS.seek(0x1E); + + uint32 objectIndexOffs = sourceS.readUint32LE(); + uint16 objectCount = sourceS.readUint16LE(); + uint32 gameStateOffs = sourceS.readUint32LE(); + _gameStateSize = sourceS.readUint32LE(); + uint32 objectsOffs = sourceS.readUint32LE(); + uint32 objectsSize = sourceS.readUint32LE(); + _mainCodeObjectIndex = sourceS.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]; + sourceS.seek(gameStateOffs); + sourceS.read(_gameState, _gameStateSize); + + Common::Array<uint32> objectOffsets; + sourceS.seek(objectIndexOffs); + for (uint32 i = 0; i < objectCount; i++) + objectOffsets.push_back(sourceS.readUint32LE()); + + for (uint32 i = 0; i < objectCount; i++) { + Object *obj = new ObjectV3(); + + // The LSB indicates if it's a constant or variable object. + // Constant objects are loaded from disk, while variable objects exist + // in the _gameState buffer. + + if (objectOffsets[i] & 1) { + sourceS.seek(objectsOffs + objectOffsets[i] - 1); + obj->load(sourceS); + } else { + obj->load(_gameState + objectOffsets[i]); + } + _objects.push_back(obj); + } + +} + +bool GameDatabaseV3::getSavegameDescription(const char *filename, Common::String &description) { + Common::InSaveFile *in; + char desc[64]; + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + return false; + } + in->skip(4); // TODO: Verify marker 'SGAM' + in->skip(4); // TODO: Verify size + in->skip(2); // TODO: Verify version + in->read(desc, 64); + description = desc; + delete in; + return true; +} + +int16 GameDatabaseV3::savegame(const char *filename, const char *description, int16 version) { + Common::OutSaveFile *out; + char desc[64]; + int16 result = 0; + uint32 size = 4 + 4 + 2 + _gameStateSize; + if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { + warning("Can't create file '%s', game not saved", filename); + return 6; + } + strncpy(desc, description, 64); + out->writeUint32BE(MKID_BE('SGAM')); + out->writeUint32LE(size); + out->writeUint16LE(version); + out->write(desc, 64); + out->write(_gameState, _gameStateSize); + delete out; + return result; +} + +int16 GameDatabaseV3::loadgame(const char *filename, int16 version) { + Common::InSaveFile *in; + int16 result = 0; + //uint32 expectedSize = 4 + 4 + 2 + _gameStateSize; + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + warning("Can't open file '%s', game not loaded", filename); + return 1; + } + in->skip(4); // TODO: Verify marker 'SGAM' + in->skip(4); // TODO: Verify size + in->skip(2); // TODO: Verify version + in->skip(64); // skip savegame description + in->read(_gameState, _gameStateSize); + delete in; + return result; +} + +int16 *GameDatabaseV3::findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { Object *obj = getObject(objectIndex); int16 *prop = (int16*)obj->getData(); @@ -502,14 +626,11 @@ int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, // 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); - obj = getObject(parentObjectIndex); prop = (int16*)obj->getData(); @@ -551,70 +672,13 @@ int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, } - //debug(2, "! NULL(nf)\n"); return NULL; - -} - -int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { - switch (_vm->_engineVersion) { - case 2: - return getObjectPropertyPtrV2(objectIndex, propertyId, propertyFlag); - case 3: - return getObjectPropertyPtrV3(objectIndex, propertyId, propertyFlag); - default: - error("GameDatabase::getObjectPropertyPtr() Unknown engine version"); - return NULL; - } -} - -int16 GameDatabase::getObjectProperty(int16 objectIndex, int16 propertyId) { - - if (objectIndex == 0) - return 0; - - int16 propertyFlag; - int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag); - if (property) { - return (int16)READ_LE_UINT16(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) { - WRITE_LE_UINT16(property, value); - } else { - debug(2, "GameDatabase::setObjectProperty(%04X, %04X, %04X) Trying to set constant property\n", - objectIndex, propertyId, value); - } - return value; - } else { - return 0; - } - -} - -const char *GameDatabase::getString(uint16 offset) { - return (const char*)&_gameText[offset * 4]; -} - -void GameDatabase::dumpObject(int16 index) { - Object *obj = getObject(index); - char fn[512]; - sprintf(fn, "obj%04X.0", index); - obj->dump(fn); +const char *GameDatabaseV3::getString(uint16 offset) { + // Not used in version 3 games + return NULL; } } // End of namespace Made diff --git a/engines/made/database.h b/engines/made/database.h index b92bd8f2dd..466d1a8f69 100644 --- a/engines/made/database.h +++ b/engines/made/database.h @@ -40,26 +40,25 @@ namespace Made { class Object { public: Object(); - ~Object(); - int loadVersion2(Common::SeekableReadStream &source); - int loadVersion3(Common::SeekableReadStream &source); - int loadVersion3(byte *source); + virtual ~Object(); + + virtual int load(Common::SeekableReadStream &source) = 0; + virtual int load(byte *source) = 0; + virtual int save(Common::WriteStream &dest) = 0; + virtual uint16 getFlags() = 0; + virtual uint16 getClass() = 0; + virtual uint16 getSize() = 0; + virtual byte getCount1() = 0; + virtual byte getCount2() = 0; + virtual byte *getData() = 0; + virtual bool isConstant() = 0; - uint16 getFlags() const; - uint16 getClass() const; - uint16 getSize() const; - - byte getCount1() const; - byte getCount2() const; - - byte *getData(); const char *getString(); void setString(const char *str); bool isObject(); bool isVector(); - bool isConstant() const { return !(getFlags() & 1); } - + int16 getVectorSize(); int16 getVectorItem(int16 index); void setVectorItem(int16 index, int16 value); @@ -72,52 +71,113 @@ protected: byte *_objData; }; +class ObjectV2 : public Object { +public: + int load(Common::SeekableReadStream &source); + int load(byte *source); + int save(Common::WriteStream &dest); + uint16 getFlags(); + uint16 getClass(); + uint16 getSize(); + byte getCount1(); + byte getCount2(); + byte *getData(); + + bool isConstant() { + return false; + } + +}; + +class ObjectV3 : public Object { +public: + int load(Common::SeekableReadStream &source); + int load(byte *source); + int save(Common::WriteStream &dest); + uint16 getFlags(); + uint16 getClass(); + uint16 getSize(); + byte getCount1(); + byte getCount2(); + byte *getData(); + + bool isConstant() { + return !(getFlags() & 1); + } + +}; + class GameDatabase { public: GameDatabase(MadeEngine *vm); - ~GameDatabase(); + virtual ~GameDatabase(); void open(const char *filename); void openFromRed(const char *redFilename, const char *filename); - bool getSavegameDescription(const char *filename, Common::String &description); - int16 savegame(const char *filename, const char *description, int16 version); - int16 loadgame(const char *filename, int16 version); - - Object *getObject(int16 index) const { + Object *getObject(int16 index) const { if (index >= 1) return _objects[index - 1]; else return NULL; } + uint getObjectCount() const { return _objects.size(); } + int16 getMainCodeObjectIndex() const { return _mainCodeObjectIndex; } int16 getVar(int16 index); void setVar(int16 index, int16 value); - - int16 *getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, int16 &propertyFlag); - int16 *getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, int16 &propertyFlag); - int16 *getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag); - + + const char *getObjectString(int16 index); + void setObjectString(int16 index, const char *str); + + virtual int16 *findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag) = 0; + virtual const char *getString(uint16 offset) = 0; + virtual bool getSavegameDescription(const char *filename, Common::String &description) = 0; + virtual int16 savegame(const char *filename, const char *description, int16 version) = 0; + virtual int16 loadgame(const char *filename, int16 version) = 0; + int16 getObjectProperty(int16 objectIndex, int16 propertyId); int16 setObjectProperty(int16 objectIndex, int16 propertyId, int16 value); - - const char *getString(uint16 offset); void dumpObject(int16 index); - + protected: MadeEngine *_vm; Common::Array<Object*> _objects; byte *_gameState; uint32 _gameStateSize; - char *_gameText; int16 _mainCodeObjectIndex; + virtual void load(Common::SeekableReadStream &sourceS) = 0; +}; + +class GameDatabaseV2 : public GameDatabase { +public: + GameDatabaseV2(MadeEngine *vm); + ~GameDatabaseV2(); + int16 *findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag); + const char *getString(uint16 offset); + bool getSavegameDescription(const char *filename, Common::String &description); + int16 savegame(const char *filename, const char *description, int16 version); + int16 loadgame(const char *filename, int16 version); +protected: + char *_gameText; + void load(Common::SeekableReadStream &sourceS); +}; + +class GameDatabaseV3 : public GameDatabase { +public: + GameDatabaseV3(MadeEngine *vm); + int16 *findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag); + const char *getString(uint16 offset); + bool getSavegameDescription(const char *filename, Common::String &description); + int16 savegame(const char *filename, const char *description, int16 version); + int16 loadgame(const char *filename, int16 version); +protected: + char *_gameText; void load(Common::SeekableReadStream &sourceS); - void loadVersion2(Common::SeekableReadStream &sourceS); - void loadVersion3(Common::SeekableReadStream &sourceS); }; } // End of namespace Made diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index 6da3189163..dc7dbdee87 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -65,6 +65,7 @@ static const PlainGameDescriptor madeGames[] = { {"manhole", "The Manhole"}, {"rtz", "Return to Zork"}, {"lgop2", "Leather Goddesses of Phobos 2"}, + {"rodney", "Rodney's Fun Screen"}, {0, 0} }; @@ -74,9 +75,45 @@ namespace Made { static const MadeGameDescription gameDescriptions[] = { { - // Return to Zork - English CD version - // NOTE: This detects the game via the rtzcd.dat which is inside rtzcd.red. - // The entry below detects via rtzcd.red directly, which is the "official" way. + // NOTE: Return to Zork entries with *.dat are used to detect the game via rtzcd.dat, + // which is packed inside rtzcd.red. Entries with *.red refer to the packed file + // directly, which is the "official" way. + + // Return to Zork - English CD version 1.0 9/15/93 + // Patch #1953654 submitted by spookypeanut + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.dat", "e95c38ded389e39cfbf87a8cb250b12e"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD, + 0, + }, + + { + // Return to Zork - English CD version 1.0 9/15/93 + // Patch #1953654 submitted by spookypeanut + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.red", "cd8b62ece4677c438688c1de3f5379b9"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD_COMPRESSED, + 0, + }, + + { + // Return to Zork - English CD version 1.1 12/7/93 { "rtz", "CD", @@ -109,6 +146,23 @@ static const MadeGameDescription gameDescriptions[] = { { // Return to Zork - English CD version 1.2 9/29/94 + // Supplied by Dark-Star in the ScummVM forums + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.dat", "9d740378da2d16e83d0d0efff01bf83a"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD, + 0, + }, + + { + // Return to Zork - English CD version 1.2 9/29/94 { "rtz", "CD", @@ -123,6 +177,41 @@ static const MadeGameDescription gameDescriptions[] = { 0, }, + { + // Return to Zork - German CD version 1.2 9/29/94 + // (same as the English 1.2 version) + // Supplied by Dark-Star in the ScummVM forums + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.dat", "9d740378da2d16e83d0d0efff01bf83a"), + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD, + 0, + }, + + { + // Return to Zork - German CD version 1.2 4/18/95 + // (same as the English 1.2 version) + // Supplied by Dark-Star in the ScummVM forums + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2"), + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RTZ, + 0, + GF_CD_COMPRESSED, + 0, + }, { // Return to Zork - English floppy version @@ -188,6 +277,22 @@ static const MadeGameDescription gameDescriptions[] = { 0, }, + { + // Rodney's Fun Screen + { + "rodney", + "", + AD_ENTRY1("rodneys.dat", "a79887dbaa47689facd7c6f09258ba5a"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GID_RODNEY, + 0, + GF_FLOPPY, + 0, + }, + { AD_TABLE_END_MARKER, 0, 0, 0, 0 } }; @@ -240,7 +345,7 @@ public: } virtual const char *getCopyright() const { - return "MADE Engine"; + return "MADE Engine (C) Activision"; } virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const; @@ -268,7 +373,8 @@ const Common::ADGameDescription *MadeMetaEngine::fallbackDetect(const FSList *fs Made::g_fallbackDesc.features = 0; Made::g_fallbackDesc.version = 0; - return (const Common::ADGameDescription *)&Made::g_fallbackDesc; + //return (const Common::ADGameDescription *)&Made::g_fallbackDesc; + return NULL; } #if PLUGIN_ENABLED_DYNAMIC(MADE) diff --git a/engines/made/graphics.cpp b/engines/made/graphics.cpp index 081621ef18..ee702893a0 100644 --- a/engines/made/graphics.cpp +++ b/engines/made/graphics.cpp @@ -29,7 +29,24 @@ namespace Made { -void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, bool deltaFrame) { +byte ValueReader::readPixel() { + byte value; + if (_nibbleMode) { + if (_nibbleSwitch) { + value = (_buffer[0] >> 4) & 0x0F; + _buffer++; + } else { + value = _buffer[0] & 0x0F; + } + _nibbleSwitch = !_nibbleSwitch; + } else { + value = _buffer[0]; + _buffer++; + } + return value; +} + +void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, byte cmdFlags, byte pixelFlags, byte maskFlags, bool deltaFrame) { const int offsets[] = { 0, 1, 2, 3, @@ -43,11 +60,10 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u byte *cmdBuffer = source + cmdOffs; byte *maskBuffer = source + maskOffs; - byte *pixelBuffer = source + pixelOffs; + ValueReader pixelReader(source + pixelOffs, (pixelFlags & 2) != 0); byte *destPtr = (byte*)surface.getBasePtr(0, 0); - //byte lineBuf[320 * 4]; byte lineBuf[640 * 4]; byte bitBuf[40]; @@ -85,14 +101,14 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u switch (cmd) { case 0: - pixels[0] = *pixelBuffer++; + pixels[0] = pixelReader.readPixel(); for (int i = 0; i < 16; i++) lineBuf[drawDestOfs + offsets[i]] = pixels[0]; break; case 1: - pixels[0] = *pixelBuffer++; - pixels[1] = *pixelBuffer++; + pixels[0] = pixelReader.readPixel(); + pixels[1] = pixelReader.readPixel(); mask = READ_LE_UINT16(maskBuffer); maskBuffer += 2; for (int i = 0; i < 16; i++) { @@ -102,10 +118,10 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u break; case 2: - pixels[0] = *pixelBuffer++; - pixels[1] = *pixelBuffer++; - pixels[2] = *pixelBuffer++; - pixels[3] = *pixelBuffer++; + pixels[0] = pixelReader.readPixel(); + pixels[1] = pixelReader.readPixel(); + pixels[2] = pixelReader.readPixel(); + pixels[3] = pixelReader.readPixel(); mask = READ_LE_UINT32(maskBuffer); maskBuffer += 4; for (int i = 0; i < 16; i++) { @@ -149,4 +165,112 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u } +void decompressMovieImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize) { + + uint16 width = surface.w; + uint16 height = surface.h; + uint16 bx = 0, by = 0, bw = ((width + 3) / 4) * 4; + + byte *cmdBuffer = source + cmdOffs; + byte *maskBuffer = source + maskOffs; + byte *pixelBuffer = source + pixelOffs; + + byte *destPtr = (byte*)surface.getBasePtr(0, 0); + + byte bitBuf[40]; + + int bitBufLastOfs = (((lineSize + 1) >> 1) << 1) - 2; + int bitBufLastCount = ((width + 3) >> 2) & 7; + if (bitBufLastCount == 0) + bitBufLastCount = 8; + + debug(1, "width = %d; bw = %d", width, bw); + + while (height > 0) { + + 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++) { + uint cmd = bits & 3; + bits >>= 2; + + byte pixels[4], block[16]; + uint32 mask; + + switch (cmd) { + + case 0: + pixels[0] = *pixelBuffer++; + for (int i = 0; i < 16; i++) + block[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++) { + block[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++) { + block[i] = pixels[mask & 3]; + mask >>= 2; + } + break; + + case 3: + break; + + } + + if (cmd != 3) { + uint16 blockPos = 0; + uint32 maxW = MIN(4, surface.w - bx); + uint32 maxH = (MIN(4, surface.h - by) + by) * width; + for (uint32 yc = by * width; yc < maxH; yc += width) { + for (uint32 xc = 0; xc < maxW; xc++) { + destPtr[(bx + xc) + yc] = block[xc + blockPos]; + } + blockPos += 4; + } + } + + bx += 4; + if (bx >= bw) { + bx = 0; + by += 4; + } + + } + + } + + height -= 4; + + } + +} + } // End of namespace Made diff --git a/engines/made/graphics.h b/engines/made/graphics.h index 3c56bb4231..1a5cf72677 100644 --- a/engines/made/graphics.h +++ b/engines/made/graphics.h @@ -33,7 +33,18 @@ namespace Made { -void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, bool deltaFrame = false); +class ValueReader { +public: + ValueReader(byte *source, bool nibbleMode) : _buffer(source), _nibbleBuf(0), _nibbleMode(nibbleMode), _nibbleSwitch(false) {} + byte readPixel(); +protected: + byte _nibbleBuf; + bool _nibbleMode, _nibbleSwitch; + byte *_buffer; +}; + +void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, byte cmdFlags, byte pixelFlags, byte maskFlags, bool deltaFrame = false); +void decompressMovieImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize); } // End of namespace Made diff --git a/engines/made/made.cpp b/engines/made/made.cpp index 932f5ddcc4..59ec487c37 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -35,6 +35,7 @@ #include "base/plugins.h" #include "base/version.h" +#include "sound/audiocd.h" #include "sound/mixer.h" #include "made/made.h" @@ -86,7 +87,15 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng _pmvPlayer = new PmvPlayer(this, _mixer); _res = new ProjectReader(); _screen = new Screen(this); - _dat = new GameDatabase(this); + + if (getGameID() == GID_LGOP2 || getGameID() == GID_MANHOLE || getGameID() == GID_RODNEY) { + _dat = new GameDatabaseV2(this); + } else if (getGameID() == GID_RTZ) { + _dat = new GameDatabaseV3(this); + } else { + error("Unknown GameID"); + } + _script = new ScriptInterpreter(this); int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); @@ -107,7 +116,15 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng debug(1, "Music disabled."); } - _soundRate = 8000; + _quit = false; + + // Set default sound frequency + // Return to Zork sets it itself via a script funtion + if (getGameID() == GID_MANHOLE || getGameID() == GID_RODNEY) { + _soundRate = 11025; + } else { + _soundRate = 8000; + } } @@ -132,21 +149,26 @@ int MadeEngine::init() { } int16 MadeEngine::getTimer(int16 timerNum) { - return (_system->getMillis() - _timers[timerNum]) / 60; + if (timerNum > 0 && timerNum <= ARRAYSIZE(_timers) && _timers[timerNum - 1] != -1) + return (_system->getMillis() - _timers[timerNum - 1]) / kTimerResolution; + else + return 32000; } void MadeEngine::setTimer(int16 timerNum, int16 value) { - _timers[timerNum] = value * 60; + if (timerNum > 0 && timerNum <= ARRAYSIZE(_timers)) + _timers[timerNum - 1] = value * kTimerResolution; } void MadeEngine::resetTimer(int16 timerNum) { - _timers[timerNum] = _system->getMillis(); + if (timerNum > 0 && timerNum <= ARRAYSIZE(_timers)) + _timers[timerNum - 1] = _system->getMillis(); } int16 MadeEngine::allocTimer() { for (int i = 0; i < ARRAYSIZE(_timers); i++) { if (_timers[i] == -1) { - resetTimer(i); + _timers[i] = _system->getMillis(); return i + 1; } } @@ -154,14 +176,79 @@ int16 MadeEngine::allocTimer() { } void MadeEngine::freeTimer(int16 timerNum) { - _timers[timerNum] = -1; + if (timerNum > 0 && timerNum <= ARRAYSIZE(_timers)) + _timers[timerNum - 1] = -1; +} + +Common::String MadeEngine::getSavegameFilename(int16 saveNum) { + char filename[256]; + snprintf(filename, 256, "%s.%03d", getTargetName().c_str(), saveNum); + return filename; +} + +void MadeEngine::handleEvents() { + + Common::Event event; + Common::EventManager *eventMan = _system->getEventManager(); + + // NOTE: Don't reset _eventNum to 0 here or no events will get through to the scripts. + + while (eventMan->pollEvent(event)) { + switch (event.type) { + + case Common::EVENT_MOUSEMOVE: + _eventMouseX = event.mouse.x; + _eventMouseY = event.mouse.y; + break; + + case Common::EVENT_LBUTTONDOWN: + _eventNum = 1; + break; + + /* + case Common::EVENT_LBUTTONUP: + _eventNum = 2; // TODO: Is this correct? + break; + */ + + case Common::EVENT_RBUTTONDOWN: + _eventNum = 3; + break; + + /* + case Common::EVENT_RBUTTONUP: + eventNum = 4; // TODO: Is this correct? + break; + */ + + case Common::EVENT_KEYDOWN: + _eventKey = event.kbd.ascii; + // For unknown reasons, the game accepts ASCII code + // 9 as backspace + if (_eventKey == Common::KEYCODE_BACKSPACE) + _eventKey = 9; + _eventNum = 5; + break; + + case Common::EVENT_QUIT: + _quit = true; + break; + + default: + break; + + } + } + + AudioCD.updateCD(); + } int MadeEngine::go() { for (int i = 0; i < ARRAYSIZE(_timers); i++) _timers[i] = -1; - + if (getGameID() == GID_RTZ) { _engineVersion = 3; if (getFeatures() & GF_DEMO) { @@ -187,12 +274,28 @@ int MadeEngine::go() { _engineVersion = 2; _dat->open("lgop2.dat"); _res->open("lgop2.prj"); + } else if (getGameID() == GID_RODNEY) { + _engineVersion = 2; + _dat->open("rodneys.dat"); + _res->open("rodneys.prj"); } else { error ("Unknown MADE game"); } - _eventMouseX = _eventMouseY = 0; + // FIXME: This should make things a little faster until proper dirty rectangles + // are implemented. + // NOTE: Disabled again since it causes major graphics errors. + //_system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true); + + _autoStopSound = false; + _eventNum = _eventKey = _eventMouseX = _eventMouseY = 0; + +#ifdef DUMP_SCRIPTS + _script->dumpAllScripts(); +#else + _screen->setDefaultMouseCursor(); _script->runScript(_dat->getMainCodeObjectIndex()); +#endif return 0; } diff --git a/engines/made/made.h b/engines/made/made.h index b3a25b4e02..461941e5cf 100644 --- a/engines/made/made.h +++ b/engines/made/made.h @@ -48,18 +48,21 @@ namespace Made { enum MadeGameID { - GID_RTZ = 0, - GID_MANHOLE = 1, - GID_LGOP2 = 2 + GID_RTZ = 0, + GID_MANHOLE = 1, + GID_LGOP2 = 2, + GID_RODNEY = 3 }; enum MadeGameFeatures { - GF_DEMO = 1 << 0, - GF_CD = 1 << 1, - GF_CD_COMPRESSED = 1 << 2, - GF_FLOPPY = 1 << 3 + GF_DEMO = 1 << 0, + GF_CD = 1 << 1, + GF_CD_COMPRESSED = 1 << 2, + GF_FLOPPY = 1 << 3 }; +const uint32 kTimerResolution = 40; + struct MadeGameDescription; class ProjectReader; @@ -91,7 +94,6 @@ public: uint32 getFeatures() const; uint16 getVersion() const; Common::Platform getPlatform() const; - void update_events(); private: public: @@ -102,9 +104,15 @@ public: ScriptInterpreter *_script; MusicPlayer *_music; + bool _quit; + + uint16 _eventNum; int _eventMouseX, _eventMouseY; uint16 _eventKey; + int _soundRate; + bool _autoStopSound; + int _musicVolume; // 2 = LGOP2, Manhole N&E @@ -118,6 +126,11 @@ public: int16 allocTimer(); void freeTimer(int16 timerNum); + const Common::String getTargetName() { return _targetName; } + Common::String getSavegameFilename(int16 saveNum); + + void handleEvents(); + }; } // End of namespace Made diff --git a/engines/made/module.mk b/engines/made/module.mk index 164e1bfba4..b3d004aa4c 100644 --- a/engines/made/module.mk +++ b/engines/made/module.mk @@ -10,10 +10,9 @@ MODULE_OBJS = \ redreader.o \ resource.o \ screen.o \ + screenfx.o \ script.o \ - scriptfuncs_lgop2.o \ - scriptfuncs_mhne.o \ - scriptfuncs_rtz.o \ + scriptfuncs.o \ sound.o diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index 06dc4e5aed..1a8ca9c50a 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -48,14 +48,17 @@ void PmvPlayer::play(const char *filename) { 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; + // Note: There seem to be weird sound frequencies in PMV videos. + // Not sure why, but leaving those original frequencies intact + // results to sound being choppy. Therefore, we set them to more + // "common" values here (11025 instead of 11127 and 22050 instead + // of 22254) + if (soundFreq == 11127) soundFreq = 11025; + if (soundFreq == 22254) soundFreq = 22050; int unk; @@ -74,10 +77,12 @@ void PmvPlayer::play(const char *filename) { uint32 frameCount = 0; uint16 chunkCount = 0; uint32 soundSize = 0; - uint32 palChunkOfs = 0; + uint32 soundChunkOfs = 0, palChunkOfs = 0; uint32 palSize = 0; byte *frameData, *audioData, *soundData, *palData, *imageData; bool firstTime = true; + + uint32 soundStartTime = 0, skipFrames = 0; uint32 frameNum; uint16 width, height, cmdOffs, pixelOffs, maskOffs, lineSize; @@ -89,6 +94,8 @@ void PmvPlayer::play(const char *filename) { while (!_abort && !_fd->eof()) { + int32 frameTime = _vm->_system->getMillis(); + readChunk(chunkType, chunkSize); if (_fd->eof()) @@ -96,27 +103,34 @@ void PmvPlayer::play(const char *filename) { frameData = new byte[chunkSize]; _fd->read(frameData, chunkSize); + + soundChunkOfs = READ_LE_UINT32(frameData + 8); + palChunkOfs = READ_LE_UINT32(frameData + 16); // Handle audio - audioData = frameData + READ_LE_UINT32(frameData + 8) - 8; - chunkSize = READ_LE_UINT16(audioData + 4); - chunkCount = READ_LE_UINT16(audioData + 6); + if (soundChunkOfs) { + + audioData = frameData + soundChunkOfs - 8; + chunkSize = READ_LE_UINT16(audioData + 4); + chunkCount = READ_LE_UINT16(audioData + 6); - if (chunkCount > 50) break; // FIXME: this is a hack + debug(1, "chunkCount = %d; chunkSize = %d; total = %d\n", chunkCount, chunkSize, chunkCount * chunkSize); - debug(2, "chunkCount = %d; chunkSize = %d\n", chunkCount, chunkSize); + if (chunkCount > 50) break; // FIXME: this is a hack - soundSize = chunkCount * chunkSize; - soundData = new byte[soundSize]; - decompressSound(audioData + 8, soundData, chunkSize, chunkCount); - _audioStream->queueBuffer(soundData, soundSize); + soundSize = chunkCount * chunkSize; + soundData = new byte[soundSize]; + decompressSound(audioData + 8, soundData, chunkSize, chunkCount); + _audioStream->queueBuffer(soundData, soundSize); + + } // Handle palette - palChunkOfs = READ_LE_UINT32(frameData + 16); if (palChunkOfs) { palData = frameData + palChunkOfs - 8; palSize = READ_LE_UINT32(palData + 4); decompressPalette(palData + 8, _paletteRGB, palSize); + _vm->_screen->setRGBPalette(_paletteRGB); } // Handle video @@ -138,24 +152,34 @@ void PmvPlayer::play(const char *filename) { _surface->create(width, height, 1); } - decompressImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize, frameNum > 0); + decompressMovieImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize); if (firstTime) { _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream); + soundStartTime = g_system->getMillis(); + skipFrames = 0; firstTime = false; } - _vm->_screen->setRGBPalette(_paletteRGB); handleEvents(); updateScreen(); - frameCount++; - delete[] frameData; - while (_mixer->getSoundElapsedTime(_audioStreamHandle) < frameCount * frameDelay) { - _vm->_system->delayMillis(10); - } + if (skipFrames == 0) { + int32 waitTime = (frameCount * frameDelay) - + (g_system->getMillis() - soundStartTime) - (_vm->_system->getMillis() - frameTime); + + if (waitTime < 0) { + skipFrames = -waitTime / frameDelay; + warning("Video A/V sync broken, skipping %d frame(s)", skipFrames + 1); + } else if (waitTime > 0) + g_system->delayMillis(waitTime); + + } else + skipFrames--; + + frameCount++; } @@ -188,8 +212,8 @@ void PmvPlayer::handleEvents() { _abort = true; break; case Common::EVENT_QUIT: - // TODO: Exit more gracefully - g_system->quit(); + _vm->_quit = true; + _abort = true; break; default: break; diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp index 7151f2424a..2cae8b276c 100644 --- a/engines/made/resource.cpp +++ b/engines/made/resource.cpp @@ -59,9 +59,9 @@ void PictureResource::load(byte *source, int size) { Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size); _hasPalette = (sourceS->readByte() != 0); - sourceS->readByte(); - sourceS->readByte(); - sourceS->readByte(); + byte cmdFlags = sourceS->readByte(); + byte pixelFlags = sourceS->readByte(); + byte maskFlags = sourceS->readByte(); uint16 cmdOffs = sourceS->readUint16LE(); uint16 pixelOffs = sourceS->readUint16LE(); uint16 maskOffs = sourceS->readUint16LE(); @@ -69,7 +69,11 @@ void PictureResource::load(byte *source, int size) { /*uint16 u = */sourceS->readUint16LE(); uint16 width = sourceS->readUint16LE(); uint16 height = sourceS->readUint16LE(); - + + if (cmdFlags || pixelFlags || maskFlags) { + warning("PictureResource::load() Graphic has flags set"); + } + _paletteColorCount = (cmdOffs - 18) / 3; // 18 = sizeof header debug(2, "width = %d; height = %d\n", width, height); @@ -82,7 +86,7 @@ void PictureResource::load(byte *source, int size) { _picture = new Graphics::Surface(); _picture->create(width, height, 1); - decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize); + decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize, cmdFlags, pixelFlags, maskFlags); delete sourceS; @@ -94,7 +98,8 @@ AnimationResource::AnimationResource() { } AnimationResource::~AnimationResource() { - // TODO: Free anim frames + for (uint i = 0; i < _frames.size(); i++) + delete _frames[i]; } void AnimationResource::load(byte *source, int size) { @@ -136,7 +141,7 @@ void AnimationResource::load(byte *source, int size) { Graphics::Surface *frame = new Graphics::Surface(); frame->create(frameWidth, frameHeight, 1); - decompressImage(source + frameOffs, *frame, cmdOffs, pixelOffs, maskOffs, lineSize, _flags & 1); + decompressImage(source + frameOffs, *frame, cmdOffs, pixelOffs, maskOffs, lineSize, 0, 0, 0, _flags & 1); _frames.push_back(frame); @@ -372,7 +377,7 @@ 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); + debug(2, "ProjectReader::loadResource() %08X", slot->offs + 62); _fd->seek(slot->offs + 62); _fd->read(buffer, size); return true; @@ -384,8 +389,7 @@ bool ProjectReader::loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size ResourceSlot *ProjectReader::getResourceSlot(uint32 resType, uint index) { ResourceSlots *slots = _resSlots[resType]; if (index >= 1 && index < slots->size()) { - ResourceSlot *slot = &slots->operator[](index); - return slot; + return &slots->operator[](index); } else { return NULL; } @@ -398,22 +402,20 @@ Resource *ProjectReader::getResourceFromCache(ResourceSlot *slot) { } void ProjectReader::addResourceToCache(ResourceSlot *slot, Resource *res) { - if (_cacheCount >= kMaxResourceCacheCount) { + if (_cacheCount >= kMaxResourceCacheCount) purgeCache(); - } slot->res = res; - slot->refCount = 0; + slot->refCount = 1; _cacheCount++; } void ProjectReader::tossResourceFromCache(ResourceSlot *slot) { - if (slot->res) { + if (slot->res) slot->refCount--; - } } void ProjectReader::purgeCache() { - printf("ProjectReader::purgeCache()\n"); + debug(2, "ProjectReader::purgeCache()"); 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) { diff --git a/engines/made/resource.h b/engines/made/resource.h index be85561318..cb6e0b65f4 100644 --- a/engines/made/resource.h +++ b/engines/made/resource.h @@ -35,7 +35,7 @@ namespace Made { -const int kMaxResourceCacheCount = 200; +const int kMaxResourceCacheCount = 100; enum ResourceType { kResARCH = MKID_BE('ARCH'), @@ -81,7 +81,14 @@ public: ~AnimationResource(); void load(byte *source, int size); int getCount() const { return _frames.size(); } - Graphics::Surface *getFrame(int index) const { return _frames[index]; } + Graphics::Surface *getFrame(int index) const { + if ((uint)index < _frames.size()) { + return _frames[index]; + } else { + warning("getFrame: Tried to obtain invalid frame %i, array has %i frames", index, _frames.size()); + return _frames[_frames.size() - 1]; + } + } uint16 getFlags() const { return _flags; } int16 getWidth() const { return _width; } int16 getHeight() const { return _height; } diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index 74053e70a2..cecd0c8968 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -32,20 +32,27 @@ namespace Made { Screen::Screen(MadeEngine *vm) : _vm(vm) { - _screen1 = new Graphics::Surface(); - _screen1->create(320, 200, 1); - _screen2 = new Graphics::Surface(); - _screen2->create(320, 200, 1); - - _clipInfo1.x = _clipInfo2.x = 0; - _clipInfo1.y = _clipInfo2.y = 0; - _clipInfo1.w = _clipInfo2.w = 320; - _clipInfo1.h = _clipInfo2.h = 200; - - _clipInfo1.destSurface = _screen1; - _clipInfo2.destSurface = _screen2; - _clipArea.destSurface = _screen2; - + _backgroundScreen = new Graphics::Surface(); + _backgroundScreen->create(320, 200, 1); + + _workScreen = new Graphics::Surface(); + _workScreen->create(320, 200, 1); + + _backgroundScreenDrawCtx.clipRect = Common::Rect(320, 200); + _workScreenDrawCtx.clipRect = Common::Rect(320, 200); + + _backgroundScreenDrawCtx.destSurface = _backgroundScreen; + _workScreenDrawCtx.destSurface = _workScreen; + _clipArea.destSurface = _workScreen; + + // Screen mask is only needed in v2 games + if (_vm->getGameID() != GID_RTZ) { + _screenMask = new Graphics::Surface(); + _screenMask->create(320, 200, 1); + _maskDrawCtx.clipRect = Common::Rect(320, 200); + _maskDrawCtx.destSurface = _screenMask; + } + for (int i = 0; i <= 3; i++) _excludeClipAreaEnabled[i] = false; @@ -62,8 +69,10 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) { _ground = 1; _clip = 0; _exclude = 0; + _mask = 0; _visualEffectNum = 0; + _fx = new ScreenEffects(this); _textX = 0; _textY = 0; @@ -74,64 +83,130 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) { _textRect.bottom = 200; _font = NULL; _currentFontNum = 0; - _fontDrawCtx.x = 0; - _fontDrawCtx.y = 0; - _fontDrawCtx.w = 320; - _fontDrawCtx.h = 200; - _fontDrawCtx.destSurface = _screen1; + _fontDrawCtx.clipRect = Common::Rect(320, 200); + _fontDrawCtx.destSurface = _backgroundScreen; clearChannels(); } Screen::~Screen() { - delete _screen1; - delete _screen2; + delete _backgroundScreen; + delete _workScreen; + if (_vm->getGameID() != GID_RTZ) + delete _screenMask; + delete _fx; } void Screen::clearScreen() { - _screen1->fillRect(Common::Rect(0, 0, 320, 200), 0); - _screen2->fillRect(Common::Rect(0, 0, 320, 200), 0); + _backgroundScreen->fillRect(Common::Rect(0, 0, 320, 200), 0); + _workScreen->fillRect(Common::Rect(0, 0, 320, 200), 0); + if (_vm->getGameID() != GID_RTZ) + _screenMask->fillRect(Common::Rect(0, 0, 320, 200), 0); + _mask = 0; _needPalette = true; } -void Screen::drawSurface(Graphics::Surface *sourceSurface, int x, int y, const ClipInfo &clipInfo) { +void Screen::setExcludeArea(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { + + _excludeClipAreaEnabled[0] = false; + _excludeClipAreaEnabled[1] = false; + _excludeClipAreaEnabled[2] = false; + _excludeClipAreaEnabled[3] = false; + + if (x1 == 0 && y1 == 0 && x2 == 0 && y2 == 0) { + _excludeClipArea[0].clipRect = Common::Rect(320, 200); + _excludeClipAreaEnabled[0] = true; + return; + } + + if (y1 > 0 && y2 > 0) { + _excludeClipArea[0].clipRect = Common::Rect(320, y1); + _excludeClipAreaEnabled[0] = true; + } + + if (y1 < 200 && y2 < 200) { + _excludeClipArea[1].clipRect = Common::Rect(0, y2, 320, 200); + _excludeClipAreaEnabled[1] = true; + } + + if (x1 > 0 && x2 > 0) { + _excludeClipArea[2].clipRect = Common::Rect(0, y1, x1, y2); + _excludeClipAreaEnabled[2] = true; + } + + if (x1 < 320 && x2 < 320) { + _excludeClipArea[3].clipRect = Common::Rect(x2, y1, 320, y2); + _excludeClipAreaEnabled[3] = true; + } + +} + +void Screen::drawSurface(Graphics::Surface *sourceSurface, int x, int y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo) { - byte *source, *dest; + byte *source, *dest, *maskp = 0; int startX = 0; int startY = 0; int clipWidth = sourceSurface->w; int clipHeight = sourceSurface->h; - if (x < 0) { - startX = -x; + if (x < clipInfo.clipRect.left) { + startX = clipInfo.clipRect.left - x; clipWidth -= startX; - x = 0; + x = clipInfo.clipRect.left; } - if (y < 0) { - startY = -y; + if (y < clipInfo.clipRect.top) { + startY = clipInfo.clipRect.top - y; clipHeight -= startY; - y = 0; + y = clipInfo.clipRect.top; } - if (x + clipWidth > clipInfo.x + clipInfo.w) { - clipWidth = clipInfo.x + clipInfo.w - x; + if (x + clipWidth > clipInfo.clipRect.right) { + clipWidth = clipInfo.clipRect.right - x; } - if (y + clipHeight > clipInfo.y + clipInfo.h) { - clipHeight = clipInfo.y + clipInfo.h - y; + if (y + clipHeight > clipInfo.clipRect.bottom) { + clipHeight = clipInfo.clipRect.bottom - y; } source = (byte*)sourceSurface->getBasePtr(startX, startY); dest = (byte*)clipInfo.destSurface->getBasePtr(x, y); + if (_vm->getGameID() != GID_RTZ) + maskp = (byte*)_maskDrawCtx.destSurface->getBasePtr(x, y); + + int32 sourcePitch, linePtrAdd; + byte *linePtr; + + if (flipX) { + linePtrAdd = -1; + } else { + linePtrAdd = 1; + } + + if (flipY) { + sourcePitch = -sourceSurface->pitch; + source += (clipHeight - 1) * sourceSurface->pitch; + } else { + sourcePitch = sourceSurface->pitch; + } for (int16 yc = 0; yc < clipHeight; yc++) { + if (flipX) { + linePtr = source + sourceSurface->w; + } else { + linePtr = source; + } for (int16 xc = 0; xc < clipWidth; xc++) { - if (source[xc]) - dest[xc] = source[xc]; + if (*linePtr && (_vm->getGameID() == GID_RTZ || (mask == 0 || maskp[xc] == 0))) { + if (*linePtr) + dest[xc] = *linePtr; + } + linePtr += linePtrAdd; } - source += sourceSurface->pitch; + source += sourcePitch; dest += clipInfo.destSurface->pitch; + if (_vm->getGameID() != GID_RTZ) + maskp += _maskDrawCtx.destSurface->pitch; } } @@ -191,11 +266,16 @@ uint16 Screen::setChannelLocation(uint16 channelIndex, int16 x, int16 y) { 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::setChannelUseMask(uint16 channelIndex) { + if (channelIndex < 1 || channelIndex >= 100) + return; + _channels[channelIndex - 1].mask = _mask; +} + void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask, int16 excludeStateMask) { for (int i = 0; i <= 3; i++) @@ -208,8 +288,8 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask 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; + int16 flipX = _channels[i].state & 0x10; + int16 flipY = _channels[i].state & 0x20; debug(2, "drawSpriteChannels() type = %d; index = %04X\n", _channels[i].type, _channels[i].index); @@ -217,38 +297,38 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask case 1: // drawFlex if (_channels[i].state & 4) { - drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, _clipArea); + drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flipX, flipY, _channels[i].mask, _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]); + drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flipX, flipY, _channels[i].mask, _excludeClipArea[excludeIndex]); } } } else { - drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, clipInfo); + drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flipX, flipY, _channels[i].mask, clipInfo); } break; - + case 2: // drawObjectText printObjectText(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].fontNum, _channels[i].textColor, _channels[i].outlineColor, clipInfo); 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); + drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flipX, flipY, _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]); + drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flipX, flipY, _excludeClipArea[excludeIndex]); } } } else { - drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, clipInfo); + drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flipX, flipY, clipInfo); } break; case 4: // drawMenuText - // TODO + // Never used in any game break; default: @@ -265,12 +345,14 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask void Screen::updateSprites() { // TODO: This needs some more work, dirty rectangles are currently not used - memcpy(_screen2->pixels, _screen1->pixels, 64000); + memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000); - drawSpriteChannels(_clipInfo1, 3, 0); - drawSpriteChannels(_clipInfo2, 1, 2); + drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0); + drawSpriteChannels(_workScreenDrawCtx, 1, 2); - _vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h); + _vm->_system->copyRectToScreen((const byte*)_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); + + _vm->_system->updateScreen(); } @@ -278,11 +360,12 @@ void Screen::clearChannels() { for (uint16 i = 0; i < ARRAYSIZE(_channels); i++) { _channels[i].type = 0; _channels[i].index = 0; + _channels[i].mask = 0; } _channelsUsedCount = 0; } -uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) { +uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo) { if (flexIndex == 0) return 0; @@ -290,7 +373,7 @@ uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 PictureResource *flex = _vm->_res->getPicture(flexIndex); Graphics::Surface *sourceSurface = flex->getPicture(); - drawSurface(sourceSurface, x, y, clipInfo); + drawSurface(sourceSurface, x, y, flipX, flipY, mask, clipInfo); // Palette is set in showPage if (flex->hasPalette() && !_paletteLock && _needPalette) { @@ -307,7 +390,7 @@ uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 return 0; } -void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) { +void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY, const ClipInfo &clipInfo) { if (frameNum < 0) return; @@ -315,24 +398,29 @@ void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, u AnimationResource *anim = _vm->_res->getAnimation(animIndex); Graphics::Surface *sourceSurface = anim->getFrame(frameNum); - drawSurface(sourceSurface, x, y, clipInfo); + drawSurface(sourceSurface, x, y, flipX, flipY, 0, clipInfo); _vm->_res->freeResource(anim); } -uint16 Screen::drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2) { - drawFlex(index, x, y, flag1, flag2, _clipInfo1); +uint16 Screen::drawPic(uint16 index, int16 x, int16 y, int16 flipX, int16 flipY) { + drawFlex(index, x, y, flipX, flipY, 0, _backgroundScreenDrawCtx); 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); +uint16 Screen::drawMask(uint16 index, int16 x, int16 y) { + drawFlex(index, x, y, 0, 0, 0, _maskDrawCtx); + return 0; +} + +uint16 Screen::drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY) { + drawAnimFrame(animIndex, x, y, frameNum, flipX, flipY, _backgroundScreenDrawCtx); return 0; } void Screen::addSprite(uint16 spriteIndex) { bool oldScreenLock = _screenLock; - drawFlex(spriteIndex, 0, 0, 0, 0, _clipInfo1); + drawFlex(spriteIndex, 0, 0, 0, 0, 0, _backgroundScreenDrawCtx); _screenLock = oldScreenLock; } @@ -342,7 +430,7 @@ uint16 Screen::drawSprite(uint16 flexIndex, int16 x, int16 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); + debug(2, "placeSprite(%d, %04X, %d, %d)\n", channelIndex, flexIndex, x, y); if (channelIndex < 1 || channelIndex >= 100) return 0; @@ -379,8 +467,8 @@ uint16 Screen::placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 _channels[channelIndex].y1 = y1; _channels[channelIndex].x2 = x2; _channels[channelIndex].y2 = y2; - _channels[channelIndex].area = (x2 - x2) * (y2 - y1); - + _channels[channelIndex].area = (x2 - x1) * (y2 - y1); + if (_channelsUsedCount <= channelIndex) _channelsUsedCount = channelIndex + 1; @@ -432,7 +520,7 @@ uint16 Screen::placeAnim(uint16 channelIndex, uint16 animIndex, int16 x, int16 y _channels[channelIndex].y1 = y1; _channels[channelIndex].x2 = x2; _channels[channelIndex].y2 = y2; - _channels[channelIndex].area = (x2 - x2) * (y2 - y1); + _channels[channelIndex].area = (x2 - x1) * (y2 - y1); if (_channelsUsedCount <= channelIndex) _channelsUsedCount = channelIndex + 1; @@ -462,17 +550,6 @@ int16 Screen::getAnimFrame(uint16 channelIndex) { 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) { if (channelIndex < 1 || channelIndex >= 100 || textObjectIndex == 0 || fontNum == 0) @@ -525,7 +602,7 @@ uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, i _channels[channelIndex].y1 = y1; _channels[channelIndex].x2 = x2; _channels[channelIndex].y2 = y2; - _channels[channelIndex].area = (x2 - x2) * (y2 - y1); + _channels[channelIndex].area = (x2 - x1) * (y2 - y1); if (_channelsUsedCount <= channelIndex) _channelsUsedCount = channelIndex + 1; @@ -536,18 +613,17 @@ uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, i void Screen::show() { // TODO - + if (_screenLock) return; - drawSpriteChannels(_clipInfo1, 3, 0); - memcpy(_screen2->pixels, _screen1->pixels, 64000); - drawSpriteChannels(_clipInfo2, 1, 2); + drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0); + memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000); + drawSpriteChannels(_workScreenDrawCtx, 1, 2); + + _fx->run(_visualEffectNum, _workScreen, _palette, _newPalette, _paletteColorCount); + _visualEffectNum = 0; - // TODO: Implement visual effects (palette fading etc.) - if (!_paletteLock) - setRGBPalette(_palette, 0, _paletteColorCount); - _vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h); _vm->_system->updateScreen(); if (!_paletteInitialized) { @@ -559,19 +635,7 @@ void Screen::show() { } void Screen::flash(int flashCount) { - int palSize = _paletteColorCount * 3; - if (flashCount < 1) - flashCount = 1; - for (int i = 0; i < palSize; i++) - _fxPalette[i] = CLIP<byte>(255 - _palette[i], 0, 255); - while (flashCount--) { - setRGBPalette(_fxPalette, 0, _paletteColorCount); - _vm->_system->updateScreen(); - _vm->_system->delayMillis(30); - setRGBPalette(_palette, 0, _paletteColorCount); - _vm->_system->updateScreen(); - _vm->_system->delayMillis(30); - } + _fx->flash(flashCount, _palette, _paletteColorCount); } void Screen::setFont(int16 fontNum) { @@ -588,7 +652,7 @@ void Screen::printChar(uint c, int16 x, int16 y, byte color) { if (!_font) return; - int height = _font->getHeight(); + uint width = 8, height = _font->getHeight(); byte *charData = _font->getChar(c); if (!charData) @@ -596,10 +660,10 @@ void Screen::printChar(uint c, int16 x, int16 y, byte color) { byte p; byte *dest = (byte*)_fontDrawCtx.destSurface->getBasePtr(x, y); - - for (int16 yc = 0; yc < height; yc++) { + + for (uint yc = 0; yc < height; yc++) { p = charData[yc]; - for (int16 xc = 0; xc < 8; xc++) { + for (uint xc = 0; xc < width; xc++) { if (p & 0x80) dest[xc] = color; p <<= 1; @@ -690,7 +754,7 @@ void Screen::printText(const char *text) { } void Screen::printTextEx(const char *text, int16 x, int16 y, int16 fontNum, int16 textColor, int16 outlineColor, const ClipInfo &clipInfo) { - if (*text == 0 || x == 0 || y == 0) + if (*text == 0 || x < 0 || y < 0) return; int16 oldFontNum = _currentFontNum; @@ -728,5 +792,48 @@ int16 Screen::getTextWidth(int16 fontNum, const char *text) { return _font->getTextWidth(text); } +Graphics::Surface *Screen::lockScreen() { + return _vm->_system->lockScreen(); +} + +void Screen::unlockScreen() { + _vm->_system->unlockScreen(); +} + +void Screen::showWorkScreen() { + _vm->_system->copyRectToScreen((const byte*)_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); +} + +void Screen::updateScreenAndWait(int delay) { + _vm->_system->updateScreen(); + _vm->_system->delayMillis(delay); +} + +int16 Screen::addToSpriteList(int16 index, int16 xofs, int16 yofs) { + SpriteListItem item; + item.index = index; + item.xofs = xofs; + item.yofs = yofs; + _spriteList.push_back(item); + return _spriteList.size(); +} + +SpriteListItem Screen::getFromSpriteList(int16 index) { + if (((uint) index) > _spriteList.size()) { + SpriteListItem emptyItem; + emptyItem.index = 0; + return emptyItem; + } else { + return _spriteList[index - 1]; + } +} + +void Screen::clearSpriteList() { + _spriteList.clear(); +} + +void Screen::setDefaultMouseCursor() { + CursorMan.replaceCursor(defaultMouseCursor, 16, 16, 9, 2, 0); +} } // End of namespace Made diff --git a/engines/made/screen.h b/engines/made/screen.h index 0ca28086f9..5d55085e5c 100644 --- a/engines/made/screen.h +++ b/engines/made/screen.h @@ -28,10 +28,13 @@ #include "common/endian.h" #include "common/util.h" +#include "common/rect.h" #include "graphics/surface.h" +#include "graphics/cursorman.h" #include "made/resource.h" +#include "made/screenfx.h" namespace Made { @@ -46,15 +49,39 @@ struct SpriteChannel { uint16 fontNum; int16 textColor, outlineColor; int16 frameNum; + int16 mask; }; struct ClipInfo { - uint16 x, y, w, h; + Common::Rect clipRect; Graphics::Surface *destSurface; }; +struct SpriteListItem { + int16 index, xofs, yofs; +}; + class MadeEngine; +static const byte defaultMouseCursor[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 1, 1, 15, 1, 15, 1, 15, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 1, 15, 15, 1, 15, 1, 15, 1, 15, 15, 1, 0, 0, 0, 0, 0, + 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 0, 1, 1, 1, 0, + 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 15, 15, 15, 1, + 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 1, + 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, 0, + 1, 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, 0, 0, + 0, 1, 1, 15, 15, 15, 15, 15, 15, 15, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + class Screen { public: Screen(MadeEngine *vm); @@ -62,16 +89,27 @@ public: void clearScreen(); - void drawSurface(Graphics::Surface *sourceSurface, int x, int y, const ClipInfo &clipInfo); + void drawSurface(Graphics::Surface *sourceSurface, int x, int y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo); + void loadRGBPalette(byte *palRGB, int count = 256); void setRGBPalette(byte *palRGB, int start = 0, int count = 256); bool isPaletteLocked() { return _paletteLock; } - void setScreenLock(bool lock) { _screenLock = lock; } void setPaletteLock(bool lock) { _paletteLock = lock; } + bool isScreenLocked() { return _screenLock; } + void setScreenLock(bool lock) { _screenLock = lock; } void setVisualEffectNum(int visualEffectNum) { _visualEffectNum = visualEffectNum; } - void setClip(uint16 clip) { _clip = clip; } - void setExclude(uint16 exclude) { _exclude = exclude; } - void setGround(uint16 ground) { _ground = ground; } + + void setClipArea(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { + _clipArea.clipRect = Common::Rect(x1, y1, x2, y2); + } + + void setExcludeArea(uint16 x1, uint16 y1, uint16 x2, uint16 y2); + + void setClip(int16 clip) { _clip = clip; } + void setExclude(int16 exclude) { _exclude = exclude; } + void setGround(int16 ground) { _ground = ground; } + void setMask(int16 mask) { _mask = mask; } + void setTextColor(int16 color) { _textColor = color; } void setTextRect(const Common::Rect &textRect) { @@ -99,6 +137,11 @@ public: _textY = y; } + void homeText() { + _textX = _textRect.left; + _textY = _textRect.top; + } + uint16 updateChannel(uint16 channelIndex); void deleteChannel(uint16 channelIndex); int16 getChannelType(uint16 channelIndex); @@ -106,15 +149,19 @@ public: void setChannelState(uint16 channelIndex, int16 state); uint16 setChannelLocation(uint16 channelIndex, int16 x, int16 y); uint16 setChannelContent(uint16 channelIndex, uint16 index); + void setChannelUseMask(uint16 channelIndex); 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 drawFlex(uint16 flexIndex, int16 x, int16 y, int16 flipX, int16 flipY, int16 mask, const ClipInfo &clipInfo); + + void drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY, 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 drawPic(uint16 index, int16 x, int16 y, int16 flipX, int16 flipY); + uint16 drawMask(uint16 index, int16 x, int16 y); + + uint16 drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, int16 flipX, int16 flipY); void addSprite(uint16 spriteIndex); @@ -124,14 +171,12 @@ public: 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 flash(int count); - + void setFont(int16 fontNum); void printChar(uint c, int16 x, int16 y, byte color); void printText(const char *text); @@ -139,15 +184,27 @@ public: void printObjectText(int16 objectIndex, int16 x, int16 y, int16 fontNum, int16 textColor, int16 outlineColor, const ClipInfo &clipInfo); int16 getTextWidth(int16 fontNum, const char *text); + // Interface functions for the screen effects class + Graphics::Surface *lockScreen(); + void unlockScreen(); + void showWorkScreen(); + void updateScreenAndWait(int delay); + + int16 addToSpriteList(int16 index, int16 xofs, int16 yofs); + SpriteListItem getFromSpriteList(int16 index); + void clearSpriteList(); + + void setDefaultMouseCursor(); protected: MadeEngine *_vm; + ScreenEffects *_fx; bool _screenLock; bool _paletteLock; byte _screenPalette[256 * 4]; - byte _palette[768], _newPalette[768], _fxPalette[768]; + byte _palette[768], _newPalette[768]; int _paletteColorCount, _oldPaletteColorCount; bool _paletteInitialized, _needPalette; int16 _textColor; @@ -160,17 +217,20 @@ protected: FontResource *_font; ClipInfo _fontDrawCtx; - uint16 _clip, _exclude, _ground; + int16 _clip, _exclude, _ground, _mask; int _visualEffectNum; - Graphics::Surface *_screen1, *_screen2; - ClipInfo _clipArea, _clipInfo1, _clipInfo2; + Graphics::Surface *_backgroundScreen, *_workScreen, *_screenMask; + ClipInfo _clipArea, _backgroundScreenDrawCtx, _workScreenDrawCtx, _maskDrawCtx; ClipInfo _excludeClipArea[4]; bool _excludeClipAreaEnabled[4]; uint16 _channelsUsedCount; SpriteChannel _channels[100]; + + Common::Array<SpriteListItem> _spriteList; + }; } // End of namespace Made diff --git a/engines/made/screenfx.cpp b/engines/made/screenfx.cpp new file mode 100644 index 0000000000..ee96af601a --- /dev/null +++ b/engines/made/screenfx.cpp @@ -0,0 +1,356 @@ +/* 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/screenfx.h" + +namespace Made { + +const byte ScreenEffects::vfxOffsTable[64] = { + 5, 2, 6, 1, 4, 7, 3, 0, + 7, 4, 0, 3, 6, 1, 5, 2, + 2, 5, 1, 6, 3, 0, 4, 7, + 0, 3, 7, 4, 1, 6, 2, 5, + 4, 0, 2, 5, 7, 3, 1, 6, + 1, 6, 4, 0, 2, 5, 7, 3, + 6, 1, 3, 7, 5, 2, 0, 4, + 3, 7, 5, 2, 0, 4, 6, 1 +}; + +const byte ScreenEffects::vfxOffsIndexTable[8] = { + 6, 7, 2, 3, 4, 5, 0, 1 +}; + + +ScreenEffects::ScreenEffects(Screen *screen) : _screen(screen) { + vfxOffsTablePtr = &vfxOffsTable[6 * 8]; + vfxX1 = 0; + vfxY1 = 0; + vfxWidth = 0; + vfxHeight = 0; +} + +void ScreenEffects::run(int16 effectNum, Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + + // TODO: Put effect functions into an array + // TODO: Implement more visual effects + + switch (effectNum) { + + case 0: // No effect + vfx00(surface, palette, newPalette, colorCount); + break; + + case 2: + vfx02(surface, palette, newPalette, colorCount); + break; + + case 9: // "Checkerboard" effect + vfx09(surface, palette, newPalette, colorCount); + break; + + case 10: // "Screen wipe in", left to right + vfx10(surface, palette, newPalette, colorCount); + break; + + case 11: // "Screen wipe in", right to left + vfx11(surface, palette, newPalette, colorCount); + break; + + case 12: // "Screen wipe in", top to bottom + vfx12(surface, palette, newPalette, colorCount); + break; + + case 13: // "Screen wipe in", bottom to top + vfx13(surface, palette, newPalette, colorCount); + break; + + case 14: // "Screen open" effect + vfx14(surface, palette, newPalette, colorCount); + break; + + case 15: + vfx15(surface, palette, newPalette, colorCount); + break; + + case 17: // Palette fadeout/fadein + vfx17(surface, palette, newPalette, colorCount); + break; + + default: + vfx00(surface, palette, newPalette, colorCount); + warning("Unimplemented visual effect %d", effectNum); + + } + +} + +void ScreenEffects::flash(int flashCount, byte *palette, int colorCount) { + int palSize = colorCount * 3; + if (flashCount < 1) + flashCount = 1; + for (int i = 0; i < palSize; i++) + _fxPalette[i] = CLIP<byte>(255 - palette[i], 0, 255); + while (flashCount--) { + _screen->setRGBPalette(_fxPalette, 0, colorCount); + _screen->updateScreenAndWait(20); + _screen->setRGBPalette(palette, 0, colorCount); + _screen->updateScreenAndWait(20); + } +} + +void ScreenEffects::setPalette(byte *palette) { + if (!_screen->isPaletteLocked()) { + _screen->setRGBPalette(palette, 0, 256); + } +} + +void ScreenEffects::setBlendedPalette(byte *palette, byte *newPalette, int colorCount, int16 value, int16 maxValue) { + if (!_screen->isPaletteLocked()) { + int32 mulValue = (value * 64) / maxValue; + for (int i = 0; i < colorCount * 3; i++) + _fxPalette[i] = CLIP(newPalette[i] - (newPalette[i] - palette[i]) * mulValue / 64, 0, 255); + _screen->setRGBPalette(_fxPalette, 0, 256); + } +} + +void ScreenEffects::copyFxRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2) { + + // TODO: Clean up + + byte *src, *dst; + + x1 = CLIP<int16>(x1, 0, 320); + y1 = CLIP<int16>(y1, 0, 200); + x2 = CLIP<int16>(x2, 0, 320); + y2 = CLIP<int16>(y2, 0, 200); + + x2 -= x1; + y2 -= y1; + vfxX1 = x1 & 0x0E; + x1 += 16; + x1 = x1 & 0xFFF0; + x2 += vfxX1; + x2 -= 15; + if (x2 < 0) + x2 = 0; + vfxWidth = x2 & 0x0E; + x2 = x2 & 0xFFF0; + + vfxY1 = y1 & 7; + + byte *source = (byte*)surface->getBasePtr(x1, y1); + + Graphics::Surface *vgaScreen = _screen->lockScreen(); + byte *dest = (byte*)vgaScreen->getBasePtr(x1, y1); + + int16 addX = x2 / 16; + + while (y2-- > 0) { + + int16 addVal = vfxOffsTablePtr[vfxY1] * 2; + int16 w = 0; + vfxY1 = (vfxY1 + 1) & 7; + + src = source + addVal; + dst = dest + addVal; + + if (addVal < vfxX1) { + if (addVal < vfxWidth) + w = 1; + else + w = 0; + } else { + src -= 16; + dst -= 16; + if (addVal < vfxWidth) + w = 2; + else + w = 1; + } + + w += addX; + + while (w-- > 0) { + *dst++ = *src++; + *dst++ = *src++; + src += 14; + dst += 14; + } + + source += 320; + dest += 320; + + } + + vfxHeight = (vfxHeight + 1) & 7; + vfxOffsTablePtr = &vfxOffsTable[vfxOffsIndexTable[vfxHeight] * 8]; + + _screen->unlockScreen(); + +} + +void ScreenEffects::copyRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2) { + Graphics::Surface *vgaScreen = _screen->lockScreen(); + byte *source = (byte*)surface->getBasePtr(x1, y1); + byte *dest = (byte*)vgaScreen->getBasePtr(x1, y1); + for (int y = 0; y < y2 - y1; y++) { + memcpy(dest, source, x2 - x1); + dest += 320; + source += 320; + } + _screen->unlockScreen(); +} + +// No effect +void ScreenEffects::vfx00(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + setPalette(palette); + _screen->showWorkScreen(); + // FIXME: For Manhole; causes sluggish mouse + _screen->updateScreenAndWait(100); +} + +void ScreenEffects::vfx02(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int x = 312; x >= 0; x -= 8) { + copyRect(surface, x, 0, x + 8, 200); + setBlendedPalette(palette, newPalette, colorCount, 312 - x, 312); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Checkerboard" effect +void ScreenEffects::vfx09(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int i = 0; i < 8; i++) { + copyFxRect(surface, 0, 0, 320, 200); + for (int j = 0; j < 4; j++) { + setBlendedPalette(palette, newPalette, colorCount, i * 4 + j, 36/*FIX?*/); + _screen->updateScreenAndWait(25); + } + } + setPalette(palette); +} + +// "Screen wipe in", left to right +void ScreenEffects::vfx10(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int x = -56; x < 312; x += 8) { + copyFxRect(surface, x, 0, x + 64, 200); + setBlendedPalette(palette, newPalette, colorCount, x + 56, 368); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Screen wipe in", right to left +void ScreenEffects::vfx11(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int x = 312; x > -56; x -= 8) { + copyFxRect(surface, x, 0, x + 64, 200); + setBlendedPalette(palette, newPalette, colorCount, x + 56, 368); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Screen wipe in", top to bottom +void ScreenEffects::vfx12(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int y = -70; y < 312; y += 10) { + copyFxRect(surface, 0, y, 320, y + 80); + setBlendedPalette(palette, newPalette, colorCount, y + 70, 260); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Screen wipe in", bottom to top +void ScreenEffects::vfx13(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + for (int y = 312; y > -70; y -= 10) { + copyFxRect(surface, 0, y, 320, y + 80); + setBlendedPalette(palette, newPalette, colorCount, y + 70, 260); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// "Screen open" effect +void ScreenEffects::vfx14(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + int16 x = 8, y = 5; + for (int i = 0; i < 27; i++) { + copyFxRect(surface, 160 - x, 100 - y, 160 + x, 100 + y); + x += 8; + y += 5; + setBlendedPalette(palette, newPalette, colorCount, i, 27); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +void ScreenEffects::vfx15(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + int16 x = 8; + for (int i = 0; i < 27; i++) { + copyFxRect(surface, 160 - x, 0, 160 + x, 200); + x += 8; + setBlendedPalette(palette, newPalette, colorCount, i, 27); + _screen->updateScreenAndWait(25); + } + setPalette(palette); +} + +// Palette fadeout/fadein +void ScreenEffects::vfx17(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { + + byte tempPalette[768]; + + bool savedPaletteLock = _screen->isPaletteLocked(); + _screen->setPaletteLock(false); + + memcpy(tempPalette, palette, 768); + + // Fade out to black + memset(palette, 0, 768); + for (int i = 0; i < 50; i++) { + setBlendedPalette(palette, newPalette, colorCount, i, 50); + _screen->updateScreenAndWait(25); + } + _screen->setRGBPalette(palette, 0, colorCount); + + memcpy(palette, tempPalette, 768); + + _screen->showWorkScreen(); + + // Fade from black to palette + memset(newPalette, 0, 768); + for (int i = 0; i < 50; i++) { + setBlendedPalette(palette, newPalette, colorCount, i, 50); + _screen->updateScreenAndWait(25); + } + _screen->setRGBPalette(palette, 0, colorCount); + + _screen->setPaletteLock(savedPaletteLock); + +} + + +} // End of namespace Made diff --git a/engines/made/screenfx.h b/engines/made/screenfx.h new file mode 100644 index 0000000000..e5023621ae --- /dev/null +++ b/engines/made/screenfx.h @@ -0,0 +1,70 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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_SCREENFX_H +#define MADE_SCREENFX_H + +#include "common/endian.h" +#include "common/util.h" +#include "common/rect.h" + +#include "graphics/surface.h" + +#include "made/made.h" +#include "made/screen.h" + +namespace Made { + +class ScreenEffects { +public: + ScreenEffects(Screen *screen); + void run(int16 effectNum, Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void flash(int count, byte *palette, int colorCount); +private: + Screen *_screen; + byte _fxPalette[768]; + static const byte vfxOffsTable[64]; + static const byte vfxOffsIndexTable[8]; + const byte *vfxOffsTablePtr; + int16 vfxX1, vfxY1, vfxWidth, vfxHeight; + void setPalette(byte *palette); + void setBlendedPalette(byte *palette, byte *newPalette, int colorCount, int16 value, int16 maxValue); + void copyFxRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2); + void copyRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2); + void vfx00(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx02(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx09(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx10(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx11(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx12(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx13(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx14(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx15(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); + void vfx17(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount); +}; + +} // End of namespace Made + +#endif /* MADE_H */ diff --git a/engines/made/script.cpp b/engines/made/script.cpp index 74dc9e0d9f..6f4ff7ace3 100644 --- a/engines/made/script.cpp +++ b/engines/made/script.cpp @@ -91,96 +91,92 @@ int16 *ScriptStack::getStackPtr() { /* ScriptInterpreter */ ScriptInterpreter::ScriptInterpreter(MadeEngine *vm) : _vm(vm) { -#define COMMAND(x) { &ScriptInterpreter::x, #x } +#ifdef DUMP_SCRIPTS +#define COMMAND(x, sig) { &ScriptInterpreter::x, #x, sig } +#else +#define COMMAND(x, sig) { &ScriptInterpreter::x, #x} +#endif static CommandEntry commandProcs[] = { /* 01 */ - COMMAND(cmd_branchTrue), - COMMAND(cmd_branchFalse), - COMMAND(cmd_branch), - COMMAND(cmd_true), + COMMAND(cmd_branchTrue, "W"), + COMMAND(cmd_branchFalse, "W"), + COMMAND(cmd_branch, "W"), + COMMAND(cmd_true, ""), /* 05 */ - COMMAND(cmd_false), - COMMAND(cmd_push), - COMMAND(cmd_not), - COMMAND(cmd_add), + 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), + 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), + 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), + COMMAND(cmd_eq, ""), + COMMAND(cmd_gt, ""), + COMMAND(cmd_loadConstant, "w"), + COMMAND(cmd_loadVariable, "w"), /* 21 */ - COMMAND(cmd_getObjectProperty), - COMMAND(cmd_setObjectProperty), - COMMAND(cmd_set), - COMMAND(cmd_print), + COMMAND(cmd_getObjectProperty, ""), + COMMAND(cmd_setObjectProperty, ""), + COMMAND(cmd_set, "w"), + COMMAND(cmd_print, ""), /* 25 */ - COMMAND(cmd_terpri), - COMMAND(cmd_printNumber), - COMMAND(cmd_vref), - COMMAND(cmd_vset), + 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), + COMMAND(cmd_vsize, ""), + COMMAND(cmd_exit, ""), + COMMAND(cmd_return, ""), + COMMAND(cmd_call, "b"), /* 33 */ - COMMAND(cmd_svar), - COMMAND(cmd_sset), - COMMAND(cmd_split), - COMMAND(cmd_snlit), + 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), + COMMAND(cmd_yorn, ""), + COMMAND(cmd_save, ""), + COMMAND(cmd_restore, ""), + COMMAND(cmd_arg, "b"), /* 41 */ - COMMAND(cmd_aset), - COMMAND(cmd_tmp), - COMMAND(cmd_tset), - COMMAND(cmd_tspace), + COMMAND(cmd_aset, "b"), + COMMAND(cmd_tmp, "b"), + COMMAND(cmd_tset, "b"), + COMMAND(cmd_tspace, "b"), /* 45 */ - COMMAND(cmd_class), - COMMAND(cmd_objectp), - COMMAND(cmd_vectorp), - COMMAND(cmd_restart), + 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), + COMMAND(cmd_rand, ""), + COMMAND(cmd_randomize, ""), + COMMAND(cmd_send, "b"), + COMMAND(cmd_extend, "Eb"), /* 53 */ - COMMAND(cmd_catch), - COMMAND(cmd_cdone), - COMMAND(cmd_throw), - COMMAND(cmd_functionp), + 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) + COMMAND(cmd_le, ""), + COMMAND(cmd_ge, ""), + COMMAND(cmd_varx, ""), + COMMAND(cmd_setx, "") }; _commands = commandProcs; _commandsMax = ARRAYSIZE(commandProcs) + 1; - if (_vm->getGameID() == GID_RTZ) - _functions = new ScriptFunctionsRtz(_vm); - else if (_vm->getGameID() == GID_LGOP2) - _functions = new ScriptFunctionsLgop2(_vm); - else if (_vm->getGameID() == GID_MANHOLE) - _functions = new ScriptFunctionsMhne(_vm); - else - error("Unsupported GameID"); - + _functions = new ScriptFunctions(_vm); _functions->setupExternalsTable(); #undef COMMAND @@ -191,8 +187,7 @@ ScriptInterpreter::~ScriptInterpreter() { } void ScriptInterpreter::runScript(int16 scriptObjectIndex) { - - _terminated = false; + _vm->_quit = false; _runningScriptObjectIndex = scriptObjectIndex; _localStackPos = _stack.getStackPos(); @@ -200,16 +195,19 @@ void ScriptInterpreter::runScript(int16 scriptObjectIndex) { _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData(); _codeIp = _codeBase; - while (!_terminated) { + while (!_vm->_quit) { + + _vm->handleEvents(); + byte opcode = readByte(); if (opcode >= 1 && opcode <= _commandsMax) { - debug(4, "opcode = %s\n", _commands[opcode - 1].desc); + debug(4, "[%04X:%04X] %s", _runningScriptObjectIndex, (uint) (_codeIp - _codeBase), _commands[opcode - 1].desc); (this->*_commands[opcode - 1].proc)(); } else { - warning("ScriptInterpreter::runScript(%d) Unknown opcode %02X\n", _runningScriptObjectIndex, opcode); + warning("ScriptInterpreter::runScript(%d) Unknown opcode %02X", _runningScriptObjectIndex, opcode); } + } - } byte ScriptInterpreter::readByte() { @@ -219,7 +217,7 @@ byte ScriptInterpreter::readByte() { int16 ScriptInterpreter::readInt16() { int16 temp = (int16)READ_LE_UINT16(_codeIp); _codeIp += 2; - debug(4, "readInt16() value = %04X\n", temp); + debug(4, "readInt16() value = %04X", temp); return temp; } @@ -330,14 +328,14 @@ void ScriptInterpreter::cmd_gt() { void ScriptInterpreter::cmd_loadConstant() { int16 value = readInt16(); - debug(4, "value = %04X (%d)\n", value, value); + debug(4, "value = %04X (%d)", 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); + debug(4, "variable = %d; value = %d (%04X)", variable, value, value); _stack.setTop(value); } @@ -345,7 +343,7 @@ 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); + debug(4, "value = %04X(%d)", value, value); _stack.setTop(value); } @@ -359,15 +357,14 @@ void ScriptInterpreter::cmd_setObjectProperty() { void ScriptInterpreter::cmd_set() { int16 variable = readInt16(); - debug(4, "var(%d) = %04d (%d)\n", variable, _stack.top(), _stack.top()); + debug(4, "var(%d) = %04d (%d)", 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); + const char *text = _vm->_dat->getObjectString(_stack.top()); + debug(4, "%s", text); _stack.setTop(0); } @@ -386,20 +383,20 @@ void ScriptInterpreter::cmd_vref() { int16 value = 0; int16 index = _stack.pop(); int16 objectIndex = _stack.top(); - debug(4, "index = %d; objectIndex = %d\n", index, objectIndex); fflush(stdout); + debug(4, "index = %d; objectIndex = %d", index, objectIndex); if (objectIndex > 0) { Object *obj = _vm->_dat->getObject(objectIndex); value = obj->getVectorItem(index); } _stack.setTop(value); - debug(4, "--> value = %d\n", value); fflush(stdout); + debug(4, "--> value = %d", value); } 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); + debug(4, "index = %d; objectIndex = %d; value = %d", index, objectIndex, value); if (objectIndex > 0) { Object *obj = _vm->_dat->getObject(objectIndex); obj->setVectorItem(index, value); @@ -418,11 +415,17 @@ void ScriptInterpreter::cmd_vsize() { } void ScriptInterpreter::cmd_exit() { - warning("Unimplemented command: cmd_exit"); + _vm->_quit = true; } void ScriptInterpreter::cmd_return() { - // TODO: Check if returning from main function + + // Check if returning from main function + if (_localStackPos == kScriptStackSize) { + _vm->_quit = true; + return; + } + int16 funcResult = _stack.top(); _stack.setStackPos(_localStackPos); _localStackPos = kScriptStackLimit - _stack.pop(); @@ -432,95 +435,115 @@ void ScriptInterpreter::cmd_return() { byte argc = _stack.pop(); _stack.free(argc); _stack.setTop(funcResult); - debug(4, "LEAVE: stackPtr = %d; _localStackPos = %d\n\n\n", _stack.getStackPos(), _localStackPos); + debug(4, "LEAVE: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos); } void ScriptInterpreter::cmd_call() { - debug(4, "\n\n\nENTER: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos); + debug(4, "\nENTER: stackPtr = %d; _localStackPos = %d", _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); + debug(4, "argc = %d; _runningScriptObjectIndex = %04X", argc, _runningScriptObjectIndex); _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData(); _codeIp = _codeBase; } void ScriptInterpreter::cmd_svar() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_svar"); } void ScriptInterpreter::cmd_sset() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_sset"); } void ScriptInterpreter::cmd_split() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_split"); } void ScriptInterpreter::cmd_snlit() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_snlit"); } void ScriptInterpreter::cmd_yorn() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_yorn"); } void ScriptInterpreter::cmd_save() { - warning("Unimplemented command: cmd_save"); - _stack.setTop(0); + int16 result = 0; + int16 stringOfs = _stack.top(); + const char *filename = _vm->_dat->getString(stringOfs); + result = _vm->_dat->savegame(filename, "", 0); + _stack.setTop(result); } void ScriptInterpreter::cmd_restore() { - warning("Unimplemented command: cmd_restore"); + int16 result = 0; + int16 stringOfs = _stack.top(); + const char *filename = _vm->_dat->getString(stringOfs); + result = _vm->_dat->loadgame(filename, 0); + _stack.setTop(result); } 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)); + debug(4, "argIndex = %d; value = %04X (%d)", 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)); + debug(4, "argIndex = %d; value = %d", 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)); + debug(4, "tempIndex = %d; value = %d", 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()); + debug(4, "tempIndex = %d; value = %d", tempIndex, _stack.top()); _stack.poke(_localStackPos - tempIndex - 1, _stack.top()); } void ScriptInterpreter::cmd_tspace() { int16 tempCount = readByte(); - debug(4, "tempCount = %d\n", tempCount); + debug(4, "tempCount = %d", tempCount); _stack.alloc(tempCount); } void ScriptInterpreter::cmd_class() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_class"); } void ScriptInterpreter::cmd_objectp() { - warning("Unimplemented command: cmd_objectp"); + Object *obj = _vm->_dat->getObject(_stack.top()); + if (obj->isObject()) + _stack.setTop(-1); + else + _stack.setTop(0); } void ScriptInterpreter::cmd_vectorp() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_vectorp"); } void ScriptInterpreter::cmd_restart() { + // TODO: Used in RTZ warning("Unimplemented command: cmd_restart"); } @@ -535,11 +558,11 @@ void ScriptInterpreter::cmd_randomize() { void ScriptInterpreter::cmd_send() { - debug(4, "\n\n\nENTER: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos); + debug(4, "\nENTER: stackPtr = %d; _localStackPos = %d", _stack.getStackPos(), _localStackPos); byte argc = readByte(); - debug(4, "argc = %d\n", argc); + debug(4, "argc = %d", argc); _stack.push(argc); _stack.push(_codeIp - _codeBase); @@ -550,7 +573,7 @@ void ScriptInterpreter::cmd_send() { 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); + debug(4, "objectIndex = %d (%04X); propertyId = %d(%04X)", objectIndex, objectIndex, propertyId, propertyId); if (objectIndex != 0) { objectIndex = _vm->_dat->getObject(objectIndex)->getClass(); @@ -558,7 +581,7 @@ void ScriptInterpreter::cmd_send() { objectIndex = _stack.peek(_localStackPos + argc + 3); } - debug(4, "--> objectIndex = %d(%04X)\n", objectIndex, objectIndex); fflush(stdout); + debug(4, "--> objectIndex = %d(%04X)", objectIndex, objectIndex); if (objectIndex != 0) { _runningScriptObjectIndex = _vm->_dat->getObjectProperty(objectIndex, propertyId); @@ -583,13 +606,12 @@ void ScriptInterpreter::cmd_extend() { byte argc = readByte(); int16 *argv = _stack.getStackPtr(); - //debug(4, "func = %d (%s); argc = %d\n", func, extendFuncNames[func], argc); - debug(4, "func = %d; argc = %d\n", func, argc); + debug(4, "func = %d (%s); argc = %d", func, _functions->getFuncName(func), argc); for (int i = 0; i < argc; i++) - debug(4, "argv[%02d] = %04X (%d)\n", i, argv[i], argv[i]); + debug(2, "argv[%02d] = %04X (%d)", i, argv[i], argv[i]); int16 result = _functions->callFunction(func, argc, argv); - debug(4, "result = %04X (%d)\n", result, result); + debug(2, "result = %04X (%d)", result, result); _stack.free(argc); @@ -598,18 +620,22 @@ void ScriptInterpreter::cmd_extend() { } void ScriptInterpreter::cmd_catch() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_catch"); } void ScriptInterpreter::cmd_cdone() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_cdone"); } void ScriptInterpreter::cmd_throw() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_throw"); } void ScriptInterpreter::cmd_functionp() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_functionp"); } @@ -630,11 +656,133 @@ void ScriptInterpreter::cmd_ge() { } void ScriptInterpreter::cmd_varx() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_varx"); } void ScriptInterpreter::cmd_setx() { + // Never used in LGOP2, RTZ, Manhole:NE warning("Unimplemented command: cmd_setx"); } +#ifdef DUMP_SCRIPTS +void ScriptInterpreter::dumpScript(int16 objectIndex, int *opcodeStats, int *externStats) { + + debug(1, "Dumping code for object %04X", objectIndex); + + Object *obj = _vm->_dat->getObject(objectIndex); + byte *code = obj->getData(), *codeStart = code, *codeEnd = code + obj->getSize(); + + while (code < codeEnd) { + byte opcode = *code++; + if (opcode >= 1 && opcode <= _commandsMax) { + Common::String codeLine; + const char *desc = _commands[opcode - 1].desc; + const char *sig = _commands[opcode - 1].sig; + int valueType; /* 0: dec; 1: hex; 2: extended function */ + int16 value; + char tempStr[32]; + opcodeStats[opcode - 1]++; + snprintf(tempStr, 32, "[%04X] ", (uint16)(code - codeStart - 1)); + codeLine += tempStr; + codeLine += desc; + for (; *sig != '\0'; sig++) { + codeLine += " "; + switch (*sig) { + case 'b': + valueType = 0; + value = *code++; + break; + case 'B': + valueType = 1; + value = *code++; + break; + case 'w': + valueType = 0; + value = READ_LE_UINT16(code); + code += 2; + break; + case 'W': + valueType = 1; + value = READ_LE_UINT16(code); + code += 2; + break; + case 'E': + valueType = 2; + value = *code++; + break; + } + switch (valueType) { + case 0: + snprintf(tempStr, 32, "%d", value); + break; + case 1: + snprintf(tempStr, 32, "0x%X", value); + break; + case 2: + if (value < _functions->getCount()) { + snprintf(tempStr, 32, "%s", _functions->getFuncName(value)); + externStats[value]++; + } else { + snprintf(tempStr, 32, "invalid: %d", value); + } + break; + } + codeLine += tempStr; + } + debug(1, "%s", codeLine.c_str()); + } else { + error("ScriptInterpreter::dumpScript(%d) Unknown opcode %02X", objectIndex, opcode); + } + } + debug(1, "-------------------------------------------"); +} + +void ScriptInterpreter::dumpAllScripts() { + int *opcodeStats = new int[_commandsMax - 1]; + int *externStats = new int[_functions->getCount()]; + + for (int i = 0; i < _commandsMax; i++) + opcodeStats[i] = 0; + for (int i = 0; i < _functions->getCount(); i++) + externStats[i] = 0; + + for (uint objectIndex = 1; objectIndex <= _vm->_dat->getObjectCount(); objectIndex++) { + Object *obj = _vm->_dat->getObject(objectIndex); + // Check if it's a byte array which might contain code + if (obj->getClass() != 0x7FFF) + continue; + // Code objects aren't excplicitly marked as such, we need to check if + // the last byte is a cmd_return opcode. + byte *retByte = obj->getData() + obj->getSize() - 1; + if (*retByte == 0x1F) { + dumpScript(objectIndex, opcodeStats, externStats); + } + } + + debug(1, "OPCODE statistics:"); + for (int i = 0; i < _commandsMax - 1; i++) + if (opcodeStats[i] > 0) + debug(1, "%-30s: %d", _commands[i].desc, opcodeStats[i]); + debug(1, "UNUSED OPCODE statistics:"); + for (int i = 0; i < _commandsMax - 1; i++) + if (opcodeStats[i] == 0) + debug(1, "%-30s: %d", _commands[i].desc, opcodeStats[i]); + debug(1, "."); + + debug(1, "EXTERN statistics (%d):", _functions->getCount()); + for (int i = 0; i < _functions->getCount(); i++) + if (externStats[i] > 0) + debug(1, "%-30s: %d", _functions->getFuncName(i), externStats[i]); + debug(1, "UNUSED EXTERN statistics (%d):", _functions->getCount()); + for (int i = 0; i < _functions->getCount(); i++) + if (externStats[i] == 0) + debug(1, "%-30s: %d", _functions->getFuncName(i), externStats[i]); + debug(1, "."); + + delete[] opcodeStats; + delete[] externStats; +} +#endif + } // End of namespace Made diff --git a/engines/made/script.h b/engines/made/script.h index 6c031f8708..459a088cb8 100644 --- a/engines/made/script.h +++ b/engines/made/script.h @@ -32,6 +32,11 @@ namespace Made { +// Define this to dump all game scripts and a usage statistic of all +// opcodes/extended functions instead of running the actual game. +// Then run ScummVM with debuglevel 1. +//#define DUMP_SCRIPTS + class MadeEngine; class ScriptFunctions; @@ -63,6 +68,8 @@ public: ScriptInterpreter(MadeEngine *vm); ~ScriptInterpreter(); void runScript(int16 scriptObjectIndex); + void dumpScript(int16 objectIndex, int *opcodeStats, int *externStats); + void dumpAllScripts(); protected: MadeEngine *_vm; @@ -81,6 +88,9 @@ protected: struct CommandEntry { CommandProc proc; const char *desc; +#ifdef DUMP_SCRIPTS + const char *sig; +#endif }; const CommandEntry *_commands; diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp index 7fc61ee410..932447a1eb 100644 --- a/engines/made/scriptfuncs.cpp +++ b/engines/made/scriptfuncs.cpp @@ -26,8 +26,8 @@ #include "common/endian.h" #include "common/util.h" #include "common/events.h" - #include "graphics/cursorman.h" +#include "sound/audiocd.h" #include "made/made.h" #include "made/resource.h" @@ -40,386 +40,414 @@ namespace Made { -int16 ScriptFunctions::callFunction(uint16 index, int16 argc, int16 *argv) { - if (index >= _externalFuncs.size()) { - // TODO: ERROR! - return 0; - } +typedef Common::Functor2Mem<int16, int16*, int16, ScriptFunctions> ExternalScriptFunc; +#define External(x) \ + _externalFuncs.push_back(new ExternalScriptFunc(this, &ScriptFunctions::x)); \ + _externalFuncNames.push_back(#x); +void ScriptFunctions::setupExternalsTable() { + + External(sfSystemCall); + External(sfInitGraf); + External(sfRestoreGraf); + External(sfDrawPicture); + External(sfClearScreen); + External(sfShowPage); + External(sfPollEvent); + External(sfGetMouseX); + External(sfGetMouseY); + External(sfGetKey); + External(sfSetVisualEffect); + External(sfPlaySound); + External(sfPlayMusic); + External(sfStopMusic); + External(sfIsMusicPlaying); + External(sfSetTextPos); + External(sfFlashScreen); + External(sfPlayNote); + External(sfStopNote); + External(sfPlayTele); + External(sfStopTele); + External(sfHideMouseCursor); + External(sfShowMouseCursor); + External(sfGetMusicBeat); + External(sfSetScreenLock); + External(sfAddSprite); + External(sfFreeAnim); + External(sfDrawSprite); + External(sfEraseSprites); + External(sfUpdateSprites); + External(sfGetTimer); + External(sfSetTimer); + External(sfResetTimer); + External(sfAllocTimer); + External(sfFreeTimer); + External(sfSetPaletteLock); + External(sfSetFont); + External(sfDrawText); + External(sfHomeText); + External(sfSetTextRect); + External(sfSetTextXY); + External(sfSetFontDropShadow); + External(sfSetFontColor); + External(sfSetFontOutline); + External(sfLoadMouseCursor); + External(sfSetSpriteGround); + External(sfLoadResText); - fflush(stdout); - //g_system->delayMillis(2000); + if (_vm->getGameID() == GID_MANHOLE || _vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_RODNEY) { + External(sfAddScreenMask); + External(sfSetSpriteMask); + } else if (_vm->getGameID() == GID_RTZ) { + External(sfSetClipArea); + External(sfSetSpriteClip); + } + + External(sfSoundPlaying); + External(sfStopSound); + External(sfPlayVoice); + + if (_vm->getGameID() == GID_MANHOLE || _vm->getGameID() == GID_RTZ) { + External(sfPlayCd); + External(sfStopCd); + External(sfGetCdStatus); + External(sfGetCdTime); + External(sfPlayCdSegment); + } - return (*_externalFuncs[index])(argc, argv); -} - -typedef Common::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]); + if (_vm->getGameID() == GID_RTZ) { + External(sfPrintf); + External(sfClearMono); + External(sfGetSoundEnergy); + External(sfClearText); + External(sfAnimText); + External(sfGetTextWidth); + External(sfPlayMovie); + External(sfLoadSound); + External(sfLoadMusic); + External(sfLoadPicture); + External(sfSetMusicVolume); + External(sfRestartEvents); + External(sfPlaceSprite); + External(sfPlaceText); + External(sfDeleteChannel); + External(sfGetChannelType); + External(sfSetChannelState); + External(sfSetChannelLocation); + External(sfSetChannelContent); + External(sfSetExcludeArea); + External(sfSetSpriteExclude); + External(sfGetChannelState); + External(sfPlaceAnim); + External(sfSetAnimFrame); + External(sfGetAnimFrame); + External(sfGetAnimFrameCount); + External(sfGetPictureWidth); + External(sfGetPictureHeight); + External(sfSetSoundRate); + External(sfDrawAnimPic); + External(sfLoadAnim); + External(sfReadText); + External(sfReadMenu); + External(sfDrawMenu); + External(sfGetMenuCount); + External(sfSaveGame); + External(sfLoadGame); + External(sfGetGameDescription); + External(sfShakeScreen); + External(sfPlaceMenu); + External(sfSetSoundVolume); + External(sfGetSynthType); + External(sfIsSlowSystem); + } } #undef External -int16 ScriptFunctionsRtz::o1_SYSTEM(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSystemCall(int16 argc, int16 *argv) { // This opcode is empty. return 0; } -int16 ScriptFunctionsRtz::o1_INITGRAF(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfInitGraf(int16 argc, int16 *argv) { // This opcode is empty. return 0; } -int16 ScriptFunctionsRtz::o1_RESTOREGRAF(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfRestoreGraf(int16 argc, int16 *argv) { // This opcode is empty. return 0; } -int16 ScriptFunctionsRtz::o1_DRAWPIC(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfDrawPicture(int16 argc, int16 *argv) { return _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_CLS(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfClearScreen(int16 argc, int16 *argv) { + if (_vm->_screen->isScreenLocked()) + return 0; + if (_vm->_autoStopSound) { + _vm->_mixer->stopHandle(_audioStreamHandle); + _vm->_autoStopSound = false; + } _vm->_screen->clearScreen(); return 0; } -int16 ScriptFunctionsRtz::o1_SHOWPAGE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfShowPage(int16 argc, int16 *argv) { _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: - _vm->_eventKey = event.kbd.ascii; - eventNum = 5; - break; - - case Common::EVENT_QUIT: - // TODO: Exit more gracefully. - g_system->quit(); - break; - - default: - break; - - } - } +int16 ScriptFunctions::sfPollEvent(int16 argc, int16 *argv) { _vm->_system->updateScreen(); + int16 eventNum = _vm->_eventNum; + _vm->_eventNum = 0; return eventNum; } -int16 ScriptFunctionsRtz::o1_EVENTX(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetMouseX(int16 argc, int16 *argv) { return _vm->_eventMouseX; } -int16 ScriptFunctionsRtz::o1_EVENTY(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetMouseY(int16 argc, int16 *argv) { return _vm->_eventMouseY; } -int16 ScriptFunctionsRtz::o1_EVENTKEY(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetKey(int16 argc, int16 *argv) { return _vm->_eventKey; } -int16 ScriptFunctionsRtz::o1_VISUALFX(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetVisualEffect(int16 argc, int16 *argv) { _vm->_screen->setVisualEffectNum(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_PLAYSND(int16 argc, int16 *argv) { - int soundNum = argv[0]; - bool loop = false; - +int16 ScriptFunctions::sfPlaySound(int16 argc, int16 *argv) { + int16 soundNum = argv[0]; + _vm->_autoStopSound = false; + _vm->_mixer->stopHandle(_audioStreamHandle); if (argc > 1) { soundNum = argv[1]; - loop = (argv[0] == 1); + _vm->_autoStopSound = (argv[0] == 1); } - if (soundNum > 0) { - if (!_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, loop)); - } + _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, + _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, false)); } - return 0; } -int16 ScriptFunctionsRtz::o1_PLAYMUS(int16 argc, int16 *argv) { - int16 musicNum = argv[0]; - if (musicNum > 0) { - XmidiResource *xmidi = _vm->_res->getXmidi(musicNum); - _vm->_music->play(xmidi); - _vm->_res->freeResource(xmidi); +int16 ScriptFunctions::sfPlayMusic(int16 argc, int16 *argv) { + // TODO: Music in LGOP2 and Manhole isn't supported yet + if (_vm->getGameID() == GID_RTZ) { + int16 musicNum = argv[0]; + if (musicNum > 0) { + _musicRes = _vm->_res->getXmidi(musicNum); + if (_musicRes) + _vm->_music->playXMIDI(_musicRes); + } } return 0; } -int16 ScriptFunctionsRtz::o1_STOPMUS(int16 argc, int16 *argv) { - _vm->_music->stop(); +int16 ScriptFunctions::sfStopMusic(int16 argc, int16 *argv) { + if (_vm->_music->isPlaying() && _musicRes) { + _vm->_music->stop(); + _vm->_res->freeResource(_musicRes); + _musicRes = NULL; + } return 0; } -int16 ScriptFunctionsRtz::o1_ISMUS(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfIsMusicPlaying(int16 argc, int16 *argv) { if (_vm->_music->isPlaying()) return 1; else return 0; } -int16 ScriptFunctionsRtz::o1_TEXTPOS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTPOS"); +int16 ScriptFunctions::sfSetTextPos(int16 argc, int16 *argv) { + // Used in Manhole:NE + //warning("Unimplemented opcode: sfSetTextPos"); // This seems to be some kind of low-level opcode. // The original engine calls int 10h to set the VGA cursor position. + // Since this seems to be used for debugging purposes only it's left out. return 0; } -int16 ScriptFunctionsRtz::o1_FLASH(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfFlashScreen(int16 argc, int16 *argv) { _vm->_screen->flash(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_PLAYNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYNOTE"); +int16 ScriptFunctions::sfPlayNote(int16 argc, int16 *argv) { + // TODO: Used in Manhole:NE + warning("Unimplemented opcode: sfPlayNote"); return 0; } -int16 ScriptFunctionsRtz::o1_STOPNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPNOTE"); +int16 ScriptFunctions::sfStopNote(int16 argc, int16 *argv) { + // TODO: Used in Manhole:NE + warning("Unimplemented opcode: sfStopNote"); return 0; } -int16 ScriptFunctionsRtz::o1_PLAYTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYTELE"); +int16 ScriptFunctions::sfPlayTele(int16 argc, int16 *argv) { + // TODO: Used in Manhole:NE + warning("Unimplemented opcode: sfPlayTele"); return 0; } -int16 ScriptFunctionsRtz::o1_STOPTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPTELE"); +int16 ScriptFunctions::sfStopTele(int16 argc, int16 *argv) { + // TODO: Used in Manhole:NE + warning("Unimplemented opcode: sfStopTele"); return 0; } -int16 ScriptFunctionsRtz::o1_HIDECURS(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfHideMouseCursor(int16 argc, int16 *argv) { _vm->_system->showMouse(false); return 0; } -int16 ScriptFunctionsRtz::o1_SHOWCURS(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfShowMouseCursor(int16 argc, int16 *argv) { _vm->_system->showMouse(true); return 0; } -int16 ScriptFunctionsRtz::o1_MUSICBEAT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICBEAT"); +int16 ScriptFunctions::sfGetMusicBeat(int16 argc, int16 *argv) { + // This is called loads of times in the intro of the floppy version + // of RtZ. Not sure what it does. Commented out to reduce spam + //warning("Unimplemented opcode: sfGetMusicBeat"); return 0; } -int16 ScriptFunctionsRtz::o1_SCREENLOCK(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetScreenLock(int16 argc, int16 *argv) { _vm->_screen->setScreenLock(argv[0] != 0); return 0; } -int16 ScriptFunctionsRtz::o1_ADDSPRITE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ADDSPRITE"); - //_vm->_screen->addSprite(argv[0]); - return 0; +int16 ScriptFunctions::sfAddSprite(int16 argc, int16 *argv) { + if (_vm->getGameID() == GID_RTZ) { + // Unused in RTZ + return 0; + } if (_vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_MANHOLE) { + return _vm->_screen->addToSpriteList(argv[2], argv[1], argv[0]); + } else { + return 0; + } } -int16 ScriptFunctionsRtz::o1_FREEANIM(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfFreeAnim(int16 argc, int16 *argv) { _vm->_screen->clearChannels(); + if (_vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_MANHOLE) { + _vm->_screen->clearSpriteList(); + } return 0; } -int16 ScriptFunctionsRtz::o1_DRAWSPRITE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_DRAWSPRITE"); - return 0; +int16 ScriptFunctions::sfDrawSprite(int16 argc, int16 *argv) { + if (_vm->getGameID() == GID_RTZ) { + return _vm->_screen->drawSprite(argv[2], argv[1], argv[0]); + } if (_vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_MANHOLE) { + SpriteListItem item = _vm->_screen->getFromSpriteList(argv[2]); + int16 channelIndex = _vm->_screen->drawSprite(item.index, argv[1] - item.xofs, argv[0] - item.yofs); + _vm->_screen->setChannelUseMask(channelIndex); + return 0; + } else { + return 0; + } } -int16 ScriptFunctionsRtz::o1_ERASESPRITES(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfEraseSprites(int16 argc, int16 *argv) { _vm->_screen->clearChannels(); return 0; } -int16 ScriptFunctionsRtz::o1_UPDATESPRITES(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfUpdateSprites(int16 argc, int16 *argv) { _vm->_screen->updateSprites(); return 0; } -int16 ScriptFunctionsRtz::o1_GETTIMER(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetTimer(int16 argc, int16 *argv) { return _vm->getTimer(argv[0]); } -int16 ScriptFunctionsRtz::o1_SETTIMER(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetTimer(int16 argc, int16 *argv) { _vm->setTimer(argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_RESETTIMER(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfResetTimer(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 ScriptFunctions::sfAllocTimer(int16 argc, int16 *argv) { + return _vm->allocTimer(); } -int16 ScriptFunctionsRtz::o1_FREETIMER(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfFreeTimer(int16 argc, int16 *argv) { _vm->freeTimer(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_PALETTELOCK(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetPaletteLock(int16 argc, int16 *argv) { _vm->_screen->setPaletteLock(argv[0] != 0); return 0; } -int16 ScriptFunctionsRtz::o1_FONT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetFont(int16 argc, int16 *argv) { _vm->_screen->setFont(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_DRAWTEXT(int16 argc, int16 *argv) { - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); - _vm->_screen->printText(text); +int16 ScriptFunctions::sfDrawText(int16 argc, int16 *argv) { + + const char *text = NULL; + + if (_vm->getGameID() == GID_RTZ) { + text = _vm->_dat->getObjectString(argv[argc - 1]); + } if (_vm->getGameID() == GID_LGOP2 || _vm->getGameID() == GID_MANHOLE) { + text = _vm->_dat->getString(argv[argc - 1]); + } + + if (text) { + char finalText[1024]; + switch (argc) { + case 1: + snprintf(finalText, 1024, "%s", text); + break; + case 2: + snprintf(finalText, 1024, text, argv[0]); + break; + case 3: + snprintf(finalText, 1024, text, argv[1], argv[0]); + break; + case 4: + snprintf(finalText, 1024, text, argv[2], argv[1], argv[0]); + break; + case 5: + snprintf(finalText, 1024, text, argv[3], argv[2], argv[1], argv[0]); + break; + default: + finalText[0] = '\0'; + break; + } + _vm->_screen->printText(finalText); + } + return 0; } -int16 ScriptFunctionsRtz::o1_HOMETEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_HOMETEXT"); +int16 ScriptFunctions::sfHomeText(int16 argc, int16 *argv) { + _vm->_screen->homeText(); return 0; } -int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetTextRect(int16 argc, int16 *argv) { + // Used in the save/load screens of RtZ, and perhaps other places as well int16 x1 = CLIP<int16>(argv[4], 1, 318); int16 y1 = CLIP<int16>(argv[3], 1, 198); int16 x2 = CLIP<int16>(argv[2], 1, 318); @@ -430,158 +458,179 @@ int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_TEXTXY(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetTextXY(int16 argc, int16 *argv) { int16 x = CLIP<int16>(argv[1], 1, 318); int16 y = CLIP<int16>(argv[0], 1, 198); _vm->_screen->setTextXY(x, y); return 0; } -int16 ScriptFunctionsRtz::o1_DROPSHADOW(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetFontDropShadow(int16 argc, int16 *argv) { // if the drop shadow color is -1, then text drop shadow is disabled // when font drop shadow is enabled, outline is disabled _vm->_screen->setDropShadowColor(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_TEXTCOLOR(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetFontColor(int16 argc, int16 *argv) { _vm->_screen->setTextColor(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_OUTLINE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetFontOutline(int16 argc, int16 *argv) { // if the outline color is -1, then text outline is disabled // when font outline is enabled, drop shadow is disabled _vm->_screen->setOutlineColor(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_LOADCURSOR(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadMouseCursor(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); + if (flex) { + Graphics::Surface *surf = flex->getPicture(); + CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, argv[1], argv[0], 0); + _vm->_res->freeResource(flex); + } return 0; } -int16 ScriptFunctionsRtz::o1_SETGROUND(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSpriteGround(int16 argc, int16 *argv) { _vm->_screen->setGround(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_RESTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTEXT"); +int16 ScriptFunctions::sfLoadResText(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfLoadResText"); return 0; } -int16 ScriptFunctionsRtz::o1_CLIPAREA(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CLIPAREA"); +int16 ScriptFunctions::sfSetClipArea(int16 argc, int16 *argv) { + _vm->_screen->setClipArea(argv[3], argv[2], argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_SETCLIP(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSpriteClip(int16 argc, int16 *argv) { _vm->_screen->setClip(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_ISSND(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfAddScreenMask(int16 argc, int16 *argv) { + _vm->_screen->drawMask(argv[2], argv[1], argv[0]); + return 0; +} + +int16 ScriptFunctions::sfSetSpriteMask(int16 argc, int16 *argv) { + _vm->_screen->setMask(argv[0]); + return 0; +} + +int16 ScriptFunctions::sfSoundPlaying(int16 argc, int16 *argv) { if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) return 1; else return 0; } -int16 ScriptFunctionsRtz::o1_STOPSND(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfStopSound(int16 argc, int16 *argv) { _vm->_mixer->stopHandle(_audioStreamHandle); + _vm->_autoStopSound = false; return 0; } -int16 ScriptFunctionsRtz::o1_PLAYVOICE(int16 argc, int16 *argv) { - if (argv[0] > 0) { - if (!_vm->_mixer->isSoundHandleActive(_voiceStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_voiceStreamHandle, - _vm->_res->getSound(argv[0])->getAudioStream(_vm->_soundRate, false)); - } +int16 ScriptFunctions::sfPlayVoice(int16 argc, int16 *argv) { + int16 soundNum = argv[0]; + _vm->_mixer->stopHandle(_audioStreamHandle); + if (soundNum > 0) { + _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, + _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, false)); + _vm->_autoStopSound = true; } return 0; } -int16 ScriptFunctionsRtz::o1_CDPLAY(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDPLAY"); +int16 ScriptFunctions::sfPlayCd(int16 argc, int16 *argv) { + AudioCD.play(argv[0], -1, 0, 0); return 0; } -int16 ScriptFunctionsRtz::o1_STOPCD(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPCD"); - return 0; +int16 ScriptFunctions::sfStopCd(int16 argc, int16 *argv) { + if (AudioCD.isPlaying()) { + AudioCD.stop(); + return 1; + } else { + return 0; + } } -int16 ScriptFunctionsRtz::o1_CDSTATUS(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDSTATUS"); - return 0; +int16 ScriptFunctions::sfGetCdStatus(int16 argc, int16 *argv) { + return AudioCD.isPlaying() ? 1 : 0; } -int16 ScriptFunctionsRtz::o1_CDTIME(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CDTIME"); +int16 ScriptFunctions::sfGetCdTime(int16 argc, int16 *argv) { + // This one is called loads of times, so it has been commented out to reduce spam + //warning("Unimplemented opcode: sfGetCdTime"); + // TODO return 0; } -int16 ScriptFunctionsRtz::o1_CDPLAYSEG(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CDPLAYSEG"); +int16 ScriptFunctions::sfPlayCdSegment(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfPlayCdSegment"); return 0; } -int16 ScriptFunctionsRtz::o1_PRINTF(int16 argc, int16 *argv) { - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); +int16 ScriptFunctions::sfPrintf(int16 argc, int16 *argv) { + const char *text = _vm->_dat->getObjectString(argv[argc - 1]); debug(4, "--> text = %s", text); return 0; } -int16 ScriptFunctionsRtz::o1_MONOCLS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MONOCLS"); +int16 ScriptFunctions::sfClearMono(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfClearMono"); return 0; } -int16 ScriptFunctionsRtz::o1_SNDENERGY(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetSoundEnergy(int16 argc, int16 *argv) { // This is called while in-game voices are played // Not sure what it's used for // -> It's used to animate mouths when NPCs are talking - // Commented out to reduce spam - //warning("Unimplemented opcode: o1_SNDENERGY"); - return 0; + // FIXME: This is a workaround for the "sound energy" problem + // At least the characters move their lips when talking now + return _vm->_rnd->getRandomNumber(5); } -int16 ScriptFunctionsRtz::o1_CLEARTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CLEARTEXT"); +int16 ScriptFunctions::sfClearText(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfClearText"); return 1; } -int16 ScriptFunctionsRtz::o1_ANIMTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ANIMTEXT"); +int16 ScriptFunctions::sfAnimText(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfAnimText"); return 0; } -int16 ScriptFunctionsRtz::o1_TEXTWIDTH(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetTextWidth(int16 argc, int16 *argv) { int16 width = 0; if (argv[1] > 0) { - Object *obj = _vm->_dat->getObject(argv[1]); - const char *text = obj->getString(); + const char *text = _vm->_dat->getObjectString(argv[1]); width = _vm->_screen->getTextWidth(argv[0], text); } return width; } -int16 ScriptFunctionsRtz::o1_PLAYMOVIE(int16 argc, int16 *argv) { - const char *movieName = _vm->_dat->getObject(argv[1])->getString(); +int16 ScriptFunctions::sfPlayMovie(int16 argc, int16 *argv) { + const char *movieName = _vm->_dat->getObjectString(argv[1]); + _vm->_system->showMouse(false); _vm->_pmvPlayer->play(movieName); + _vm->_system->showMouse(true); return 0; } -int16 ScriptFunctionsRtz::o1_LOADSND(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadSound(int16 argc, int16 *argv) { SoundResource *sound = _vm->_res->getSound(argv[0]); if (sound) { _vm->_res->freeResource(sound); @@ -590,8 +639,8 @@ int16 ScriptFunctionsRtz::o1_LOADSND(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_LOADMUS(int16 argc, int16 *argv) { - XmidiResource *xmidi = _vm->_res->getXmidi(argv[0]); +int16 ScriptFunctions::sfLoadMusic(int16 argc, int16 *argv) { + GenericResource *xmidi = _vm->_res->getXmidi(argv[0]); if (xmidi) { _vm->_res->freeResource(xmidi); return 1; @@ -599,7 +648,7 @@ int16 ScriptFunctionsRtz::o1_LOADMUS(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_LOADPIC(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadPicture(int16 argc, int16 *argv) { PictureResource *flex = _vm->_res->getPicture(argv[0]); if (flex) { _vm->_res->freeResource(flex); @@ -608,83 +657,92 @@ int16 ScriptFunctionsRtz::o1_LOADPIC(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_MUSICVOL(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICVOL"); +int16 ScriptFunctions::sfSetMusicVolume(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfSetMusicVolume"); return 0; } -int16 ScriptFunctionsRtz::o1_RESTARTEVENTS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTARTEVENTS"); +int16 ScriptFunctions::sfRestartEvents(int16 argc, int16 *argv) { + // Used in RTZ + //warning("Unimplemented opcode: sfRestartEvents"); + // This is used to reset the event recording/queue. + // Since we don't use either it's left out. return 0; } -int16 ScriptFunctionsRtz::o1_PLACESPRITE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfPlaceSprite(int16 argc, int16 *argv) { return _vm->_screen->placeSprite(argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_PLACETEXT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfPlaceText(int16 argc, int16 *argv) { return _vm->_screen->placeText(argv[6], argv[5], argv[4], argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_DELETECHANNEL(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfDeleteChannel(int16 argc, int16 *argv) { _vm->_screen->deleteChannel(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_CHANNELTYPE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetChannelType(int16 argc, int16 *argv) { return _vm->_screen->getChannelType(argv[0]); } -int16 ScriptFunctionsRtz::o1_SETSTATE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetChannelState(int16 argc, int16 *argv) { _vm->_screen->setChannelState(argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_SETLOCATION(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETLOCATION"); +int16 ScriptFunctions::sfSetChannelLocation(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfSetChannelLocation"); return 0; } -int16 ScriptFunctionsRtz::o1_SETCONTENT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETCONTENT"); +int16 ScriptFunctions::sfSetChannelContent(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfSetChannelContent"); return 0; } -int16 ScriptFunctionsRtz::o1_EXCLUDEAREA(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_EXCLUDEAREA"); +int16 ScriptFunctions::sfSetExcludeArea(int16 argc, int16 *argv) { + _vm->_screen->setExcludeArea(argv[3], argv[2], argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_SETEXCLUDE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSpriteExclude(int16 argc, int16 *argv) { _vm->_screen->setExclude(argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_GETSTATE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetChannelState(int16 argc, int16 *argv) { return _vm->_screen->getChannelState(argv[0]); } -int16 ScriptFunctionsRtz::o1_PLACEANIM(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfPlaceAnim(int16 argc, int16 *argv) { return _vm->_screen->placeAnim(argv[4], argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_SETFRAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetAnimFrame(int16 argc, int16 *argv) { _vm->_screen->setAnimFrame(argv[1], argv[0]); return 0; } -int16 ScriptFunctionsRtz::o1_GETFRAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetAnimFrame(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); +int16 ScriptFunctions::sfGetAnimFrameCount(int16 argc, int16 *argv) { + int16 frameCount = 0; + AnimationResource *anim = _vm->_res->getAnimation(argv[0]); + if (anim) { + frameCount = anim->getCount(); + _vm->_res->freeResource(anim); + } return frameCount; } -int16 ScriptFunctionsRtz::o1_PICWIDTH(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetPictureWidth(int16 argc, int16 *argv) { int16 width = 0; PictureResource *flex = _vm->_res->getPicture(argv[0]); if (flex) { @@ -694,7 +752,7 @@ int16 ScriptFunctionsRtz::o1_PICWIDTH(int16 argc, int16 *argv) { return width; } -int16 ScriptFunctionsRtz::o1_PICHEIGHT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetPictureHeight(int16 argc, int16 *argv) { int16 height = 0; PictureResource *flex = _vm->_res->getPicture(argv[0]); if (flex) { @@ -704,17 +762,16 @@ int16 ScriptFunctionsRtz::o1_PICHEIGHT(int16 argc, int16 *argv) { return height; } -int16 ScriptFunctionsRtz::o1_SOUNDRATE(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSoundRate(int16 argc, int16 *argv) { _vm->_soundRate = argv[0]; return 1; } -int16 ScriptFunctionsRtz::o1_DRAWANIMPIC(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_DRAWANIMPIC"); - return 0; +int16 ScriptFunctions::sfDrawAnimPic(int16 argc, int16 *argv) { + return _vm->_screen->drawAnimPic(argv[5], argv[4], argv[3], argv[2], argv[1], argv[0]); } -int16 ScriptFunctionsRtz::o1_LOADANIM(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadAnim(int16 argc, int16 *argv) { AnimationResource *anim = _vm->_res->getAnimation(argv[0]); if (anim) { _vm->_res->freeResource(anim); @@ -723,12 +780,13 @@ int16 ScriptFunctionsRtz::o1_LOADANIM(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_READTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_READTEXT"); +int16 ScriptFunctions::sfReadText(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfReadText"); return 0; } -int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfReadMenu(int16 argc, int16 *argv) { int16 objectIndex = argv[2]; int16 menuIndex = argv[1]; int16 textIndex = argv[0]; @@ -737,16 +795,17 @@ int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) { if (menu) { const char *text = menu->getString(textIndex); debug(4, "objectIndex = %04X; text = %s\n", objectIndex, text); - Object *obj = _vm->_dat->getObject(objectIndex); - obj->setString(text); + _vm->_dat->setObjectString(objectIndex, text); _vm->_res->freeResource(menu); if (text) length = strlen(text); + } else { + _vm->_dat->setObjectString(objectIndex, ""); } return length; } -int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfDrawMenu(int16 argc, int16 *argv) { int16 menuIndex = argv[1]; int16 textIndex = argv[0]; MenuResource *menu = _vm->_res->getMenu(menuIndex); @@ -759,7 +818,7 @@ int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) { return 0; } -int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetMenuCount(int16 argc, int16 *argv) { int16 menuIndex = argv[0]; int16 count = 0; MenuResource *menu = _vm->_res->getMenu(menuIndex); @@ -770,7 +829,7 @@ int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) { return count; } -int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSaveGame(int16 argc, int16 *argv) { int16 saveNum = argv[2]; int16 descObjectIndex = argv[1]; @@ -779,18 +838,13 @@ int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) { if (saveNum > 999) return 6; - Object *obj = _vm->_dat->getObject(descObjectIndex); - const char *description = obj->getString(); - - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - return _vm->_dat->savegame(filename, description, version); + const char *description = _vm->_dat->getObjectString(descObjectIndex); + Common::String filename = _vm->getSavegameFilename(saveNum); + return _vm->_dat->savegame(filename.c_str(), description, version); } -int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfLoadGame(int16 argc, int16 *argv) { int16 saveNum = argv[1]; int16 version = argv[0]; @@ -798,15 +852,12 @@ int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) { if (saveNum > 999) return 1; - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - return _vm->_dat->loadgame(filename, version); + Common::String filename = _vm->getSavegameFilename(saveNum); + return _vm->_dat->loadgame(filename.c_str(), version); } -int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetGameDescription(int16 argc, int16 *argv) { int16 descObjectIndex = argv[2]; int16 saveNum = argv[1]; @@ -816,50 +867,51 @@ int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) { if (saveNum > 999) return 1; - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - Object *obj = _vm->_dat->getObject(descObjectIndex); + Common::String filename = _vm->getSavegameFilename(saveNum); - if (_vm->_dat->getSavegameDescription(filename, description)) { - obj->setString(description.c_str()); + if (_vm->_dat->getSavegameDescription(filename.c_str(), description)) { + _vm->_dat->setObjectString(descObjectIndex, description.c_str()); return 0; } else { - obj->setString(""); + _vm->_dat->setObjectString(descObjectIndex, ""); return 1; } } -int16 ScriptFunctionsRtz::o1_SHAKESCREEN(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SHAKESCREEN"); +int16 ScriptFunctions::sfShakeScreen(int16 argc, int16 *argv) { + // TODO: Used in RTZ + warning("Unimplemented opcode: sfShakeScreen"); return 0; } -int16 ScriptFunctionsRtz::o1_PLACEMENU(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLACEMENU"); +int16 ScriptFunctions::sfPlaceMenu(int16 argc, int16 *argv) { + // Never used in LGOP2, RTZ, Manhole:NE + warning("Unimplemented opcode: sfPlaceMenu"); return 0; } -int16 ScriptFunctionsRtz::o1_SETVOLUME(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfSetSoundVolume(int16 argc, int16 *argv) { _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, argv[0] * 25); _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, argv[0] * 25); return 0; } -int16 ScriptFunctionsRtz::o1_WHATSYNTH(int16 argc, int16 *argv) { +int16 ScriptFunctions::sfGetSynthType(int16 argc, int16 *argv) { // 0 = Default // 1 = PCSPKR // 2 = SBFM/ADLIB // 3 = ADLIBG // 4 = MT32MPU - warning("Unimplemented opcode: o1_WHATSYNTH"); + warning("Unimplemented opcode: sfGetSynthType"); return 0; } -int16 ScriptFunctionsRtz::o1_SLOWSYSTEM(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SLOWSYSTEM"); +int16 ScriptFunctions::sfIsSlowSystem(int16 argc, int16 *argv) { + //warning("Unimplemented opcode: sfIsSlowSystem"); + // NOTE: In the original engine this value is set via a command-line parameter + // I don't think it's needed here + // One could maybe think about returning 1 here on actually slower systems. return 0; } diff --git a/engines/made/scriptfuncs.h b/engines/made/scriptfuncs.h index 7e826a9f5e..9879556c3f 100644 --- a/engines/made/scriptfuncs.h +++ b/engines/made/scriptfuncs.h @@ -31,6 +31,8 @@ #include "common/func.h" #include "common/stream.h" +#include "made/resource.h" + namespace Made { class MadeEngine; @@ -40,260 +42,133 @@ typedef Common::Functor2<int16, int16*, int16> ExternalFunc; class ScriptFunctions { public: ScriptFunctions(MadeEngine *vm) : _vm(vm) {} - virtual ~ScriptFunctions() {} + virtual ~ScriptFunctions() { + for (uint i = 0; i < _externalFuncs.size(); ++i) + delete _externalFuncs[i]; + } int16 callFunction(uint16 index, int16 argc, int16 *argv) { - if (index >= _externalFuncs.size()) { - // TODO: ERROR! - return 0; - } + if (index >= _externalFuncs.size()) + error("ScriptFunctions::callFunction() Invalid function index %d", index); + debug(4, "%s", _externalFuncNames[index]); return (*_externalFuncs[index])(argc, argv); } - virtual void setupExternalsTable() = 0; + void setupExternalsTable(); + const char* getFuncName(int index) { return _externalFuncNames[index]; } + int getCount() const { return _externalFuncs.size(); } protected: MadeEngine *_vm; Audio::SoundHandle _audioStreamHandle; Audio::SoundHandle _voiceStreamHandle; Common::Array<const ExternalFunc*> _externalFuncs; + Common::Array<const char *> _externalFuncNames; + GenericResource *_musicRes; + + int16 sfSystemCall(int16 argc, int16 *argv); + int16 sfInitGraf(int16 argc, int16 *argv); + int16 sfRestoreGraf(int16 argc, int16 *argv); + int16 sfDrawPicture(int16 argc, int16 *argv); + int16 sfClearScreen(int16 argc, int16 *argv); + int16 sfShowPage(int16 argc, int16 *argv); + int16 sfPollEvent(int16 argc, int16 *argv); + int16 sfGetMouseX(int16 argc, int16 *argv); + int16 sfGetMouseY(int16 argc, int16 *argv); + int16 sfGetKey(int16 argc, int16 *argv); + int16 sfSetVisualEffect(int16 argc, int16 *argv); + int16 sfPlaySound(int16 argc, int16 *argv); + int16 sfPlayMusic(int16 argc, int16 *argv); + int16 sfStopMusic(int16 argc, int16 *argv); + int16 sfIsMusicPlaying(int16 argc, int16 *argv); + int16 sfSetTextPos(int16 argc, int16 *argv); + int16 sfFlashScreen(int16 argc, int16 *argv); + int16 sfPlayNote(int16 argc, int16 *argv); + int16 sfStopNote(int16 argc, int16 *argv); + int16 sfPlayTele(int16 argc, int16 *argv); + int16 sfStopTele(int16 argc, int16 *argv); + int16 sfHideMouseCursor(int16 argc, int16 *argv); + int16 sfShowMouseCursor(int16 argc, int16 *argv); + int16 sfGetMusicBeat(int16 argc, int16 *argv); + int16 sfSetScreenLock(int16 argc, int16 *argv); + int16 sfAddSprite(int16 argc, int16 *argv); + int16 sfFreeAnim(int16 argc, int16 *argv); + int16 sfDrawSprite(int16 argc, int16 *argv); + int16 sfEraseSprites(int16 argc, int16 *argv); + int16 sfUpdateSprites(int16 argc, int16 *argv); + int16 sfGetTimer(int16 argc, int16 *argv); + int16 sfSetTimer(int16 argc, int16 *argv); + int16 sfResetTimer(int16 argc, int16 *argv); + int16 sfAllocTimer(int16 argc, int16 *argv); + int16 sfFreeTimer(int16 argc, int16 *argv); + int16 sfSetPaletteLock(int16 argc, int16 *argv); + int16 sfSetFont(int16 argc, int16 *argv); + int16 sfDrawText(int16 argc, int16 *argv); + int16 sfHomeText(int16 argc, int16 *argv); + int16 sfSetTextRect(int16 argc, int16 *argv); + int16 sfSetTextXY(int16 argc, int16 *argv); + int16 sfSetFontDropShadow(int16 argc, int16 *argv); + int16 sfSetFontColor(int16 argc, int16 *argv); + int16 sfSetFontOutline(int16 argc, int16 *argv); + int16 sfLoadMouseCursor(int16 argc, int16 *argv); + int16 sfSetSpriteGround(int16 argc, int16 *argv); + int16 sfLoadResText(int16 argc, int16 *argv); + int16 sfSetClipArea(int16 argc, int16 *argv); + int16 sfSetSpriteClip(int16 argc, int16 *argv); + int16 sfAddScreenMask(int16 argc, int16 *argv); + int16 sfSetSpriteMask(int16 argc, int16 *argv); + int16 sfSoundPlaying(int16 argc, int16 *argv); + int16 sfStopSound(int16 argc, int16 *argv); + int16 sfPlayVoice(int16 argc, int16 *argv); + int16 sfPlayCd(int16 argc, int16 *argv); + int16 sfStopCd(int16 argc, int16 *argv); + int16 sfGetCdStatus(int16 argc, int16 *argv); + int16 sfGetCdTime(int16 argc, int16 *argv); + int16 sfPlayCdSegment(int16 argc, int16 *argv); + int16 sfPrintf(int16 argc, int16 *argv); + int16 sfClearMono(int16 argc, int16 *argv); + int16 sfGetSoundEnergy(int16 argc, int16 *argv); + int16 sfClearText(int16 argc, int16 *argv); + int16 sfAnimText(int16 argc, int16 *argv); + int16 sfGetTextWidth(int16 argc, int16 *argv); + int16 sfPlayMovie(int16 argc, int16 *argv); + int16 sfLoadSound(int16 argc, int16 *argv); + int16 sfLoadMusic(int16 argc, int16 *argv); + int16 sfLoadPicture(int16 argc, int16 *argv); + int16 sfSetMusicVolume(int16 argc, int16 *argv); + int16 sfRestartEvents(int16 argc, int16 *argv); + int16 sfPlaceSprite(int16 argc, int16 *argv); + int16 sfPlaceText(int16 argc, int16 *argv); + int16 sfDeleteChannel(int16 argc, int16 *argv); + int16 sfGetChannelType(int16 argc, int16 *argv); + int16 sfSetChannelState(int16 argc, int16 *argv); + int16 sfSetChannelLocation(int16 argc, int16 *argv); + int16 sfSetChannelContent(int16 argc, int16 *argv); + int16 sfSetExcludeArea(int16 argc, int16 *argv); + int16 sfSetSpriteExclude(int16 argc, int16 *argv); + int16 sfGetChannelState(int16 argc, int16 *argv); + int16 sfPlaceAnim(int16 argc, int16 *argv); + int16 sfSetAnimFrame(int16 argc, int16 *argv); + int16 sfGetAnimFrame(int16 argc, int16 *argv); + int16 sfGetAnimFrameCount(int16 argc, int16 *argv); + int16 sfGetPictureWidth(int16 argc, int16 *argv); + int16 sfGetPictureHeight(int16 argc, int16 *argv); + int16 sfSetSoundRate(int16 argc, int16 *argv); + int16 sfDrawAnimPic(int16 argc, int16 *argv); + int16 sfLoadAnim(int16 argc, int16 *argv); + int16 sfReadText(int16 argc, int16 *argv); + int16 sfReadMenu(int16 argc, int16 *argv); + int16 sfDrawMenu(int16 argc, int16 *argv); + int16 sfGetMenuCount(int16 argc, int16 *argv); + int16 sfSaveGame(int16 argc, int16 *argv); + int16 sfLoadGame(int16 argc, int16 *argv); + int16 sfGetGameDescription(int16 argc, int16 *argv); + int16 sfShakeScreen(int16 argc, int16 *argv); + int16 sfPlaceMenu(int16 argc, int16 *argv); + int16 sfSetSoundVolume(int16 argc, int16 *argv); + int16 sfGetSynthType(int16 argc, int16 *argv); + int16 sfIsSlowSystem(int16 argc, int16 *argv); }; -class ScriptFunctionsLgop2 : public ScriptFunctions { -public: - ScriptFunctionsLgop2(MadeEngine *vm) : ScriptFunctions(vm) {} - ~ScriptFunctionsLgop2() {} - 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_ADDMASK(int16 argc, int16 *argv); - int16 o1_SETMASK(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); -}; - -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); -}; - -class ScriptFunctionsMhne : public ScriptFunctions { -public: - ScriptFunctionsMhne(MadeEngine *vm) : ScriptFunctions(vm) {} - ~ScriptFunctionsMhne() {} - 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_ADDMASK(int16 argc, int16 *argv); - int16 o1_SETMASK(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); -}; - } // End of namespace Made #endif /* MADE_H */ diff --git a/engines/made/scriptfuncs_lgop2.cpp b/engines/made/scriptfuncs_lgop2.cpp deleted file mode 100644 index 579492a39e..0000000000 --- a/engines/made/scriptfuncs_lgop2.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* 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" -#include "made/music.h" - -namespace Made { - -/* ScriptFunctionsLgop2 */ - -typedef Common::Functor2Mem<int16, int16*, int16, ScriptFunctionsLgop2> ExternalFuncLgop2; -#define External(x) ExternalFuncLgop2(this, &ScriptFunctionsLgop2::x) -void ScriptFunctionsLgop2::setupExternalsTable() { - static const ExternalFuncLgop2 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_ADDMASK), - External(o1_SETMASK), - External(o1_ISSND), - External(o1_STOPSND), - External(o1_PLAYVOICE) - }; - - for (int i = 0; i < ARRAYSIZE(externalsTable); ++i) - _externalFuncs.push_back(&externalsTable[i]); - -} -#undef External - -int16 ScriptFunctionsLgop2::o1_SYSTEM(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsLgop2::o1_INITGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsLgop2::o1_RESTOREGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsLgop2::o1_DRAWPIC(int16 argc, int16 *argv) { - return _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsLgop2::o1_CLS(int16 argc, int16 *argv) { - _vm->_screen->clearScreen(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_SHOWPAGE(int16 argc, int16 *argv) { - _vm->_screen->show(); - return 0; -} - -int16 ScriptFunctionsLgop2::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_LBUTTONUP: - eventNum = 2; // TODO: Is this correct? - break; - */ - - case Common::EVENT_RBUTTONDOWN: - eventNum = 3; - break; - - /* - case Common::EVENT_RBUTTONUP: - eventNum = 4; // TODO: Is this correct? - break; - */ - - case Common::EVENT_KEYDOWN: - _vm->_eventKey = event.kbd.ascii; - eventNum = 5; - break; - - case Common::EVENT_QUIT: - // TODO: Exit more gracefully. - g_system->quit(); - break; - - default: - break; - - } - } - - _vm->_system->updateScreen(); - - return eventNum; -} - -int16 ScriptFunctionsLgop2::o1_EVENTX(int16 argc, int16 *argv) { - return _vm->_eventMouseX; -} - -int16 ScriptFunctionsLgop2::o1_EVENTY(int16 argc, int16 *argv) { - return _vm->_eventMouseY; -} - -int16 ScriptFunctionsLgop2::o1_EVENTKEY(int16 argc, int16 *argv) { - return _vm->_eventKey; -} - -int16 ScriptFunctionsLgop2::o1_VISUALFX(int16 argc, int16 *argv) { - _vm->_screen->setVisualEffectNum(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYSND(int16 argc, int16 *argv) { - int soundNum = argv[0]; - bool loop = false; - - if (argc > 1) { - soundNum = argv[1]; - loop = (argv[0] == 1); - } - - if (soundNum > 0) { - if (!_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, loop)); - } - } - - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYMUS(int16 argc, int16 *argv) { - /* - - Disabled for now since MIDI player doesn't support all commands - which results in strange behavior. - - int16 musicNum = argv[0]; - if (musicNum > 0) { - GenericResource *midi = _vm->_res->getMidi(musicNum); - _vm->_music->playSMF(midi); - _vm->_res->freeResource(midi); - } - */ - return 0; -} - -int16 ScriptFunctionsLgop2::o1_STOPMUS(int16 argc, int16 *argv) { - _vm->_music->stop(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ISMUS(int16 argc, int16 *argv) { - if (_vm->_music->isPlaying()) - return 1; - else - return 0; -} - -int16 ScriptFunctionsLgop2::o1_TEXTPOS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTPOS"); - // This seems to be some kind of low-level opcode. - // The original engine calls int 10h to set the VGA cursor position. - return 0; -} - -int16 ScriptFunctionsLgop2::o1_FLASH(int16 argc, int16 *argv) { - _vm->_screen->flash(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYNOTE"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_STOPNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPNOTE"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYTELE"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_STOPTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPTELE"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_HIDECURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(false); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_SHOWCURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(true); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_MUSICBEAT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICBEAT"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_SCREENLOCK(int16 argc, int16 *argv) { - _vm->_screen->setScreenLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ADDSPRITE(int16 argc, int16 *argv) { - //_vm->_screen->drawSprite(argv[2], argv[1], argv[0]); - return argv[2]; -} - -int16 ScriptFunctionsLgop2::o1_FREEANIM(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_DRAWSPRITE(int16 argc, int16 *argv) { - return _vm->_screen->drawSprite(argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsLgop2::o1_ERASESPRITES(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_UPDATESPRITES(int16 argc, int16 *argv) { - _vm->_screen->updateSprites(); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_GETTIMER(int16 argc, int16 *argv) { - return _vm->getTimer(argv[0]); -} - -int16 ScriptFunctionsLgop2::o1_SETTIMER(int16 argc, int16 *argv) { - _vm->setTimer(argv[1], argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_RESETTIMER(int16 argc, int16 *argv) { - _vm->resetTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ALLOCTIMER(int16 argc, int16 *argv) { - int16 timerNum = _vm->allocTimer(); - return timerNum; -} - -int16 ScriptFunctionsLgop2::o1_FREETIMER(int16 argc, int16 *argv) { - _vm->freeTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PALETTELOCK(int16 argc, int16 *argv) { - _vm->_screen->setPaletteLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_FONT(int16 argc, int16 *argv) { - _vm->_screen->setFont(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_DRAWTEXT(int16 argc, int16 *argv) { - // TODO: Needs vsprintf to get the correct text - const char *text = _vm->_dat->getString(argv[argc - 1]); - _vm->_screen->printText(text); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_HOMETEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_HOMETEXT"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_TEXTRECT(int16 argc, int16 *argv) { - int16 x1 = CLIP<int16>(argv[4], 1, 318); - int16 y1 = CLIP<int16>(argv[3], 1, 198); - int16 x2 = CLIP<int16>(argv[2], 1, 318); - int16 y2 = CLIP<int16>(argv[1], 1, 198); - //int16 textValue = argv[0]; - // TODO: textValue - _vm->_screen->setTextRect(Common::Rect(x1, y1, x2, y2)); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_TEXTXY(int16 argc, int16 *argv) { - int16 x = CLIP<int16>(argv[1], 1, 318); - int16 y = CLIP<int16>(argv[0], 1, 198); - _vm->_screen->setTextXY(x, y); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_DROPSHADOW(int16 argc, int16 *argv) { - // if the drop shadow color is -1, then text drop shadow is disabled - // when font drop shadow is enabled, outline is disabled - _vm->_screen->setDropShadowColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_TEXTCOLOR(int16 argc, int16 *argv) { - _vm->_screen->setTextColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_OUTLINE(int16 argc, int16 *argv) { - // if the outline color is -1, then text outline is disabled - // when font outline is enabled, drop shadow is disabled - _vm->_screen->setOutlineColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::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 ScriptFunctionsLgop2::o1_SETGROUND(int16 argc, int16 *argv) { - _vm->_screen->setGround(argv[0]); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_RESTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTEXT"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ADDMASK(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ADDMASK"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_SETMASK(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETMASK"); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_ISSND(int16 argc, int16 *argv) { - if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) - return 1; - else - return 0; -} - -int16 ScriptFunctionsLgop2::o1_STOPSND(int16 argc, int16 *argv) { - _vm->_mixer->stopHandle(_audioStreamHandle); - return 0; -} - -int16 ScriptFunctionsLgop2::o1_PLAYVOICE(int16 argc, int16 *argv) { - if (argv[0] > 0) { - _vm->_mixer->stopHandle(_audioStreamHandle); - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(argv[0])->getAudioStream(_vm->_soundRate, false)); - } - return 0; -} - -} // End of namespace Made diff --git a/engines/made/scriptfuncs_mhne.cpp b/engines/made/scriptfuncs_mhne.cpp deleted file mode 100644 index 65e9c6e070..0000000000 --- a/engines/made/scriptfuncs_mhne.cpp +++ /dev/null @@ -1,494 +0,0 @@ -/* 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" -#include "made/music.h" - -namespace Made { - -/* ScriptFunctionsMhne */ - -typedef Common::Functor2Mem<int16, int16*, int16, ScriptFunctionsMhne> ExternalFuncMhne; -#define External(x) ExternalFuncMhne(this, &ScriptFunctionsMhne::x) -void ScriptFunctionsMhne::setupExternalsTable() { - static const ExternalFuncMhne 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_ADDMASK), - External(o1_SETMASK), - External(o1_ISSND), - External(o1_STOPSND), - External(o1_PLAYVOICE), - External(o1_CDPLAY), - External(o1_STOPCD), - External(o1_CDSTATUS), - External(o1_CDTIME), - External(o1_CDPLAYSEG), - }; - - for (int i = 0; i < ARRAYSIZE(externalsTable); ++i) - _externalFuncs.push_back(&externalsTable[i]); - -} -#undef External - -int16 ScriptFunctionsMhne::o1_SYSTEM(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsMhne::o1_INITGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsMhne::o1_RESTOREGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsMhne::o1_DRAWPIC(int16 argc, int16 *argv) { - return _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsMhne::o1_CLS(int16 argc, int16 *argv) { - _vm->_screen->clearScreen(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_SHOWPAGE(int16 argc, int16 *argv) { - _vm->_screen->show(); - return 0; -} - -int16 ScriptFunctionsMhne::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_LBUTTONUP: - eventNum = 2; // TODO: Is this correct? - break; - */ - - case Common::EVENT_RBUTTONDOWN: - eventNum = 3; - break; - - /* - case Common::EVENT_RBUTTONUP: - eventNum = 4; // TODO: Is this correct? - break; - */ - - case Common::EVENT_KEYDOWN: - _vm->_eventKey = event.kbd.ascii; - eventNum = 5; - break; - - case Common::EVENT_QUIT: - // TODO: Exit more gracefully. - g_system->quit(); - break; - - default: - break; - - } - } - - _vm->_system->updateScreen(); - - return eventNum; -} - -int16 ScriptFunctionsMhne::o1_EVENTX(int16 argc, int16 *argv) { - return _vm->_eventMouseX; -} - -int16 ScriptFunctionsMhne::o1_EVENTY(int16 argc, int16 *argv) { - return _vm->_eventMouseY; -} - -int16 ScriptFunctionsMhne::o1_EVENTKEY(int16 argc, int16 *argv) { - return _vm->_eventKey; -} - -int16 ScriptFunctionsMhne::o1_VISUALFX(int16 argc, int16 *argv) { - _vm->_screen->setVisualEffectNum(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYSND(int16 argc, int16 *argv) { - int soundNum = argv[0]; - bool loop = false; - - if (argc > 1) { - soundNum = argv[1]; - loop = (argv[0] == 1); - } - - if (soundNum > 0) { - if (!_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, loop)); - } - } - - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYMUS(int16 argc, int16 *argv) { - int16 musicNum = argv[0]; - if (musicNum > 0) { - GenericResource *xmidi = _vm->_res->getXmidi(musicNum); - _vm->_music->playXMIDI(xmidi); - _vm->_res->freeResource(xmidi); - } - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPMUS(int16 argc, int16 *argv) { - _vm->_music->stop(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ISMUS(int16 argc, int16 *argv) { - if (_vm->_music->isPlaying()) - return 1; - else - return 0; -} - -int16 ScriptFunctionsMhne::o1_TEXTPOS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTPOS"); - // This seems to be some kind of low-level opcode. - // The original engine calls int 10h to set the VGA cursor position. - return 0; -} - -int16 ScriptFunctionsMhne::o1_FLASH(int16 argc, int16 *argv) { - _vm->_screen->flash(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYNOTE"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPNOTE"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYTELE"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPTELE"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_HIDECURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(false); - return 0; -} - -int16 ScriptFunctionsMhne::o1_SHOWCURS(int16 argc, int16 *argv) { - _vm->_system->showMouse(true); - return 0; -} - -int16 ScriptFunctionsMhne::o1_MUSICBEAT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MUSICBEAT"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_SCREENLOCK(int16 argc, int16 *argv) { - _vm->_screen->setScreenLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ADDSPRITE(int16 argc, int16 *argv) { - //_vm->_screen->drawSprite(argv[2], argv[1], argv[0]); - return argv[2]; -} - -int16 ScriptFunctionsMhne::o1_FREEANIM(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_DRAWSPRITE(int16 argc, int16 *argv) { - return _vm->_screen->drawSprite(argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsMhne::o1_ERASESPRITES(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_UPDATESPRITES(int16 argc, int16 *argv) { - _vm->_screen->updateSprites(); - return 0; -} - -int16 ScriptFunctionsMhne::o1_GETTIMER(int16 argc, int16 *argv) { - return _vm->getTimer(argv[0]); -} - -int16 ScriptFunctionsMhne::o1_SETTIMER(int16 argc, int16 *argv) { - _vm->setTimer(argv[1], argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_RESETTIMER(int16 argc, int16 *argv) { - _vm->resetTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ALLOCTIMER(int16 argc, int16 *argv) { - int16 timerNum = _vm->allocTimer(); - return timerNum; -} - -int16 ScriptFunctionsMhne::o1_FREETIMER(int16 argc, int16 *argv) { - _vm->freeTimer(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PALETTELOCK(int16 argc, int16 *argv) { - _vm->_screen->setPaletteLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsMhne::o1_FONT(int16 argc, int16 *argv) { - _vm->_screen->setFont(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_DRAWTEXT(int16 argc, int16 *argv) { - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); - _vm->_screen->printText(text); - return 0; -} - -int16 ScriptFunctionsMhne::o1_HOMETEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_HOMETEXT"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_TEXTRECT(int16 argc, int16 *argv) { - int16 x1 = CLIP<int16>(argv[4], 1, 318); - int16 y1 = CLIP<int16>(argv[3], 1, 198); - int16 x2 = CLIP<int16>(argv[2], 1, 318); - int16 y2 = CLIP<int16>(argv[1], 1, 198); - //int16 textValue = argv[0]; - // TODO: textValue - _vm->_screen->setTextRect(Common::Rect(x1, y1, x2, y2)); - return 0; -} - -int16 ScriptFunctionsMhne::o1_TEXTXY(int16 argc, int16 *argv) { - int16 x = CLIP<int16>(argv[1], 1, 318); - int16 y = CLIP<int16>(argv[0], 1, 198); - _vm->_screen->setTextXY(x, y); - return 0; -} - -int16 ScriptFunctionsMhne::o1_DROPSHADOW(int16 argc, int16 *argv) { - // if the drop shadow color is -1, then text drop shadow is disabled - // when font drop shadow is enabled, outline is disabled - _vm->_screen->setDropShadowColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_TEXTCOLOR(int16 argc, int16 *argv) { - _vm->_screen->setTextColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_OUTLINE(int16 argc, int16 *argv) { - // if the outline color is -1, then text outline is disabled - // when font outline is enabled, drop shadow is disabled - _vm->_screen->setOutlineColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::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 ScriptFunctionsMhne::o1_SETGROUND(int16 argc, int16 *argv) { - _vm->_screen->setGround(argv[0]); - return 0; -} - -int16 ScriptFunctionsMhne::o1_RESTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTEXT"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ADDMASK(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ADDMASK"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_SETMASK(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETMASK"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_ISSND(int16 argc, int16 *argv) { - if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) - return 1; - else - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPSND(int16 argc, int16 *argv) { - _vm->_mixer->stopHandle(_audioStreamHandle); - return 0; -} - -int16 ScriptFunctionsMhne::o1_PLAYVOICE(int16 argc, int16 *argv) { - if (argv[0] > 0) { - _vm->_mixer->stopHandle(_audioStreamHandle); - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(argv[0])->getAudioStream(_vm->_soundRate, false)); - } - return 0; -} - -int16 ScriptFunctionsMhne::o1_CDPLAY(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDPLAY"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_STOPCD(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPCD"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_CDSTATUS(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDSTATUS"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_CDTIME(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDTIME"); - return 0; -} - -int16 ScriptFunctionsMhne::o1_CDPLAYSEG(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CDPLAYSEG"); - return 0; -} - -} // End of namespace Made diff --git a/engines/made/scriptfuncs_rtz.cpp b/engines/made/scriptfuncs_rtz.cpp deleted file mode 100644 index 1186a88de8..0000000000 --- a/engines/made/scriptfuncs_rtz.cpp +++ /dev/null @@ -1,864 +0,0 @@ -/* 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" -#include "made/music.h" - -namespace Made { - -/* ScriptFunctionsRtz */ - -typedef Common::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) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsRtz::o1_INITGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsRtz::o1_RESTOREGRAF(int16 argc, int16 *argv) { - // This opcode is empty. - return 0; -} - -int16 ScriptFunctionsRtz::o1_DRAWPIC(int16 argc, int16 *argv) { - return _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]); -} - -int16 ScriptFunctionsRtz::o1_CLS(int16 argc, int16 *argv) { - _vm->_screen->clearScreen(); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SHOWPAGE(int16 argc, int16 *argv) { - _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_LBUTTONUP: - eventNum = 2; // TODO: Is this correct? - break; - */ - - case Common::EVENT_RBUTTONDOWN: - eventNum = 3; - break; - - /* - case Common::EVENT_RBUTTONUP: - eventNum = 4; // TODO: Is this correct? - break; - */ - - case Common::EVENT_KEYDOWN: - _vm->_eventKey = event.kbd.ascii; - eventNum = 5; - break; - - case Common::EVENT_QUIT: - // TODO: Exit more gracefully. - g_system->quit(); - break; - - default: - break; - - } - } - - _vm->_system->updateScreen(); - - 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 _vm->_eventKey; -} - -int16 ScriptFunctionsRtz::o1_VISUALFX(int16 argc, int16 *argv) { - _vm->_screen->setVisualEffectNum(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYSND(int16 argc, int16 *argv) { - int soundNum = argv[0]; - bool loop = false; - - if (argc > 1) { - soundNum = argv[1]; - loop = (argv[0] == 1); - } - - if (soundNum > 0) { - if (!_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) { - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(soundNum)->getAudioStream(_vm->_soundRate, loop)); - } - } - - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYMUS(int16 argc, int16 *argv) { - int16 musicNum = argv[0]; - if (musicNum > 0) { - GenericResource *xmidi = _vm->_res->getXmidi(musicNum); - _vm->_music->playXMIDI(xmidi); - _vm->_res->freeResource(xmidi); - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPMUS(int16 argc, int16 *argv) { - _vm->_music->stop(); - return 0; -} - -int16 ScriptFunctionsRtz::o1_ISMUS(int16 argc, int16 *argv) { - if (_vm->_music->isPlaying()) - return 1; - else - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTPOS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTPOS"); - // This seems to be some kind of low-level opcode. - // The original engine calls int 10h to set the VGA cursor position. - return 0; -} - -int16 ScriptFunctionsRtz::o1_FLASH(int16 argc, int16 *argv) { - _vm->_screen->flash(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYNOTE"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPNOTE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPNOTE"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLAYTELE"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPTELE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPTELE"); - 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) { - warning("Unimplemented opcode: o1_MUSICBEAT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SCREENLOCK(int16 argc, int16 *argv) { - _vm->_screen->setScreenLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsRtz::o1_ADDSPRITE(int16 argc, int16 *argv) { - //_vm->_screen->drawSprite(argv[2], argv[1], argv[0]); - return 0;//argv[2]; -} - -int16 ScriptFunctionsRtz::o1_FREEANIM(int16 argc, int16 *argv) { - _vm->_screen->clearChannels(); - return 0; -} - -int16 ScriptFunctionsRtz::o1_DRAWSPRITE(int16 argc, int16 *argv) { - return _vm->_screen->drawSprite(argv[2], argv[1], argv[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) { - _vm->setTimer(argv[1], argv[0]); - 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) { - _vm->_screen->setPaletteLock(argv[0] != 0); - return 0; -} - -int16 ScriptFunctionsRtz::o1_FONT(int16 argc, int16 *argv) { - _vm->_screen->setFont(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_DRAWTEXT(int16 argc, int16 *argv) { - // TODO: Needs vsprintf to get the correct text - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); - _vm->_screen->printText(text); - return 0; -} - -int16 ScriptFunctionsRtz::o1_HOMETEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_HOMETEXT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) { - int16 x1 = CLIP<int16>(argv[4], 1, 318); - int16 y1 = CLIP<int16>(argv[3], 1, 198); - int16 x2 = CLIP<int16>(argv[2], 1, 318); - int16 y2 = CLIP<int16>(argv[1], 1, 198); - //int16 textValue = argv[0]; - // TODO: textValue - _vm->_screen->setTextRect(Common::Rect(x1, y1, x2, y2)); - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTXY(int16 argc, int16 *argv) { - int16 x = CLIP<int16>(argv[1], 1, 318); - int16 y = CLIP<int16>(argv[0], 1, 198); - _vm->_screen->setTextXY(x, y); - return 0; -} - -int16 ScriptFunctionsRtz::o1_DROPSHADOW(int16 argc, int16 *argv) { - // if the drop shadow color is -1, then text drop shadow is disabled - // when font drop shadow is enabled, outline is disabled - _vm->_screen->setDropShadowColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTCOLOR(int16 argc, int16 *argv) { - _vm->_screen->setTextColor(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_OUTLINE(int16 argc, int16 *argv) { - // if the outline color is -1, then text outline is disabled - // when font outline is enabled, drop shadow is disabled - _vm->_screen->setOutlineColor(argv[0]); - 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) { - _vm->_screen->setGround(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_RESTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTEXT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CLIPAREA(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CLIPAREA"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETCLIP(int16 argc, int16 *argv) { - _vm->_screen->setClip(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_ISSND(int16 argc, int16 *argv) { - if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle)) - return 1; - else - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPSND(int16 argc, int16 *argv) { - _vm->_mixer->stopHandle(_audioStreamHandle); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLAYVOICE(int16 argc, int16 *argv) { - if (argv[0] > 0) { - _vm->_mixer->stopHandle(_audioStreamHandle); - _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, - _vm->_res->getSound(argv[0])->getAudioStream(_vm->_soundRate, false)); - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_CDPLAY(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDPLAY"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_STOPCD(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_STOPCD"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CDSTATUS(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDSTATUS"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CDTIME(int16 argc, int16 *argv) { - // This one is called loads of times, so it has been commented out to reduce spam - //warning("Unimplemented opcode: o1_CDTIME"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CDPLAYSEG(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CDPLAYSEG"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PRINTF(int16 argc, int16 *argv) { - Object *obj = _vm->_dat->getObject(argv[argc - 1]); - const char *text = obj->getString(); - debug(4, "--> text = %s", text); - return 0; -} - -int16 ScriptFunctionsRtz::o1_MONOCLS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_MONOCLS"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SNDENERGY(int16 argc, int16 *argv) { - // This is called while in-game voices are played - // Not sure what it's used for - // -> It's used to animate mouths when NPCs are talking - // Commented out to reduce spam - //warning("Unimplemented opcode: o1_SNDENERGY"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_CLEARTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_CLEARTEXT"); - return 1; -} - -int16 ScriptFunctionsRtz::o1_ANIMTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_ANIMTEXT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_TEXTWIDTH(int16 argc, int16 *argv) { - int16 width = 0; - if (argv[1] > 0) { - Object *obj = _vm->_dat->getObject(argv[1]); - const char *text = obj->getString(); - width = _vm->_screen->getTextWidth(argv[0], text); - } - return width; -} - -int16 ScriptFunctionsRtz::o1_PLAYMOVIE(int16 argc, int16 *argv) { - const char *movieName = _vm->_dat->getObject(argv[1])->getString(); - _vm->_pmvPlayer->play(movieName); - return 0; -} - -int16 ScriptFunctionsRtz::o1_LOADSND(int16 argc, int16 *argv) { - SoundResource *sound = _vm->_res->getSound(argv[0]); - if (sound) { - _vm->_res->freeResource(sound); - return 1; - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_LOADMUS(int16 argc, int16 *argv) { - GenericResource *xmidi = _vm->_res->getXmidi(argv[0]); - if (xmidi) { - _vm->_res->freeResource(xmidi); - return 1; - } - 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) { - warning("Unimplemented opcode: o1_MUSICVOL"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_RESTARTEVENTS(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_RESTARTEVENTS"); - 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) { - return _vm->_screen->placeText(argv[6], argv[5], argv[4], argv[3], argv[2], argv[1], argv[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) { - warning("Unimplemented opcode: o1_SETLOCATION"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETCONTENT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SETCONTENT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_EXCLUDEAREA(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_EXCLUDEAREA"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETEXCLUDE(int16 argc, int16 *argv) { - _vm->_screen->setExclude(argv[0]); - return 0; -} - -int16 ScriptFunctionsRtz::o1_GETSTATE(int16 argc, int16 *argv) { - return _vm->_screen->getChannelState(argv[0]); -} - -int16 ScriptFunctionsRtz::o1_PLACEANIM(int16 argc, int16 *argv) { - return _vm->_screen->placeAnim(argv[4], argv[3], argv[2], argv[1], argv[0]); -} - -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) { - return _vm->_screen->getAnimFrameCount(argv[0]); -} - -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) { - _vm->_soundRate = argv[0]; - return 1; -} - -int16 ScriptFunctionsRtz::o1_DRAWANIMPIC(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_DRAWANIMPIC"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_LOADANIM(int16 argc, int16 *argv) { - AnimationResource *anim = _vm->_res->getAnimation(argv[0]); - if (anim) { - _vm->_res->freeResource(anim); - return 1; - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_READTEXT(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_READTEXT"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) { - int16 objectIndex = argv[2]; - int16 menuIndex = argv[1]; - int16 textIndex = argv[0]; - int16 length = 0; - MenuResource *menu = _vm->_res->getMenu(menuIndex); - if (menu) { - const char *text = menu->getString(textIndex); - debug(4, "objectIndex = %04X; text = %s\n", objectIndex, text); - Object *obj = _vm->_dat->getObject(objectIndex); - obj->setString(text); - _vm->_res->freeResource(menu); - if (text) - length = strlen(text); - } - return length; -} - -int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) { - int16 menuIndex = argv[1]; - int16 textIndex = argv[0]; - MenuResource *menu = _vm->_res->getMenu(menuIndex); - if (menu) { - const char *text = menu->getString(textIndex); - if (text) - _vm->_screen->printText(text); - _vm->_res->freeResource(menu); - } - return 0; -} - -int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) { - int16 menuIndex = argv[0]; - int16 count = 0; - MenuResource *menu = _vm->_res->getMenu(menuIndex); - if (menu) { - count = menu->getCount(); - _vm->_res->freeResource(menu); - } - return count; -} - -int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) { - - int16 saveNum = argv[2]; - int16 descObjectIndex = argv[1]; - int16 version = argv[0]; - - if (saveNum > 999) - return 6; - - Object *obj = _vm->_dat->getObject(descObjectIndex); - const char *description = obj->getString(); - - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - return _vm->_dat->savegame(filename, description, version); - -} - -int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) { - - int16 saveNum = argv[1]; - int16 version = argv[0]; - - if (saveNum > 999) - return 1; - - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - return _vm->_dat->loadgame(filename, version); - -} - -int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) { - - int16 descObjectIndex = argv[2]; - int16 saveNum = argv[1]; - /*int16 version = argv[0];*/ - Common::String description; - - if (saveNum > 999) - return 1; - - // TODO: Use better filename - char filename[256]; - snprintf(filename, 256, "rtz.%03d", saveNum); - - Object *obj = _vm->_dat->getObject(descObjectIndex); - - if (_vm->_dat->getSavegameDescription(filename, description)) { - obj->setString(description.c_str()); - return 0; - } else { - obj->setString(""); - return 1; - } - -} - -int16 ScriptFunctionsRtz::o1_SHAKESCREEN(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SHAKESCREEN"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_PLACEMENU(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_PLACEMENU"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SETVOLUME(int16 argc, int16 *argv) { - _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, argv[0] * 25); - _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, argv[0] * 25); - return 0; -} - -int16 ScriptFunctionsRtz::o1_WHATSYNTH(int16 argc, int16 *argv) { - // 0 = Default - // 1 = PCSPKR - // 2 = SBFM/ADLIB - // 3 = ADLIBG - // 4 = MT32MPU - warning("Unimplemented opcode: o1_WHATSYNTH"); - return 0; -} - -int16 ScriptFunctionsRtz::o1_SLOWSYSTEM(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_SLOWSYSTEM"); - return 0; -} - -} // End of namespace Made |