scummvm/engines/lure/res_struct.h

882 lines
20 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef LURE_RESSTRUCT_H
#define LURE_RESSTRUCT_H
#include "lure/luredefs.h"
#include "common/list.h"
#include "common/file.h"
namespace Lure {
using namespace Common;
/*-------------------------------------------------------------------------*/
/* Structure definitions */
/* */
/*-------------------------------------------------------------------------*/
/* HACK/FIXME: three structs are misaligned (at least on 4-byte aligned system,
should have more troubles with coming 64bit systems), GET_NEXT let us read
properly sequence of struct in lure.dat hardcoding size of struct.
*/
#define GET_NEXT(v, sc) v = (sc *)(((byte *)v) + kSizeOf##sc)
#define kSizeOfRoomExitJoinResource 13
#define kSizeOfHotspotResource 62
#define kSizeOfHotspotActionResource 3
#include "common/pack-start.h" // START STRUCT PACKING
struct VersionStructure {
uint16 id;
byte vMajor;
byte vMinor;
} PACKED_STRUCT;
struct FileEntry {
uint16 id;
byte unused;
byte sizeExtension;
uint16 size;
uint16 offset;
} PACKED_STRUCT;
struct HotspotResource {
uint16 hotspotId;
uint16 nameId;
uint16 descId;
uint16 descId2;
uint32 actions;
uint16 actionsOffset;
uint16 roomNumber;
byte layer;
byte scriptLoadFlag;
uint16 loadOffset;
uint16 startX;
uint16 startY;
uint16 width;
uint16 height;
uint16 widthCopy;
uint16 heightCopy;
uint16 yCorrection;
int16 walkX;
uint16 walkY;
int8 talkX;
int8 talkY;
uint16 colourOffset;
uint16 animRecordId;
uint16 hotspotScriptOffset;
uint16 talkScriptOffset;
uint16 tickProcId;
uint16 tickTimeout;
uint16 tickScriptOffset;
uint16 npcSchedule;
uint16 characterMode;
uint16 delayCtr;
byte flags2;
byte hdrFlags;
} PACKED_STRUCT;
struct HotspotAnimResource {
uint16 animRecordId;
uint16 animId;
uint16 flags;
uint16 upOffset;
uint16 downOffset;
uint16 leftOffset;
uint16 rightOffset;
uint8 upFrame;
uint8 downFrame;
uint8 leftFrame;
uint8 rightFrame;
} PACKED_STRUCT;
struct MovementResource {
uint16 frameNumber;
int16 xChange;
int16 yChange;
} PACKED_STRUCT;
struct RoomRect {
int16 xs, xe;
int16 ys, ye;
} PACKED_STRUCT;
struct RoomResource {
uint16 roomNumber;
uint8 hdrFlags;
uint8 unused;
uint32 actions;
uint16 descId;
uint16 numLayers;
uint16 layers[4];
uint16 sequenceOffset;
int16 clippingXStart;
int16 clippingXEnd;
uint8 areaFlag;
uint8 numExits;
uint32 exitTime;
RoomRect walkBounds;
} PACKED_STRUCT;
struct RoomExitResource {
int16 xs, xe, ys, ye;
uint16 sequenceOffset;
uint8 newRoom;
uint8 direction;
int16 newRoomX, newRoomY;
} PACKED_STRUCT;
struct HotspotOverrideResource {
uint16 hotspotId;
int16 xs, xe, ys, ye;
} PACKED_STRUCT;
struct RoomExitHotspotResource {
uint16 hotspotId;
int16 xs, xe;
int16 ys, ye;
uint16 cursorNum;
uint16 destRoomNumber;
} PACKED_STRUCT;
struct RoomExitJoinResource {
uint16 hotspot1Id;
byte h1CurrentFrame;
byte h1DestFrame;
uint8 h1OpenSound;
uint8 h1CloseSound;
uint16 hotspot2Id;
byte h2CurrentFrame;
byte h2DestFrame;
uint8 h2OpenSound;
uint8 h2CloseSound;
byte blocked;
} PACKED_STRUCT;
struct HotspotActionResource {
byte action;
uint16 sequenceOffset;
} PACKED_STRUCT;
struct TalkHeaderResource {
uint16 hotspotId;
uint16 offset;
} PACKED_STRUCT;
struct TalkDataHeaderResource {
uint16 recordId;
uint16 listOffset;
uint16 responsesOffset;
} PACKED_STRUCT;
struct TalkDataResource {
uint16 preSequenceId;
uint16 descId;
uint16 postSequenceId;
} PACKED_STRUCT;
struct TalkResponseResource {
uint16 sequenceId1;
uint16 sequenceId2;
uint16 sequenceId3;
} PACKED_STRUCT;
struct RoomExitCoordinateResource {
int16 x;
int16 y;
uint16 roomNumber;
} PACKED_STRUCT;
#define ROOM_EXIT_COORDINATES_NUM_ENTRIES 6
#define ROOM_EXIT_COORDINATES_NUM_ROOMS 52
struct RoomExitCoordinateEntryResource {
uint8 roomIndex[ROOM_EXIT_COORDINATES_NUM_ROOMS];
RoomExitCoordinateResource entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES];
} PACKED_STRUCT;
#define MAX_SCHEDULE_ENTRY_PARAMS 5
struct CharacterScheduleResource {
uint16 action;
uint16 params[MAX_SCHEDULE_ENTRY_PARAMS];
} PACKED_STRUCT;
struct RoomExitIndexedHotspotResource {
uint8 roomNumber;
uint8 hotspotIndex;
uint16 hotspotId;
} PACKED_STRUCT;
enum SoundDescFlags {SF_IN_USE = 1, SF_RESTORE = 2};
// In desc entry, numChannels: bits 0-1 # roland, bits 2-3 #adlib, bits 4-5 #internal
struct SoundDescResource {
uint8 soundNumber;
uint8 channel;
uint8 numChannels;
uint8 flags;
uint8 volume;
} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
/**
* Class template for a derived list that destroys the contained
* object when the record containing it is destroyed. It's not
* perfect, since the underlying list doesn't have virtual
* methods, but it's sufficient for my usage.
*/
template <class T>
class ManagedList: public Common::List<T> {
typedef typename Common::List<T> Common_List;
public:
~ManagedList() {
clear();
}
void clear() {
typename Common_List::iterator i = Common_List::begin();
while (i != Common_List::end()) {
T v = *i;
i = Common_List::erase(i);
delete v;
}
}
typename Common_List::iterator erase(typename Common_List::iterator pos) {
T obj = *pos;
typename Common_List::iterator result = Common_List::erase(pos);
delete obj;
return result;
}
typename Common_List::iterator erase(typename Common_List::iterator first,
typename Common_List::iterator last) {
while (first != last)
erase(first++);
return last;
}
T operator[](int index) {
typename Common_List::iterator i = Common_List::begin();
while (index-- > 0)
++i;
return *i;
}
};
/** Enumeration used for direction facings */
enum Direction {UP, DOWN, LEFT, RIGHT, NO_DIRECTION};
// Support classes to hold loaded resources
class RoomExitHotspotData {
public:
RoomExitHotspotData(RoomExitHotspotResource *rec);
uint16 hotspotId;
int16 xs, xe;
int16 ys, ye;
uint16 cursorNum;
uint16 destRoomNumber;
};
typedef ManagedList<RoomExitHotspotData *> RoomExitHotspotList;
class RoomExitData {
public:
RoomExitData(RoomExitResource *rec);
bool insideRect(int16 xp, int16 yp);
int16 xs, xe, ys, ye;
uint16 sequenceOffset;
Direction direction;
uint8 roomNumber;
uint16 x, y;
};
class RoomExitList: public ManagedList<RoomExitData *> {
public:
RoomExitData *checkExits(int16 xp, int16 yp);
};
#define ROOM_PATHS_WIDTH 40
#define ROOM_PATHS_HEIGHT 24
#define ROOM_PATHS_SIZE (ROOM_PATHS_WIDTH / 8 * ROOM_PATHS_HEIGHT)
#define DECODED_PATHS_WIDTH 42
#define DECODED_PATHS_HEIGHT 26
typedef uint16 RoomPathsDecompressedData[DECODED_PATHS_WIDTH * DECODED_PATHS_HEIGHT];
class RoomPathsData {
private:
byte _data[ROOM_PATHS_HEIGHT * ROOM_PATHS_WIDTH];
public:
RoomPathsData() {}
RoomPathsData(byte *srcData) { load(srcData); }
void load(byte *srcData) {
memcpy(_data, srcData, ROOM_PATHS_SIZE);
}
const byte *data() { return _data; }
bool isOccupied(int x, int y);
bool isOccupied(int x, int y, int width);
void setOccupied(int x, int y, int width);
void clearOccupied(int x, int y, int width);
void decompress(RoomPathsDecompressedData &dataOut, int characterWidth);
};
#define MAX_NUM_LAYERS 4
class RoomData {
public:
RoomData(RoomResource *rec, MemoryBlock *pathData);
uint16 roomNumber;
uint8 hdrFlags;
uint8 flags;
uint32 actions;
uint16 descId;
uint16 numLayers;
uint16 layers[MAX_NUM_LAYERS];
uint16 sequenceOffset;
int16 clippingXStart;
int16 clippingXEnd;
uint8 areaFlag;
uint32 exitTime;
Common::Rect walkBounds;
RoomExitHotspotList exitHotspots;
RoomExitList exits;
RoomPathsData paths;
};
class RoomDataList: public ManagedList<RoomData *> {
public:
void saveToStream(WriteStream *stream);
void loadFromStream(ReadStream *stream);
};
struct RoomExitJoinStruct {
uint16 hotspotId;
byte currentFrame;
byte destFrame;
uint8 openSound;
uint8 closeSound;
};
class RoomExitJoinData {
public:
RoomExitJoinData(RoomExitJoinResource *rec);
RoomExitJoinStruct hotspots[2];
byte blocked;
};
class RoomExitJoinList: public ManagedList<RoomExitJoinData *> {
public:
void saveToStream(WriteStream *stream);
void loadFromStream(ReadStream *stream);
};
class HotspotActionData {
public:
HotspotActionData(HotspotActionResource *rec);
Action action;
uint16 sequenceOffset;
};
class HotspotActionList: public ManagedList<HotspotActionData *> {
public:
uint16 recordId;
HotspotActionList(uint16 id, byte *data);
uint16 getActionOffset(Action action);
};
class HotspotActionSet: public ManagedList<HotspotActionList *> {
public:
HotspotActionList *getActions(uint16 recordId);
};
enum CharacterMode {CHARMODE_NONE, CHARMODE_HESITATE, CHARMODE_IDLE, CHARMODE_PAUSED,
CHARMODE_WAIT_FOR_PLAYER, CHARMODE_CONVERSING, CHARMODE_PLAYER_WAIT,
CHARMODE_WAIT_FOR_INTERACT, CHARMODE_INTERACTING, CHARMODE_SPECIAL_PLAYER};
enum BlockedState {BS_NONE, BS_INITIAL, BS_FINAL};
enum VariantBool {VB_INITIAL, VB_FALSE, VB_TRUE};
class HotspotData {
public:
HotspotData(HotspotResource *rec);
uint16 hotspotId;
uint16 nameId;
uint16 descId;
uint16 descId2;
uint32 actions;
uint16 actionsOffset;
byte flags;
uint16 roomNumber;
byte layer;
byte scriptLoadFlag;
uint16 loadOffset;
int16 startX;
int16 startY;
uint16 width;
uint16 height;
uint16 widthCopy;
uint16 heightCopy;
uint16 yCorrection;
int16 walkX;
uint16 walkY;
int8 talkX;
int8 talkY;
uint16 colourOffset;
uint16 animRecordId;
uint16 hotspotScriptOffset;
uint16 talkScriptOffset;
uint16 tickProcId;
uint16 tickTimeout;
uint16 tickScriptOffset;
uint16 npcSchedule;
CharacterMode characterMode;
uint16 delayCtr;
uint8 flags2;
uint8 headerFlags;
// Runtime fields
uint16 actionCtr;
BlockedState blockedState;
bool blockedFlag;
VariantBool coveredFlag;
uint16 talkMessageId;
uint16 talkerId;
uint16 talkDestCharacterId;
uint16 talkCountdown;
uint16 pauseCtr;
uint16 useHotspotId;
uint16 talkGate;
uint16 actionHotspotId;
uint16 talkOverride;
uint16 scriptHotspotId;
void enable() { flags |= 0x80; }
void disable() { flags &= 0x7F; }
Direction nonVisualDirection() { return (Direction) scriptLoadFlag; }
void saveToStream(WriteStream *stream);
void loadFromStream(ReadStream *stream);
};
class HotspotDataList: public ManagedList<HotspotData *> {
public:
void saveToStream(WriteStream *stream);
void loadFromStream(ReadStream *stream);
};
class HotspotOverrideData {
public:
HotspotOverrideData(HotspotOverrideResource *rec);
uint16 hotspotId;
int16 xs, xe, ys, ye;
};
typedef ManagedList<HotspotOverrideData *> HotspotOverrideList;
class MovementData {
public:
MovementData(MovementResource *);
uint16 frameNumber;
int16 xChange;
int16 yChange;
};
class MovementDataList: public ManagedList<MovementData *> {
public:
bool getFrame(uint16 currentFrame, int16 &xChange, int16 &yChange,
uint16 &nextFrame);
};
class HotspotAnimData {
public:
HotspotAnimData(HotspotAnimResource *rec);
uint16 animRecordId;
uint16 animId;
uint16 flags;
uint8 upFrame;
uint8 downFrame;
uint8 leftFrame;
uint8 rightFrame;
MovementDataList leftFrames, rightFrames;
MovementDataList upFrames, downFrames;
};
typedef ManagedList<HotspotAnimData *> HotspotAnimList;
// Talk header list
class TalkHeaderData {
private:
uint16 *_data;
int _numEntries;
public:
TalkHeaderData(uint16 charId, uint16 *entries);
~TalkHeaderData();
uint16 characterId;
uint16 getEntry(int index);
};
typedef ManagedList<TalkHeaderData *> TalkHeaderList;
class TalkEntryData {
public:
TalkEntryData(TalkDataResource *rec);
uint16 preSequenceId;
uint16 descId;
uint16 postSequenceId;
};
typedef ManagedList<TalkEntryData *> TalkEntryList;
class TalkData {
public:
TalkData(uint16 id);
~TalkData();
uint16 recordId;
TalkEntryList entries;
TalkEntryList responses;
TalkEntryData *getResponse(int index);
};
typedef ManagedList<TalkData *> TalkDataList;
struct RoomExitCoordinateData {
int16 x;
int16 y;
uint16 roomNumber;
byte hotspotIndexId;
};
class RoomExitCoordinates {
private:
RoomExitCoordinateData _entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES];
uint8 _roomIndex[ROOM_EXIT_COORDINATES_NUM_ROOMS];
public:
RoomExitCoordinates(RoomExitCoordinateEntryResource *rec);
RoomExitCoordinateData &getData(uint16 destRoomNumber);
};
class RoomExitCoordinatesList: public ManagedList<RoomExitCoordinates *> {
public:
RoomExitCoordinates &getEntry(uint16 roomNumber);
};
class RoomExitIndexedHotspotData {
public:
RoomExitIndexedHotspotData(RoomExitIndexedHotspotResource *rec);
uint16 roomNumber;
uint8 hotspotIndex;
uint16 hotspotId;
};
class RoomExitIndexedHotspotList: public ManagedList<RoomExitIndexedHotspotData *> {
public:
uint16 getHotspot(uint16 roomNumber, uint8 hotspotIndexId);
};
// The following classes hold any sequence offsets that are being delayed
class SequenceDelayData {
private:
SequenceDelayData() {};
public:
SequenceDelayData(uint16 delay, uint16 seqOffset, bool canClearFlag);
static SequenceDelayData *load(uint32 delay, uint16 seqOffset, bool canClearFlag);
uint32 timeoutCtr;
uint16 sequenceOffset;
bool canClear;
};
class SequenceDelayList: public ManagedList<SequenceDelayData *> {
public:
void add(uint16 delay, uint16 seqOffset, bool canClear);
void tick();
void clear(bool forceClear = false);
void saveToStream(WriteStream *stream);
void loadFromStream(ReadStream *stream);
};
// The following classes holds the data for NPC schedules
extern const int actionNumParams[NPC_JUMP_ADDRESS+1];
class CharacterScheduleSet;
class CharacterScheduleEntry {
private:
CharacterScheduleSet *_parent;
Action _action;
uint16 _params[MAX_TELL_COMMANDS * 3];
int _numParams;
public:
CharacterScheduleEntry() { _action = NONE; _parent = NULL; }
CharacterScheduleEntry(Action theAction, ...);
CharacterScheduleEntry(CharacterScheduleSet *parentSet,
CharacterScheduleResource *&rec);
CharacterScheduleEntry(CharacterScheduleEntry *src);
Action action() { return _action; }
int numParams() { return _numParams; }
uint16 param(int index);
void setDetails(Action theAction, ...);
void setDetails2(Action theAction, int numParamEntries, uint16 *paramList);
CharacterScheduleEntry *next();
CharacterScheduleSet *parent() { return _parent; }
uint16 id();
};
class CharacterScheduleSet: public ManagedList<CharacterScheduleEntry *> {
private:
uint16 _id;
public:
CharacterScheduleSet(CharacterScheduleResource *rec, uint16 setId);
uint16 getId(CharacterScheduleEntry *rec);
uint16 id() { return _id; }
};
class CharacterScheduleList: public ManagedList<CharacterScheduleSet *> {
public:
CharacterScheduleEntry *getEntry(uint16 id, CharacterScheduleSet *currentSet = NULL);
};
typedef List<uint16> CharacterScheduleOffsets;
// The follow classes are used to store the NPC schedule Ids for the random actions a follower can do in each room
enum RandomActionType {REPEATABLE, REPEAT_ONCE, REPEAT_ONCE_DONE};
class RandomActionSet {
private:
uint16 _roomNumber;
int _numActions;
RandomActionType *_types;
uint16 *_ids;
public:
RandomActionSet(uint16 *&offset);
~RandomActionSet();
uint16 roomNumber() { return _roomNumber; }
int numActions() { return _numActions; }
void getEntry(int index, RandomActionType &actionType, uint16 &id) {
assert((index >= 0) && (index < _numActions));
actionType = _types[index];
id = _ids[index];
}
void setDone(int index) {
assert((index >= 0) && (index < _numActions));
assert(_types[index] == REPEAT_ONCE);
_types[index] = REPEAT_ONCE_DONE;
}
void saveToStream(Common::WriteStream *stream);
void loadFromStream(Common::ReadStream *stream);
};
class RandomActionList: public ManagedList<RandomActionSet *> {
public:
RandomActionSet *getRoom(uint16 roomNumber);
void saveToStream(Common::WriteStream *stream);
void loadFromStream(Common::ReadStream *stream);
};
class PausedCharacter {
public:
PausedCharacter(uint16 SrcCharId, uint16 DestCharId);
uint16 srcCharId;
uint16 destCharId;
uint16 counter;
HotspotData *charHotspot;
};
class Hotspot;
class PausedCharacterList: public ManagedList<PausedCharacter *> {
public:
void reset(uint16 hotspotId);
void countdown();
void scan(Hotspot &h);
int check(uint16 charId, int numImpinging, uint16 *impingingList);
};
struct ServeEntry {
uint16 hotspotId;
uint8 serveFlags;
};
#define NUM_SERVE_CUSTOMERS 4
enum BarmanGraphicType {BG_RANDOM = 0, BG_BEER = 1, BG_EXTRA1 = 2, BG_EXTRA2 = 3};
struct BarEntry {
uint16 roomNumber;
uint16 barmanId;
ServeEntry customers[NUM_SERVE_CUSTOMERS];
const uint16 *graphics[4];
uint16 gridLine;
ServeEntry *currentCustomer;
};
class BarmanLists {
BarEntry _barList[3];
public:
BarmanLists();
void reset();
BarEntry &getDetails(uint16 roomNumber);
void saveToStream(Common::WriteStream *stream);
void loadFromStream(Common::ReadStream *stream);
};
enum BarmanAction {WALK_AROUND = 1, POLISH_BAR = 2, WAIT = 3, WAIT_DIALOG = 4, SERVE_BEER = 5};
struct RoomTranslationRecord {
uint8 srcRoom;
uint8 destRoom;
};
extern const RoomTranslationRecord roomTranslations[];
enum StringEnum {S_CREDITS = 25, S_RESTART_GAME = 26, S_SAVE_GAME = 27, S_RESTORE_GAME = 28,
S_QUIT = 29, S_FAST_TEXT = 30, S_SLOW_TEXT = 31, S_SOUND_ON = 32, S_SOUND_OFF = 33,
S_ACTION_NOTHING = 34, S_FOR = 35, S_TO = 36, S_ON = 37, S_AND_THEN = 38, S_FINISH = 39,
S_CONFIRM_YN = 40, S_YOU_ARE_CARRYING = 41, S_INV_NOTHING = 42, S_YOU_HAVE = 43,
S_GROAT = 44, S_GROATS = 45,
S_ARTICLE_LIST = 46};
class StringList {
private:
MemoryBlock *_data;
int _numEntries;
char **_entries;
public:
StringList() { _numEntries = 0; }
~StringList() { clear(); }
void load(MemoryBlock *data);
void clear();
int count() { return _numEntries; }
const char *getString(int index) {
if ((index < 0) || (index >= _numEntries)) error("Invalid index specified to String List");
return _entries[index];
}
const char *getString(Action action) { return getString((int) action - 1); }
const char *getString(StringEnum sEnum) { return getString((int) sEnum); }
};
// The following class holds the field list used by the script engine as
// well as miscellaneous fields used by the game.
#define NUM_VALUE_FIELDS 90
enum FieldName {
ROOM_NUMBER = 0,
CHARACTER_HOTSPOT_ID = 1,
USE_HOTSPOT_ID = 2,
ACTIVE_HOTSPOT_ID = 3,
SEQUENCE_RESULT = 4,
GENERAL = 5,
GIVE_TALK_INDEX = 6,
NEW_ROOM_NUMBER = 7,
OLD_ROOM_NUMBER = 8,
CELL_DOOR_STATE = 9,
TORCH_HIDE = 10,
PRISONER_DEAD = 15,
BOTTLE_FILLED = 18,
TALK_INDEX = 19,
SACK_CUT = 20,
ROOM_EXIT_ANIMATION = 76,
AREA_FLAG = 82
};
struct PlayerNewPosition {
Point position;
uint16 roomNumber;
};
class ValueTableData {
private:
uint16 _numGroats;
PlayerNewPosition _playerNewPos;
uint8 _textCtr1, _textCtr2; // originally 2 2-bit counters
uint8 _hdrFlagMask;
uint16 _fieldList[NUM_VALUE_FIELDS];
bool isKnownField(uint16 fieldIndex);
public:
ValueTableData();
void reset();
uint16 getField(uint16 fieldIndex);
uint16 getField(FieldName fieldName);
void setField(uint16 fieldIndex, uint16 value);
void setField(FieldName fieldName, uint16 value);
int size() { return NUM_VALUE_FIELDS; }
uint16 &numGroats() { return _numGroats; }
uint8 &textCtr1() { return _textCtr1; }
uint8 &textCtr2() { return _textCtr2; }
uint8 &hdrFlagMask() { return _hdrFlagMask; }
PlayerNewPosition &playerNewPos() { return _playerNewPos; }
void saveToStream(Common::WriteStream *stream);
void loadFromStream(Common::ReadStream *stream);
};
} // End of namespace Lure
#endif