From 39e4a9b180d37f2fef108391d5f04a3c7e3b2ea0 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sat, 25 Aug 2007 20:34:10 +0000 Subject: Added an abstract base class for representing multiple-frames for animations. Changed user code to rely on the new interface. Cnv has been turned into an implementation of the new interface, and it is now known as a concrete class only to Disk and Font code for Nippon Safes. svn-id: r28734 --- engines/parallaction/dialogue.cpp | 4 +- engines/parallaction/disk.h | 27 +++-- engines/parallaction/disk_br.cpp | 94 +++++++++++++++- engines/parallaction/disk_ns.cpp | 12 +- engines/parallaction/exec_ns.cpp | 6 +- engines/parallaction/graphics.cpp | 15 ++- engines/parallaction/graphics.h | 32 +++++- engines/parallaction/inventory.cpp | 13 ++- engines/parallaction/inventory.h | 2 - engines/parallaction/objects.cpp | 12 +- engines/parallaction/objects.h | 4 +- engines/parallaction/parallaction.cpp | 182 +------------------------------ engines/parallaction/parallaction.h | 16 ++- engines/parallaction/parallaction_br.cpp | 8 ++ engines/parallaction/parallaction_ns.cpp | 177 +++++++++++++++++++++++++++++- engines/parallaction/parser_ns.cpp | 5 +- 16 files changed, 379 insertions(+), 230 deletions(-) diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index 721d43fa19..7539d89368 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -65,8 +65,8 @@ class DialogueManager { bool _askPassword; bool isNpc; - Cnv *_questioner; - Cnv *_answerer; + Frames *_questioner; + Frames *_answerer; Question *_q; diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index d58d85e15c..6adab69f51 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -38,7 +38,9 @@ class Gfx; class Script; class Font; +struct Frames; struct Cnv; +struct Sprites; struct BackgroundInfo; class Disk { @@ -52,13 +54,13 @@ public: virtual Script* loadLocation(const char *name) = 0; virtual Script* loadScript(const char* name) = 0; - virtual Cnv* loadTalk(const char *name) = 0; - virtual Cnv* loadObjects(const char *name) = 0; + virtual Frames* loadTalk(const char *name) = 0; + virtual Frames* loadObjects(const char *name) = 0; virtual Graphics::Surface* loadPointer(const char *name) = 0; virtual Graphics::Surface* loadHead(const char* name) = 0; virtual Font* loadFont(const char* name) = 0; virtual Graphics::Surface* loadStatic(const char* name) = 0; - virtual Cnv* loadFrames(const char* name) = 0; + virtual Frames* loadFrames(const char* name) = 0; virtual void loadSlide(BackgroundInfo& info, const char *filename) = 0; virtual void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path) = 0; virtual Table* loadTable(const char* name) = 0; @@ -144,13 +146,13 @@ public: Script* loadLocation(const char *name); Script* loadScript(const char* name); - Cnv* loadTalk(const char *name); - Cnv* loadObjects(const char *name); + Frames* loadTalk(const char *name); + Frames* loadObjects(const char *name); Graphics::Surface* loadPointer(const char *name); Graphics::Surface* loadHead(const char* name); Font* loadFont(const char* name); Graphics::Surface* loadStatic(const char* name); - Cnv* loadFrames(const char* name); + Frames* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path); Table* loadTable(const char* name); @@ -178,13 +180,13 @@ public: Script* loadLocation(const char *name); Script* loadScript(const char* name); - Cnv* loadTalk(const char *name); - Cnv* loadObjects(const char *name); + Frames* loadTalk(const char *name); + Frames* loadObjects(const char *name); Graphics::Surface* loadPointer(const char *name); Graphics::Surface* loadHead(const char* name); Font* loadFont(const char* name); Graphics::Surface* loadStatic(const char* name); - Cnv* loadFrames(const char* name); + Frames* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path); Table* loadTable(const char* name); @@ -206,6 +208,7 @@ protected: protected: void errorFileNotFound(const char *s); Font *createFont(const char *name, Common::ReadStream &stream); + Sprites* createSprites(const char *name); public: DosDisk_br(Parallaction *vm); @@ -215,13 +218,13 @@ public: void setLanguage(uint16 language); Script* loadLocation(const char *name); Script* loadScript(const char* name); - Cnv* loadTalk(const char *name); - Cnv* loadObjects(const char *name); + Frames* loadTalk(const char *name); + Frames* loadObjects(const char *name); Graphics::Surface* loadPointer(const char *name); Graphics::Surface* loadHead(const char* name); Font* loadFont(const char* name); Graphics::Surface* loadStatic(const char* name); - Cnv* loadFrames(const char* name); + Frames* loadFrames(const char* name); void loadSlide(BackgroundInfo& info, const char *filename); void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path); Table* loadTable(const char* name); diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 4853a9fb1a..64eb6b533d 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -30,6 +30,57 @@ namespace Parallaction { +struct Sprite { + uint16 size; + uint16 x; + uint16 y; + uint16 w; + uint16 h; + + byte *packedData; + + Sprite() : size(0), x(0), y(0), w(0), h(0), packedData(0) { + } + + ~Sprite() { + if (packedData) + free(packedData); + } +}; + +struct Sprites : public Frames { + uint16 _num; + Sprite* _sprites; + + Sprites(uint num) { + _num = num; + _sprites = new Sprite[_num]; + } + + ~Sprites() { + delete _sprites; + } + + uint16 getNum() { + return _num; + } + + byte* getData(uint16 index) { + assert(index < _num); + return _sprites[index].packedData; + } + + void getRect(uint16 index, Common::Rect &r) { + assert(index < _num); + r.setWidth(_sprites[index].w); + r.setHeight(_sprites[index].h); + r.moveTo(_sprites[index].x, _sprites[index].y); +} + +}; + + + void DosDisk_br::errorFileNotFound(const char *s) { error("File '%s' not found", s); } @@ -78,10 +129,13 @@ DosDisk_br::DosDisk_br(Parallaction* vm) : _vm(vm) { DosDisk_br::~DosDisk_br() { } -Cnv* DosDisk_br::loadTalk(const char *name) { +Frames* DosDisk_br::loadTalk(const char *name) { debugC(5, kDebugDisk, "DosDisk_br::loadTalk"); - return 0; + char path[PATH_LEN]; + sprintf(path, "%s/tal/%s.tal", _partPath, name); + + return createSprites(path); } Script* DosDisk_br::loadLocation(const char *name) { @@ -159,7 +213,7 @@ Font* DosDisk_br::loadFont(const char* name) { } -Cnv* DosDisk_br::loadObjects(const char *name) { +Frames* DosDisk_br::loadObjects(const char *name) { debugC(5, kDebugDisk, "DosDisk_br::loadObjects"); return 0; } @@ -173,9 +227,39 @@ Graphics::Surface* DosDisk_br::loadStatic(const char* name) { return 0; } -Cnv* DosDisk_br::loadFrames(const char* name) { +Sprites* DosDisk_br::createSprites(const char *path) { + + Common::File stream; + if (!stream.open(path)) { + errorFileNotFound(path); + } + + uint16 num = stream.readUint16LE(); + + Sprites *sprites = new Sprites(num); + + for (uint i = 0; i < num; i++) { + Sprite *spr = &sprites->_sprites[i]; + spr->size = stream.readUint16LE(); + spr->x = stream.readUint16LE(); + spr->y = stream.readUint16LE(); + spr->w = stream.readUint16LE(); + spr->h = stream.readUint16LE(); + + spr->packedData = (byte*)malloc(spr->size); + stream.read(spr->packedData, spr->size); + } + + return sprites; +} + +Frames* DosDisk_br::loadFrames(const char* name) { debugC(5, kDebugDisk, "DosDisk_br::loadFrames"); - return 0; + + char path[PATH_LEN]; + sprintf(path, "%s/ani/%s.ani", _partPath, name); + + return createSprites(path); } // Slides in Nippon Safes are basically screen-sized pictures with valid diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index 8e71e4a6b7..cb224b713b 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -393,7 +393,7 @@ Cnv* DosDisk_ns::loadCnv(const char *filename) { return new Cnv(numFrames, width, height, data); } -Cnv* DosDisk_ns::loadTalk(const char *name) { +Frames* DosDisk_ns::loadTalk(const char *name) { const char *ext = strstr(name, ".talk"); if (ext != NULL) { @@ -487,7 +487,7 @@ Font* DosDisk_ns::loadFont(const char* name) { } -Cnv* DosDisk_ns::loadObjects(const char *name) { +Frames* DosDisk_ns::loadObjects(const char *name) { if (IS_MINI_CHARACTER(name)) { name += 4; @@ -524,7 +524,7 @@ Graphics::Surface* DosDisk_ns::loadStatic(const char* name) { return cnv; } -Cnv* DosDisk_ns::loadFrames(const char* name) { +Frames* DosDisk_ns::loadFrames(const char* name) { return loadCnv(name); } @@ -1305,7 +1305,7 @@ void AmigaDisk_ns::loadSlide(BackgroundInfo& info, const char *name) { return; } -Cnv* AmigaDisk_ns::loadFrames(const char* name) { +Frames* AmigaDisk_ns::loadFrames(const char* name) { debugC(1, kDebugDisk, "AmigaDisk_ns::loadFrames '%s'", name); Common::SeekableReadStream *s; @@ -1338,7 +1338,7 @@ Graphics::Surface* AmigaDisk_ns::loadHead(const char* name) { } -Cnv* AmigaDisk_ns::loadObjects(const char *name) { +Frames* AmigaDisk_ns::loadObjects(const char *name) { debugC(1, kDebugDisk, "AmigaDisk_ns::loadObjects"); char path[PATH_LEN]; @@ -1356,7 +1356,7 @@ Cnv* AmigaDisk_ns::loadObjects(const char *name) { } -Cnv* AmigaDisk_ns::loadTalk(const char *name) { +Frames* AmigaDisk_ns::loadTalk(const char *name) { debugC(1, kDebugDisk, "AmigaDisk_ns::loadTalk '%s'", name); Common::SeekableReadStream *s; diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp index 1df78da9c4..641a23b772 100644 --- a/engines/parallaction/exec_ns.cpp +++ b/engines/parallaction/exec_ns.cpp @@ -622,10 +622,12 @@ void jobToggleDoor(void *parm, Job *j) { Zone *z = (Zone*)parm; if (z->u.door->_cnv) { - Common::Rect r(z->_left, z->_top, z->_left+z->u.door->_cnv->_width, z->_top+z->u.door->_cnv->_height); + Common::Rect r; + z->u.door->_cnv->getRect(0, r); + r.moveTo(z->_left, z->_top); uint16 _ax = (z->_flags & kFlagsClosed ? 1 : 0); - _vm->_gfx->restoreDoorBackground(r, z->u.door->_cnv->getFramePtr(_ax), z->u.door->_background); + _vm->_gfx->restoreDoorBackground(r, z->u.door->_cnv->getData(_ax), z->u.door->_background); _ax = (z->_flags & kFlagsClosed ? 0 : 1); _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack); diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index c142779167..1cf5216963 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -463,13 +463,16 @@ void jobEraseLabel(void *parm, Job *j) { // // Cnv management // -void Gfx::flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer) { +void Gfx::flatBlitCnv(Frames *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer) { Graphics::Surface scnv; + Common::Rect r; - scnv.w = cnv->_width; - scnv.h = cnv->_height; - scnv.pixels = cnv->getFramePtr(frame); + cnv->getRect(frame, r); + + scnv.w = r.width(); + scnv.h = r.height(); + scnv.pixels = cnv->getData(frame); flatBlitCnv(&scnv, x, y, buffer); } @@ -493,7 +496,9 @@ void Gfx::blitCnv(Graphics::Surface *cnv, int16 x, int16 y, uint16 z, Gfx::Buffe void Gfx::backupDoorBackground(DoorData *data, int16 x, int16 y) { byte *s = (byte*)_buffers[kBit2]->getBasePtr(x, y); - copyRect(data->_cnv->_width, data->_cnv->_height, data->_background, data->_cnv->_width, s,_backgroundWidth); + Common::Rect r; + data->_cnv->getRect(0, r); + copyRect(r.width(), r.height(), data->_background, r.width(), s,_backgroundWidth); return; } diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index 6082f78343..3913eebbdf 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -72,7 +72,19 @@ public: }; -struct Cnv { + +struct Frames { + + virtual uint16 getNum() = 0; + virtual byte* getData(uint16 index) = 0; + virtual void getRect(uint16 index, Common::Rect &r) = 0; + + virtual ~Frames() { } + +}; + + +struct Cnv : public Frames { uint16 _count; // # of frames uint16 _width; // uint16 _height; // @@ -99,6 +111,21 @@ public: return NULL; return &_data[index * _width * _height]; } + + uint16 getNum() { + return _count; + } + + byte *getData(uint16 index) { + return getFramePtr(index); + } + + void getRect(uint16 index, Common::Rect &r) { + r.left = 0; + r.top = 0; + r.setWidth(_width); + r.setHeight(_height); + } }; @@ -194,7 +221,7 @@ public: // cut/paste void flatBlitCnv(Graphics::Surface *cnv, int16 x, int16 y, Gfx::Buffers buffer); - void flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer); + void flatBlitCnv(Frames *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer); void blitCnv(Graphics::Surface *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffer); void restoreBackground(const Common::Rect& r); void backupDoorBackground(DoorData *data, int16 x, int16 y); @@ -268,3 +295,4 @@ protected: + diff --git a/engines/parallaction/inventory.cpp b/engines/parallaction/inventory.cpp index 2804578c84..0a286e4204 100644 --- a/engines/parallaction/inventory.cpp +++ b/engines/parallaction/inventory.cpp @@ -117,9 +117,12 @@ void drawInventoryItem(uint16 pos, InventoryItem *item) { uint16 line = pos / INVENTORY_ITEMS_PER_LINE; uint16 col = pos % INVENTORY_ITEMS_PER_LINE; + Common::Rect r; + _vm->_char._objs->getRect(0, r); + // FIXME: this will end up in a general blit function - byte* s = _vm->_char._objs->getFramePtr(item->_index); - byte* d = _buffer + col * INVENTORYITEM_WIDTH + line * _vm->_char._objs->_height * INVENTORY_WIDTH; + byte* s = _vm->_char._objs->getData(item->_index); + byte* d = _buffer + col * INVENTORYITEM_WIDTH + line * r.height() * INVENTORY_WIDTH; for (uint32 i = 0; i < INVENTORYITEM_HEIGHT; i++) { memcpy(d, s, INVENTORYITEM_WIDTH); @@ -210,8 +213,10 @@ void highlightInventoryItem(int16 pos, byte color) { uint16 line = pos / INVENTORY_ITEMS_PER_LINE; uint16 col = pos % INVENTORY_ITEMS_PER_LINE; - Common::Rect r(INVENTORYITEM_WIDTH, _vm->_char._objs->_height); - r.moveTo(col * INVENTORYITEM_WIDTH, line * _vm->_char._objs->_height); + Common::Rect r; + _vm->_char._objs->getRect(0, r); + r.setWidth(INVENTORYITEM_WIDTH); + r.moveTo(col * INVENTORYITEM_WIDTH, line * r.height()); drawBorder(r, _buffer, color); diff --git a/engines/parallaction/inventory.h b/engines/parallaction/inventory.h index 4a3e07cc97..2ca3559b8f 100644 --- a/engines/parallaction/inventory.h +++ b/engines/parallaction/inventory.h @@ -31,8 +31,6 @@ namespace Parallaction { -struct Cnv; - struct InventoryItem { uint32 _id; // object name (lowest 16 bits are always zero) uint16 _index; // index to frame in objs file diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp index add2f87b5e..195d814265 100644 --- a/engines/parallaction/objects.cpp +++ b/engines/parallaction/objects.cpp @@ -62,22 +62,26 @@ Animation::~Animation() { uint16 Animation::width() const { if (!_cnv) return 0; - return _cnv->_width; + Common::Rect r; + _cnv->getRect(0, r); + return r.width(); } uint16 Animation::height() const { if (!_cnv) return 0; - return _cnv->_height; + Common::Rect r; + _cnv->getRect(0, r); + return r.height(); } uint16 Animation::getFrameNum() const { if (!_cnv) return 0; - return _cnv->_count; + return _cnv->getNum(); } byte* Animation::getFrameData(uint32 index) const { if (!_cnv) return NULL; - return _cnv->getFramePtr(index); + return _cnv->getData(index); } diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h index 26c841b285..9ec906f458 100644 --- a/engines/parallaction/objects.h +++ b/engines/parallaction/objects.h @@ -202,7 +202,7 @@ struct ExamineData { // size = 28 }; struct DoorData { // size = 28 char* _location; - Cnv *_cnv; + Frames *_cnv; byte* _background; Common::Point _startPos; uint16 _startFrame; @@ -384,7 +384,7 @@ struct Animation : public Zone { Common::Point _oldPos; Program *_program; - Cnv *_cnv; + Frames *_cnv; char *_scriptName; int16 _frame; uint16 field_50; // unused diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 4a93ee968b..7d150e8813 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -89,9 +89,6 @@ uint16 _introSarcData2 = 1; // private stuff static Job *_jDrawInventory = NULL; -Job *_jDrawLabel = NULL; -Job *_jEraseLabel = NULL; -Zone *_hoverZone = NULL; static Job *_jRunScripts = NULL; @@ -177,6 +174,10 @@ int Parallaction::init() { initInventory(); // needs to be pushed into subclass + _jDrawLabel = NULL; + _jEraseLabel = NULL; + _hoverZone = NULL; + _animations.push_front(&_char._ani); _gfx = new Gfx(this); @@ -664,55 +665,7 @@ void Parallaction::freeCharacter() { return; } -void Parallaction::changeCharacter(const char *name) { - debugC(1, kDebugLocation, "changeCharacter(%s)", name); - - char baseName[20]; - if (IS_MINI_CHARACTER(name)) { - strcpy(baseName, name+4); - } else { - strcpy(baseName, name); - } - - char fullName[20]; - strcpy(fullName, name); - if (_engineFlags & kEngineTransformedDonna) - strcat(fullName, "tras"); - - if (scumm_stricmp(fullName, _characterName1)) { - - // freeCharacter takes responsibility for checking - // character for sanity before memory is freed - freeCharacter(); - - Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0"); - _char._ani._cnv = _disk->loadFrames(fullName); - - if (!IS_DUMMY_CHARACTER(name)) { - if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_LANG_MULT)) - _disk->selectArchive("disk0"); - _char._head = _disk->loadHead(baseName); - _char._talk = _disk->loadTalk(baseName); - _char._objs = _disk->loadObjects(baseName); - _objectsNames = _disk->loadTable(baseName); - - _soundMan->playCharacterMusic(name); - - if (!(getFeatures() & GF_DEMO)) - parseLocation("common"); - } - - if (!oldArchive.empty()) - _disk->selectArchive(oldArchive); - } - - strcpy(_characterName1, fullName); - - debugC(1, kDebugLocation, "changeCharacter() done"); - - return; -} /* helper function to provide *descending* ordering of the job list @@ -1036,9 +989,6 @@ void Parallaction::switchBackground(const char* background, const char* mask) { return; } -extern Zone *_hoverZone; -extern Job *_jDrawLabel; -extern Job *_jEraseLabel; void Parallaction::showSlide(const char *name) { @@ -1061,131 +1011,7 @@ void Parallaction::showSlide(const char *name) { return; } -/* - changeLocation handles transitions between locations, and is able to display slides - between one and the other. The input parameter 'location' exists in some flavours: - - 1 - [S].slide.[L]{.[C]} - 2 - [L]{.[C]} - - where: - - [S] is the slide to be shown - [L] is the location to switch to (immediately in case 2, or right after slide [S] in case 1) - [C] is the character to be selected, and is optional - - The routine tells one form from the other by searching for the '.slide.' - - NOTE: there exists one script in which [L] is not used in the case 1, but its use - is commented out, and would definitely crash the current implementation. -*/ -void Parallaction::changeLocation(char *location) { - debugC(1, kDebugLocation, "changeLocation(%s)", location); - - _soundMan->playLocationMusic(location); - - // WORKAROUND: this if-statement has been added to avoid crashes caused by - // execution of label jobs after a location switch. The other workaround in - // Parallaction::runGame should have been rendered useless by this one. - if (_jDrawLabel != NULL) { - removeJob(_jDrawLabel); - removeJob(_jEraseLabel); - _jDrawLabel = NULL; - _jEraseLabel = NULL; - } - - - _hoverZone = NULL; - if (_engineFlags & kEngineBlockInput) { - changeCursor( kCursorArrow ); - } - - _animations.remove(&_char._ani); - - freeLocation(); - char buf[100]; - strcpy(buf, location); - - Common::StringList list; - char *tok = strtok(location, "."); - while (tok) { - list.push_back(tok); - tok = strtok(NULL, "."); - } - - if (list.size() < 1 || list.size() > 4) - error("changeLocation: ill-formed location string '%s'", location); - - if (list.size() > 1) { - if (list[1] == "slide") { - showSlide(list[0].c_str()); - _gfx->setFont(_menuFont); - _gfx->displayCenteredString(14, _slideText[0]); // displays text on screen - _gfx->updateScreen(); - waitUntilLeftClick(); - - list.remove_at(0); // removes slide name - list.remove_at(0); // removes 'slide' - } - - // list is now only [L].{[C]} (see above comment) - if (list.size() == 2) { - changeCharacter(list[1].c_str()); - strcpy(_characterName, list[1].c_str()); - } - } - - _animations.push_front(&_char._ani); - - strcpy(_saveData1, list[0].c_str()); - parseLocation(list[0].c_str()); - - _char._ani._oldPos.x = -1000; - _char._ani._oldPos.y = -1000; - - _char._ani.field_50 = 0; - if (_location._startPosition.x != -1000) { - _char._ani._left = _location._startPosition.x; - _char._ani._top = _location._startPosition.y; - _char._ani._frame = _location._startFrame; - _location._startPosition.y = -1000; - _location._startPosition.x = -1000; - } - - - _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); - _gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2); - _gfx->setBlackPalette(); - _gfx->updateScreen(); - - if (_location._commands.size() > 0) { - runCommands(_location._commands); - runJobs(); - _gfx->swapBuffers(); - runJobs(); - _gfx->swapBuffers(); - } - - if (_location._comment) { - doLocationEnterTransition(); - } - - runJobs(); - _gfx->swapBuffers(); - _gfx->setPalette(_gfx->_palette); - if (_location._aCommands.size() > 0) { - runCommands(_location._aCommands); - } - - if (_hasLocationSound) - _soundMan->playSfx(_locationSound, 0, true); - - debugC(1, kDebugLocation, "changeLocation() done"); - - return; - -} // displays transition before a new location // diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 1fbdcd6237..4fc9f64537 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -238,8 +238,8 @@ struct Location { struct Character { Animation _ani; Graphics::Surface *_head; - Cnv *_talk; - Cnv *_objs; + Frames *_talk; + Frames *_objs; PathBuilder _builder; Character() : _builder(&_ani) { @@ -381,7 +381,6 @@ public: void changeCursor(int32 index); void showCursor(bool visible); - void changeCharacter(const char *name); Job *addJob(JobFn fn, void *parm, uint16 tag); @@ -501,6 +500,9 @@ protected: // data BackgroundInfo *_backgroundInfo; + Job *_jDrawLabel; + Job *_jEraseLabel; + Zone *_hoverZone; protected: // members bool detectGame(void); @@ -519,7 +521,8 @@ protected: // members void doSaveGame(uint16 slot, const char* name); void doLocationEnterTransition(); - void changeLocation(char *location); + virtual void changeLocation(char *location) = 0; + virtual void changeCharacter(const char *name) = 0; void allocateLocationSlot(const char *name); void finalizeLocationParsing(); void switchBackground(const char* background, const char* mask); @@ -580,6 +583,9 @@ private: void freeFonts(); private: + void changeLocation(char *location); + void changeCharacter(const char *name); + void initResources(); void initCursors(); @@ -833,6 +839,8 @@ private: void initOpcodes(); void initParsers(); + void changeLocation(char *location); + void changeCharacter(const char *name); void initPart(); void freePart(); diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 3fd56b80aa..31b2793090 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -349,5 +349,13 @@ void Parallaction_br::startPart() { } +void Parallaction_br::changeLocation(char *location) { + +} + +void Parallaction_br::changeCharacter(const char *name) { + +} + } // namespace Parallaction diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index 2a82002f24..db0cdf84e7 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -151,7 +151,7 @@ void Parallaction_ns::setMousePointer(int16 index) { byte *v8 = (byte*)_mouseComposedArrow->pixels; // FIXME: destination offseting is not clear - byte* s = _char._objs->getFramePtr(getInventoryItemIndex(index)); + byte* s = _char._objs->getData(getInventoryItemIndex(index)); byte* d = v8 + 7 + MOUSECOMBO_WIDTH * 7; for (uint i = 0; i < INVENTORYITEM_HEIGHT; i++) { @@ -208,5 +208,180 @@ int Parallaction_ns::go() { } +/* + changeLocation handles transitions between locations, and is able to display slides + between one and the other. The input parameter 'location' exists in some flavours: + + 1 - [S].slide.[L]{.[C]} + 2 - [L]{.[C]} + + where: + + [S] is the slide to be shown + [L] is the location to switch to (immediately in case 2, or right after slide [S] in case 1) + [C] is the character to be selected, and is optional + + The routine tells one form from the other by searching for the '.slide.' + + NOTE: there exists one script in which [L] is not used in the case 1, but its use + is commented out, and would definitely crash the current implementation. +*/ +void Parallaction_ns::changeLocation(char *location) { + debugC(1, kDebugLocation, "changeLocation(%s)", location); + + _soundMan->playLocationMusic(location); + + // WORKAROUND: this if-statement has been added to avoid crashes caused by + // execution of label jobs after a location switch. The other workaround in + // Parallaction::runGame should have been rendered useless by this one. + if (_jDrawLabel != NULL) { + removeJob(_jDrawLabel); + removeJob(_jEraseLabel); + _jDrawLabel = NULL; + _jEraseLabel = NULL; + } + + + _hoverZone = NULL; + if (_engineFlags & kEngineBlockInput) { + changeCursor( kCursorArrow ); + } + + _animations.remove(&_char._ani); + + freeLocation(); + char buf[100]; + strcpy(buf, location); + + Common::StringList list; + char *tok = strtok(location, "."); + while (tok) { + list.push_back(tok); + tok = strtok(NULL, "."); + } + + if (list.size() < 1 || list.size() > 4) + error("changeLocation: ill-formed location string '%s'", location); + + if (list.size() > 1) { + if (list[1] == "slide") { + showSlide(list[0].c_str()); + _gfx->setFont(_menuFont); + _gfx->displayCenteredString(14, _slideText[0]); // displays text on screen + _gfx->updateScreen(); + waitUntilLeftClick(); + + list.remove_at(0); // removes slide name + list.remove_at(0); // removes 'slide' + } + + // list is now only [L].{[C]} (see above comment) + if (list.size() == 2) { + changeCharacter(list[1].c_str()); + strcpy(_characterName, list[1].c_str()); + } + } + + _animations.push_front(&_char._ani); + + strcpy(_saveData1, list[0].c_str()); + parseLocation(list[0].c_str()); + + _char._ani._oldPos.x = -1000; + _char._ani._oldPos.y = -1000; + + _char._ani.field_50 = 0; + if (_location._startPosition.x != -1000) { + _char._ani._left = _location._startPosition.x; + _char._ani._top = _location._startPosition.y; + _char._ani._frame = _location._startFrame; + _location._startPosition.y = -1000; + _location._startPosition.x = -1000; + } + + + _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); + _gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2); + _gfx->setBlackPalette(); + _gfx->updateScreen(); + + if (_location._commands.size() > 0) { + runCommands(_location._commands); + runJobs(); + _gfx->swapBuffers(); + runJobs(); + _gfx->swapBuffers(); + } + + if (_location._comment) { + doLocationEnterTransition(); + } + + runJobs(); + _gfx->swapBuffers(); + + _gfx->setPalette(_gfx->_palette); + if (_location._aCommands.size() > 0) { + runCommands(_location._aCommands); + } + + if (_hasLocationSound) + _soundMan->playSfx(_locationSound, 0, true); + + debugC(1, kDebugLocation, "changeLocation() done"); + + return; + +} + +void Parallaction_ns::changeCharacter(const char *name) { + debugC(1, kDebugLocation, "changeCharacter(%s)", name); + + char baseName[20]; + if (IS_MINI_CHARACTER(name)) { + strcpy(baseName, name+4); + } else { + strcpy(baseName, name); + } + + char fullName[20]; + strcpy(fullName, name); + if (_engineFlags & kEngineTransformedDonna) + strcat(fullName, "tras"); + + if (scumm_stricmp(fullName, _characterName1)) { + + // freeCharacter takes responsibility for checking + // character for sanity before memory is freed + freeCharacter(); + + Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0"); + _char._ani._cnv = _disk->loadFrames(fullName); + + if (!IS_DUMMY_CHARACTER(name)) { + if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_LANG_MULT)) + _disk->selectArchive("disk0"); + + _char._head = _disk->loadHead(baseName); + _char._talk = _disk->loadTalk(baseName); + _char._objs = _disk->loadObjects(baseName); + _objectsNames = _disk->loadTable(baseName); + + _soundMan->playCharacterMusic(name); + + if (!(getFeatures() & GF_DEMO)) + parseLocation("common"); + } + + if (!oldArchive.empty()) + _disk->selectArchive(oldArchive); + } + + strcpy(_characterName1, fullName); + + debugC(1, kDebugLocation, "changeCharacter() done"); + + return; +} } // namespace Parallaction diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp index 1956e7cb03..e3ee3157fb 100644 --- a/engines/parallaction/parser_ns.cpp +++ b/engines/parallaction/parser_ns.cpp @@ -1234,7 +1234,10 @@ void Parallaction_ns::parseZoneTypeBlock(Script &script, Zone *z) { u->door->_cnv = _disk->loadFrames(vC8); uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1); - u->door->_background = (byte*)malloc(u->door->_cnv->_width * u->door->_cnv->_height); + Common::Rect r; + u->door->_cnv->getRect(0, r); + + u->door->_background = (byte*)malloc(r.width() * r.height()); _gfx->backupDoorBackground(u->door, z->_left, z->_top); _gfx->flatBlitCnv(u->door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack); -- cgit v1.2.3