diff options
-rw-r--r-- | queen/bankman.h | 16 | ||||
-rw-r--r-- | queen/command.h | 56 | ||||
-rw-r--r-- | queen/credits.cpp | 2 | ||||
-rw-r--r-- | queen/credits.h | 35 | ||||
-rw-r--r-- | queen/cutaway.h | 400 | ||||
-rw-r--r-- | queen/display.h | 59 | ||||
-rw-r--r-- | queen/graphics.cpp | 6 | ||||
-rw-r--r-- | queen/graphics.h | 38 | ||||
-rw-r--r-- | queen/grid.h | 36 | ||||
-rw-r--r-- | queen/input.h | 204 | ||||
-rw-r--r-- | queen/logic.h | 62 | ||||
-rw-r--r-- | queen/music.cpp | 539 | ||||
-rw-r--r-- | queen/resource.cpp | 2 | ||||
-rw-r--r-- | queen/resource.h | 87 | ||||
-rw-r--r-- | queen/talk.h | 17 | ||||
-rw-r--r-- | queen/walk.cpp | 42 | ||||
-rw-r--r-- | queen/walk.h | 7 |
17 files changed, 923 insertions, 685 deletions
diff --git a/queen/bankman.h b/queen/bankman.h index f02b59d85f..06c8955502 100644 --- a/queen/bankman.h +++ b/queen/bankman.h @@ -35,14 +35,28 @@ public: BankManager(Resource *res); ~BankManager(); + //! load a bank into the specified slot void load(const char *bankname, uint32 bankslot); + + //! unpack a frame from a loaded bank void unpack(uint32 srcframe, uint32 dstframe, uint32 bankslot); + + //! unpack a frame over an existing one from a loaded bank void overpack(uint32 srcframe, uint32 dstframe, uint32 bankslot); + + //! close a bank void close(uint32 bankslot); + + //! reset this BankManager void flush(); + //! get a reference to unpacked frame BobFrame *fetchFrame(uint32 index); + + //! erase a frame void eraseFrame(uint32 index); + + //! erase all unpacked frames void eraseFrames(bool joe); enum { @@ -58,7 +72,7 @@ private: uint8 *data; }; - //! unbanked bob frames + //! unpacked bob frames BobFrame _frames[MAX_FRAMES_NUMBER]; //! banked bob frames diff --git a/queen/command.h b/queen/command.h index df9dffcc2b..685699cf8c 100644 --- a/queen/command.h +++ b/queen/command.h @@ -34,23 +34,43 @@ struct CmdText { CmdText(bool reversed, uint8 y, QueenEngine *vm); + //! reset the command sentence void clear(); + + //! display the command sentence using the specified color void display(uint8 color); + + //! display a temporary command sentence using the specified parameters void displayTemp(uint8 color, Verb v, const char *name = NULL, bool outlined = false); + + //! display a temporary command sentence using the specified parameters void displayTemp(uint8 color, const char *name, bool outlined = false); + + //! set the verb for the command sentence void setVerb(Verb v); + + //! set the link word (between verb and object) for the command sentence void addLinkWord(Verb v); + + //! add an object name to the command sentence void addObject(const char *objName); + + //! returns true if the command sentence is empty bool isEmpty() const; enum { MAX_COMMAND_LEN = 256, COMMAND_Y_POS = 151 }; - + uint8 _y; + + //! flag indicating if the words in the sentence are reversed (hebrew version) bool _isReversed; + + //! buffer containing the current command sentence char _command[MAX_COMMAND_LEN]; + QueenEngine *_vm; }; @@ -92,25 +112,49 @@ public: private: + //! get a reference to the ObjectData for the specified room object ObjectData *findObjectData(uint16 objRoomNum) const; + + //! get a reference to the ItemData for the specified inventory object ItemData *findItemData(Verb invNum) const; + //! execute the current command int16 executeCommand(uint16 comId, int16 condResult); + //! move Joe to the specified position, handling new room switching int16 makeJoeWalkTo(int16 x, int16 y, int16 objNum, Verb v, bool mustWalk); + //! update command state with current selected action void grabCurrentSelection(); + + //! update command state with current selected object void grabSelectedObject(int16 objNum, uint16 objState, uint16 objName); + + //! update command state with current selected inventory object void grabSelectedItem(); + + //! update command state with current selected room object void grabSelectedNoun(); + + //! update command state with current selected verb void grabSelectedVerb(); + //! if the description is a cutaway file, execute it bool executeIfCutaway(const char *description); + + //! if the description is a dialog file, execute it bool executeIfDialog(const char *description); + //! handle a wrong/invalid user action bool handleWrongAction(); + + //! make Joe speak something for a wrong/invalid action void sayInvalidAction(Verb action, int16 subj1, int16 subj2); + + //! update an object state void changeObjectState(Verb action, int16 obj, int16 song, bool cutDone); + + //! reset current action void cleanupCurrentAction(); //! OPEN_CLOSE_OTHER(OBJECT_DATA[S][4]) @@ -140,22 +184,32 @@ private: //! get the current icon panel under the cursor (inventory item or verb) void lookForCurrentIcon(int16 cx, int16 cy); + //! returns true if the verb is an action verb bool isVerbAction(Verb v) const { return (v >= VERB_PANEL_COMMAND_FIRST && v <= VERB_PANEL_COMMAND_LAST) || (v == VERB_WALK_TO); }; + + //! return true if the verb is an inventory item bool isVerbInv(Verb v) const { return v >= VERB_INV_FIRST && v <= VERB_INV_LAST; } + + //! returns true if the specified verb is an inventory scroll bool isVerbInvScroll(Verb v) const { return v == VERB_SCROLL_UP || v == VERB_SCROLL_DOWN; } + //! commands list for each possible action CmdListData *_cmdList; uint16 _numCmdList; + //! commands list for areas CmdArea *_cmdArea; uint16 _numCmdArea; + //! commands list for objects CmdObject *_cmdObject; uint16 _numCmdObject; + //! commands list for inventory CmdInventory *_cmdInventory; uint16 _numCmdInventory; + //! commands list for gamestate CmdGameState *_cmdGameState; uint16 _numCmdGameState; diff --git a/queen/credits.cpp b/queen/credits.cpp index 21b9d52599..0f6447b3b0 100644 --- a/queen/credits.cpp +++ b/queen/credits.cpp @@ -62,7 +62,7 @@ void Credits::update() { return; for (;;) { - char *line = _credits->nextLine(); + const char *line = _credits->nextLine(); if (0 == memcmp(line, "EN", 2)) { _running = false; diff --git a/queen/credits.h b/queen/credits.h index aa40961a15..eba91bb9cd 100644 --- a/queen/credits.h +++ b/queen/credits.h @@ -31,38 +31,55 @@ class QueenEngine; class LineReader; class Credits { - public: Credits(QueenEngine *vm, const char* filename); ~Credits(); + //! update/display credits for current room void update(); + + //! handles room switching void nextRoom(); + //! returns true if the credits are running bool running() const { return _running; } private: - QueenEngine *_vm; - LineReader *_credits; - - struct Line - { - short x,y,color,fontSize; - char *text; + struct Line { + short x, y, color, fontSize; + const char *text; }; - + + //! contains the formatted lines of texts to display Line _list[19]; + //! true if end of credits description hasn't been reached bool _running; + + //! number of elements in _list array int _count; + + //! pause counts for next room int _pause; + + //! current text justification mode int _justify; + + //! current font size (unused ?) int _fontSize; + + //! current text color int _color; + + //! current text position int _zone; + //! contains the credits description + LineReader *_credits; + + QueenEngine *_vm; }; } // End of namespace Queen diff --git a/queen/cutaway.h b/queen/cutaway.h index 29e21df03a..37bf920d82 100644 --- a/queen/cutaway.h +++ b/queen/cutaway.h @@ -30,245 +30,233 @@ namespace Queen { class QueenEngine; class Cutaway { - public: - //! Public interface to run a cutaway from a file - static void run( - const char *filename, - char *nextFilename, - QueenEngine *vm); - - public: - //! 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, - CUTAWAY_BANK = 8, - MAX_BANK_NAME_COUNT = 5, - MAX_FILENAME_LENGTH = 12, - MAX_FILENAME_SIZE = (MAX_FILENAME_LENGTH + 1), - MAX_PERSON_FACE_COUNT = 13, - 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 - }; - - private: - //! Data for a cutaway object - struct CutawayObject { - int16 objectNumber; // 0 = JOE, -1 = MESSAGE - int16 moveToX; - int16 moveToY; - int16 bank; // 0 = PBOB, 13 = Joe Bank, else BANK NAMEstr() - int16 animList; - int16 execute; // 1 Yes, 0 No - int16 limitBobX1; - int16 limitBobY1; - int16 limitBobX2; - int16 limitBobY2; - int16 specialMove; - int16 animType; // 0 - Packet, 1 - Amal, 2 - Unpack - int16 fromObject; - int16 bobStartX; - int16 bobStartY; - int16 room; - int16 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 { - int16 object; - int16 unpackFrame; // Frame to unpack - int16 speed; - int16 bank; - int16 mx; - int16 my; - int16 cx; - int16 cy; - int16 scale; - int16 currentFrame; // Index to Current Frame - int16 originalFrame; // Index to Original Object Frame - int16 song; - bool flip; // set this if unpackFrame is negative - }; - - struct ObjectDataBackup { - int index; - int16 name; - int16 image; - }; - - struct PersonFace { - int16 index; - int16 image; - }; - - QueenEngine *_vm; - - //! Raw .cut file data (without 20 byte header) - byte *_fileData; - - //! COMPANEL - int16 _comPanel; - - //! Game state data inside of _fileDat - byte *_gameStatePtr; - - //! Actual cutaway data inside of _fileData - byte *_objectData; - - //! Pointer to next sentence string in _fileData - uint16 _nextSentenceOff; - - //! ??? - bool _roomFade; - - //! Number of cutaway objects at _cutawayData - int16 _cutawayObjectCount; - - //! This cutaway is followed by another - bool _anotherCutaway; - - //! Room before cutaway - int _initialRoom; - - //! Temporary room for cutaway - int _temporaryRoom; - - //! Room to stay in - int _finalRoom; - - //! Bank names - char _bankNames[MAX_BANK_NAME_COUNT][MAX_FILENAME_SIZE]; +public: + + //! Public interface to run a cutaway from a file + static void run(const char *filename, char *nextFilename, QueenEngine *vm); + + //! 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, + CUTAWAY_BANK = 8, + MAX_BANK_NAME_COUNT = 5, + MAX_FILENAME_LENGTH = 12, + MAX_FILENAME_SIZE = (MAX_FILENAME_LENGTH + 1), + MAX_PERSON_FACE_COUNT = 13, + 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 + }; + +private: + //! Data for a cutaway object + struct CutawayObject { + int16 objectNumber; // 0 = JOE, -1 = MESSAGE + int16 moveToX; + int16 moveToY; + int16 bank; // 0 = PBOB, 13 = Joe Bank, else BANK NAMEstr() + int16 animList; + int16 execute; // 1 Yes, 0 No + int16 limitBobX1; + int16 limitBobY1; + int16 limitBobX2; + int16 limitBobY2; + int16 specialMove; + int16 animType; // 0 - Packet, 1 - Amal, 2 - Unpack + int16 fromObject; + int16 bobStartX; + int16 bobStartY; + int16 room; + int16 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 { + int16 object; + int16 unpackFrame; // Frame to unpack + int16 speed; + int16 bank; + int16 mx; + int16 my; + int16 cx; + int16 cy; + int16 scale; + int16 currentFrame; // Index to Current Frame + int16 originalFrame; // Index to Original Object Frame + int16 song; + bool flip; // set this if unpackFrame is negative + }; + + struct ObjectDataBackup { + int index; + int16 name; + int16 image; + }; + + struct PersonFace { + int16 index; + int16 image; + }; + + QueenEngine *_vm; + + //! Raw .cut file data (without 20 byte header) + byte *_fileData; + + //! COMPANEL + int16 _comPanel; + + //! Game state data inside of _fileDat + byte *_gameStatePtr; + + //! Actual cutaway data inside of _fileData + byte *_objectData; + + //! Pointer to next sentence string in _fileData + uint16 _nextSentenceOff; + + //! ??? + bool _roomFade; + + //! Number of cutaway objects at _cutawayData + int16 _cutawayObjectCount; + + //! This cutaway is followed by another + bool _anotherCutaway; + + //! Room before cutaway + int _initialRoom; + + //! Temporary room for cutaway + int _temporaryRoom; + + //! 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]; + //! Filename without ".cut" + char _basename[MAX_FILENAME_SIZE]; - //! Name of .dog file - char _talkFile[MAX_FILENAME_SIZE]; + //! Name of .dog file + char _talkFile[MAX_FILENAME_SIZE]; - //! Person to talk to - int16 _talkTo; + //! Person to talk to + int16 _talkTo; - //! Used by changeRooms - ObjectDataBackup _personData[MAX_PERSON_COUNT]; + //! Used by changeRooms + ObjectDataBackup _personData[MAX_PERSON_COUNT]; - //! Number of elements used in _personData array - int _personDataCount; + //! Number of elements used in _personData array + int _personDataCount; - //! Used by handlePersonRecord() - PersonFace _personFace[MAX_PERSON_FACE_COUNT]; + //! Used by handlePersonRecord() + PersonFace _personFace[MAX_PERSON_FACE_COUNT]; - //! Number of entries in _personFace array - int _personFaceCount; + //! Number of entries in _personFace array + int _personFaceCount; - //! Play this song when leaving cutaway - int16 _lastSong; + //! Play this song when leaving cutaway + int16 _lastSong; - //! Song played before running comic.cut - int16 _songBeforeComic; + //! Song played before running comic.cut + int16 _songBeforeComic; - int16 _currentImage; + int16 _currentImage; - Cutaway(const char *filename, - QueenEngine *vm); - ~Cutaway(); + Cutaway(const char *filename, QueenEngine *vm); + ~Cutaway(); - //! Run this cutaway object - void run(char *nextFilename); + //! Run this cutaway object + void run(char *nextFilename); - //! Load cutaway data from file - void load(const char *filename); + //! Load cutaway data from file + void load(const char *filename); - //! Used by load to read string data - void loadStrings(uint16 offset); + //! Used by load to read string data + void loadStrings(uint16 offset); - //! Get persons - const byte *turnOnPeople(const byte *ptr, CutawayObject &object); + //! Get persons + const byte *turnOnPeople(const byte *ptr, CutawayObject &object); - //! Limit the BOB - void limitBob(CutawayObject &object); + //! Limit the BOB + void limitBob(CutawayObject &object); - //! This cutaway object occurs in another room - void changeRooms(CutawayObject &object); + //! This cutaway object occurs in another room + void changeRooms(CutawayObject &object); - //! Get the object type for this CutawayObject - ObjectType getObjectType(CutawayObject &object); + //! Get the object type for this CutawayObject + ObjectType getObjectType(CutawayObject &object); - //! Perform actions for an animation - const byte *handleAnimation(const byte *ptr, CutawayObject &object); + //! Perform actions for an animation + const byte *handleAnimation(const byte *ptr, CutawayObject &object); - //! Perform actions for a person record - void handlePersonRecord( - int index, - CutawayObject &object, - const char *sentence); + //! Perform actions for a person record + void handlePersonRecord(int index, CutawayObject &object, const char *sentence); - //! Perform text actions - void handleText( - int index, - ObjectType type, - CutawayObject &object, - const char *sentence); + //! Perform text actions + void handleText(int index, ObjectType type, CutawayObject &object, const char *sentence); - //! Restore Logic::_objectData from _personData - void restorePersonData(); + //! Restore Logic::_objectData from _personData + void restorePersonData(); - //! Stop the cutaway - void stop(); + //! Stop the cutaway + void stop(); - //! Update game state after cutaway - void updateGameState(); + //! Update game state after cutaway + void updateGameState(); - //! Prepare for talk after cutaway - void talk(char *nextFilename); + //! Prepare for talk after cutaway + void talk(char *nextFilename); - //! Get CutawayAnim data from ptr and return new ptr - const byte *getCutawayAnim(const byte *ptr, int header, CutawayAnim &anim); + //! Get CutawayAnim data from ptr and return new ptr + const byte *getCutawayAnim(const byte *ptr, int header, CutawayAnim &anim); - //! Special animation - int makeComplexAnimation(int16 currentImage, CutawayAnim *objAnim, int frameCount); + //! Special animation + int makeComplexAnimation(int16 currentImage, CutawayAnim *objAnim, int frameCount); - //! Read a CutawayObject from ptr and return new ptr - static const byte *getCutawayObject(const byte *ptr, CutawayObject &object); + //! Read a CutawayObject from ptr and return new ptr + static const byte *getCutawayObject(const byte *ptr, CutawayObject &object); - //! Dump a CutawayObject with debug() - void dumpCutawayObject(int index, CutawayObject &object); + //! Dump a CutawayObject with debug() + void dumpCutawayObject(int index, CutawayObject &object); - //! Used by handleText() - int countSpaces(ObjectType type, const char *segment); + //! Used by handleText() + int countSpaces(ObjectType type, const char *segment); - //! Scale Joe - int scale(CutawayObject &object); + //! Scale Joe + int scale(CutawayObject &object); - //! Dump CutawayAnum data with debug() - static void dumpCutawayAnim(CutawayAnim &anim); + //! Dump CutawayAnum data with debug() + static void dumpCutawayAnim(CutawayAnim &anim); - bool inRange(int16 x, int16 l, int16 h) const { return (x <= h && x >= l); } + bool inRange(int16 x, int16 l, int16 h) const { return (x <= h && x >= l); } }; } // End of namespace Queen diff --git a/queen/display.h b/queen/display.h index 4c5857018f..e3d0e5b754 100644 --- a/queen/display.h +++ b/queen/display.h @@ -38,28 +38,61 @@ public: Display(QueenEngine *vm, OSystem *system); ~Display(); + //! initialise dynalum for the specified room void dynalumInit(const char *roomName, uint16 roomNum); + + //! update dynalum for the current room void dynalumUpdate(int16 x, int16 y); + //! convert palette from RGB to RGBA (used before uploading to the backend) void palConvert(uint8 *outPal, const uint8 *inPal, int start, int end); + + //! update the palette void palSet(const uint8 *pal, int start, int end, bool updateScreen = false); + + //! setup palette for Joe's dress void palSetJoeDress(); + + //! setup palette for Joe's normal clothes void palSetJoeNormal(); + + //! setup palette for panel and inventory objects void palSetPanel(); + + //! fade the current palette in void palFadeIn(uint16 roomNum, bool dynalum = false, int16 dynaX = 0, int16 dynaY = 0); + + //! fade the current palette out void palFadeOut(uint16 roomNum); + + //! grey the panel area (used when panel is disabled) void palGreyPanel(); + + //! scroll some palette colors void palScroll(int start, int end); + + //! custom palette effect for the specified room void palCustomColors(uint16 roomNum); + + //! custom palette scroll for the specified room void palCustomScroll(uint16 roomNum); + + //! process a 'palette flash' effect void palCustomFlash(); + void palCustomLightsOff(uint16 roomNum); void palCustomLightsOn(uint16 roomNum); + + //! mark all palette entries as dirty void palSetAllDirty() { _pal.dirtyMin = 0; _pal.dirtyMax = 255; } + //! returns the number of colors used by the room int getNumColorsForRoom(uint16 room) const; + + //! returns true if we shouldn't fade the palette in the specified room bool isPalFadingDisabled(uint16 room) const; + //! change fullscreen/panel mode void screenMode(int comPanel, bool inCutaway); void prepareUpdate(); @@ -75,6 +108,7 @@ public: void blit(uint8 *dstBuf, uint16 dstPitch, uint16 x, uint16 y, const uint8 *srcBuf, uint16 srcPitch, uint16 w, uint16 h, bool xflip, bool masked); void fill(uint8 *dstBuf, uint16 dstPitch, uint16 x, uint16 y, uint16 w, uint16 h, uint8 color); + //! decode a PCX stream void readPCX(uint8 *dst, uint16 dstPitch, const uint8 *src, uint16 w, uint16 h); void horizontalScrollUpdate(int16 xCamera); @@ -84,20 +118,39 @@ public: void fullscreen(bool fs) { _fullRefresh = 2; _fullscreen = fs; } bool fullscreen() const { return _fullscreen; } + //! mark the specified block as dirty void setDirtyBlock(uint16 x, uint16 y, uint16 w, uint16 h); + + //! force a full refresh (bypassing the dirtyblocks rendering), on next screen update void forceFullRefresh() { _fullRefresh = 2; } + //! change mouse cursor bitmap void setMouseCursor(uint8 *buf, uint16 w, uint16 h); + + //! show/hide mouse cursor void showMouseCursor(bool show); + //! initialise font, compute justification sizes void initFont(); + //! add the specified text to the texts list void setText(uint16 x, uint16 y, const char *text, bool outlined = true); + + //! add the specified text to the texts list void setTextCentered(uint16 y, const char *text, bool outlined = true); + + //! draw the text lists void drawTexts(); + + //! remove entries from the texts list void clearTexts(uint16 y1, uint16 y2); + + //! change the current text color void textCurrentColor(uint8 color) { _curTextColor = color; } + + //! change the text color for the specified texts list entry void textColor(uint16 y, uint8 color) { _texts[y].color = color; } + int textCenterX(const char *text) const; uint16 textWidth(const char *text) const; uint16 textWidth(const char *text, uint16 len) const; @@ -166,13 +219,15 @@ private: uint16 _horizontalScroll; uint16 _bdWidth, _bdHeight; + //! texts list TextSlot _texts[GAME_SCREEN_HEIGHT]; + + //! current text color to use for display uint8 _curTextColor; + //! font justification sizes uint8 _charWidth[256]; - bool _gotTick; - Common::RandomSource _rnd; Dynalum _dynalum; OSystem *_system; diff --git a/queen/graphics.cpp b/queen/graphics.cpp index ae87fb1e8c..1f59387e11 100644 --- a/queen/graphics.cpp +++ b/queen/graphics.cpp @@ -416,11 +416,7 @@ BobSlot *Graphics::bob(int index) { return &_bobs[index]; } -void Graphics::setBobText( - const BobSlot *pbs, - const char *text, - int textX, int textY, - int color, int flags) { +void Graphics::setBobText(const BobSlot *pbs, const char *text, int textX, int textY, int color, int flags) { if (text[0] == '\0') return; diff --git a/queen/graphics.h b/queen/graphics.h index 03fa825b5a..1f8f22310b 100644 --- a/queen/graphics.h +++ b/queen/graphics.h @@ -72,8 +72,6 @@ struct BobSlot { uint16 dx, dy; uint16 total; - static const Box _defaultBox; - void curPos(int16 xx, int16 yy); void move(int16 dstx, int16 dsty, int16 spd); void moveOneStep(); @@ -85,6 +83,8 @@ struct BobSlot { void scaleWalkSpeed(uint16 ms); void clear(); + + static const Box _defaultBox; }; class QueenEngine; @@ -95,21 +95,46 @@ public: Graphics(QueenEngine *vm); ~Graphics(); + //! unpacks control frames (ie. arrows) void unpackControlBank(); + + //! setup dialog arrows void setupArrows(); + + //! setup mouse cursor void setupMouseCursor(); + //! draw a bob void drawBob(const BobSlot *bs, const BobFrame *bf, const Box *box, int16 x, int16 y); + + //! draw an inventory item void drawInventoryItem(uint32 frameNum, uint16 x, uint16 y); + + //! draw a bob directly on the backdrop bitmap void pasteBob(uint16 objNum, uint16 image); + + //! resize a bobframe void shrinkFrame(const BobFrame *bf, uint16 percentage); + + //! animate/move bobs and sort them void sortBobs(); + + //! draw all the sorted bobs void drawBobs(); + + //! clear all setup bobs void clearBobs(); + + //! stop all animating/movings bobs void stopBobs(); + + //! returns a reference to the specified bob BobSlot *bob(int index); + + //! display a text 'near' the specified bob void setBobText(const BobSlot *bob, const char *text, int textX, int textY, int color, int flags); + //! handles parallax scrolling for the specified room void handleParallax(uint16 roomNum); void setupNewRoom(const char *room, uint16 roomNum, int16 *furniture, uint16 furnitureCount); @@ -173,18 +198,19 @@ private: uint16 _personFrames[4]; - //! Number of animated furniture in current room + //! number of animated furniture in current room uint16 _numFurnitureAnimated; - //! Number of static furniture in current room + //! number of static furniture in current room uint16 _numFurnitureStatic; - //! Total number of frames for the animated furniture + //! total number of frames for the animated furniture uint16 _numFurnitureAnimatedLen; - //! Current number of frames unpacked + //! current number of frames unpacked uint16 _numFrames; + //! bob number followed by camera int _cameraBob; QueenEngine *_vm; diff --git a/queen/grid.h b/queen/grid.h index b85451d5c7..7b53be6b77 100644 --- a/queen/grid.h +++ b/queen/grid.h @@ -41,25 +41,55 @@ public: Grid(QueenEngine *vm); ~Grid(); + //! read areas data from specified stream void readDataFrom(uint16 numObjects, uint16 numRooms, byte *&ptr); + //! defines a new zone void setZone(GridScreen screen, uint16 zoneNum, uint16 x1, uint16 y1, uint16 x2, uint16 y2); + + //! defines a new zone void setZone(GridScreen screen, uint16 zoneNum, const Box &box); + + //! find the zone number containing the specified point uint16 findZoneForPos(GridScreen screen, uint16 x, uint16 y) const; + + //! find the area number containing the specified point uint16 findAreaForPos(GridScreen screen, uint16 x, uint16 y) const; + + //! clear the zones for current room void clear(GridScreen screen); + + //! setup objects zones for the specified room void setupNewRoom(uint16 room, uint16 firstRoomObjNum); + + //! setup panel zones void setupPanel(); + + //! draw the zones for current room (debug only) void drawZones(); + + //! retuns a reference to the specified zone const Box *zone(GridScreen screen, uint16 index) const; + //! get the verb for the specified cursor position Verb findVerbUnderCursor(int16 cursorx, int16 cursory) const; + + //! get the object for the specified cursor position uint16 findObjectUnderCursor(int16 cursorx, int16 cursory) const; + + //! get the object for the specified zone number uint16 findObjectNumber(uint16 zoneNum) const; + + //! get scale for the specified position uint16 findScale(uint16 x, uint16 y) const; + //! returns a reference to the specfied room area Area *area(int room, int num) const { return &_area[room][num]; } + + //! returns the number of areas in this room uint16 areaMax(int room) const { return _areaMax[room]; } + + //! returns the number of objects in this room uint16 objMax(int room) const { return _objMax[room]; } void saveState(byte *&ptr); @@ -78,16 +108,22 @@ private: Box box; }; + //! current room zones ZoneSlot _zones[GS_COUNT][MAX_ZONES_NUMBER]; + //! number of objects for each room int16 *_objMax; + //! number of areas for each room int16 *_areaMax; + //! areas for each room Area (*_area)[MAX_AREAS_NUMBER]; + //! total number of room areas uint16 _numRoomAreas; + //! box/zone for each objects Box *_objectBox; QueenEngine *_vm; diff --git a/queen/input.h b/queen/input.h index bc50ccfe9e..7dc2f1c5b4 100644 --- a/queen/input.h +++ b/queen/input.h @@ -30,146 +30,146 @@ class OSystem; namespace Queen { class Input { +public: - public: + //! Adjust here to change delays! + enum { + DELAY_SHORT = 10, + DELAY_NORMAL = 100, + DELAY_SCREEN_BLANKER = 5 * 60 * 1000 + }; + enum { + MOUSE_LBUTTON = 1, + MOUSE_RBUTTON = 2 + }; - //! Adjust here to change delays! - enum { - DELAY_SHORT = 10, - DELAY_NORMAL = 100, - DELAY_SCREEN_BLANKER = 5 * 60 * 1000 - }; + Input(Language language, OSystem *system); - enum { - MOUSE_LBUTTON = 1, - MOUSE_RBUTTON = 2 - }; + //! calls the other delay() with a value adjusted depending on _fastMode + void delay(); - Input(Language language, OSystem *system); + //! moved QueenEngine::delay() here + void delay(uint amount); - //! calls the other delay() with a value adjusted depending on _fastMode - void delay(); + //! convert input to verb + int checkKeys(); - //! moved QueenEngine::delay() here - void delay(uint amount); + //! use instead of KEYVERB=0 + void clearKeyVerb() { _keyVerb = VERB_NONE; } - //! convert input to verb - int checkKeys(); + void canQuit(bool cq) { _canQuit = cq; } - //! use instead of KEYVERB=0 - void clearKeyVerb() { _keyVerb = VERB_NONE; } + bool cutawayRunning() const { return _cutawayRunning; } + void cutawayRunning(bool running) { _cutawayRunning = running; } - void canQuit(bool cq) { _canQuit = cq; } + bool cutawayQuit() const { return _cutawayQuit; } + void cutawayQuitReset() { _cutawayQuit = false; } - bool cutawayRunning() const { return _cutawayRunning; } - void cutawayRunning(bool running) { _cutawayRunning = running; } + void dialogueRunning(bool running) { _dialogueRunning = running; } - bool cutawayQuit() const { return _cutawayQuit; } - void cutawayQuitReset() { _cutawayQuit = false; } + bool talkQuit() const { return _talkQuit; } + void talkQuitReset() { _talkQuit = false; } - void dialogueRunning(bool running) { _dialogueRunning = running; } + bool quickSave() const { return _quickSave; } + void quickSaveReset() { _quickSave = false; } + bool quickLoad() const { return _quickLoad; } + void quickLoadReset() { _quickLoad = false; } + bool debugger() const { return _debugger; } + void debuggerReset() { _debugger = false; } - bool talkQuit() const { return _talkQuit; } - void talkQuitReset() { _talkQuit = false; } + bool fastMode() const { return _fastMode; } + void fastMode(bool fm) { _fastMode = fm; } - bool quickSave() const { return _quickSave; } - void quickSaveReset() { _quickSave = false; } - bool quickLoad() const { return _quickLoad; } - void quickLoadReset() { _quickLoad = false; } - bool debugger() const { return _debugger; } - void debuggerReset() { _debugger = false; } + Verb keyVerb() const { return _keyVerb; } - bool fastMode() const { return _fastMode; } - void fastMode(bool fm) { _fastMode = fm; } + int mousePosX() const { return _mouse_x; } + int mousePosY() const { return _mouse_y; } - Verb keyVerb() const { return _keyVerb; } + int mouseButton() const { return _mouseButton; } + void clearMouseButton() { _mouseButton = 0; } - int mousePosX() const { return _mouse_x; } - int mousePosY() const { return _mouse_y; } + //! returns user idle time (used by Display, to trigger the screensaver) + uint32 idleTime() const { return _idleTime; } - int mouseButton() const { return _mouseButton; } - void clearMouseButton() { _mouseButton = 0; } +private: - uint32 idleTime() const { return _idleTime; } - - private: - - enum KeyCode { - KEY_SPACE = ' ', - KEY_COMMA = ',', - KEY_DOT = '.', - - KEY_DIGIT_1 = '1', - KEY_DIGIT_2 = '2', - KEY_DIGIT_3 = '3', - KEY_DIGIT_4 = '4', - - KEY_ESCAPE = 27, - KEY_RETURN = 13, - KEY_BACKSPACE = 8, + enum KeyCode { + KEY_SPACE = ' ', + KEY_COMMA = ',', + KEY_DOT = '.', + + KEY_DIGIT_1 = '1', + KEY_DIGIT_2 = '2', + KEY_DIGIT_3 = '3', + KEY_DIGIT_4 = '4', + + KEY_ESCAPE = 27, + KEY_RETURN = 13, + KEY_BACKSPACE = 8, - KEY_F1 = 282, - KEY_F11 = KEY_F1 + 10, - KEY_F5 = KEY_F1 + 4, - KEY_F12 - }; - - enum { - LANGUAGE_COUNT = 6 - }; + KEY_F1 = 282, + KEY_F11 = KEY_F1 + 10, + KEY_F5 = KEY_F1 + 4, + KEY_F12 + }; + + enum { + LANGUAGE_COUNT = 6 + }; - //! Used to get keyboard and mouse events - OSystem *_system; + //! used to get keyboard and mouse events + OSystem *_system; - //! Some cutaways require update() run faster - bool _fastMode; + //! some cutaways require update() run faster + bool _fastMode; - //! The current verb received from keyboard - Verb _keyVerb; + //! the current verb received from keyboard + Verb _keyVerb; - //! set if a cutaway is running - bool _cutawayRunning; + //! set if a cutaway is running + bool _cutawayRunning; - //! set this if we can quit - bool _canQuit; + //! set this if we can quit + bool _canQuit; - //! moved Cutaway::_quit here - bool _cutawayQuit; + //! moved Cutaway::_quit here + bool _cutawayQuit; - //! set if a dialogue is running - bool _dialogueRunning; + //! set if a dialogue is running + bool _dialogueRunning; - //! moved Talk::_quit here - bool _talkQuit; + //! moved Talk::_quit here + bool _talkQuit; - //! Set if quicksave requested - bool _quickSave; + //! set if quicksave requested + bool _quickSave; - //! Set if quickload requested - bool _quickLoad; + //! set if quickload requested + bool _quickLoad; - //! Set if debugger requested - bool _debugger; + //! set if debugger requested + bool _debugger; - //! Set by delay(); - int _inKey; + //! set by delay(); + int _inKey; - //! Set by delay(); - int _mouse_x, _mouse_y; + //! set by delay(); + int _mouse_x, _mouse_y; - //! Set by delay(); - int _mouseButton; + //! set by delay(); + int _mouseButton; - uint32 _idleTime; + //! user idle time + uint32 _idleTime; - //! Command keys for current language - const char *_currentCommandKeys; + //! command keys for current language + const char *_currentCommandKeys; - //! Command keys for all languages - static const char *_commandKeys[LANGUAGE_COUNT]; + //! command keys for all languages + static const char *_commandKeys[LANGUAGE_COUNT]; - //! Verbs matching the command keys - static const Verb _verbKeys[8]; + //! verbs matching the command keys + static const Verb _verbKeys[8]; }; } // End of namespace Queen diff --git a/queen/logic.h b/queen/logic.h index 483a6c25fc..68ac144ccd 100644 --- a/queen/logic.h +++ b/queen/logic.h @@ -129,28 +129,42 @@ public: bool initPerson(uint16 noun, const char *actorName, bool loadBank, Person *pp); uint16 findPersonNumber(uint16 obj, uint16 room) const; + //! load banks used for Joe animation void loadJoeBanks(const char *animBank, const char *standBank); - //! Load the various bobs needed to animate Joe + //! load the various bobs needed to animate Joe void setupJoe(); - //! Setup Joe at the right place when entering a room + //! setup Joe at the right place when entering a room void setupJoeInRoom(bool autoPosition, uint16 scale); uint16 joeFace(); void joeGrab(int16 grabState); + //! change Joe clothes to dress void joeUseDress(bool showCut); + + //! restore Joe clothes void joeUseClothes(bool showCut); + + //! change Joe clothes to underwear void joeUseUnderwear(); - void makeJoeSpeak(uint16 descNum, bool objectType = false); + void makeJoeSpeak(uint16 descNum, bool objectType = false); void makePersonSpeak(const char *sentence, Person *person, const char *voiceFilePrefix); + + //! start the specified dialogue void startDialogue(const char *dlgFile, int personInRoom, char *cutaway); + + //! play the specified cutaway void playCutaway(const char *cutFile, char *next = NULL); void inventorySetup(); + + //! get the inventory item for the specified inventory slot uint16 findInventoryItem(int invSlot) const; + + //! refresh inventory contents void inventoryRefresh(); int16 previousInventoryItem(int16 first) const; int16 nextInventoryItem(int16 first) const; @@ -161,11 +175,13 @@ public: void inventoryScroll(uint16 count, bool up); void removeHotelItemsFromInventory(); - //! Copy data from dummy object to object + //! copy data from dummy object to object void objectCopy(int dummyObjectIndex, int objectIndex); + //! handle a particular event when Joe walks on this area void handleSpecialArea(Direction facing, uint16 areaNum, uint16 walkDataNum); + //! handle the pinnacle room (in jungle) void handlePinnacleRoom(); void update(); @@ -175,19 +191,21 @@ public: void setupRestoredGame(); - //! Ugly hack from original code + //! ugly hack from original code void sceneReset() { _scene = 0; } - //! Make a scene + //! make a scene void sceneStart(); - //! Stop making a scene + //! stop making a scene void sceneStop(); void changeRoom(); + //! enter the Journal (save/load, configuration) virtual void useJournal() = 0; + //! execute a special move void executeSpecialMove(uint16 sm); void startCredits(const char *filename); @@ -255,19 +273,19 @@ protected: uint16 _oldRoom; uint16 _newRoom; - //! Total number of room in game + //! total number of room in game uint16 _numRooms; - //! First object number in room + //! first object number in room uint16 *_roomData; - //! Background music to play in room + //! background music to play in room uint16 *_sfxName; - //! Bounding box of object + //! bounding box of object Box *_objectBox; - //! Inventory items + //! inventory items ItemData *_itemData; uint16 _numItems; @@ -283,7 +301,7 @@ protected: ActorData *_actorData; uint16 _numActors; - //! Walk off point for an object + //! walk off point for an object WalkOffData *_walkOffData; uint16 _numWalkOffs; @@ -293,32 +311,32 @@ protected: GraphicAnim *_graphicAnim; uint16 _numGraphicAnim; - //! Actor position in room is _walkOffData[_entryObj] + //! actor initial position in room is _walkOffData[_entryObj] int16 _entryObj; - //! Object description (Look At) + //! object description (Look At) Common::StringList _objDescription; uint16 _numDescriptions; Common::StringList _objName; uint16 _numNames; - //! Room name, prefix for data files (PCX, LUM...) + //! room name, prefix for data files (PCX, LUM...) Common::StringList _roomName; Common::StringList _verbName; Common::StringList _joeResponse; - //! Actor animation string + //! actor animation strings Common::StringList _aAnim; uint16 _numAAnim; - //! Actor name + //! actor names Common::StringList _aName; uint16 _numAName; - //! Actor filename + //! actor filenames Common::StringList _aFile; uint16 _numAFile; @@ -333,13 +351,13 @@ protected: TalkSelected _talkSelected[TALK_SELECTED_COUNT]; - //! Inventory items + //! inventory items int16 _inventoryItem[4]; - //! Puzzle counter for room T7 + //! puzzle counter for room T7 uint8 _puzzleAttemptCount; - //! Cutscene counter + //! cutscene counter int _scene; Credits *_credits; diff --git a/queen/music.cpp b/queen/music.cpp index c52974a757..15b6596299 100644 --- a/queen/music.cpp +++ b/queen/music.cpp @@ -42,322 +42,315 @@ static const byte mt32_to_gm[128] = { 47, 117, 127, 118, 118, 116, 115, 119, 115, 112, 55, 124, 123, 0, 14, 117 // 7x }; - MusicPlayer::MusicPlayer(MidiDriver *driver, byte *data, uint32 size) : _driver(driver), _isPlaying(false), _looping(false), _randomLoop(false), _masterVolume(192), _queuePos(0), _musicData(data), _musicDataSize(size), _passThrough(false), _buf(0) { - memset(_channel, 0, sizeof(_channel)); - queueClear(); - _lastSong = _currentSong = 0; - _parser = MidiParser::createParser_SMF(); - _parser->setMidiDriver(this); - _parser->setTimerRate(_driver->getBaseTempo()); - - _numSongs = READ_LE_UINT16(_musicData); - this->open(); - } +MusicPlayer::MusicPlayer(MidiDriver *driver, byte *data, uint32 size) : _driver(driver), _isPlaying(false), _looping(false), _randomLoop(false), _masterVolume(192), _queuePos(0), _musicData(data), _musicDataSize(size), _passThrough(false), _buf(0) { + memset(_channel, 0, sizeof(_channel)); + queueClear(); + _lastSong = _currentSong = 0; + _parser = MidiParser::createParser_SMF(); + _parser->setMidiDriver(this); + _parser->setTimerRate(_driver->getBaseTempo()); - MusicPlayer::~MusicPlayer() { - _parser->unloadMusic(); - delete _parser; - this->close(); - delete[] _buf; - } + _numSongs = READ_LE_UINT16(_musicData); + this->open(); +} + +MusicPlayer::~MusicPlayer() { + _parser->unloadMusic(); + delete _parser; + this->close(); + delete[] _buf; +} + +void MusicPlayer::setVolume(int volume) { + if (volume < 0) + volume = 0; + else if (volume > 255) + volume = 255; - void MusicPlayer::setVolume(int volume) { - if (volume < 0) - volume = 0; - else if (volume > 255) - volume = 255; - - if (_masterVolume == volume) + if (_masterVolume == volume) return; - - _masterVolume = volume; - - for (int i = 0; i < 16; ++i) { - if (_channel[i]) - _channel[i]->volume(_channelVolume[i] * _masterVolume / 255); - } - } - bool MusicPlayer::queueSong(uint16 songNum) { - if (songNum >= _numSongs && songNum < 1000) { - // this happens at the end of the car chase, where we try to play song 176, - // see Sound::_tune[], entry 39 - warning("Trying to queue an invalid song number %d, max %d", songNum, _numSongs); - return false; - } - - uint8 emptySlots = 0; - for (int i = 0; i < MUSIC_QUEUE_SIZE; i++) - if (!_songQueue[i]) - emptySlots++; - - if (!emptySlots) - return false; - - // Work around bug in Roland music, note that these numbers are 'one-off' - // from the original code - if (/*isRoland && */ songNum == 88 || songNum == 89) - songNum = 62; - - _songQueue[MUSIC_QUEUE_SIZE - emptySlots] = songNum; - return true; - } + _masterVolume = volume; - void MusicPlayer::queueClear() { - _lastSong = _songQueue[0]; - _queuePos = 0; - _looping = _randomLoop = false; - memset(_songQueue, 0, sizeof(_songQueue)); + for (int i = 0; i < 16; ++i) { + if (_channel[i]) + _channel[i]->volume(_channelVolume[i] * _masterVolume / 255); } +} + +bool MusicPlayer::queueSong(uint16 songNum) { + if (songNum >= _numSongs && songNum < 1000) { + // this happens at the end of the car chase, where we try to play song 176, + // see Sound::_tune[], entry 39 + warning("Trying to queue an invalid song number %d, max %d", songNum, _numSongs); + return false; + } + uint8 emptySlots = 0; + for (int i = 0; i < MUSIC_QUEUE_SIZE; i++) + if (!_songQueue[i]) + emptySlots++; - int MusicPlayer::open() { - // Don't ever call open without first setting the output driver! - if (!_driver) - return 255; + if (!emptySlots) + return false; + + // Work around bug in Roland music, note that these numbers are 'one-off' + // from the original code + if (/*isRoland && */ songNum == 88 || songNum == 89) + songNum = 62; + + _songQueue[MUSIC_QUEUE_SIZE - emptySlots] = songNum; + return true; +} + +void MusicPlayer::queueClear() { + _lastSong = _songQueue[0]; + _queuePos = 0; + _looping = _randomLoop = false; + memset(_songQueue, 0, sizeof(_songQueue)); +} + +int MusicPlayer::open() { + // Don't ever call open without first setting the output driver! + if (!_driver) + return 255; - int ret = _driver->open(); - if (ret) - return ret; - _driver->setTimerCallback(this, &onTimer); - return 0; - } + int ret = _driver->open(); + if (ret) + return ret; + _driver->setTimerCallback(this, &onTimer); + return 0; +} + +void MusicPlayer::close() { + _driver->setTimerCallback(NULL, NULL); + if (_driver) + _driver->close(); + _driver = 0; +} - void MusicPlayer::close() { - _driver->setTimerCallback(NULL, NULL); - if (_driver) - _driver->close(); - _driver = 0; +void MusicPlayer::send(uint32 b) { + if (_passThrough) { + _driver->send(b); + return; } - void MusicPlayer::send(uint32 b) { - if (_passThrough) { - _driver->send(b); + byte channel = (byte)(b & 0x0F); + if ((b & 0xFFF0) == 0x07B0) { + // Adjust volume changes by master volume + byte volume = (byte)((b >> 16) & 0x7F); + _channelVolume[channel] = volume; + volume = volume * _masterVolume / 255; + b = (b & 0xFF00FFFF) | (volume << 16); + } else if ((b & 0xF0) == 0xC0 && !_nativeMT32) { + b = (b & 0xFFFF00FF) | mt32_to_gm[(b >> 8) & 0xFF] << 8; + } + else if ((b & 0xFFF0) == 0x007BB0) { + //Only respond to All Notes Off if this channel + //has currently been allocated + if (_channel[b & 0x0F]) return; - } - - byte channel = (byte)(b & 0x0F); - if ((b & 0xFFF0) == 0x07B0) { - // Adjust volume changes by master volume - byte volume = (byte)((b >> 16) & 0x7F); - _channelVolume[channel] = volume; - volume = volume * _masterVolume / 255; - b = (b & 0xFF00FFFF) | (volume << 16); - } else if ((b & 0xF0) == 0xC0 && !_nativeMT32) { - b = (b & 0xFFFF00FF) | mt32_to_gm[(b >> 8) & 0xFF] << 8; - } - else if ((b & 0xFFF0) == 0x007BB0) { - //Only respond to All Notes Off if this channel - //has currently been allocated - if (_channel[b & 0x0F]) - return; - } - - //Work around annoying loud notes in certain Roland Floda tunes - if (channel == 3 && _currentSong == 90) - return; - if (channel == 4 && _currentSong == 27) - return; - if (channel == 5 && _currentSong == 38) - return; - - if (!_channel[channel]) - _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); - - if (_channel[channel]) - _channel[channel]->send(b); } - void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { - //Only thing we care about is End of Track. - if (type != 0x2F) - return; + //Work around annoying loud notes in certain Roland Floda tunes + if (channel == 3 && _currentSong == 90) + return; + if (channel == 4 && _currentSong == 27) + return; + if (channel == 5 && _currentSong == 38) + return; - if (_looping || _songQueue[1]) - playMusic(); - else - stopMusic(); - } + if (!_channel[channel]) + _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); - void MusicPlayer::onTimer(void *refCon) { - MusicPlayer *music = (MusicPlayer *)refCon; - if (music->_isPlaying) - music->_parser->onTimer(); - } + if (_channel[channel]) + _channel[channel]->send(b); +} + +void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { + //Only thing we care about is End of Track. + if (type != 0x2F) + return; - void MusicPlayer::queueTuneList(int16 tuneList) { - queueClear(); - - //Jungle is the only part of the game that uses multiple tunelists. - //For the sake of code simplification we just hardcode the extended list ourselves - if ((tuneList + 1) == 3) { - _randomLoop = true; - int i = 0; - while (Sound::_jungleList[i]) - queueSong(Sound::_jungleList[i++] - 1); - return; - } + if (_looping || _songQueue[1]) + playMusic(); + else + stopMusic(); +} + +void MusicPlayer::onTimer(void *refCon) { + MusicPlayer *music = (MusicPlayer *)refCon; + if (music->_isPlaying) + music->_parser->onTimer(); +} + +void MusicPlayer::queueTuneList(int16 tuneList) { + queueClear(); + + //Jungle is the only part of the game that uses multiple tunelists. + //For the sake of code simplification we just hardcode the extended list ourselves + if ((tuneList + 1) == 3) { + _randomLoop = true; + int i = 0; + while (Sound::_jungleList[i]) + queueSong(Sound::_jungleList[i++] - 1); + return; + } - int mode = (_numSongs == 40) ? Sound::_tuneDemo[tuneList].mode : Sound::_tune[tuneList].mode; - switch (mode) { - //Random loop - case 0: - _randomLoop = true; - setLoop(false); - break; - //Sequential loop - case 1: - setLoop(_songQueue[1] == 0); - break; - //Play once - case 2: - default: - setLoop(false); - break; - } + int mode = (_numSongs == 40) ? Sound::_tuneDemo[tuneList].mode : Sound::_tune[tuneList].mode; + switch (mode) { + case 0: // random loop + _randomLoop = true; + setLoop(false); + break; + case 1: // sequential loop + setLoop(_songQueue[1] == 0); + break; + case 2: // play once + default: + setLoop(false); + break; + } - int i = 0; - if (_numSongs == 40) { - while (Sound::_tuneDemo[tuneList].tuneNum[i]) - queueSong(Sound::_tuneDemo[tuneList].tuneNum[i++] - 1); - } else { - while (Sound::_tune[tuneList].tuneNum[i]) - queueSong(Sound::_tune[tuneList].tuneNum[i++] - 1); - } - - if (_randomLoop) - _queuePos = randomQueuePos(); + int i = 0; + if (_numSongs == 40) { + while (Sound::_tuneDemo[tuneList].tuneNum[i]) + queueSong(Sound::_tuneDemo[tuneList].tuneNum[i++] - 1); + } else { + while (Sound::_tune[tuneList].tuneNum[i]) + queueSong(Sound::_tune[tuneList].tuneNum[i++] - 1); } - void MusicPlayer::playMusic() { - if (!_songQueue[0]) { - debug(5, "MusicPlayer::playMusic - Music queue is empty!"); - return; - } + if (_randomLoop) + _queuePos = randomQueuePos(); +} - uint16 songNum = _songQueue[_queuePos]; +void MusicPlayer::playMusic() { + if (!_songQueue[0]) { + debug(5, "MusicPlayer::playMusic - Music queue is empty!"); + return; + } + + uint16 songNum = _songQueue[_queuePos]; - //Special type - // > 1000 && < 2000 -> queue different tunelist - // 2000 -> repeat music from previous queue - if (songNum > 999) { - if ((songNum + 1) == 2000) { - songNum = _lastSong; - queueClear(); - queueSong(songNum); - } else { - queueTuneList(songNum - 1000); - _queuePos = _randomLoop ? randomQueuePos() : 0; - songNum = _songQueue[_queuePos]; - } + //Special type + // > 1000 && < 2000 -> queue different tunelist + // 2000 -> repeat music from previous queue + if (songNum > 999) { + if ((songNum + 1) == 2000) { + songNum = _lastSong; + queueClear(); + queueSong(songNum); + } else { + queueTuneList(songNum - 1000); + _queuePos = _randomLoop ? randomQueuePos() : 0; + songNum = _songQueue[_queuePos]; } + } - byte *prevSong = _musicData + songOffset(_currentSong); - if (*prevSong == 0x43 || *prevSong == 0x63) { - if (_buf) { - delete[] _buf; - _buf = 0; - } + byte *prevSong = _musicData + songOffset(_currentSong); + if (*prevSong == 0x43 || *prevSong == 0x63) { + if (_buf) { + delete[] _buf; + _buf = 0; } + } - _currentSong = songNum; - if (!songNum) { - stopMusic(); - return; - } - - byte *musicPtr = _musicData + songOffset(songNum); - uint32 size = songLength(songNum); + _currentSong = songNum; + if (!songNum) { + stopMusic(); + return; + } - if (*musicPtr == 0x43 || *musicPtr == 0x63) { - uint32 packedSize = songLength(songNum) - 0x200; - _buf = new uint16[packedSize]; + byte *musicPtr = _musicData + songOffset(songNum); + uint32 size = songLength(songNum); + if (*musicPtr == 0x43 || *musicPtr == 0x63) { + uint32 packedSize = songLength(songNum) - 0x200; + _buf = new uint16[packedSize]; - uint16 *data = (uint16 *)(musicPtr + 1); - byte *idx = ((byte *)data) + 0x200; + uint16 *data = (uint16 *)(musicPtr + 1); + byte *idx = ((byte *)data) + 0x200; - for (uint i = 0; i < packedSize; i++) + for (uint i = 0; i < packedSize; i++) #if defined(SCUMM_NEED_ALIGNMENT) - memcpy(&_buf[i], &data[*(idx + i)], sizeof(uint16)); + memcpy(&_buf[i], &data[*(idx + i)], sizeof(uint16)); #else - _buf[i] = data[*(idx + i)]; + _buf[i] = data[*(idx + i)]; #endif - musicPtr = ((byte *)_buf) + ((*musicPtr == 0x63) ? 1 : 0); - size = packedSize * 2; - } - - _parser->loadMusic(musicPtr, size); - _parser->setTrack(0); - //debug(0, "Playing song %d [queue position: %d]", songNum, _queuePos); - _isPlaying = true; - queueUpdatePos(); + musicPtr = ((byte *)_buf) + ((*musicPtr == 0x63) ? 1 : 0); + size = packedSize * 2; } + + _parser->loadMusic(musicPtr, size); + _parser->setTrack(0); + debug(8, "Playing song %d [queue position: %d]", songNum, _queuePos); + _isPlaying = true; + queueUpdatePos(); +} - void MusicPlayer::queueUpdatePos() { - if (_randomLoop) - _queuePos = randomQueuePos(); - else { - if (_queuePos < (MUSIC_QUEUE_SIZE - 1) && _songQueue[_queuePos + 1]) - _queuePos++; - else - if (_looping) - _queuePos = 0; - } +void MusicPlayer::queueUpdatePos() { + if (_randomLoop) { + _queuePos = randomQueuePos(); + } else { + if (_queuePos < (MUSIC_QUEUE_SIZE - 1) && _songQueue[_queuePos + 1]) + _queuePos++; + else if (_looping) + _queuePos = 0; } +} - uint8 MusicPlayer::randomQueuePos() { - int queueSize = 0; - for (int i = 0; i < MUSIC_QUEUE_SIZE; i++) - if (_songQueue[i]) - queueSize++; - - if (!queueSize) - return 0; - - return (uint8) _rnd.getRandomNumber(queueSize - 1) & 0xFF; - } +uint8 MusicPlayer::randomQueuePos() { + int queueSize = 0; + for (int i = 0; i < MUSIC_QUEUE_SIZE; i++) + if (_songQueue[i]) + queueSize++; - void MusicPlayer::stopMusic() { - _isPlaying = false; - _parser->unloadMusic(); - } + if (!queueSize) + return 0; + + return (uint8) _rnd.getRandomNumber(queueSize - 1) & 0xFF; +} - uint32 MusicPlayer::songOffset(uint16 songNum) const { - uint16 offsLo = READ_LE_UINT16(_musicData + (songNum * 4) + 2); - uint16 offsHi = READ_LE_UINT16(_musicData + (songNum * 4) + 4); - return (offsHi << 4) | offsLo; - } +void MusicPlayer::stopMusic() { + _isPlaying = false; + _parser->unloadMusic(); +} - uint32 MusicPlayer::songLength(uint16 songNum) const { - if (songNum < _numSongs) - return (songOffset(songNum + 1) - songOffset(songNum)); - return (_musicDataSize - songOffset(songNum)); - } +uint32 MusicPlayer::songOffset(uint16 songNum) const { + uint16 offsLo = READ_LE_UINT16(_musicData + (songNum * 4) + 2); + uint16 offsHi = READ_LE_UINT16(_musicData + (songNum * 4) + 4); + return (offsHi << 4) | offsLo; +} - Music::Music(MidiDriver *driver, QueenEngine *vm) : _vToggle(false) { - if (vm->resource()->isDemo()) { - _musicData = vm->resource()->loadFile("AQ8.RL", 0, &_musicDataSize); - } else { - _musicData = vm->resource()->loadFile("AQ.RL", 0, &_musicDataSize); - } - - _player = new MusicPlayer(driver, _musicData, _musicDataSize); - } +uint32 MusicPlayer::songLength(uint16 songNum) const { + if (songNum < _numSongs) + return (songOffset(songNum + 1) - songOffset(songNum)); + return (_musicDataSize - songOffset(songNum)); +} - Music::~Music() { - delete _player; - delete[] _musicData; - } - - void Music::playSong(uint16 songNum) { - _player->queueClear(); - _player->queueSong(songNum); - _player->playMusic(); - } - - void Music::toggleVChange() { - setVolume(_vToggle ? (volume() * 2) : (volume() / 2)); - _vToggle ^= true; +Music::Music(MidiDriver *driver, QueenEngine *vm) : _vToggle(false) { + if (vm->resource()->isDemo()) { + _musicData = vm->resource()->loadFile("AQ8.RL", 0, &_musicDataSize); + } else { + _musicData = vm->resource()->loadFile("AQ.RL", 0, &_musicDataSize); } + _player = new MusicPlayer(driver, _musicData, _musicDataSize); +} + +Music::~Music() { + delete _player; + delete[] _musicData; +} + +void Music::playSong(uint16 songNum) { + _player->queueClear(); + _player->queueSong(songNum); + _player->playMusic(); +} + +void Music::toggleVChange() { + setVolume(_vToggle ? (volume() * 2) : (volume() / 2)); + _vToggle ^= true; +} } // End of namespace Queen diff --git a/queen/resource.cpp b/queen/resource.cpp index 8525f0cd8e..0766ce3be3 100644 --- a/queen/resource.cpp +++ b/queen/resource.cpp @@ -161,7 +161,7 @@ void Resource::checkJASVersion() { else if (isInterview()) offset += JAS_VERSION_OFFSET_INTV; else - offset += JAS_VERSION_OFFSET; + offset += JAS_VERSION_OFFSET_PC; _resourceFile->seek(offset); char versionStr[6]; diff --git a/queen/resource.h b/queen/resource.h index 9d32c175be..f937b03ef9 100644 --- a/queen/resource.h +++ b/queen/resource.h @@ -28,26 +28,6 @@ namespace Queen { -enum Version { - VER_ENG_FLOPPY = 0, - VER_ENG_TALKIE = 1, - VER_FRE_FLOPPY = 2, - VER_FRE_TALKIE = 3, - VER_GER_FLOPPY = 4, - VER_GER_TALKIE = 5, - VER_ITA_FLOPPY = 6, - VER_ITA_TALKIE = 7, - VER_SPA_TALKIE = 8, - VER_HEB_TALKIE = 9, - VER_DEMO_PCGAMES = 10, - VER_DEMO = 11, - VER_INTERVIEW = 12, - - VER_COUNT = 13 -}; - -enum { CURRENT_TBL_VERSION = 1 }; - struct ResourceEntry { char filename[13]; uint8 bundle; @@ -62,62 +42,123 @@ struct GameVersion { }; class LineReader { - public: + LineReader(char *buffer, uint32 bufsize); ~LineReader(); char *nextLine(); private: + char *_buffer; uint32 _bufSize; int _current; }; class Resource { - public: + Resource(); ~Resource(); + //! loads the specified from the resource file uint8 *loadFile(const char *filename, uint32 skipBytes = 0, uint32 *size = NULL, bool useMalloc = false); + + //! returns true if the file is present in the resource bool fileExists(const char *filename) const { return resourceEntry(filename) != NULL; } + //! returns a reference to a sound file File *giveCompressedSound(const char *filename, uint32 *size); bool isDemo() const { return !strcmp(_versionString, "PE100"); } bool isInterview() const { return !strcmp(_versionString, "PEint"); } bool isFloppy() const { return _versionString[0] == 'P'; } bool isCD() const { return _versionString[0] == 'C'; } + + //! returns compression type for audio files uint8 compression() const { return _compression; } + + //! returns JAS version string (contains language, platform and version information) const char *JASVersion() const { return _versionString; } + + //! returns language of the game Language getLanguage() const; + enum Version { + VER_ENG_FLOPPY = 0, + VER_ENG_TALKIE = 1, + VER_FRE_FLOPPY = 2, + VER_FRE_TALKIE = 3, + VER_GER_FLOPPY = 4, + VER_GER_TALKIE = 5, + VER_ITA_FLOPPY = 6, + VER_ITA_TALKIE = 7, + VER_SPA_TALKIE = 8, + VER_HEB_TALKIE = 9, + VER_DEMO_PCGAMES = 10, + VER_DEMO = 11, + VER_INTERVIEW = 12, + + VER_COUNT = 13 + }; + + enum { + CURRENT_TBL_VERSION = 1 + }; + enum { JAS_VERSION_OFFSET_DEMO = 0x119A8, JAS_VERSION_OFFSET_INTV = 0xCF8, - JAS_VERSION_OFFSET = 0x12484 + JAS_VERSION_OFFSET_PC = 0x12484 }; protected: + File *_resourceFile; + + //! compression type for audio files uint8 _compression; + + //! JAS version string of the game char _versionString[6]; + + //! number of entries in resource table uint32 _resourceEntries; + ResourceEntry *_resourceTable; + //! look for a normal queen version (ie. queen.1) bool findNormalVersion(); + + //! look for a compressed/rebuilt queen version (ie. queen.1c) bool findCompressedVersion(); + + //! verify the version of the selected game void checkJASVersion(); + + //! returns a reference to the ReseourceEntry for the specified filename ResourceEntry *resourceEntry(const char *filename) const; + + //! extarct the resource table for the specified game version bool readTableFile(const GameVersion *gameVersion); + + //! reads the resource table from a rebuilt datafile (ie. queen.1c) void readTableCompResource(); + + //! read the resource table from the specified file void readTableEntries(File *file); + + //! detect game version based on queen.1 datafile size const GameVersion *detectGameVersion(uint32 size) const; + //! resource table filename (queen.tbl) static const char *_tableFilename; + + //! known FOTAQ versions static const GameVersion _gameVersions[]; + #ifndef __PALM_OS__ + //! resource table for english floppy version static ResourceEntry _resourceTablePEM10[]; #endif }; diff --git a/queen/talk.h b/queen/talk.h index 395eccced9..0fcded5baf 100644 --- a/queen/talk.h +++ b/queen/talk.h @@ -30,27 +30,20 @@ namespace Queen { class QueenEngine; class Talk { - public: +public: //! Public interface to run a talk from a file - static void talk( - const char *filename, - int personInRoom, - char *cutawayFilename, - QueenEngine *vm); + static void talk(const char *filename, int personInRoom, char *cutawayFilename, QueenEngine *vm); //! Public interface to speak a sentence - static bool speak( - const char *sentence, - Person *person, - const char *voiceFilePrefix, - QueenEngine *vm); + static bool speak(const char *sentence, Person *person, const char *voiceFilePrefix, QueenEngine *vm); //! Read a string from ptr and update offset static void getString(const byte *ptr, uint16 &offset, char *str, int maxLength, int align = 2); private: - //! Collection of constants used by Talk + + //! Collection of constants used by Talk enum { LINE_HEIGHT = 10, MAX_STRING_LENGTH = 255, diff --git a/queen/walk.cpp b/queen/walk.cpp index a190f3bb5a..5f22bccc39 100644 --- a/queen/walk.cpp +++ b/queen/walk.cpp @@ -32,27 +32,27 @@ namespace Queen { const MovePersonData Walk::_moveData[] = { - {"COMPY", -1, -6, 1, 6, 0, 0, 0, 0, 12, 12, 1, 14}, - {"DEINO", -1, -8, 1, 8, 0, 0, 0, 0, 11, 11, 1, 10}, - {"FAYE", -1, -6, 1, 6, 13, 18, 7, 12, 19, 22, 2, 5}, - {"GUARDS", -1, -6, 1, 6, 0, 0, 0, 0, 7, 7, 2, 5}, - {"PRINCESS1", -1, -6, 1, 6, 13, 18, 7, 12, 19, 21, 2, 5}, - {"PRINCESS2", -1, -6, 1, 6, 13, 18, 7, 12, 19, 21, 2, 5}, - {"AMGUARD", -1, -6, 1, 6, 13, 18, 7, 12, 19, 21, 2, 5}, - {"SPARKY", -1, -6, 1, 6, 13, 18, 7, 12, 21, 20, 2, 5}, - {"LOLA_SHOWER", -1, -6, 55, 60, 0, 0, 0, 0, 7, 7, 2, 5}, - {"LOLA", -24, -29, 24, 29, 0, 0, 0, 0, 30, 30, 2, 5}, - {"BOB", -15, -20, 15, 20, 21, 26, 0, 0, 27, 29, 2, 5}, - {"CHEF", -1, -4, 1, 4, 0, 0, 0, 0, 1, 5, 2, 4}, - {"HENRY", -1, -6, 1, 6, 0, 0, 0, 0, 7, 7, 2, 6}, - {"ANDERSON", -1, -6, 1, 6, 0, 0, 0, 0, 7, 7, 2, 5}, - {"JASPAR", -4, -9, 4, 9, 16, 21, 10, 15, 1, 3, 1, 10}, - {"PYGMY", -7, -12, 7, 12, 0, 0, 0, 0, 27, 27, 2, 5}, - {"FRANK", 7, 12, 1, 6, 0, 0, 0, 0, 13, 13, 2, 4}, - {"WEDGEWOOD", -20, -25, 20, 25, 0, 0, 0, 0, 1, 1, 1, 5}, - {"TMPD", -1, -6, 1, 6, 13, 18, 7, 12, 19, 21, 2, 5}, - {"IAN", -1, -6, 1, 6, 0, 0, 0, 0, 7, 7, 2, 6}, - {"*", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + { "COMPY", -1, -6, 1, 6, 0, 0, 0, 0, 12, 12, 1, 14 }, + { "DEINO", -1, -8, 1, 8, 0, 0, 0, 0, 11, 11, 1, 10 }, + { "FAYE", -1, -6, 1, 6, 13, 18, 7, 12, 19, 22, 2, 5 }, + { "GUARDS", -1, -6, 1, 6, 0, 0, 0, 0, 7, 7, 2, 5 }, + { "PRINCESS1", -1, -6, 1, 6, 13, 18, 7, 12, 19, 21, 2, 5 }, + { "PRINCESS2", -1, -6, 1, 6, 13, 18, 7, 12, 19, 21, 2, 5 }, + { "AMGUARD", -1, -6, 1, 6, 13, 18, 7, 12, 19, 21, 2, 5 }, + { "SPARKY", -1, -6, 1, 6, 13, 18, 7, 12, 21, 20, 2, 5 }, + { "LOLA_SHOWER", -1, -6, 55, 60, 0, 0, 0, 0, 7, 7, 2, 5 }, + { "LOLA", -24, -29, 24, 29, 0, 0, 0, 0, 30, 30, 2, 5 }, + { "BOB", -15, -20, 15, 20, 21, 26, 0, 0, 27, 29, 2, 5 }, + { "CHEF", -1, -4, 1, 4, 0, 0, 0, 0, 1, 5, 2, 4 }, + { "HENRY", -1, -6, 1, 6, 0, 0, 0, 0, 7, 7, 2, 6 }, + { "ANDERSON", -1, -6, 1, 6, 0, 0, 0, 0, 7, 7, 2, 5 }, + { "JASPAR", -4, -9, 4, 9, 16, 21, 10, 15, 1, 3, 1, 10 }, + { "PYGMY", -7, -12, 7, 12, 0, 0, 0, 0, 27, 27, 2, 5 }, + { "FRANK", 7, 12, 1, 6, 0, 0, 0, 0, 13, 13, 2, 4 }, + { "WEDGEWOOD", -20, -25, 20, 25, 0, 0, 0, 0, 1, 1, 1, 5 }, + { "TMPD", -1, -6, 1, 6, 13, 18, 7, 12, 19, 21, 2, 5 }, + { "IAN", -1, -6, 1, 6, 0, 0, 0, 0, 7, 7, 2, 6 }, + { "*", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; Walk::Walk(QueenEngine *vm) diff --git a/queen/walk.h b/queen/walk.h index 1f9244193d..730b03ff6d 100644 --- a/queen/walk.h +++ b/queen/walk.h @@ -108,10 +108,16 @@ private: bool calc(uint16 oldPos, uint16 newPos, int16 oldx, int16 oldy, int16 x, int16 y); + //! areas for current room const Area *_roomArea; + + //! number of areas for current room uint16 _roomAreaCount; + //! walking steps WalkData _walkData[MAX_WALK_DATA]; + + //! number of walking steps uint16 _walkDataCount; uint16 _areaStrike[MAX_WALK_DATA]; @@ -128,6 +134,7 @@ private: QueenEngine *_vm; + //! persons walking animation data static const MovePersonData _moveData[]; }; |