/* 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 3 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, see . * */ #ifndef WATCHMAKER_STRUCT_H #define WATCHMAKER_STRUCT_H #include "watchmaker/t3d.h" #include "watchmaker/types.h" #include "watchmaker/sysdef.h" #include "common/stream.h" #include "watchmaker/message.h" namespace Watchmaker { class SerializableAsset { public: virtual ~SerializableAsset() {} virtual void loadFromStream(Common::SeekableReadStream &stream) = 0; }; template class SerializableString : public SerializableAsset { char str[strSize] = {}; public: char *c_str() { return str; } void loadFromStream(Common::SeekableReadStream &stream) override { stream.read(str, strSize); }; }; template void loadArrayFromStream(Common::SeekableReadStream &stream, T array[], uint32 size) { for (uint32 i = 0; i < size; i++) { array[i].loadFromStream(stream); } } template<> inline void loadArrayFromStream(Common::SeekableReadStream &stream, uint8 array[], uint32 size) { for (uint32 i = 0; i < size; i++) { array[i] = stream.readByte(); } } template<> inline void loadArrayFromStream(Common::SeekableReadStream &stream, uint16 array[], uint32 size) { for (uint32 i = 0; i < size; i++) { array[i] = stream.readUint16LE(); } } template<> inline void loadArrayFromStream(Common::SeekableReadStream &stream, int32 array[], uint32 size) { for (uint32 i = 0; i < size; i++) { array[i] = stream.readSint32LE(); } } template class SerializableArray : public SerializableAsset { T _array[arraySize]; // Can't do initializer here, as GCC 4.8 crashes in that case public: SerializableArray() : _array{} {} T &operator[](int index) { return _array[index]; }; T *rawArray() { return _array; } uint32 size() const { return arraySize; } void loadFromStream(Common::SeekableReadStream &stream) override { loadArrayFromStream(stream, _array, arraySize); } }; template class SerializableDynamicArray : public SerializableAsset { T *_array = nullptr; uint32 _size = 0; public: SerializableDynamicArray() : SerializableDynamicArray(0) {} // TODO SerializableDynamicArray(uint32 size) : _size(size) { _array = new T[size] {}; } ~SerializableDynamicArray() { delete[] _array; } uint32 size() const { return _size; } T &operator[](int index) { return _array[index]; }; void loadFromStream(Common::SeekableReadStream &stream) override { loadArrayFromStream(stream, _array, _size); } }; struct SRoom : public SerializableAsset { uint8 name[T3D_NAMELEN]; // nome della stanza char desc[64]; // descrizione della stanza uint16 flags; // DONE | EXTRA uint16 env; // EAX preset environment number uint16 music; // Music for this room SerializableArray objects; // oggetti nella stanza rivelabili dal mouse SerializableArray sounds; // sounds per room SerializableArray anims; // animazioni per room SerializableArray actions; // azioni per room void loadFromStream(Common::SeekableReadStream &stream) override { stream.read(name, T3D_NAMELEN); stream.read(desc, 64); flags = stream.readUint16LE(); env = stream.readUint16LE(); music = stream.readUint16LE(); objects.loadFromStream(stream); sounds.loadFromStream(stream); anims.loadFromStream(stream); actions.loadFromStream(stream); } }; struct SObject : public SerializableAsset { uint16 name; // frase nome SerializableArray examine; // frase esamina SerializableArray action; // frase azione SerializableArray text; // Frasi user SerializableArray anim; // animazione su action SerializableArray anim2; // animazione aggiunta (su examine) uint8 room; // Stanza in cui si trova l'oggetto uint8 goroom; // Se direzione num stanza - se persona num dialog uint8 ninv; // ptr inventario uint16 flags; // EXAMINE | EXAMINEACT | ROOM | PERSON | TAKE | USEWITH | EXTRA | EXTRA2 | DONE | ON | HIDE uint8 pos; // 0 se no position SerializableArray, MAX_OBJ_MESHLINKS> meshlink_int = {};// link -> oggetto mesh (nome mesh) -> da rimuovere uint8 *meshlink[MAX_OBJ_MESHLINKS]; void loadFromStream(Common::SeekableReadStream &stream) override { name = stream.readUint16LE(); examine.loadFromStream(stream); action.loadFromStream(stream); text.loadFromStream(stream); anim.loadFromStream(stream); anim2.loadFromStream(stream); room = stream.readByte(); goroom = stream.readByte(); ninv = stream.readByte(); flags = stream.readUint16LE(); pos = stream.readByte(); meshlink_int.loadFromStream(stream); // HACK: for (int i = 0; i < MAX_OBJ_MESHLINKS; i++) { meshlink[i] = meshlink_int.rawArray()[i].rawArray(); } } }; struct SInvObject : public SerializableAsset { uint16 name; // Nome Oggetto in inventario SerializableArray examine; // Frase se si esamina SerializableArray action; // Frase se si opera uint16 flags; // USEWITH | EXTRA | EXTRA2 | DONE | ON | WITHI | WITHO SerializableArray text; // Frasi user uint16 uwobj; // usewithobj automatico SerializableArray anim; // animazione su usewith SerializableArray anim2; // animazione su usewith SerializableArray meshlink; // link -> mesh void loadFromStream(Common::SeekableReadStream &stream) override { name = stream.readUint16LE(); examine.loadFromStream(stream); action.loadFromStream(stream); flags = stream.readUint16LE(); text.loadFromStream(stream); uwobj = stream.readUint16LE(); anim.loadFromStream(stream); anim2.loadFromStream(stream); meshlink.loadFromStream(stream); } }; struct SAtFrame : public SerializableAsset { uint8 type = 0; // ATFTEXT, ATFSND, ATFEVENT uint8 anim = 0; // solo se subanim e' attiva int16 nframe = 0; // 10000 se attraversa portale uint16 index = 0; void loadFromStream(Common::SeekableReadStream &stream) override { type = stream.readByte(); anim = stream.readByte(); nframe = stream.readSint16LE(); index = stream.readUint16LE(); } }; struct SAnim : public SerializableAsset { SerializableArray, MAX_SUBANIMS> meshlink; // link -> anim mesh (nome mesh) -> da rimuovere SerializableArray, MAX_SUBANIMS> name; // nome animazione SerializableArray RoomName; // nome stanza destinazione SerializableArray atframe; // atframe uint32 flags; int16 active; // indece tra le animazioni attive int32 obj; // obj a cui e' collegato uint8 pos; // posizione uint8 cam; // camera per l'azione void loadFromStream(Common::SeekableReadStream &stream) override { meshlink.loadFromStream(stream); name.loadFromStream(stream); RoomName.loadFromStream(stream); atframe.loadFromStream(stream); flags = stream.readUint32LE(); active = stream.readSint16LE(); obj = stream.readSint32LE(); pos = stream.readByte(); cam = stream.readByte(); } }; struct SSound : public SerializableAsset { char name[T3D_NAMELEN]; uint8 flags; SerializableArray, MAX_SOUND_MESHLINKS> meshlink; uint32 ConeInside, ConeOutside; int32 ConeOutsideVolume; t3dF32 MinDist, MaxDist; int32 Angle; void loadFromStream(Common::SeekableReadStream &stream) override { stream.read(name, T3D_NAMELEN); flags = stream.readByte(); meshlink.loadFromStream(stream); ConeInside = stream.readUint32LE(); ConeOutside = stream.readUint32LE(); ConeOutsideVolume = stream.readSint32LE(); MinDist = stream.readFloatLE(); MaxDist = stream.readFloatLE(); Angle = stream.readSint32LE(); } }; struct SMusic : public SerializableAsset { char name[MAX_SUB_MUSICS][T3D_NAMELEN]; SerializableArray vol; void loadFromStream(Common::SeekableReadStream &stream) override { for (int i = 0; i < MAX_SUB_MUSICS; i++) { stream.read(name[i], T3D_NAMELEN); } vol.loadFromStream(stream); } }; struct SDlgMenu : public SerializableAsset { // struttura di appoggio per riempiere i DlgItem uint8 parent, on; uint16 titolo; // indice della sentence di titolo void loadFromStream(Common::SeekableReadStream &stream) override { parent = stream.readByte(); on = stream.readByte(); titolo = stream.readUint16LE(); } }; struct SItemCommand : public SerializableAsset { uint8 com; // comando uint16 param1; // parametro 1 uint16 param2; // parametro 2 void loadFromStream(Common::SeekableReadStream &stream) override { com = stream.readByte(); param1 = stream.readUint16LE(); param2 = stream.readUint16LE(); } }; struct SDlgItem : public SerializableAsset { SerializableArray, MAX_PLAYERS> item; // lista di comandi per personaggio void loadFromStream(Common::SeekableReadStream &stream) override { item.loadFromStream(stream); } }; struct SDialog : public SerializableAsset { uint16 flags; // flags del dialogo - per ora non serve int32 obj; // Personaggio con cui fa il dialogo SerializableArray AltPosSco; // Scostamento posizione alternate SerializableArray AltCamSco; // Scostamento camere alternate SerializableArray, MAX_ALT_ANIMS>, MAX_ALTERNATES> AltAnims; // Rimappatura anim alternative dialoghi SerializableArray ItemIndex; // indice delle liste di comandi void loadFromStream(Common::SeekableReadStream &stream) override { flags = stream.readUint16LE(); obj = stream.readSint32LE(); AltPosSco.loadFromStream(stream); AltCamSco.loadFromStream(stream); AltAnims.loadFromStream(stream); ItemIndex.loadFromStream(stream); } }; struct SDiaryItem : public SerializableAsset { uint16 rand; uint16 loop; uint16 loopc; uint16 bnd, saved_bnd; uint16 cur; uint16 on; SerializableArray anim; void loadFromStream(Common::SeekableReadStream &stream) override { rand = stream.readUint16LE(); loop = stream.readUint16LE(); loopc = stream.readUint16LE(); bnd = stream.readUint16LE(); saved_bnd = stream.readUint16LE(); cur = stream.readUint16LE(); on = stream.readUint16LE(); anim.loadFromStream(stream); } }; struct SDiary : public SerializableAsset { uint16 startt, endt; int32 room; uint16 obj; uint16 cur; uint16 end_hideobj; //se il bit piu' alto e' settato vuol dire che il diario e' stato lanciato almeno una volta e quindi questa variabile e' valida solo per oggetti da 0..32767 SerializableArray item; void loadFromStream(Common::SeekableReadStream &stream) override { startt = stream.readUint16LE(); endt = stream.readUint16LE(); room = stream.readSint32LE(); obj = stream.readUint16LE(); cur = stream.readUint16LE(); end_hideobj = stream.readUint16LE(); item.loadFromStream(stream); } }; struct SPlayerStand { uint8 pos = 0; int32 an = 0; int32 cr = 0; uint16 bnd = 0; Common::String roomName; SPlayerStand() = default; SPlayerStand(Common::SeekableReadStream &stream) { pos = stream.readByte(); an = stream.readSint32LE(); cr = stream.readSint32LE(); bnd = stream.readUint16LE(); } }; struct SPDALog : public SerializableAsset { int32 time = 0; SerializableString info; SerializableArray text; SerializableArray, MAX_PDA_LINES *MAX_PDA_INFO> formatted; int32 menu_appartenenza = 0, menu_creato = 0; int32 flags = 0; int32 lines = 0; int32 dx = 0, dy = 0; void loadFromStream(Common::SeekableReadStream &stream) override { time = stream.readSint32LE(); info.loadFromStream(stream); text.loadFromStream(stream); formatted.loadFromStream(stream); menu_appartenenza = stream.readSint32LE(); menu_creato = stream.readSint32LE(); flags = stream.readSint32LE(); lines = stream.readSint32LE(); dx = stream.readSint32LE(); dy = stream.readSint32LE(); } }; struct SString { char text[MAX_STRING_LEN] = {}; uint16 x = 0, y = 0, dx = 0; constexpr SString() = default; SString(const char *_text, uint16 _x = 0, uint16 _y = 0, uint16 _dx = 0) : x(_x), y(_y), dx(_dx) { if (_text != nullptr) { memcpy(this->text, _text, strlen(_text)); } } }; struct SRect { int32 x1 = 0, y1 = 0, x2 = 0, y2 = 0; constexpr SRect() = default; constexpr SRect(int32 _x1, int32 _y1, int32 _x2, int32 _y2): x1(_x1), y1(_y1), x2(_x2), y2(_y2) {} void reset() { x1 = 0; y1 = 0; x2 = 0; y2 = 0; } }; struct SD3DRect { int32 px = 0, py = 0, dx = 0, dy = 0; uint8 r = 0, g = 0, b = 0, a = 0; }; struct SD3DTriangle { int32 x1 = 0, y1 = 0, x2 = 0, y2 = 0, x3 = 0, y3 = 0; uint8 r = 0, g = 0, b = 0, a = 0; }; struct SD3DBitmap { int32 tnum = 0; int32 px = 0, py = 0, dx = 0, dy = 0; int32 rtype = 0; }; struct SDDBitmap { int32 tnum; int32 px, py, ox, oy, dx, dy; SDDBitmap() { reset(); } void reset() { tnum =0; px = 0; py = 0; ox = 0; oy = 0; dx = 0; dy = 0; } }; struct SDDText { SDDText() { reset(); } SDDText(const char *_text, FontKind _font, FontColor _color, int32 _tnum) : font(_font), color(_color), tnum(_tnum) { Common::strlcpy(this->text, _text, sizeof(this->text)); } void reset() { for(uint i = 0; i < ARRAYSIZE(text); i++) text[i] = '\0'; font = FontKind::Standard; color = FontColor::WHITE_FONT; tnum = 0; } char text[MAX_STRING_LEN]; FontKind font; FontColor color; int32 tnum; }; struct SScript { uint16 firstframe = 0; uint8 flags = 0; // 0 - BREAKABLE - Se si interrompe con la pressione dei tasti del mouse }; // 1 - DIALOGEXITNOANIM - Se lo script e' lanciato da un dialogo all'ultima battuta esce dal dialogo senza anim di link e di default struct SGameOptions { uint8 sound_on = 0; uint8 sound_volume = 0; uint8 music_on = 0; uint8 music_volume = 0; uint8 speech_on = 0; uint8 speech_volume = 0; uint8 subtitles_on = 0; }; // MESSAGGI PER LO SCHEDULER struct message { EventClass classe; // message classe uint8 event = 0; // message name uint16 flags = 0; // message priority | NOWAIT per script uint8 bparam = 0; int16 wparam1 = 0; // t3dS16 parameter 1 int16 wparam2 = 0; // t3dS16 parameter 2 union { int32 lparam[3] = {}; // long parameter t3dF32 fparam[3]; // float parameter }; message() = default; message(EventClass _classe, uint8 _event, uint16 _flags) : classe(_classe), event(_event), flags(_flags) {} void reset() { classe = MC_IDLE; event = 0; flags = 0; bparam = 0; wparam1 = 0; wparam2 = 0; for (uint i = 0; i < ARRAYSIZE(lparam); i++) lparam[i] = 0; // fparam cleared as union with lparam i.e. shared memory } }; struct pqueue { uint8 head = 0, tail = 0, len = 0; message *event[MAX_MESSAGES] = {}; }; // STRUTTURE PER TITOLI DI CODA struct SCreditsName : public SerializableAsset { char name[64] = {}; uint16 role = 0; uint8 flags = 0; void loadFromStream(Common::SeekableReadStream &stream) override { stream.read(name, 64); role = stream.readUint16LE(); flags = stream.readByte(); } }; struct SCreditsRole : public SerializableAsset { char role[48] = {}; uint8 flags = 0; void loadFromStream(Common::SeekableReadStream &stream) override { stream.read(role, 48); flags = stream.readByte(); } }; struct STitoliCoda { char *s = nullptr; //puntatore alla stringa int32 px = 0, py = 0; //posizione int32 dx = 0, dy = 0; //dimensione int32 tnum = 0; //bitmap uint32 time = 0; //quando deve apparire (solo nel caso degli StaticCredits) }; struct SRoomInfo { char name[64] = {}; //nome della stanza char fullstring[64 + 16 + 1] = {}; //stringa con ora int32 px = 0, py = 0; //posizione int32 dx = 0, dy = 0; //dimensione totale int32 _dx = 0, _dy = 0; //dimensione della stringa attuale int32 tnum = 0; //bitmap char *letter_ptr = nullptr; //puntatore alla lettera corrente int16 t_next_letter = 0; //quando deve apparire la nuova lettera FontKind f; //il font }; } // End of namespace Watchmaker #endif // WATCHMAKER_STRUCT_H