aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--queen/cutaway.cpp721
-rw-r--r--queen/cutaway.h202
-rw-r--r--queen/module.mk1
3 files changed, 924 insertions, 0 deletions
diff --git a/queen/cutaway.cpp b/queen/cutaway.cpp
new file mode 100644
index 0000000000..938c003829
--- /dev/null
+++ b/queen/cutaway.cpp
@@ -0,0 +1,721 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2003 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "stdafx.h"
+#include "cutaway.h"
+
+/*
+ Functions needed:
+
+ queen.c: DISP_ROOM
+ MOVE_JOE
+ MOVE_OTHER
+
+ talk.c: SPEAK
+
+
+ Data needed:
+
+ JX,JY (Joe's coordintes)
+ OBJECT_DATA
+ ROOM_DATA
+
+ */
+
+void QueenCutaway::run(
+ const char *filename,
+ QueenLogic *queenLogic,
+ QueenResource *queenResource) {
+ QueenCutaway *cutaway = new QueenCutaway(filename, queenLogic, queenResource);
+ cutaway->run();
+ delete cutaway;
+}
+
+QueenCutaway::QueenCutaway(
+ const char *filename,
+ QueenLogic *queenLogic,
+ QueenResource *queenResource) : _queenLogic(queenLogic), _quit(false) {
+ memset(&_bankNames, 0, sizeof(_bankNames));
+ load(filename, queenResource);
+ }
+
+QueenCutaway::~QueenCutaway() {
+ delete[] _fileData;
+}
+
+void QueenCutaway::load(const char *filename, QueenResource *queenResource) {
+ byte *ptr;
+
+ /* XXX: make sure that loadFile is not case sensitive */
+ ptr = _fileData = queenResource->loadFile(filename, 20);
+ if (!_fileData) {
+ /* XXX: error message? */
+ _quit = true;
+ return;
+ }
+
+ strcpy(_basename, filename);
+ _basename[strlen(_basename)-4] = '\0';
+
+ int COMPANEL = READ_BE_UINT16(ptr);
+ ptr += 2;
+ debug(0, "COMPANEL = %i", COMPANEL);
+
+ _cutawayObjectCount = READ_BE_UINT16(ptr);
+ ptr += 2;
+ debug(0, "_cutawayObjectCount = %i", _cutawayObjectCount);
+
+ if (_cutawayObjectCount < 0) {
+ _cutawayObjectCount = -_cutawayObjectCount;
+ _canQuit = false;
+ }
+ else
+ _canQuit = true;
+
+ int flags1 = READ_BE_UINT16(ptr);
+ ptr += 2;
+ debug(0, "flags1 = %i", (int16)flags1);
+
+ if (flags1 < 0) {
+ /* ENTRY_OBJ = 0 */
+ _finalRoom = -flags1;
+ }
+ else
+ _finalRoom = PREVIOUS_ROOM;
+
+ if (flags1 == 1)
+ /* ANOTHER_CUT = 1 */;
+ else
+ /* ANOTHER_CUT = 0 */;
+
+ /*
+ Pointers to other places in the cutaway data
+ */
+
+ byte *gameStatesPtr = _fileData + READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ _nextSentence = _fileData + READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ byte *bankNamesPtr = _fileData + READ_BE_UINT16(ptr);
+ ptr += 2;
+ debug(0, "Bank name file offset = %08x", 20 + bankNamesPtr - _fileData);
+
+ _objectData = ptr;
+
+ loadStrings(bankNamesPtr);
+
+ if (_bankNames[0][0]) {
+ debug(0, "Loading bank '%s'", _bankNames[0]);
+ /* loadbank(_bankNames[0]) */ ;
+ }
+
+ char entryString[MAX_STRING_SIZE];
+ _nextSentence = getString(_nextSentence, entryString, MAX_STRING_LENGTH);
+ debug(0, "Entry string = '%s'", entryString);
+
+ if (entryString[0] == '*' &&
+ entryString[1] == 'F' &&
+ entryString[3] == '\0') {
+ switch (entryString[2]) {
+ case 'L':
+ /* CUTJOEF = LEFT; */
+ break;
+ case 'R':
+ /* CUTJOEF = RIGHT; */
+ break;
+ case 'F':
+ /* CUTJOEF = FRONT; */
+ break;
+ case 'B':
+ /* CUTJOEF = BACK; */
+ break;
+ }
+ }
+
+}
+
+byte *QueenCutaway::getString(byte *ptr, char *str, int maxLength) {
+ int length = *ptr;
+ ptr++;
+
+ if (length > maxLength) {
+ error("String too long. Length = %i, maxLength = %i, str = '%*s'",
+ length, maxLength, length, (const char*)ptr);
+ }
+ else if (length) {
+ memcpy(str, (const char*)ptr, length);
+ ptr += length;
+
+ while ((int)ptr % 2)
+ ptr++;
+ }
+
+ str[length] = '\0';
+
+ return ptr;
+}
+
+void QueenCutaway::loadStrings(byte *ptr) {
+ int i,j;
+
+ int bankNameCount = READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ debug(0, "Bank name count = %i", bankNameCount);
+
+ /*
+ The _bankNames zero-based array is the one-based BANK_NAMEstr array in
+ the original source code.
+ */
+
+ for (i = 0, j = 0; i < bankNameCount; i++) {
+ ptr = getString(ptr, _bankNames[j], MAX_FILENAME_LENGTH);
+
+ if (_bankNames[j][0]) {
+ debug(0, "Bank name %i = '%s'", _bankNames[j]);
+ j++;
+ }
+ }
+
+ debug(0, "Getting talk file");
+ ptr = getString(ptr, _talkFile, MAX_FILENAME_LENGTH);
+ debug(0, "Talk file = '%s'", _talkFile);
+
+ int TALKTO = READ_BE_UINT16(ptr);
+ ptr += 2;
+ debug(0, "TALKTO = %i", TALKTO);
+}
+
+byte *QueenCutaway::getCutawayObject(byte *ptr, CutawayObject &object)
+{
+ byte *oldPtr = ptr;
+
+ object.objectNumber = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.moveToX = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.moveToY = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.bank = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.animList = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.execute = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.limitBobX1 = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.limitBobY1 = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.limitBobX2 = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.limitBobY2 = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.specialMove = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.animType = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.fromObject = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.bobStartX = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.bobStartY = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.room = (int16)READ_BE_UINT16(ptr); ptr += 2;
+ object.scale = (int16)READ_BE_UINT16(ptr); ptr += 2;
+
+ if ((ptr - oldPtr) != 17*sizeof(int16))
+ error("Wrong number of values read");
+
+ // Make ugly reuse of data less ugly
+ if (object.limitBobX1 < 0)
+ object.song = -object.limitBobX1;
+ else
+ object.song = 0;
+
+ return ptr;
+}
+
+void QueenCutaway::dumpCutawayObject(int index, CutawayObject &object)
+{
+ debug(0, "----- CutawayObject[%i] -----", index);
+
+ const char *objectNumberStr;
+
+ switch (object.objectNumber) {
+ case -1: objectNumberStr = "MESSAGE"; break;
+ case 0: objectNumberStr = "JOE"; break;
+ default: objectNumberStr = "unknown"; break;
+ }
+
+ debug(0, "objectNumber = %i (%s)", object.objectNumber, objectNumberStr);
+
+ if (object.moveToX) debug(0, "moveToX = %i", object.moveToX);
+ if (object.moveToY) debug(0, "moveToY = %i", object.moveToY);
+ if (object.bank) debug(0, "bank = %i", object.bank);
+ if (object.animList) debug(0, "animList = %i", object.animList);
+ if (object.execute) debug(0, "execute = %i", object.execute);
+ if (object.limitBobX1) debug(0, "limitBobX1 = %i", object.limitBobX1);
+ if (object.limitBobY1) debug(0, "limitBobY1 = %i", object.limitBobY1);
+ if (object.limitBobX2) debug(0, "limitBobX2 = %i", object.limitBobX2);
+ if (object.limitBobY2) debug(0, "limitBobY2 = %i", object.limitBobY2);
+ if (object.specialMove) debug(0, "specialMove = %i", object.specialMove);
+ if (object.animType) debug(0, "animType = %i", object.animType);
+ if (object.fromObject) debug(0, "fromObject = %i", object.fromObject);
+ if (object.bobStartX) debug(0, "bobStartX = %i", object.bobStartX);
+ if (object.bobStartY) debug(0, "bobStartY = %i", object.bobStartY);
+ if (object.room) debug(0, "room = %i", object.room);
+ if (object.scale) debug(0, "scale = %i", object.scale);
+
+}
+
+void QueenCutaway::specialMove(int index) {
+
+ switch (index) {
+ default:
+ warning("Unhandled special move: %i", index);
+ break;
+ }
+}
+
+byte *QueenCutaway::turnOnPeople(byte *ptr, CutawayObject &object) {
+ // Lines 1248-1259 in cutaway.c
+ object.personCount = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ if (object.personCount > MAX_PERSON_COUNT)
+ error("[QueenCutaway::turnOnPeople] object.personCount > MAX_PERSON_COUNT");
+
+ for (int i = 0; i < object.personCount; i++) {
+ object.person[i] = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+ debug(0, "[%i] Turn on person %i", i, object.person[i]);
+ }
+
+ return ptr;
+}
+
+void QueenCutaway::limitBob(CutawayObject &object) {
+ if (object.limitBobX1) {
+ warning("QueenCutaway::limitBob() not implemented");
+ // FIND_BOB(object.objectNumber);
+ // XXX K=Param;
+ // bobs[K].x1 = object.limitBobX1;
+ // bobs[K].y1 = object.limitBobY1;
+ // bobs[K].x2 = object.limitBobX2;
+ // bobs[K].y2 = object.limitBobY2;
+ }
+}
+
+void QueenCutaway::changeRooms(CutawayObject &object) {
+ // Lines 1291-1385 in cutaway.c
+ warning("QueenCutaway::changeRooms() not implemented properly");
+
+ for (int i = 0; i < _savedPersonCount; i++) {
+ // restore parts of OBJECT_DATA array from PERSON_DATA array
+ }
+
+ _savedPersonCount = 0;
+
+ if (_finalRoom != object.room) {
+ // XXX loop room data and do stuff
+ // uses ROOM_DATA
+ // uses OBJECT_DATA
+ // backup parts of OBJECT_DATA array in PERSON_DATA array
+ // increase _savedPersonCount
+ }
+
+ // set coordinates for Joe if he is on screen
+
+ // XXX this is global data!
+ int joeX = 0;
+ int joeY = 0;
+
+ for (int i = 0; i < object.personCount; i++) {
+ if (PERSON_JOE == object.person[i]) {
+ joeX = object.bobStartX;
+ joeY = object.bobStartY;
+ }
+ }
+
+ // XXX OLDROOM=IROOM;
+
+ if (!joeX && !joeY) {
+ // XXX DISP_ROOM(ROOM_NAMEstr[ROOM],0,SF);
+ }
+ else {
+ // XXX We need to display Joe on screen
+#if 0
+ if(ROOMFADE==1)
+ DISP_ROOM(ROOM_NAMEstr[ROOM],2,SF);
+ else
+ DISP_ROOM(ROOM_NAMEstr[ROOM],3,SF);
+#endif
+ }
+
+ // XXX CI=FRAMES;
+
+ // XXX TROOM=ROOM;
+
+ for (int i = 0; i < _savedPersonCount; i++) {
+ // restore parts of OBJECT_DATA array from PERSON_DATA array
+ }
+
+ // XXX CUTAWAY_SCALE(OBJECT);
+ // XXX SF=Param;
+ // XXX if(SCALE_FACTOR>0 && SCALE_FACTOR<100)
+ // XXX SF=SCALE_FACTOR;
+
+}
+
+QueenCutaway::ObjectType QueenCutaway::getObjectType(CutawayObject &object) {
+ ObjectType objectType = OBJECT_TYPE_ANIMATION;
+
+ if (object.objectNumber > 0) {
+ if (!object.animList) {
+ // No anim frames, so treat as a PERSON, ie. allow to speak/walk
+
+ //if(OBJECT_DATA[OBJECT][7]==-3 || OBJECT_DATA[OBJECT][7]==-4)
+ // OBJTYPE=1;
+ }
+ }
+ else if (object.objectNumber == OBJECT_JOE) {
+ // It's Joe. See if he's to be treated as a person.
+ if (!object.animList) {
+ // There's no animation list, so Joe must be talking.
+ objectType = OBJECT_TYPE_PERSON;
+ }
+ }
+
+ if (object.fromObject > 0) {
+ warning("Cannot copy objects yet");
+
+ /* Copy FROM_OBJECT into OBJECT */
+
+#if 0
+ if(FROM_OBJECT!=OBJECT)
+ P3_COPY_FROM(FROM_OBJECT,OBJECT);
+ else
+
+ // Same object, so just turn it on!
+
+ OBJECT_DATA[OBJECT][0]=abs(OBJECT_DATA[OBJECT][0]);
+ REDISP_OBJECT(OBJECT);
+#endif
+
+ // Skip doing any anim stuff
+
+ objectType = OBJECT_TYPE_NO_ANIMATION;
+ }
+
+ switch(object.objectNumber) {
+ case -2:
+ // Text to be spoken
+ objectType = OBJECT_TYPE_TEXT_SPEAK;
+ break;
+ case -3:
+ // Text to be displayed AND spoken
+ objectType = OBJECT_TYPE_TEXT_DISPLAY_AND_SPEAK;
+ break;
+ case -4:
+ // Text to be displayed only (not spoken)
+ objectType = OBJECT_TYPE_TEXT_DISPLAY;
+ break;
+ }
+
+ if (OBJECT_TYPE_ANIMATION == objectType && !object.execute) {
+ // Execute is not on, and it's an object, so ignore any Anims
+ objectType = OBJECT_TYPE_NO_ANIMATION;
+ }
+
+ return objectType;
+}
+
+byte *QueenCutaway::getCutawayAnim(byte *ptr, int header, CutawayAnim &anim) {
+
+ anim.currentFrame = 0;
+ anim.originalFrame = 0;
+
+ if (-1 == header)
+ header = 0;
+
+ if (0 == header) {
+ anim.object = 0;
+ // XXX
+#if 0
+ anim.originalFrame =29+XTRA;
+ // 21/9/94, Make sure that bobs are clipped on 150 screens
+ if(FULLSCREEN) bobs[0].y2=199;
+#endif
+ }
+ else {
+ warning("Stuff not yet implemented in QueenCutaway::handleAnimation()");
+ // XXX
+ // FIND_BOB(header);
+ // anim.object = Param;
+
+#if 0
+ // If fullscreen cutaway then clip to 199 down
+
+ // 21/9/94, Make sure that bobs are clipped on 150 screens
+ if(COMPANEL==2 && OBJ_CUT[6]<=0 && BDyres==200) bobs[Param].y2=199;
+ FIND_FRAME(J);
+ anim.originalFrame =Param;
+#endif
+ }
+
+ anim.unpackFrame = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ anim.speed = ((int16)READ_BE_UINT16(ptr)) / 3 + 1;
+ ptr += 2;
+
+ anim.bank = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ anim.mx = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ anim.my = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ anim.cx = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ anim.cy = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ anim.scale = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+
+#if 1
+ anim.song = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+#else
+ anim.song = 0;
+#endif
+
+ return ptr;
+}
+
+void QueenCutaway::dumpCutawayAnim(CutawayAnim &anim) {
+ debug(0, "----- CutawayAnim -----");
+ if (anim.object) debug(0, "object = %i", anim.object);
+ if (anim.unpackFrame) debug(0, "unpackFrame = %i", anim.unpackFrame);
+ if (anim.speed) debug(0, "speed = %i", anim.speed);
+ if (anim.bank) debug(0, "bank = %i", anim.bank);
+ if (anim.mx) debug(0, "mx = %i", anim.mx);
+ if (anim.my) debug(0, "my = %i", anim.my);
+ if (anim.cx) debug(0, "cx = %i", anim.cx);
+ if (anim.cy) debug(0, "cy = %i", anim.cy);
+ if (anim.scale) debug(0, "scale = %i", anim.scale);
+ if (anim.currentFrame) debug(0, "currentFrame = %i", anim.currentFrame);
+ if (anim.originalFrame) debug(0, "originalFrame = %i", anim.originalFrame);
+ if (anim.song) debug(0, "song = %i", anim.song);
+}
+
+byte *QueenCutaway::handleAnimation(byte *ptr, CutawayObject &object) {
+ int frameCount = 0;
+ int header = 0;
+
+ // Read animation frames
+ for (;;) {
+
+ CutawayAnim tmp; // make array
+ header = (int16)READ_BE_UINT16(ptr);
+ ptr += 2;
+
+ if (-2 == header)
+ break;
+
+ debug(0, "Animation frame %i, header = %i", frameCount, header);
+
+ if (header > 1000)
+ error("Header too large");
+
+ ptr = getCutawayAnim(ptr, header, tmp);
+ dumpCutawayAnim(tmp);
+
+ frameCount++;
+
+ if (_quit)
+ return NULL;
+ }
+
+ if (object.animType == 1) {
+ // XXX
+ }
+
+ // Setup the SYNCHRO bob channels
+ // XXX
+
+ // Normal cutaway
+
+ if (object.animType != 1) {
+ // XXX
+ }
+
+
+ return ptr;
+}
+
+void QueenCutaway::handlePersonRecord(
+ int index,
+ CutawayObject &object,
+ const char *sentence) {
+ // Lines 1455-1516 in cutaway.c
+
+ char name[MAX_STRING_SIZE];
+
+ if (object.objectNumber == OBJECT_JOE) {
+ if (object.moveToX || object.moveToY) {
+ // XXX X=IX ; Y=IY;
+ // XXX MOVE_JOE(0);
+ }
+ strcpy(name, "JOE");
+ }
+ else {
+ // Not Joe XXX
+ warning("Person not Joe");
+ strcpy(name, "unknown");
+#if 0
+ K=OBJECT-ROOM_DATA[ROOM];
+
+ /* Find out which object position on the screen the person is */
+
+ SET_PERSON_DATA(K,NULLstr,0);
+ if(OBJ_CUT[13]>0 || OBJ_CUT[14]>0)
+ {
+ bobs[P_BNUM].scale=SF;
+ bobs[P_BNUM].x=OBJ_CUT[13];
+ bobs[P_BNUM].y=OBJ_CUT[14];
+ }
+ /* Add person's direction to be passed across */
+
+ MOVE_OTHER(P_NAMEstr,IX,IY,CI+1,OBJECT_DATA[OBJECT][7]);
+#endif
+ }
+
+ if (_quit)
+ return;
+
+ if (0 != strcmp(sentence, "*")) {
+ if (sentence[0] == '#') {
+ warning("Credit scripting system not yet implemented");
+ // XXX Cinit(sentence + 1);
+ }
+ else {
+ if (object.objectNumber > 0) {
+ // XXX
+ warning("Stuff not implemented");
+#if 0
+ MTCH=0;
+ for(K=1;K<=PERSON_FACE_MAX;K++)
+ {
+ if(PERSON_FACE[K][0]==OBJECT) MTCH=1;
+ }
+ if(MTCH==0)
+ {
+ PERSON_FACE_MAX++;
+ PERSON_FACE[PERSON_FACE_MAX][0]=OBJECT;
+ PERSON_FACE[PERSON_FACE_MAX][1]=OBJECT_DATA[OBJECT][7];
+ }
+#endif
+ }
+
+ // XXX SPEAK(sentence, name, findCdCut(_basename, index));
+ }
+
+ }
+
+ if (_quit)
+ return;
+}
+
+void QueenCutaway::run() {
+
+ byte *ptr = _objectData;
+
+ int initialRoom = _queenLogic->currentRoom();
+ int previousRoom = initialRoom;
+
+ // XXX if(COMPANEL==0 || COMPANEL==2) SCENE_START(0);
+
+ for (int i = 0; i < _cutawayObjectCount; i++) {
+ CutawayObject object;
+ ptr = getCutawayObject(ptr, object);
+#if 1
+ dumpCutawayObject(i, object);
+#endif
+
+ if (!object.moveToX &&
+ !object.moveToY &&
+ object.specialMove &&
+ object.objectNumber >= 0) {
+ specialMove(object.specialMove);
+ object.specialMove = 0;
+ }
+
+ if (CURRENT_ROOM == object.room) {
+ // Get current room
+ object.room = _queenLogic->currentRoom();
+ }
+ else {
+ // Change current room
+ warning("Not yet able to change current room");
+ // XXX queenLogic->currentRoom(object.room);
+ }
+
+ ptr = turnOnPeople(ptr, object);
+
+ limitBob(object);
+
+ char sentence[MAX_STRING_SIZE];
+ _nextSentence = getString(_nextSentence, sentence, MAX_STRING_LENGTH);
+ debug(0, "Sentence = '%s'", sentence);
+
+ if (OBJECT_ROOMFADE == object.objectNumber) {
+ // ROOMFADE = 1;
+ object.objectNumber = OBJECT_JOE;
+ }
+ else {
+ // ROOMFADE = 0;
+ }
+
+ if (object.room != previousRoom)
+ changeRooms(object);
+
+ ObjectType objectType = getObjectType(object);
+
+ if (object.song) {
+ debug(0, "Should play song %i here", object.song);
+ // XXX playsong(object.song);
+ }
+
+ switch (objectType) {
+ case OBJECT_TYPE_ANIMATION:
+ ptr = handleAnimation(ptr, object);
+ break;
+
+ case OBJECT_TYPE_PERSON:
+ handlePersonRecord(i, object, sentence);
+ break;
+
+ case OBJECT_TYPE_NO_ANIMATION:
+ // Do nothing?
+ break;
+
+ default:
+ error("Unhandled object type: %i", objectType);
+ break;
+ }
+
+ if (_quit)
+ break;
+ }
+}
+
diff --git a/queen/cutaway.h b/queen/cutaway.h
new file mode 100644
index 0000000000..274c9ef534
--- /dev/null
+++ b/queen/cutaway.h
@@ -0,0 +1,202 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2003 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef QUEENCUTAWAY_H
+#define QUEENCUTAWAY_H
+
+#include "queen/queen.h"
+
+class QueenResource;
+class QueenLogic;
+
+class QueenCutaway {
+ public:
+ //! Public interface to run a cutaway from a file
+ static void run(
+ const char *filename,
+ QueenLogic *queenLogic,
+ QueenResource *queenResource);
+ private:
+ //! Collection of constants used by QueenCutaway
+ enum {
+ PREVIOUS_ROOM = 0,
+ CURRENT_ROOM = 0,
+ OBJECT_ROOMFADE = -1,
+ PERSON_JOE = -1,
+ OBJECT_JOE = 0,
+ MAX_PERSON_COUNT = 6,
+ MAX_BANK_NAME_COUNT = 5,
+ MAX_FILENAME_LENGTH = 12,
+ MAX_FILENAME_SIZE = (MAX_FILENAME_LENGTH + 1),
+ MAX_STRING_LENGTH = 255,
+ MAX_STRING_SIZE = (MAX_STRING_LENGTH + 1),
+ LEFT = 1,
+ RIGHT = 2,
+ FRONT = 3,
+ BACK = 4
+ };
+
+ //! Different kinds of cutaway objects
+ enum ObjectType {
+ OBJECT_TYPE_ANIMATION = 0,
+ OBJECT_TYPE_PERSON = 1,
+ OBJECT_TYPE_NO_ANIMATION = 2,
+ OBJECT_TYPE_TEXT_SPEAK = 3,
+ OBJECT_TYPE_TEXT_DISPLAY_AND_SPEAK = 4,
+ OBJECT_TYPE_TEXT_DISPLAY = 5
+ };
+
+ //! Data for a cutaway object
+ struct CutawayObject {
+ int objectNumber; // 0 = JOE, -1 = MESSAGE
+ int moveToX;
+ int moveToY;
+ int bank; // 0 = PBOB, 13 = Joe Bank, else BANK NAMEstr()
+ int animList;
+ int execute; // 1 Yes, 0 No
+ int limitBobX1;
+ int limitBobY1;
+ int limitBobX2;
+ int limitBobY2;
+ int specialMove;
+ int animType; // 0 - Packet, 1 - Amal, 2 - Unpack
+ int fromObject;
+ int bobStartX;
+ int bobStartY;
+ int room;
+ int scale;
+
+ // Variables derived from the variables above
+ int song;
+
+ //! People to turn on
+ int person[MAX_PERSON_COUNT];
+
+ //! Number of elements used in _person array
+ int personCount;
+ };
+
+ struct CutawayAnim {
+ int object;
+ int unpackFrame; // Frame to unpack
+ int speed;
+ int bank;
+ int mx;
+ int my;
+ int cx;
+ int cy;
+ int scale;
+ int currentFrame; // Index to Current Frame
+ int originalFrame; // Index to Original Object Frame
+ int song;
+ };
+
+ QueenLogic *_queenLogic;
+
+ //! Raw .cut file data (without 20 byte header)
+ byte *_fileData;
+
+ //! Actual cutaway data inside of _fileData
+ byte *_objectData;
+
+ //! Pointer to next sentence string in _fileData
+ byte *_nextSentence;
+
+ //! Number of cutaway objects at _cutawayData
+ int _cutawayObjectCount;
+
+ //! Specify if the player can quit this cutaway or not
+ bool _canQuit;
+
+ //! Set to true to abort the cutaway
+ bool _quit;
+
+ //! Room to stay in
+ int _finalRoom;
+
+ //! Bank names
+ char _bankNames[MAX_BANK_NAME_COUNT][MAX_FILENAME_SIZE];
+
+ //! Filename without ".cut"
+ char _basename[MAX_FILENAME_SIZE];
+
+ //! Name of .dog file
+ char _talkFile[MAX_FILENAME_SIZE];
+
+ //! Used by changeRooms
+ int _savedPersonCount;
+
+ QueenCutaway(
+ const char *filename,
+ QueenLogic *queenLogic,
+ QueenResource *queenResource);
+ ~QueenCutaway();
+
+ //! Run this cutaway object
+ void run();
+
+ //! Load cutaway data from file
+ void load(const char *filename, QueenResource *queenResource);
+
+ //! Used by load to read string data
+ void loadStrings(byte *ptr);
+
+ //! Do something special
+ void specialMove(int index);
+
+ //! Get persons
+ byte *turnOnPeople(byte *ptr, CutawayObject &object);
+
+ //! Limit the BOB
+ void limitBob(CutawayObject &object);
+
+ //! This cutaway object occurs in another room
+ void changeRooms(CutawayObject &object);
+
+ //! Get the object type for this CutawayObject
+ ObjectType getObjectType(CutawayObject &object);
+
+ //! Perform actions for an animation
+ byte *handleAnimation(byte *ptr, CutawayObject &object);
+
+ //! Perform actions for a person record
+ void handlePersonRecord(
+ int index,
+ CutawayObject &object,
+ const char *sentence);
+
+ //! Read a string from ptr and return new ptr
+ static byte *getString(byte *ptr, char *str, int maxLength);
+
+ //! Read a CutawayObject from ptr and return new ptr
+ static byte *getCutawayObject(byte *ptr, CutawayObject &object);
+
+ //! Dump a CutawayObject with debug()
+ static void dumpCutawayObject(int index, CutawayObject &object);
+
+ static byte *getCutawayAnim(byte *ptr, int header, CutawayAnim &anim);
+ static void dumpCutawayAnim(CutawayAnim &anim);
+
+
+};
+
+#endif
+
diff --git a/queen/module.mk b/queen/module.mk
index aed3cba6c1..e2b250e22d 100644
--- a/queen/module.mk
+++ b/queen/module.mk
@@ -1,6 +1,7 @@
MODULE := queen
MODULE_OBJS = \
+ queen/cutaway.o \
queen/graphics.o \
queen/logic.o \
queen/resource.o \