diff options
99 files changed, 17819 insertions, 2541 deletions
diff --git a/base/commandLine.cpp b/base/commandLine.cpp index 2d7b9f2d9f..51fee811d6 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -386,9 +386,15 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha } else { // On MacOS X prior to 10.9 the OS is sometimes adding a -psn_X_XXXXXX argument (where X are digits) // to pass the process serial number. We need to ignore it to avoid an error. + // When using XCode it also adds -NSDocumentRevisionsDebugMode YES argument if XCode option + // "Allow debugging when using document Versions Browser" is on (which is the default). #ifdef MACOSX if (strncmp(s, "-psn_", 5) == 0) continue; + if (strcmp(s, "-NSDocumentRevisionsDebugMode") == 0) { + ++i; // Also skip the YES that follows + continue; + } #endif bool isLongCmd = (s[0] == '-' && s[1] == '-'); diff --git a/common/scummsys.h b/common/scummsys.h index 27fcb84505..938770baa6 100644 --- a/common/scummsys.h +++ b/common/scummsys.h @@ -309,6 +309,23 @@ #endif #endif +// +// Determine 64 bitness +// Reference: http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros +// +#if !defined(HAVE_CONFIG_H) + + #if defined(__x86_64__) || \ + defined(_M_X64) || \ + defined(__ppc64__) || \ + defined(__powerpc64__) || \ + defined(__LP64__) + + #define SCUMM_64BITS + + #endif + +#endif // // Some more system specific settings. diff --git a/common/span.h b/common/span.h index 0bb5a25972..2acc0b5fe7 100644 --- a/common/span.h +++ b/common/span.h @@ -393,14 +393,14 @@ public: inline String getStringAt(const index_type index, size_type numEntries = kSpanMaxSize) const { STATIC_ASSERT(sizeof(value_type) == sizeof(char), strings_can_only_be_read_from_byte_or_char_spans); - const char *string = (const char *)impl().data(); + const char *string = (const char *)impl().data() + index; if (numEntries == kSpanMaxSize) { numEntries = strnlen(string, impl().size() - index); } impl().validate(index, numEntries); - return String(string + index, numEntries); + return String(string, numEntries); } /** diff --git a/devtools/create_cryo/create_led_dat.cpp b/devtools/create_cryo/create_led_dat.cpp new file mode 100644 index 0000000000..e58ee7512d --- /dev/null +++ b/devtools/create_cryo/create_led_dat.cpp @@ -0,0 +1,105 @@ +/* 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. + * + */ + +#include <stdio.h> + +#include "eden.h" +#include "eden_icons.h" +#include "eden_rooms.h" + +template <typename T> +static void writeLE(FILE *f, T value) { + for (int i = 0; i < sizeof(value); i++, value >>= 8) { + unsigned char b = value & 0xFF; + fwrite(&b, 1, 1, f); + } +} + +struct _icon_t : icon_t { + void write(FILE *f) { + writeLE<int16>(f, sx); + writeLE<int16>(f, sy); + writeLE<int16>(f, ex); + writeLE<int16>(f, ey); + writeLE<uint16>(f, cursor_id); + writeLE<unsigned int>(f, action_id); + writeLE<unsigned int>(f, object_id); + } +}; + +static void emitIcons(FILE *f) { + _icon_t *icons = (_icon_t*)gameIcons; + for (int i = 0; i < kNumIcons; i++) + icons[i].write(f); +} + +struct _room_t : room_t { + void write(FILE *f) { + writeLE<byte>(f, ff_0); + writeLE<byte>(f, exits[0]); + writeLE<byte>(f, exits[1]); + writeLE<byte>(f, exits[2]); + writeLE<byte>(f, exits[3]); + writeLE<byte>(f, flags); + writeLE<uint16>(f, bank); + writeLE<uint16>(f, party); + writeLE<byte>(f, level); + writeLE<byte>(f, video); + writeLE<byte>(f, location); + writeLE<byte>(f, background); + } +}; + +static void emitRooms(FILE *f) { + _room_t *rooms = (_room_t*)gameRooms; + for (int i = 0; i < kNumRooms; i++) + rooms[i].write(f); +} + +static int emitData(char *outputFilename) { + FILE *f = fopen(outputFilename, "w+b"); + if (!f) { + printf("ERROR: Unable to create output file %s\n", outputFilename); + return 1; + } + + printf("Generating %s...\n", outputFilename); + + emitIcons(f); + emitRooms(f); + + fclose(f); + + printf("Done!\n"); + + return 0; +} + +int main(int argc, char **argv) { + + if (argc > 1) + return emitData(argv[1]); + else + printf("Usage: %s <output.dat>\n", argv[0]); + + return 0; +} diff --git a/devtools/create_cryo/eden.h b/devtools/create_cryo/eden.h new file mode 100644 index 0000000000..dfbe7cae52 --- /dev/null +++ b/devtools/create_cryo/eden.h @@ -0,0 +1,51 @@ +/* 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. + * + */ + +#pragma once + +typedef unsigned char byte; +typedef short int16; +typedef unsigned short uint16; + +struct icon_t { + int16 sx; + int16 sy; + int16 ex; + int16 ey; + uint16 cursor_id; // & 0x8000 - inactive/hidden + unsigned int action_id; + unsigned int object_id; +}; +#define END_ICONS {-1, -1, -1, -1, 0, 0, 0} + +struct room_t { + byte ff_0; + byte exits[4]; + byte flags; + uint16 bank; + uint16 party; + byte level; + byte video; + byte location; + byte background; +}; +#define END_ROOMS {0xFF, {0xFF, 0xFF, 0xFF, 0xFF}, 0xFF, 0xFFFF, 0xFFFF, 0xFF, 0xFF, 0xFF, 0xFF} diff --git a/devtools/create_cryo/eden_icons.h b/devtools/create_cryo/eden_icons.h new file mode 100644 index 0000000000..1feb0a64cf --- /dev/null +++ b/devtools/create_cryo/eden_icons.h @@ -0,0 +1,236 @@ +/* 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. + * + */ + +#pragma once +#include "eden.h" + +// Note: the following data can be found in the original game's executable + +// NB! this enum must match kActionCursors[] array +enum kCursors { // offset in the executable + cuNone = 0, // 0x51F + cu1 = 1, // 0x563 + cu2 = 2, // 0x556 + cu3 = 3, // 0x549 + cu4 = 4, // 0x570 + cu5 = 5, // 0x57D + cuHand = 6, // 0x502 + cu7 = 7, // 0x52C + cu8 = 8, // 0x58A + cu9 = 9, // 0x539 + cuFa = 0xF, // 0x50F + cuFinger = 53, // 0x541 + ICON_HIDDEN = 0x8000 +}; + +// NB! this enum must match EdenGame::*mouse_actions[] array +enum kActions { // offset in the executable + ac_ret = 27, // 0xD651 + ac_clicplanval = 139, // 0xE068 + ac_endFrescoes = 140, // 0xB12A + ac_choisir = 141, // 0xDD68 + ac_parle_moi = 246, // 0xBFE + ac_adam = 247, // 0x9E4 + ac_takeobject = 248, // 0xE66B + ac_putobject = 249, // 0xE681 + ac_clictimbre = 250, // 0xE03F + ac_dinaparle = 251, // 0xDF32 + ac_close_perso = 252, // 0x13EC + ac_generique = 260, // 0xAF51 + ac_choixsubtitle = 261, // 0xACBF + ac_EdenQuit = 262, // 0xAF6D + ac_restart = 263, // 0xAEE7 + ac_cancel2 = 264, // 0xACE8 + ac_testvoice = 265, // 0xACF8 + ac_reglervol = 266, // 0xAB9E + ac_load = 267, // 0xAD76 + ac_save = 268, // 0xAD40 + ac_cliccurstape = 269, // 0xB004 + ac_playtape = 270, // 0x19DB + ac_stoptape = 271, // 0xB095 + ac_rewindtape = 272, // 0xB0C9 + ac_forwardtape = 273, // 0xB0E3 + ac_confirmyes = 274, // 0xADAE + ac_confirmno = 275, // 0xADC1 + ac_gotocarte = 276 // 0xE07E +}; + +// Indicies in to gotos[] array for World map areas +enum kTravel { // offset in the executable + goMo = 24, // 0x324D + goChamaar = 40, // 0x3287 + goUluru = 51, // 0x32AF + goKoto = 65, // 0x32E3 + goNarim = 70, // 0x32F5 + goTamara = 75, // 0x3307 + goCantura = 84, // 0x3329 + goShandovra = 93, // 0x334B + goEmbalmers = 102, // 0x336D + goWhiteArch = 111, // 0x338F + goMoorkusLair = 120 // 0x33B1 +}; + +const int kNumIcons = 136; +const icon_t gameIcons[kNumIcons] = { + {90, 50, 220, 150, cu8, ac_parle_moi, 0}, + {0, 0, 319, 178, cuNone, ac_close_perso, 0}, + END_ICONS, + {220, 16, 310, 176, cu5, ac_adam, 0}, + {0, 0, 320, 200, cu8, ac_parle_moi, 0}, + END_ICONS, + {215, 140, 245, 176, cuHand, ac_choisir, 0}, + {245, 140, 275, 176, cuHand, ac_choisir, 1}, + {275, 140, 305, 176, cuHand, ac_choisir, 2}, + END_ICONS, + {245, 140, 275, 176, cuHand, ac_choisir, 0}, + {275, 140, 305, 176, cuHand, ac_choisir, 1}, + END_ICONS, + {0, 0, 320, 165, cuFa, ac_dinaparle, 0}, + {0, 165, 320, 200, cu2, ac_endFrescoes, 0}, + END_ICONS, + {0, 176, 319, 200, ICON_HIDDEN|cu9, ac_putobject, 0}, + {120, 0, 200, 16, cuFinger, ac_clictimbre, 0}, + {266, 0, 320, 16, ICON_HIDDEN|cuFinger, ac_clicplanval, 0}, + // Inventory bar items + // Mac version displays only 9 items, with extra margins + {0, 178, 28, 200, cuHand, ac_takeobject, 0}, // Not on Mac + {30, 178, 57, 200, cuHand, ac_takeobject, 0}, + {59, 178, 86, 200, cuHand, ac_takeobject, 0}, + {88, 178, 115, 200, cuHand, ac_takeobject, 0}, + {117, 178, 144, 200, cuHand, ac_takeobject, 0}, + {146, 178, 173, 200, cuHand, ac_takeobject, 0}, + {175, 178, 202, 200, cuHand, ac_takeobject, 0}, + {204, 178, 231, 200, cuHand, ac_takeobject, 0}, + {233, 178, 260, 200, cuHand, ac_takeobject, 0}, + {262, 178, 289, 200, cuHand, ac_takeobject, 0}, + {290, 178, 317, 200, cuHand, ac_takeobject, 0}, // Not on Mac + // reserve for room's icons + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, + END_ICONS, + // Menu icons + {0, 0, 319, 15, cuFinger, ac_generique, 32}, + {8, 42, 86, 51, cuFinger, ac_choixsubtitle, 16}, + {8, 51, 86, 60, cuFinger, ac_choixsubtitle, 17}, + {8, 60, 86, 69, cuFinger, ac_choixsubtitle, 18}, + {8, 69, 86, 78, cuFinger, ac_choixsubtitle, 19}, + {8, 78, 86, 87, cuFinger, ac_choixsubtitle, 20}, + {8, 87, 86, 96, cuFinger, ac_choixsubtitle, 21}, + {16, 137, 79, 148, cuFinger, ac_EdenQuit, 34}, + {129, 137, 192, 148, cuFinger, ac_restart, 35}, + {239, 137, 302, 148, cuFinger, ac_cancel2, 36}, + {130, 112, 193, 123, cuFinger, ac_testvoice, 37}, + {114, 40, 121, 110, cuFinger, ac_reglervol, 48}, + {121, 40, 128, 110, cuFinger, ac_reglervol, 56}, + {128, 40, 136, 110, cuFinger, ac_reglervol, 49}, + {147, 40, 154, 110, cuFinger, ac_reglervol, 50}, + {154, 40, 161, 110, cuFinger, ac_reglervol, 58}, + {161, 40, 169, 110, cuFinger, ac_reglervol, 51}, + {179, 40, 186, 110, cuFinger, ac_reglervol, 52}, + {186, 40, 193, 110, cuFinger, ac_reglervol, 60}, + {193, 40, 201, 110, cuFinger, ac_reglervol, 53}, + {249, 42, 307, 51, cuFinger, ac_load, 65}, + {249, 51, 307, 60, cuFinger, ac_load, 66}, + {249, 60, 307, 69, cuFinger, ac_load, 67}, + {231, 69, 307, 78, cuFinger, ac_load, 68}, + {230, 104, 307, 112, cuFinger, ac_save, 81}, + {230, 113, 307, 121, cuFinger, ac_save, 82}, + {230, 122, 307, 130, cuFinger, ac_save, 83}, + {0, 176, 0, 185, cuFinger, ac_cliccurstape, 100}, + {149, 185, 166, 200, cuFinger, ac_playtape, 96}, + {254, 185, 269, 200, cuFinger, ac_stoptape, 97}, + {85, 185, 111, 200, cuFinger, ac_rewindtape, 98}, + {204, 185, 229, 200, cuFinger, ac_forwardtape, 99}, + {0, 0, 320, 200, cuFinger, ac_ret, 0}, + END_ICONS, + // Yes/No dialog icons + {129, 84, 157, 98, cuFinger, ac_confirmyes, 0}, + {165, 84, 188, 98, cuFinger, ac_confirmno, 113}, + {0, 0, 320, 200, cuFinger, ac_ret, 0}, + END_ICONS, + // World map hotspots + {136, 100, 160, 124, cu5, ac_gotocarte, goMo}, + {150, 55, 174, 79, cu5, ac_gotocarte, goChamaar}, + {186, 29, 210, 53, ICON_HIDDEN|cu5, ac_gotocarte, goUluru}, + {217, 20, 241, 44, ICON_HIDDEN|cu5, ac_gotocarte, goKoto}, + {248, 45, 272, 69, ICON_HIDDEN|cu5, ac_gotocarte, goNarim}, + {233, 68, 257, 92, ICON_HIDDEN|cu5, ac_gotocarte, goTamara}, + {235, 109, 259, 133, ICON_HIDDEN|cu5, ac_gotocarte, goCantura}, + {163, 137, 187, 161, ICON_HIDDEN|cu5, ac_gotocarte, goEmbalmers}, + {93, 145, 117, 169, ICON_HIDDEN|cu5, ac_gotocarte, goWhiteArch}, + {70, 39, 94, 63, ICON_HIDDEN|cu5, ac_gotocarte, goShandovra}, + {99, 8, 123, 32, ICON_HIDDEN|cu5, ac_gotocarte, goMoorkusLair}, + {0, 0, 319, 199, cuNone, ac_close_perso, 0}, + END_ICONS, +}; diff --git a/devtools/create_cryo/eden_rooms.h b/devtools/create_cryo/eden_rooms.h new file mode 100644 index 0000000000..e28bc468f4 --- /dev/null +++ b/devtools/create_cryo/eden_rooms.h @@ -0,0 +1,465 @@ +/* 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. + * + */ + +#pragma once +#include "eden.h" + +// Note: the following data can be found in the original game's executable +const int kNumRooms = 424; +const room_t gameRooms[kNumRooms] = { + // Mo + { 1, {255, 0, 0, 0}, 0, 66, 0xFFFF,29, 93, 1, 4}, + { 7, { 4, 0, 6, 0}, 4, 72, 0xFFFF, 8,143, 2, 2}, + { 3, { 24, 0, 5, 0}, 6, 99, 1, 6, 6, 3, 0}, + { 3, { 24, 0, 5, 0}, 6, 68, 0x21, 6,146, 3, 0}, + {30, { 24, 0, 5, 0}, 2, 97, 9, 6,147, 3, 0}, + { 4, { 24, 0, 5, 0}, 2, 69, 0x29, 6,147, 3, 0}, + {31, { 24, 0, 5, 0}, 2, 98, 8, 6,147, 3, 0}, + { 2, { 24, 0, 5, 0}, 2, 67, 0, 6,147, 3, 0}, + { 5, { 5, 20, 2, 8}, 4, 70, 0xFFFF, 7, 64, 4, 72}, + { 6, { 3, 7, 4, 9}, 4, 71, 0xFFFF, 5, 4, 5, 6}, + { 8, { 1, 0, 23, 2}, 4, 73, 0x400,23,145, 6, 2}, + {29, { 1, 0, 0, 2}, 4, 96, 0, 0, 0, 6, 2}, + { 9, { 0, 0, 5, 0}, 0, 74, 0, 0,112, 7, 8}, + {10, { 0, 0, 5, 0}, 0, 75, 0x20, 0,112, 7, 8}, + {28, { 0, 0, 4, 0}, 0, 95, 0, 0, 0, 8, 10}, + {11, { 0, 0, 4, 0}, 0, 76, 0x10, 5,110, 8, 10}, + {27, { 11, 0, 5, 0}, 4, 94, 0,37,152, 9, 12}, + {12, { 11, 0, 5, 0}, 4, 77, 8, 6, 5, 9, 12}, + {27, { 11, 0, 5, 0}, 4, 94, 0xFFFF,37,152, 9, 12}, + {13, { 13, 0, 12, 0}, 6, 78, 0,15, 10, 10, 48}, + {14, { 12, 0, 9, 0}, 4, 79, 0,12, 9, 11, 12}, + {15, { 10, 0, 11, 0}, 6, 80, 0,14, 12, 12, 16}, + {16, { 14, 0, 10, 0}, 6, 81, 0,13, 11, 13, 14}, + {17, { 15, 0, 13, 0}, 4, 82, 0, 0, 0, 14, 16}, + {18, { 16, 0, 14, 0}, 4, 83, 0,17, 13, 15, 16}, + {19, { 17, 0, 13, 0}, 0, 84, 0,18, 15, 16, 16}, + {20, { 18, 0, 9, 0}, 4, 85, 0,19, 16, 17, 16}, + {21, { 0, 1, 17, 0}, 0, 86, 0,20, 0, 18, 70}, + {21, { 0, 1, 17, 0}, 6, 87, 2,20, 14, 18, 70}, + {37, { 0, 0, 9, 0}, 0, 34, 0xFFFF, 0, 0, 19, 12}, + { 6, { 0, 0, 4, 0}, 4, 53, 0xFFFF, 5,156, 20, 72}, + {22, {130, 0, 4, 0}, 0, 88, 0, 1, 0, 22, 46}, + {22, {130, 0, 4, 0}, 4, 89, 2, 5, 8, 22, 46}, + {23, { 6, 0, 0, 0}, 4, 90, 0xFFFF, 0, 0, 23, 2}, + {24, {103, 25, 3, 0}, 6, 91, 0, 3, 1, 24, 0}, + {25, { 0, 26, 3, 24}, 4, 92, 0,24, 2, 25, 0}, + {26, { 0, 0, 3, 25}, 4, 93, 0,25, 3, 26, 0}, + {32, { 0, 0, 89, 0}, 6,100, 0xFFFF, 0, 75, 32, 18}, + {33, { 0, 0, 50, 0}, 6,105, 0xFFFF, 0, 26, 33, 20}, + {33, { 0, 0, 51, 0}, 6,105, 0xFFFF, 0, 26, 34, 20}, + {33, { 0, 0, 52, 0}, 6,105, 0xFFFF, 0, 26, 35, 20}, + {33, { 0, 68, 53, 85}, 6,107, 0xFFFF, 0, 28, 36, 20}, + {33, { 33, 0, 54, 86}, 6,109, 0xFFFF, 0, 30, 37, 20}, + {33, { 34, 0, 55, 87}, 6,109, 0xFFFF, 0, 30, 38, 20}, + {33, { 35, 71, 56, 88}, 6,106, 0xFFFF, 0, 27, 39, 20}, + {33, { 36, 0, 57, 90}, 6,109, 0xFFFF, 0, 30, 40, 20}, + {33, { 37, 74, 58, 91}, 6,106, 0xFFFF, 0, 27, 41, 20}, + {33, { 0, 0, 59, 0}, 6,105, 0xFFFF, 0, 26, 42, 20}, + {33, { 0, 0, 60, 0}, 6,105, 0xFFFF, 0, 26, 43, 20}, + {33, { 0, 0, 61, 0}, 6,105, 0xFFFF, 0, 26, 44, 20}, + {33, { 0, 0, 62, 0}, 6,105, 0xFFFF, 0, 26, 45, 20}, + {33, { 42, 0, 63, 97}, 6,109, 0xFFFF, 0, 30, 46, 20}, + {33, { 43, 80, 64, 0}, 6,108, 0xFFFF, 0, 29, 47, 20}, + {33, { 44, 81, 65, 0}, 6,108, 0xFFFF, 0, 29, 48, 20}, + {33, { 46, 83, 66,101}, 6,106, 0xFFFF, 0, 27, 49, 20}, + {33, { 54, 86, 33, 0}, 6,108, 0xFFFF, 0, 29, 50, 20}, + {33, { 55, 87, 34, 0}, 6,108, 0xFFFF, 0, 29, 51, 20}, + {33, { 56, 88, 35, 71}, 6,106, 0xFFFF, 0, 27, 52, 20}, + {33, { 57, 90, 36, 0}, 6,108, 0xFFFF, 0, 29, 53, 20}, + {33, { 58, 91, 37, 74}, 6,106, 0xFFFF, 0, 27, 54, 20}, + {33, { 0, 92, 38, 75}, 6,107, 0xFFFF, 0, 28, 55, 20}, + {33, { 0, 93, 39, 76}, 6,107, 0xFFFF, 0, 28, 56, 20}, + {33, { 0, 95, 40, 78}, 6,107, 0xFFFF, 0, 28, 57, 20}, + {33, { 0, 96, 41, 79}, 6,110, 0xFFFF, 0, 59, 58, 20}, + {33, { 63, 97, 42, 0}, 6,108, 0xFFFF, 0, 29, 59, 20}, + {33, { 64, 0, 43, 80}, 6,109, 0xFFFF, 0, 30, 60, 20}, + {33, { 65, 0, 44, 81}, 6,109, 0xFFFF, 0, 30, 61, 20}, + {33, { 0, 99, 45, 82}, 6,107, 0xFFFF, 0, 28, 62, 20}, + {33, { 66,100, 46, 83}, 6,106, 0xFFFF, 0, 27, 63, 20}, + {33, { 0,101, 47, 84}, 6,107, 0xFFFF, 0, 28, 64, 20}, + {33, { 3, 0, 48, 0}, 6,104, 0xFFFF, 0, 74, 65, 20}, + {33, { 3, 0, 49, 0}, 6,104, 0xFFFF, 0, 74, 66, 20}, + {33, { 68, 53, 85, 0}, 6,108, 0xFFFF, 0, 29, 67, 20}, + {33, { 0, 54, 86, 33}, 6,107, 0xFFFF, 0, 28, 68, 20}, + {33, { 0, 55, 87, 34}, 6,107, 0xFFFF, 0, 28, 69, 20}, + {33, { 71, 56, 88, 35}, 6,106, 0xFFFF, 0, 27, 70, 20}, + {33, { 32, 0, 89, 0}, 6,104, 0xFFFF, 0, 74, 71, 20}, + {33, { 0, 57, 90, 36}, 6,107, 0xFFFF, 0, 28, 72, 20}, + {33, { 74, 58, 91, 37}, 6,106, 0xFFFF, 0, 27, 73, 20}, + {33, { 75, 0, 92, 38}, 6,109, 0xFFFF, 0, 30, 74, 20}, + {33, { 76, 0, 93, 39}, 6,109, 0xFFFF, 0, 30, 75, 20}, + {33, { 0, 0, 94, 0}, 6,105, 0xFFFF, 0, 26, 76, 20}, + {33, { 78, 0, 95, 40}, 6,109, 0xFFFF, 0, 30, 77, 20}, + {33, { 79, 0, 96, 41}, 6,112, 0xFFFF, 0, 61, 78, 20}, + {33, { 0, 63, 97, 42}, 6,107, 0xFFFF, 0, 28, 79, 20}, + {33, { 0, 0, 98, 0}, 6,105, 0xFFFF, 0, 26, 80, 20}, + {33, { 82, 0, 99, 45}, 6,109, 0xFFFF, 0, 30, 81, 20}, + {33, { 83, 66,100, 46}, 6,106, 0xFFFF, 0, 27, 82, 20}, + {33, { 84, 0,101, 47}, 6,109, 0xFFFF, 0, 30, 83, 20}, + {33, { 0, 0,102, 0}, 6,105, 0xFFFF, 0, 26, 84, 20}, + {33, { 0, 0, 67, 0}, 6,105, 0xFFFF, 0, 26, 85, 20}, + {33, { 85, 0, 68, 53}, 6,109, 0xFFFF, 0, 30, 86, 20}, + {33, { 0, 0, 69, 0}, 6,105, 0xFFFF, 0, 26, 87, 20}, + {33, { 0, 0, 70, 0}, 6,105, 0xFFFF, 0, 26, 88, 20}, + {33, { 88, 35, 71, 56}, 6,106, 0xFFFF, 0, 27, 89, 20}, + {33, { 0, 0, 72, 0}, 6,105, 0xFFFF, 0, 26, 90, 20}, + {33, { 0, 0, 73, 0}, 6,105, 0xFFFF, 0, 26, 91, 20}, + {33, { 91, 37, 74, 58}, 6,106, 0xFFFF, 0, 27, 92, 20}, + {33, { 92, 38, 75, 0}, 6,108, 0xFFFF, 0, 29, 93, 20}, + {33, { 93, 39, 76, 0}, 6,108, 0xFFFF, 0, 29, 94, 20}, + {33, { 0, 0, 77, 0}, 6,105, 0xFFFF, 0, 26, 95, 20}, + {33, { 95, 40, 78, 0}, 6,108, 0xFFFF, 0, 29, 96, 20}, + {33, { 96, 41, 79, 0}, 6,111, 0xFFFF, 0, 60, 97, 20}, + {33, { 0, 43, 80, 64}, 6,107, 0xFFFF, 0, 28, 98, 20}, + {33, { 0, 44, 81, 65}, 6,107, 0xFFFF, 0, 28, 99, 20}, + {33, { 99, 45, 82, 0}, 6,108, 0xFFFF, 0, 29,100, 20}, + {33, {100, 46, 83, 66}, 6,106, 0xFFFF, 0, 27,101, 20}, + {33, {101, 47, 84, 0}, 6,108, 0xFFFF, 0, 29,102, 20}, + {34, { 49, 0, 3,104}, 0,101, 0xFFFF, 0, 0,103, 20}, + {35, {105, 0,103, 0}, 0,102, 0xFFFF, 0, 0,104, 20}, + {36, { 48, 0,104, 0}, 0,103, 0xFFFF, 0, 0,105, 20}, + END_ROOMS, + // Tau's + { 1, {2, 0,129, 0}, 4, 118, 0xFFFF, 22, 0, 1, 74}, + { 2, {0, 0, 1, 0}, 6, 119, 0xFFFF, 1, 34, 2, 56}, + END_ROOMS, + // Narim's + { 1, {2, 0,255, 0}, 4, 321, 0xFFFF, 1, 0, 1, 24}, + { 2, {0, 0, 1, 0}, 6, 324, 0xFFFF, 1, 32, 2, 66}, + END_ROOMS, + // Embalmers + { 1, {2, 0,129, 0}, 6, 243, 0xFFFF, 1, 0, 1, 62}, + { 2, {0, 0, 1, 0}, 4, 244, 0x200, 1, 49, 2, 58}, + { 2, {0, 0, 1, 0}, 0, 245, 0, 1, 0, 2, 58}, + END_ROOMS, + // White Arch + { 1, {0, 0,255, 0}, 6, 120, 0xFFFF, 1, 0, 1, 42}, + { 2, {3, 0, 0, 0}, 0, 231, 0xFFFF, 0, 0, 2, 20}, + { 3, {0, 0, 2, 0}, 6, 232, 0xFFFF, 0, 50, 3, 20}, + { 4, {0, 0, 0, 0}, 6, 233, 0xFFFF, 0, 96, 4, 44}, + END_ROOMS, + // Moorkus Lair + { 1, {255, 2, 0, 0}, 4, 121, 0x588, 1, 0, 1, 64}, + { 1, {255, 2, 0, 0}, 4, 323, 0xFFFF, 1, 0, 1, 64}, + { 2, { 3, 4, 0, 0}, 0, 122, 0xFFFF, 1, 90, 2, 60}, + { 3, { 0, 0, 0, 0}, 4, 123, 0xFFFF, 2, 91, 3, 60}, + { 4, { 0, 0, 2, 0}, 4, 320, 0xFFFF, 2,150, 4, 60}, + END_ROOMS, + // Chamaar + { 1, {255, 0, 0, 0}, 0x18, 17, 0xFFFF, 1, 0, 1, 68}, + { 2, {255, 0, 0, 0}, 0x18, 17, 0xFFFF, 0, 0, 1, 68}, + { 3, { 0, 17, 32, 0}, 0x81, 124, 0xFFFF, 0, 0, 16, 22}, + { 3, { 0, 18, 33, 16}, 0x81, 125, 0xFFFF, 0, 0, 17, 22}, + { 3, { 0, 19, 34, 17}, 0x81, 126, 0xFFFF, 0, 0, 18, 22}, + { 3, { 0, 20, 35, 18}, 0x86, 143, 0xFFFF, 0, 0, 19, 22}, + { 3, { 0, 21, 36, 19}, 0x81, 127, 0xFFFF, 0, 0, 20, 22}, + { 3, { 0, 22, 37, 20}, 0x81, 128, 0xFFFF, 0, 0, 21, 22}, + { 3, { 0, 23, 38, 21}, 0x81, 129, 0xFFFF, 0, 0, 22, 22}, + { 3, { 0, 24, 39, 22}, 0x81, 130, 0xFFFF, 0, 0, 23, 22}, + { 3, { 0, 25, 40, 23}, 0x81, 131, 0xFFFF, 0, 0, 24, 22}, + { 3, { 0, 26, 41, 24}, 0x81, 132, 0xFFFF, 0, 0, 25, 22}, + { 3, { 0, 27, 42, 25}, 0x81, 133, 0xFFFF, 0, 0, 26, 22}, + { 3, { 0, 0, 43, 26}, 0x81, 134, 0xFFFF, 0, 0, 27, 22}, + { 3, {16, 33, 48, 0}, 0xC1, 193, 0xFFFF, 0, 0, 32, 26}, + { 3, {17, 34, 49, 32}, 0x81, 135, 0xFFFF, 0, 0, 33, 22}, + { 3, {18, 35, 50, 33}, 0x81, 136, 0xFFFF, 0, 0, 34, 22}, + { 3, {19, 36, 51, 34}, 0x81, 137, 0xFFFF, 0, 0, 35, 22}, + { 3, {20, 37, 52, 35}, 0x81, 138, 0xFFFF, 0, 0, 36, 22}, + { 3, {21, 38, 53, 36}, 0x81, 139, 0xFFFF, 0, 0, 37, 22}, + { 3, {22, 39, 54, 37}, 0x81, 140, 0xFFFF, 0, 0, 38, 22}, + { 3, {23, 40, 55, 38}, 0x81, 141, 0xFFFF, 0, 0, 39, 22}, + { 3, {24, 41, 56, 39}, 0x81, 142, 0xFFFF, 0, 0, 40, 22}, + { 3, {25, 42, 57, 40}, 0x81, 143, 0xFFFF, 0, 0, 41, 22}, + { 3, {26, 43, 58, 41}, 0x81, 144, 0xFFFF, 0, 0, 42, 22}, + { 3, {27, 0, 59, 42}, 0x81, 145, 0xFFFF, 0, 0, 43, 22}, + { 3, {32, 49, 64, 0}, 0xC0, 235, 0, 0, 0, 48, 26}, + { 4, {32, 49, 64, 0}, 0xC6, 234, 0x200, 0,31, 48, 26}, + { 9, {33, 50, 65, 48}, 0xC0, 277, 0xFFFF, 0, 0, 49, 26}, + {10, { 0, 0, 49, 0}, 0xC4, 278, 0xFFFF, 0,52, 49, 26}, + { 3, {34, 51, 66, 49}, 0xC1, 197, 0xFFFF, 0, 0, 50, 26}, + { 3, {35, 52, 67, 50}, 0xC1, 202, 0xFFFF, 0, 0, 51, 26}, + { 3, {36, 53, 68, 51}, 0x81, 146, 0xFFFF, 0, 0, 52, 22}, + { 3, {37, 54, 69, 52}, 1, 173, 0xFFFF, 0, 0, 53, 28}, + { 3, {38, 55, 70, 53}, 1, 174, 0xFFFF, 0, 0, 54, 28}, + { 3, {39, 56, 71, 54}, 1, 175, 0xFFFF, 0, 0, 55, 28}, + { 3, {40, 57, 72, 55}, 1, 176, 0xFFFF, 0, 0, 56, 28}, + { 3, {41, 58, 73, 56}, 1, 177, 0xFFFF, 0, 0, 57, 28}, + { 3, {42, 59, 74, 57}, 1, 178, 0xFFFF, 0, 0, 58, 28}, + { 3, {43, 0, 75, 58}, 1, 181, 0xFFFF, 0, 0, 59, 28}, + { 5, {48, 65, 1, 0}, 0xC0, 276, 0xFFFF, 0, 0, 64, 26}, + { 3, {49, 66, 1, 64}, 0xC1, 194, 0xFFFF, 0, 0, 65, 26}, + { 3, {50, 67, 1, 65}, 0xC1, 200, 0xFFFF, 0, 0, 66, 26}, + { 3, {51, 68, 1, 66}, 0xC1, 195, 0xFFFF, 0, 0, 67, 26}, + { 9, {52, 69, 1, 67}, 0xC0, 279, 0xFFFF, 0, 0, 68, 26}, + {10, { 0, 0, 68, 0}, 0xC4, 280, 0xFFFF, 0,78, 68, 26}, + { 3, {53, 70, 1, 68}, 1, 163, 0xFFFF, 0, 0, 69, 28}, + { 3, {54, 71, 1, 69}, 1, 170, 0xFFFF, 0, 0, 70, 28}, + { 3, {55, 72, 1, 70}, 1, 171, 0xFFFF, 0, 0, 71, 28}, + { 3, {56, 73, 1, 71}, 1, 167, 0xFFFF, 0, 0, 72, 28}, + {11, {57, 74, 1, 72}, 0x40, 223, 0xFFFF, 0, 0, 73, 32}, + {12, {58, 75, 1, 73}, 0x40, 215, 0xFFFF, 0, 0, 74, 32}, + { 3, {59, 0, 1, 74}, 1, 166, 0xFFFF, 0, 0, 75, 28}, + END_ROOMS, + // Uluru + { 1, {255, 0, 0, 0}, 0x18, 41, 0xFFFF, 1, 0, 1, 36}, + { 2, {255, 0, 0, 0}, 0x18, 41, 0xFFFF, 0, 0, 1, 36}, + { 3, { 0, 17, 32, 0}, 0x81, 149, 0xFFFF, 0, 0, 16, 24}, + { 3, { 0, 18, 33, 16}, 0x81, 150, 0xFFFF, 0, 0, 17, 24}, + { 3, { 0, 19, 34, 17}, 0x81, 151, 0xFFFF, 0, 0, 18, 24}, + { 3, { 0, 20, 35, 18}, 0x81, 152, 0xFFFF, 0, 0, 19, 24}, + { 3, { 0, 21, 36, 19}, 0x81, 153, 0xFFFF, 0, 0, 20, 24}, + { 3, { 0, 22, 37, 20}, 0x81, 149, 0xFFFF, 0, 0, 21, 24}, + { 3, { 0, 23, 38, 21}, 0x81, 154, 0xFFFF, 0, 0, 22, 24}, + { 3, { 0, 24, 39, 22}, 0x81, 155, 0xFFFF, 0, 0, 23, 24}, + { 3, { 0, 25, 40, 23}, 0x81, 156, 0xFFFF, 0, 0, 24, 24}, + { 3, { 0, 26, 41, 24}, 0x81, 157, 0xFFFF, 0, 0, 25, 24}, + { 3, { 0, 27, 42, 25}, 0x81, 158, 0xFFFF, 0, 0, 26, 24}, + { 4, { 0, 0, 43, 26}, 0x86, 238, 0xA00, 0,47, 27, 52}, + { 4, { 0, 0, 43, 26}, 0x80, 239, 0x800, 0, 0, 27, 52}, + { 9, { 16, 33, 48, 0}, 0xC0, 277, 0xFFFF, 0, 0, 32, 26}, + {10, { 0, 0, 32, 0}, 0xC4, 278, 0xFFFF, 0,52, 32, 26}, + { 3, { 17, 34, 49, 32}, 1, 191, 0xFFFF, 0, 0, 33, 30}, + { 3, { 18, 35, 50, 33}, 1, 184, 0xFFFF, 0, 0, 34, 30}, + { 3, { 19, 36, 51, 34}, 1, 185, 0xFFFF, 0, 0, 35, 30}, + { 3, { 20, 37, 52, 35}, 1, 186, 0xFFFF, 0, 0, 36, 30}, + { 3, { 21, 38, 53, 36}, 0x81, 161, 0xFFFF, 0, 0, 37, 24}, + { 3, { 22, 39, 54, 37}, 1, 189, 0xFFFF, 0, 0, 38, 30}, + { 3, { 23, 40, 55, 38}, 1, 186, 0xFFFF, 0, 0, 39, 30}, + { 3, { 24, 41, 56, 39}, 1, 185, 0xFFFF, 0, 0, 40, 30}, + {13, { 25, 42, 57, 40}, 1, 192, 0xFFFF, 0, 0, 41, 30}, + { 3, { 26, 43, 58, 41}, 0x81, 159, 0xFFFF, 0, 0, 42, 24}, + { 3, { 27, 0, 59, 42}, 0x81, 160, 0xFFFF, 0, 0, 43, 24}, + {12, { 32, 49, 0, 0}, 0x40, 205, 0xFFFF, 0, 0, 48, 34}, + {11, { 33, 50, 0, 48}, 0x40, 210, 0xFFFF, 0, 0, 49, 34}, + {11, { 34, 51, 0, 49}, 0x40, 212, 0xFFFF, 0, 0, 50, 34}, + {11, { 35, 52, 0, 50}, 0x40, 211, 0xFFFF, 0, 0, 51, 34}, + {11, { 36, 53, 68, 51}, 0x40, 207, 0xFFFF, 0, 0, 52, 34}, + { 3, { 37, 54, 69, 52}, 0xC1, 195, 0xFFFF, 0, 0, 53, 26}, + { 3, { 38, 55, 70, 53}, 1, 190, 0xFFFF, 0, 0, 54, 30}, + { 3, { 39, 56, 71, 54}, 1, 182, 0xFFFF, 0, 0, 55, 30}, + { 3, { 40, 57, 72, 55}, 1, 187, 0xFFFF, 0, 0, 56, 30}, + { 3, { 41, 58, 73, 56}, 1, 188, 0xFFFF, 0, 0, 57, 30}, + { 3, { 42, 59, 74, 57}, 1, 190, 0xFFFF, 0, 0, 58, 30}, + { 3, { 43, 0, 75, 58}, 0xC1, 197, 0xFFFF, 0, 0, 59, 26}, + {11, { 52, 69, 1, 0}, 0x40, 208, 0xFFFF, 0, 0, 68, 34}, + { 3, { 53, 70, 1, 68}, 1, 182, 0xFFFF, 0, 0, 69, 30}, + { 3, { 54, 71, 1, 69}, 1, 187, 0xFFFF, 0, 0, 70, 30}, + { 3, { 55, 72, 1, 70}, 1, 188, 0xFFFF, 0, 0, 71, 30}, + { 3, { 56, 73, 1, 71}, 1, 190, 0xFFFF, 0, 0, 72, 30}, + { 3, { 57, 74, 1, 72}, 1, 187, 0xFFFF, 0, 0, 73, 30}, + { 3, { 58, 75, 1, 73}, 1, 182, 0xFFFF, 0, 0, 74, 30}, + { 6, { 59, 0, 1, 74}, 0xC0, 276, 0xFFFF, 0, 0, 75, 26}, + END_ROOMS, + // Koto + { 1, {255, 0, 0, 0}, 0x18, 42, 0xFFFF, 1, 0, 1, 40}, + { 2, {255, 0, 0, 0}, 0x18, 42, 0xFFFF, 0, 0, 1, 40}, + {13, { 0, 17, 32, 0}, 0x86, 283, 0xFFFF, 0,57, 16, 50}, + { 3, { 0, 18, 33, 16}, 0x81, 125, 0xFFFF, 0, 0, 17, 22}, + { 3, { 0, 19, 34, 17}, 0x81, 126, 0xFFFF, 0, 0, 18, 22}, + { 3, { 0, 20, 35, 18}, 0x81, 127, 0xFFFF, 0, 0, 19, 22}, + { 3, { 0, 21, 36, 19}, 0x81, 128, 0xFFFF, 0, 0, 20, 22}, + { 3, { 0, 22, 37, 20}, 0x81, 131, 0xFFFF, 0, 0, 21, 22}, + { 3, { 0, 23, 38, 21}, 0x81, 129, 0xFFFF, 0, 0, 22, 22}, + { 3, { 0, 24, 39, 22}, 0x81, 126, 0xFFFF, 0, 0, 23, 22}, + { 3, { 0, 25, 40, 23}, 0x81, 125, 0xFFFF, 0, 0, 24, 22}, + { 3, { 0, 26, 41, 24}, 0x81, 127, 0xFFFF, 0, 0, 25, 22}, + { 3, { 0, 27, 42, 25}, 0x81, 133, 0xFFFF, 0, 0, 26, 22}, + { 3, { 0, 0, 43, 26}, 0x81, 132, 0xFFFF, 0, 0, 27, 22}, + { 3, { 16, 33, 48, 0}, 0x81, 133, 0xFFFF, 0, 0, 32, 22}, + { 3, { 17, 34, 49, 32}, 0x81, 124, 0xFFFF, 0, 0, 33, 22}, + { 3, { 18, 35, 50, 33}, 0x81, 132, 0xFFFF, 0, 0, 34, 22}, + { 3, { 19, 36, 51, 34}, 0x81, 131, 0xFFFF, 0, 0, 35, 22}, + { 3, { 20, 37, 52, 35}, 0x81, 126, 0xFFFF, 0, 0, 36, 22}, + { 3, { 21, 38, 53, 36}, 0x81, 125, 0xFFFF, 0, 0, 37, 22}, + { 3, { 22, 39, 54, 37}, 0x81, 126, 0xFFFF, 0, 0, 38, 22}, + { 3, { 23, 40, 55, 38}, 0x81, 128, 0xFFFF, 0, 0, 39, 22}, + { 3, { 24, 41, 56, 39}, 0x81, 127, 0xFFFF, 0, 0, 40, 22}, + { 3, { 25, 42, 57, 40}, 0x81, 133, 0xFFFF, 0, 0, 41, 22}, + { 3, { 26, 43, 58, 41}, 0x81, 124, 0xFFFF, 0, 0, 42, 22}, + { 3, { 27, 0, 59, 42}, 0x81, 129, 0xFFFF, 0, 0, 43, 22}, + {11, { 32, 49, 0, 0}, 0x40, 221, 0xFFFF, 0, 0, 48, 32}, + {12, { 33, 50, 0, 48}, 0x40, 215, 0xFFFF, 0, 0, 49, 32}, + {11, { 34, 51, 66, 49}, 0x40, 217, 0xFFFF, 0, 0, 50, 32}, + {11, { 35, 52, 67, 50}, 0x40, 223, 0xFFFF, 0, 0, 51, 32}, + { 3, { 36, 53, 68, 51}, 1, 179, 0xFFFF, 0, 0, 52, 28}, + { 3, { 37, 54, 69, 52}, 1, 180, 0xFFFF, 0, 0, 53, 28}, + { 3, { 38, 55, 70, 53}, 1, 178, 0xFFFF, 0, 0, 54, 28}, + { 3, { 39, 56, 71, 54}, 1, 177, 0xFFFF, 0, 0, 55, 28}, + { 3, { 40, 57, 72, 55}, 0xC1, 196, 0xFFFF, 0, 0, 56, 26}, + { 3, { 41, 58, 73, 56}, 0xC1, 197, 0xFFFF, 0, 0, 57, 26}, + { 9, { 42, 59, 74, 57}, 0xC0, 279, 0xFFFF, 0, 0, 58, 26}, + {10, { 0, 0, 58, 0}, 0xC4, 280, 0xFFFF, 0,78, 58, 26}, + { 3, { 43, 0, 75, 58}, 0xC0, 237, 0, 0, 0, 59, 26}, + { 4, { 43, 0, 75, 58}, 0xC6, 236, 0x200, 0,46, 59, 26}, + {11, { 50, 67, 1, 0}, 0x40, 218, 0xFFFF, 0, 0, 66, 32}, + {11, { 51, 68, 1, 66}, 0x40, 217, 0xFFFF, 0, 0, 67, 32}, + { 3, { 52, 69, 1, 67}, 1, 168, 0xFFFF, 0, 0, 68, 28}, + { 3, { 53, 70, 1, 68}, 1, 172, 0xFFFF, 0, 0, 69, 28}, + { 3, { 54, 71, 1, 69}, 1, 170, 0xFFFF, 0, 0, 70, 28}, + { 3, { 55, 72, 1, 70}, 0xC1, 201, 0xFFFF, 0, 0, 71, 26}, + { 7, { 56, 73, 1, 71}, 0xC0, 276, 0xFFFF, 0, 0, 72, 26}, + { 3, { 57, 74, 1, 72}, 0xC1, 194, 0xFFFF, 0, 0, 73, 26}, + { 3, { 58, 75, 1, 73}, 0xC1, 195, 0xFFFF, 0, 0, 74, 26}, + { 9, { 59, 0, 1, 74}, 0xC0, 277, 0xFFFF, 0, 0, 75, 26}, + {10, { 0, 0, 75, 0}, 0xC4, 278, 0xFFFF, 0,52, 75, 26}, + END_ROOMS, + // Tamara + { 1, {255, 0, 0, 0}, 0x1A, 43, 0xFFFF, 1, 0, 1, 36}, + { 2, {255, 0, 0, 0}, 0x1A, 43, 0xFFFF, 0, 0, 1, 36}, + { 3, { 0, 17, 32, 0}, 0x81, 147, 0xFFFF, 0, 0, 16, 24}, + { 3, { 0, 18, 33, 16}, 0x81, 148, 0xFFFF, 0, 0, 17, 24}, + { 3, { 0, 19, 34, 17}, 0x81, 149, 0xFFFF, 0, 0, 18, 24}, + { 3, { 0, 20, 35, 18}, 0x81, 150, 0xFFFF, 0, 0, 19, 24}, + { 3, { 0, 21, 36, 19}, 0x81, 151, 0xFFFF, 0, 0, 20, 24}, + { 3, { 0, 22, 37, 20}, 0x81, 152, 0xFFFF, 0, 0, 21, 24}, + { 3, { 0, 23, 38, 21}, 0x81, 153, 0xFFFF, 0, 0, 22, 24}, + { 3, { 0, 24, 39, 22}, 0x81, 154, 0xFFFF, 0, 0, 23, 24}, + { 3, { 0, 0, 40, 23}, 0x81, 155, 0xFFFF, 0, 0, 24, 24}, + { 3, { 16, 33, 48, 0}, 0x81, 154, 0xFFFF, 0, 0, 32, 24}, + { 3, { 17, 34, 49, 32}, 0x81, 156, 0xFFFF, 0, 0, 33, 24}, + { 3, { 18, 35, 50, 33}, 0x81, 157, 0xFFFF, 0, 0, 34, 24}, + { 3, { 19, 36, 51, 34}, 0x81, 158, 0xFFFF, 0, 0, 35, 24}, + { 3, { 20, 37, 52, 35}, 0x81, 159, 0xFFFF, 0, 0, 36, 24}, + { 3, { 21, 38, 53, 36}, 0x81, 160, 0xFFFF, 0, 0, 37, 24}, + { 3, { 22, 39, 54, 37}, 0x81, 161, 0xFFFF, 0, 0, 38, 24}, + { 3, { 23, 40, 55, 38}, 0x81, 162, 0xFFFF, 0, 0, 39, 24}, + { 4, { 24, 41, 56, 39}, 0xC0, 248, 0x280, 0, 0, 40, 26}, + { 4, { 24, 41, 56, 39}, 0xC0, 247, 0x200, 0, 0, 40, 26}, + { 4, { 24, 41, 56, 39}, 0xC0, 246, 0xFFFF, 0, 0, 40, 26}, + {11, { 0, 0, 57, 40}, 0x40, 207, 0xFFFF, 0, 0, 41, 34}, + { 3, { 32, 49, 64, 0}, 0xC1, 193, 0xFFFF, 0, 0, 48, 26}, + { 3, { 33, 50, 65, 48}, 0xC1, 200, 0xFFFF, 0, 0, 49, 26}, + { 3, { 34, 51, 66, 49}, 1, 184, 0xFFFF, 0, 0, 50, 30}, + { 3, { 35, 52, 67, 50}, 1, 185, 0xFFFF, 0, 0, 51, 30}, + { 3, { 36, 53, 68, 51}, 0x81, 189, 0xFFFF, 0, 0, 52, 30}, + { 3, { 37, 54, 69, 52}, 1, 192, 0xFFFF, 0, 0, 53, 30}, + { 3, { 38, 55, 70, 53}, 1, 191, 0xFFFF, 0, 0, 54, 30}, + { 9, { 39, 56, 71, 54}, 0xC0, 277, 0xFFFF, 0, 0, 55, 26}, + {10, { 0, 0, 55, 0}, 0xC4, 278, 0xFFFF, 0,52, 55, 26}, + { 3, { 40, 57, 72, 55}, 0xC1, 195, 0xFFFF, 0, 0, 56, 26}, + {11, { 41, 58, 0, 56}, 0x40, 208, 0xFFFF, 0, 0, 57, 34}, + {11, { 0, 0, 0, 57}, 0x40, 212, 0xFFFF, 0, 0, 58, 34}, + { 8, { 48, 65, 1, 0}, 0xC1, 276, 0xFFFF, 0, 0, 64, 26}, + { 3, { 49, 66, 1, 64}, 1, 187, 0xFFFF, 0, 0, 65, 30}, + { 3, { 50, 67, 1, 65}, 1, 188, 0xFFFF, 0, 0, 66, 30}, + { 3, { 51, 68, 1, 66}, 1, 190, 0xFFFF, 0, 0, 67, 30}, + {12, { 52, 69, 1, 67}, 0x40, 205, 0xFFFF, 0, 0, 68, 34}, + {11, { 53, 70, 1, 68}, 0x40, 203, 0xFFFF, 0, 0, 69, 34}, + {11, { 54, 71, 1, 69}, 0x40, 211, 0xFFFF, 0, 0, 70, 34}, + {14, { 55, 72, 1, 70}, 0x40, 213, 2, 0, 0, 71, 34}, + {11, { 55, 72, 1, 70}, 0x40, 210, 0xFFFF, 0, 0, 71, 34}, + {11, { 56, 0, 1, 71}, 0x40, 207, 0xFFFF, 0, 0, 72, 34}, + END_ROOMS, + // Cantura + { 1, {255, 0, 0, 0}, 0x18, 44, 0xFFFF, 1, 0, 1, 38}, + { 2, {255, 0, 0, 0}, 0x18, 44, 0xFFFF, 0, 0, 1, 38}, + { 4, { 0, 0, 18, 0}, 0x86, 240, 0xA00, 0,48, 17, 54}, + {13, { 0, 0, 18, 0}, 0x80, 241, 0xA80, 0, 0, 17, 54}, + {14, { 0, 0, 18, 0}, 0x80, 242, 0xA02, 0, 0, 17, 54}, + {14, { 0, 0, 18, 0}, 0x80, 242, 0xFFFF, 0, 0, 17, 54}, + {15, { 17, 19, 0, 0}, 0x40, 224, 0xFFFF, 0, 0, 18, 32}, + { 3, { 0, 20, 0, 18}, 0x40, 225, 0xFFFF, 0, 0, 19, 32}, + { 3, { 0, 21, 0, 19}, 0x40, 226, 0xFFFF, 0, 0, 20, 32}, + { 3, { 0, 22, 0, 20}, 0x40, 227, 0xFFFF, 0, 0, 21, 32}, + { 9, { 0, 23, 38, 21}, 0xC0, 277, 0xFFFF, 0, 0, 22, 26}, + {10, { 0, 0, 22, 0}, 0xC4, 278, 0xFFFF, 0,52, 22, 26}, + { 5, { 0, 24, 39, 22}, 0xC0, 276, 0xFFFF, 0, 0, 23, 26}, + { 3, { 0, 25, 40, 23}, 0x81, 125, 0xFFFF, 0, 0, 24, 22}, + { 3, { 0, 26, 41, 24}, 0x81, 131, 0xFFFF, 0, 0, 25, 22}, + { 3, { 0, 27, 42, 25}, 0x81, 133, 0xFFFF, 0, 0, 26, 22}, + { 3, { 0, 0, 43, 26}, 0x81, 132, 0xFFFF, 0, 0, 27, 22}, + {11, { 22, 39, 54, 0}, 0x40, 223, 0xFFFF, 0, 0, 38, 32}, + { 3, { 23, 40, 55, 38}, 1, 167, 0xFFFF, 0, 0, 39, 28}, + { 3, { 24, 41, 56, 39}, 0x81, 126, 0xFFFF, 0, 0, 40, 22}, + { 3, { 25, 42, 57, 40}, 1, 172, 0xFFFF, 0, 0, 41, 28}, + { 3, { 26, 43, 58, 41}, 1, 163, 0xFFFF, 0, 0, 42, 28}, + { 3, { 27, 0, 59, 42}, 1, 168, 0xFFFF, 0, 0, 43, 28}, + { 3, { 38, 55, 70, 0}, 1, 164, 0xFFFF, 0, 0, 54, 28}, + { 3, { 39, 56, 71, 54}, 1, 165, 0xFFFF, 0, 0, 55, 28}, + { 3, { 40, 57, 72, 55}, 1, 163, 0xFFFF, 0, 0, 56, 28}, + { 3, { 41, 58, 73, 56}, 1, 167, 0xFFFF, 0, 0, 57, 28}, + { 3, { 42, 59, 74, 57}, 1, 166, 0xFFFF, 0, 0, 58, 28}, + { 3, { 43, 0, 75, 58}, 1, 171, 0xFFFF, 0, 0, 59, 28}, + {12, { 0, 70, 1, 0}, 0x40, 215, 0xFFFF, 0, 0, 69, 32}, + { 3, { 54, 71, 1, 69}, 1, 173, 0xFFFF, 0, 0, 70, 28}, + { 3, { 55, 72, 1, 70}, 1, 168, 0xFFFF, 0, 0, 71, 28}, + { 3, { 56, 73, 1, 71}, 1, 169, 0xFFFF, 0, 0, 72, 28}, + { 3, { 57, 74, 1, 72}, 1, 170, 0xFFFF, 0, 0, 73, 28}, + { 3, { 58, 75, 1, 73}, 1, 172, 0xFFFF, 0, 0, 74, 28}, + { 3, { 59, 0, 1, 74}, 1, 175, 0xFFFF, 0, 0, 75, 28}, + END_ROOMS, + // Shandovra + { 1, {255, 0, 0, 0}, 0x18, 45, 0xFFFF, 1, 0, 1, 40}, + { 2, {255, 0, 0, 0}, 0x18, 45, 0xFFFF, 0, 0, 1, 40}, + { 3, { 0, 17, 32, 0}, 0xC1, 193, 0xFFFF, 0, 0, 16, 26}, + { 3, { 0, 18, 33, 16}, 0x81, 125, 0xFFFF, 0, 0, 17, 22}, + { 3, { 0, 19, 34, 17}, 0x81, 126, 0xFFFF, 0, 0, 18, 22}, + { 3, { 0, 20, 35, 18}, 0x81, 127, 0xFFFF, 0, 0, 19, 22}, + { 3, { 0, 21, 36, 19}, 0x81, 128, 0xFFFF, 0, 0, 20, 22}, + { 3, { 0, 22, 37, 20}, 0x81, 131, 0xFFFF, 0, 0, 21, 22}, + { 3, { 0, 23, 38, 21}, 0x81, 129, 0xFFFF, 0, 0, 22, 22}, + { 3, { 0, 24, 39, 22}, 0x81, 130, 0xFFFF, 0, 0, 23, 22}, + { 3, { 0, 25, 40, 23}, 0x81, 125, 0xFFFF, 0, 0, 24, 22}, + { 3, { 0, 26, 41, 24}, 0x81, 124, 0xFFFF, 0, 0, 25, 22}, + { 4, { 0, 27, 42, 25}, 0x80, 250, 0x100, 0, 0, 26, 22}, + { 4, { 0, 27, 42, 25}, 0x80, 250, 0x300, 0, 0, 26, 22}, + { 4, { 0, 27, 42, 25}, 0x80, 251, 0x200, 0, 0, 26, 22}, + { 4, { 0, 27, 42, 25}, 0x80, 249, 0xFFFF, 0, 0, 26, 22}, + { 3, { 0, 0, 43, 26}, 0x81, 132, 0xFFFF, 0, 0, 27, 22}, + { 3, {16, 33, 48, 0}, 0xC1, 193, 0xFFFF, 0, 0, 32, 26}, + { 3, {17, 34, 49, 32}, 0xC1, 193, 0xFFFF, 0, 0, 33, 26}, + { 3, {18, 35, 50, 33}, 0xC1, 201, 0xFFFF, 0, 0, 34, 26}, + { 3, {19, 36, 51, 34}, 1, 170, 0xFFFF, 0, 0, 35, 28}, + { 3, {20, 37, 52, 35}, 1, 165, 0xFFFF, 0, 0, 36, 28}, + { 3, {21, 38, 53, 36}, 1, 164, 0xFFFF, 0, 0, 37, 28}, + { 3, {22, 39, 54, 37}, 0x81, 126, 0xFFFF, 0, 0, 38, 22}, + { 3, {23, 40, 55, 38}, 1, 167, 0xFFFF, 0, 0, 39, 28}, + { 3, {24, 41, 56, 39}, 0x81, 126, 0xFFFF, 0, 0, 40, 22}, + { 3, {25, 42, 0, 40}, 0x81, 132, 0xFFFF, 0, 0, 41, 22}, + { 3, {26, 43, 58, 41}, 0x81, 124, 0xFFFF, 0, 0, 42, 22}, + { 3, {27, 0, 59, 42}, 0x81, 129, 0xFFFF, 0, 0, 43, 22}, + { 6, {32, 49, 64, 0}, 0xC0, 276, 0xFFFF, 0, 0, 48, 26}, + { 9, {33, 50, 65, 48}, 0xC0, 279, 0xFFFF, 0, 0, 49, 26}, + {10, { 0, 0, 49, 0}, 0xC4, 280, 0xFFFF, 0, 78, 49, 26}, + { 3, {34, 51, 66, 49}, 0xC1, 197, 0xFFFF, 0, 0, 50, 26}, + { 3, {35, 52, 67, 50}, 0xC1, 202, 0xFFFF, 0, 0, 51, 26}, + { 3, {36, 53, 68, 51}, 1, 177, 0xFFFF, 0, 0, 52, 28}, + { 3, {37, 54, 69, 52}, 0x81, 124, 0xFFFF, 0, 0, 53, 22}, + { 3, {38, 55, 70, 53}, 0x81, 125, 0xFFFF, 0, 0, 54, 22}, + { 3, {39, 56, 71, 54}, 1, 180, 0xFFFF, 0, 0, 55, 28}, + {12, {40, 0, 72, 55}, 0x40, 215, 0xFFFF, 0, 0, 56, 32}, + {11, {42, 59, 0, 0}, 0x40, 218, 0xFFFF, 0, 0, 58, 32}, + {11, {43, 0, 75, 58}, 0x40, 216, 0xFFFF, 0, 0, 59, 32}, + { 9, {48, 65, 1, 0}, 0xC0, 277, 0xFFFF, 0, 0, 64, 26}, + {10, { 0, 0, 64, 0}, 0xC4, 278, 0xFFFF, 0, 52, 64, 26}, + { 3, {49, 66, 1, 64}, 0xC1, 197, 0xFFFF, 0, 0, 65, 26}, + { 3, {50, 67, 1, 65}, 0xC1, 200, 0xFFFF, 0, 0, 66, 26}, + { 3, {51, 68, 1, 66}, 0x81, 125, 0xFFFF, 0, 0, 67, 22}, + { 3, {52, 69, 1, 67}, 0x81, 129, 0xFFFF, 0, 0, 68, 22}, + { 3, {53, 70, 1, 68}, 0x81, 133, 0xFFFF, 0, 0, 69, 22}, + { 3, {54, 71, 1, 69}, 1, 179, 0xFFFF, 0, 0, 70, 28}, + { 3, {55, 72, 1, 70}, 1, 181, 0xFFFF, 0, 0, 71, 28}, + {11, {56, 0, 1, 71}, 0x40, 214, 0xFFFF, 0, 0, 72, 32}, + {11, {59, 0, 1, 0}, 0x40, 223, 0xFFFF, 0, 0, 75, 32}, + END_ROOMS +}; diff --git a/devtools/create_cryo/module.mk b/devtools/create_cryo/module.mk new file mode 100644 index 0000000000..f8e350a95d --- /dev/null +++ b/devtools/create_cryo/module.mk @@ -0,0 +1,11 @@ + +MODULE := devtools/create_cryo + +MODULE_OBJS := \ + create_led_dat.o + +# Set the name of the executable +TOOL_EXECUTABLE := create_led_dat + +# Include common rules +include $(srcdir)/rules.mk diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp index 6072120a15..2baaf91a71 100644 --- a/devtools/create_project/create_project.cpp +++ b/devtools/create_project/create_project.cpp @@ -300,6 +300,19 @@ int main(int argc, char *argv[]) { for (EngineDescList::iterator j = setup.engines.begin(); j != setup.engines.end(); ++j) j->enable = false; } + + // Disable engines for which we are missing dependencies + for (EngineDescList::const_iterator i = setup.engines.begin(); i != setup.engines.end(); ++i) { + if (i->enable) { + for (StringList::const_iterator ef = i->requiredFeatures.begin(); ef != i->requiredFeatures.end(); ++ef) { + FeatureList::iterator feature = std::find(setup.features.begin(), setup.features.end(), *ef); + if (feature != setup.features.end() && !feature->enable) { + setEngineBuildState(i->name, setup.engines, false); + break; + } + } + } + } // Print status cout << "Enabled engines:\n\n"; @@ -906,7 +919,7 @@ namespace { */ bool parseEngine(const std::string &line, EngineDesc &engine) { // Format: - // add_engine engine_name "Readable Description" enable_default ["SubEngineList"] + // add_engine engine_name "Readable Description" enable_default ["SubEngineList"] ["base games"] ["dependencies"] TokenList tokens = tokenize(line); if (tokens.size() < 4) @@ -921,8 +934,14 @@ bool parseEngine(const std::string &line, EngineDesc &engine) { engine.name = *token; ++token; engine.desc = *token; ++token; engine.enable = (*token == "yes"); ++token; - if (token != tokens.end()) + if (token != tokens.end()) { engine.subEngines = tokenize(*token); + ++token; + if (token != tokens.end()) + ++token; + if (token != tokens.end()) + engine.requiredFeatures = tokenize(*token); + } return true; } @@ -1024,6 +1043,7 @@ const Feature s_features[] = { { "scalers", "USE_SCALERS", "", true, "Scalers" }, { "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" }, { "16bit", "USE_RGB_COLOR", "", true, "16bit color support" }, + { "highres", "USE_HIGHRES", "", true, "high resolution" }, { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" }, { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling. { "opengl", "USE_OPENGL", "", true, "OpenGL support" }, diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h index bd0dcf6be9..9f662ae806 100644 --- a/devtools/create_project/create_project.h +++ b/devtools/create_project/create_project.h @@ -86,6 +86,11 @@ struct EngineDesc { * Whether the engine should be included in the build or not. */ bool enable; + + /** + * Features required for this engine. + */ + StringList requiredFeatures; /** * A list of all available sub engine names. Sub engines are engines diff --git a/devtools/create_project/msvc10/create_project.vcxproj b/devtools/create_project/msvc10/create_project.vcxproj index 700c4bb283..0386c3e5ad 100644 --- a/devtools/create_project/msvc10/create_project.vcxproj +++ b/devtools/create_project/msvc10/create_project.vcxproj @@ -50,7 +50,7 @@ <WarningLevel>Level4</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <DisableLanguageExtensions>false</DisableLanguageExtensions> - <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings> + <DisableSpecificWarnings>4003;4512;4127;4100</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/devtools/create_project/msvc11/create_project.vcxproj b/devtools/create_project/msvc11/create_project.vcxproj index 09392a43e3..9168163e3e 100644 --- a/devtools/create_project/msvc11/create_project.vcxproj +++ b/devtools/create_project/msvc11/create_project.vcxproj @@ -53,7 +53,7 @@ <WarningLevel>Level4</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <DisableLanguageExtensions>false</DisableLanguageExtensions> - <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings> + <DisableSpecificWarnings>4003;4512;4127;4100</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/devtools/create_project/msvc12/create_project.vcxproj b/devtools/create_project/msvc12/create_project.vcxproj index 3b38972e51..0623b24a40 100644 --- a/devtools/create_project/msvc12/create_project.vcxproj +++ b/devtools/create_project/msvc12/create_project.vcxproj @@ -52,7 +52,7 @@ <WarningLevel>Level4</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <DisableLanguageExtensions>false</DisableLanguageExtensions> - <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings> + <DisableSpecificWarnings>4003;4512;4127;4100</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/devtools/create_project/msvc14/create_project.vcxproj b/devtools/create_project/msvc14/create_project.vcxproj index 53246d0a67..3493baf1c8 100644 --- a/devtools/create_project/msvc14/create_project.vcxproj +++ b/devtools/create_project/msvc14/create_project.vcxproj @@ -76,7 +76,7 @@ <WarningLevel>Level4</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <DisableLanguageExtensions>false</DisableLanguageExtensions> - <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings> + <DisableSpecificWarnings>4003;4512;4127;4100</DisableSpecificWarnings> <ExceptionHandling>Sync</ExceptionHandling> </ClCompile> <Link> diff --git a/devtools/create_project/msvc9/create_project.vcproj b/devtools/create_project/msvc9/create_project.vcproj index eaa72099cc..f348226337 100644 --- a/devtools/create_project/msvc9/create_project.vcproj +++ b/devtools/create_project/msvc9/create_project.vcproj @@ -45,7 +45,7 @@ RuntimeLibrary="3" WarningLevel="4" DebugInformationFormat="4" - DisableSpecificWarnings="4003;4512;4127" + DisableSpecificWarnings="4003;4512;4127;4100" /> <Tool Name="VCManagedResourceCompilerTool" diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp index 21fc25643f..221f28bb8e 100644 --- a/devtools/create_project/xcode.cpp +++ b/devtools/create_project/xcode.cpp @@ -950,6 +950,7 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) { scummvmOSX_LdFlags.push_back("-lvorbis"); scummvmOSX_LdFlags.push_back("-lmad"); scummvmOSX_LdFlags.push_back("-lFLAC"); + scummvmOSX_LdFlags.push_back("-lcurl"); if (setup.useSDL2) { scummvmOSX_LdFlags.push_back("-lSDL2main"); scummvmOSX_LdFlags.push_back("-lSDL2"); diff --git a/devtools/create_titanic/create_titanic_dat.cpp b/devtools/create_titanic/create_titanic_dat.cpp index 1457ee62e7..09b738a452 100644 --- a/devtools/create_titanic/create_titanic_dat.cpp +++ b/devtools/create_titanic/create_titanic_dat.cpp @@ -788,6 +788,36 @@ static const char *const STRINGS_DE[185] = { "Dr\0xFC" "cken Sie den Knopf um die Bombe zu entschSrfen." }; +static const char *const MUSIC_DATA[4] = { + "64,^|^|^|^|^|^|^|^|^|^|^|^|^|^|^|^|8,^^^^ 5:A///|64,/|/|/|/|/|/|/" + "|/|/|/|/|/|/|/|/|/|^|^|^|^|^|^|^|^|^|16, ^B//|64,/|/|/|/|^|16,^C/" + "/|64,/|/|/|/|", + "2:8,^^^^B//a|//g//B//|g///B//a|//g//A//|B//^C//b|//a//a//|BCb/b//" + "a|//g//A//|g/+f/D//c|//b//gA/|g/^^C//C|//C//a//|BCb////a|//g//g//" + "|g/g//B/a|/g//////|//^^B//a|//g//B//|g///B//a|//g//B//|g//^C//b|/" + "/a//a//|BCb/b//a|//g//B//|g/+f/D//c|//b//gA/|g/^^C//C|//C//a//|BC" + "b////a|//g//g//|g/g//B/a|/g//////|3:^^B//a//|g//A//g/|/^B//a//|g/" + "/A//B/|b^ 3:C//b//|a//g//+f/|+fG/G/GA/|B/a/g///|B///+f//G|G/G/+f/" + "G/|^^e//d//|c//b//gA|g/B//a//|g//g//g/|g//B/a/g|//////^^|^^Ga///G" + "|////////|////////|////////|", + "2:8,^^^^^^D/|/E//E//E|/d//^^d/|/E//E//E|/E//^^G/|/d//d//d|/^^^^^d" + "/|/E//E//E|/d/^^^E/|/E//d/+F/|bD^^^^G/|/e//e//e|^^^^^^d/|/E//E//E" + "|//d///d/|//b/////|^^^^^^D/|/E//E//E|/d//^^d/|/E//E//E|/E//^^G/|/" + "d//d//d|/^^^^^d/|/E//E//E|/d/^^^E/|/E//d/d/|d/^^^^G/|/e//e//e|^^^" + "^^^d/|/E//E//E|//d///d/|//b/////|3:D///c//b|//b//b//|D///c//b|//b" + "//g//|E///d//c|//b//a//|aB/B/BC/|D/c/b///|^^^D//DE|/E/E/d/d|//E/g" + "//g|//g//d//|^^^^g//E|//E//E//|d///d///|b///////|// 3:Db///C|///b" + "/// 5:A|64,/|/|/|/|/|/|/|/|", + "2:8,^^G//+f//|e//e//e/|//G//+f//|e//e//+F/|G/a//g//|+f//+f//+f/|/" + "/G//+F//|e//e//e/|//B//a//|g//e///d|//c//b//|a//a//a/|+f/G// 2:+F" + "//|e//e//C/|//b/g/+f/|//G/////|^^G//+f//|e//e//e/|//G//+f//|e//e/" + "/e/|//a//g//|+f//+f//+f/|//G//+F//|e//e//e/|//B//a//|g//e///d|/ " + "2:dC//b//|a//a//a/|+f/G//+F//|e//e//C/|//b/g/+f/|//G/////|d//d//d" + "/|/E//E//d|d//d//E/|/+F//G//b|a//a//a/|/D//D// 3:D|//g/g//D|/d/G/" + "///|^^b//b//|b//ba/B/|c//B//a/|/g//+f//+f|G//+F//e/|/c//C///|b/g/" + "+f///|G///////|G///////|C///////|////////|////////|" +}; + void NORETURN_PRE error(const char *s, ...) { printf("%s\n", s); exit(1); @@ -1269,6 +1299,7 @@ void writeData() { writeStringArray("TEXT/REPLACEMENTS2", TEXT_REPLACEMENTS2[_version], 1576); writeStringArray("TEXT/REPLACEMENTS3", TEXT_REPLACEMENTS3[_version], 82); writeStringArray("TEXT/PRONOUNS", TEXT_PRONOUNS[_version], 15); + writeStringArray("MUSIC/PARSER", MUSIC_DATA, 4); const int SENTENCES_DEFAULT[3] = { 0x5C0130, 0x5BEFC8, 0x5BE008 }; const int SENTENCES_BARBOT[2][3] = { diff --git a/engines/adl/adl_v4.cpp b/engines/adl/adl_v4.cpp index 262cd62dbe..8370bead6f 100644 --- a/engines/adl/adl_v4.cpp +++ b/engines/adl/adl_v4.cpp @@ -190,24 +190,23 @@ Common::String AdlEngine_v4::getItemDescription(const Item &item) const { return _itemDesc[item.id - 1]; } -DiskImage *AdlEngine_v4::loadDisk(byte volume) const { +Common::String AdlEngine_v4::getDiskImageName(byte volume) const { const ADGameFileDescription *ag; - for (ag = _gameDescription->desc.filesDescriptions; ag->fileName; ag++) { - if (ag->fileType == volume) { - DiskImage *disk = new DiskImage(); - if (!disk->open(ag->fileName)) - error("Failed to open %s", ag->fileName); - return disk; - } - } + for (ag = _gameDescription->desc.filesDescriptions; ag->fileName; ag++) + if (ag->fileType == volume) + return ag->fileName; error("Disk volume %d not found", volume); } void AdlEngine_v4::insertDisk(byte volume) { delete _disk; - _disk = loadDisk(volume); + _disk = new DiskImage(); + + if (!_disk->open(getDiskImageName(volume))) + error("Failed to open disk volume %d", volume); + _currentVolume = volume; } @@ -274,6 +273,27 @@ void AdlEngine_v4::adjustDataBlockPtr(byte &track, byte §or, byte &offset, b fixupDiskOffset(track, sector); } +AdlEngine_v4::RegionChunkType AdlEngine_v4::getRegionChunkType(const uint16 addr) const { + switch (addr) { + case 0x9000: + return kRegionChunkMessages; + case 0x4a80: + return kRegionChunkGlobalPics; + case 0x4000: + return kRegionChunkVerbs; + case 0x1800: + return kRegionChunkNouns; + case 0x0e00: + return kRegionChunkRooms; + case 0x7b00: + return kRegionChunkRoomCmds; + case 0x9500: + return kRegionChunkGlobalCmds; + default: + return kRegionChunkUnknown; + } +} + void AdlEngine_v4::loadRegion(byte region) { if (_currentVolume != _regionInitDataOffsets[region - 1].volume) { insertDisk(_regionInitDataOffsets[region - 1].volume); @@ -303,29 +323,29 @@ void AdlEngine_v4::loadRegion(byte region) { stream.reset(_disk->createReadStream(track, sector, offset, size / 256 + 1)); stream->skip(4); - switch (addr) { - case 0x9000: { + switch (getRegionChunkType(addr)) { + case kRegionChunkMessages: { // Messages _messages.clear(); uint count = size / 4; loadMessages(*stream, count); break; } - case 0x4a80: { + case kRegionChunkGlobalPics: { // Global pics _pictures.clear(); loadPictures(*stream); break; } - case 0x4000: + case kRegionChunkVerbs: // Verbs loadWords(*stream, _verbs, _priVerbs); break; - case 0x1800: + case kRegionChunkNouns: // Nouns loadWords(*stream, _nouns, _priNouns); break; - case 0x0e00: { + case kRegionChunkRooms: { // Rooms uint count = size / 14 - 1; stream->skip(14); // Skip invalid room 0 @@ -334,12 +354,11 @@ void AdlEngine_v4::loadRegion(byte region) { loadRooms(*stream, count); break; } - case 0x7b00: - // TODO: hires6 has global and room lists swapped + case kRegionChunkRoomCmds: // Room commands readCommands(*stream, _roomCommands); break; - case 0x9500: + case kRegionChunkGlobalCmds: // Global commands readCommands(*stream, _globalCommands); break; diff --git a/engines/adl/adl_v4.h b/engines/adl/adl_v4.h index 4e87530673..08cea21181 100644 --- a/engines/adl/adl_v4.h +++ b/engines/adl/adl_v4.h @@ -60,12 +60,24 @@ protected: // AdlEngine_v2 virtual void adjustDataBlockPtr(byte &track, byte §or, byte &offset, byte &size) const; - DiskImage *loadDisk(byte volume) const; + enum RegionChunkType { + kRegionChunkUnknown, + kRegionChunkMessages, + kRegionChunkGlobalPics, + kRegionChunkVerbs, + kRegionChunkNouns, + kRegionChunkRooms, + kRegionChunkRoomCmds, + kRegionChunkGlobalCmds + }; + + Common::String getDiskImageName(byte volume) const; void insertDisk(byte volume); void loadRegionLocations(Common::ReadStream &stream, uint regions); void loadRegionInitDataOffsets(Common::ReadStream &stream, uint regions); void initRegions(const byte *roomsPerRegion, uint regions); void fixupDiskOffset(byte &track, byte §or) const; + virtual RegionChunkType getRegionChunkType(const uint16 addr) const; void loadRegion(byte region); void loadItemPicIndex(Common::ReadStream &stream, uint items); void backupRoomState(byte room); diff --git a/engines/adl/adl_v5.cpp b/engines/adl/adl_v5.cpp index 7e7c6e40ac..795899c070 100644 --- a/engines/adl/adl_v5.cpp +++ b/engines/adl/adl_v5.cpp @@ -30,43 +30,24 @@ namespace Adl { AdlEngine_v5::AdlEngine_v5(OSystem *syst, const AdlGameDescription *gd) : - AdlEngine_v3(syst, gd), - _curDisk(0) { + AdlEngine_v4(syst, gd) { } -Common::String AdlEngine_v5::loadMessage(uint idx) const { - Common::String str = AdlEngine_v2::loadMessage(idx); - - for (uint i = 0; i < str.size(); ++i) { - const char *xorStr = "AVISDURGAN"; - str.setChar(str[i] ^ xorStr[i % strlen(xorStr)], i); +AdlEngine_v5::RegionChunkType AdlEngine_v5::getRegionChunkType(const uint16 addr) const { + switch (addr) { + case 0x7b00: + return kRegionChunkGlobalCmds; + case 0x9500: + return kRegionChunkRoomCmds; + default: + return AdlEngine_v4::getRegionChunkType(addr); } - - return str; -} - -Common::String AdlEngine_v5::getItemDescription(const Item &item) const { - return _itemDesc[item.id - 1]; } -void AdlEngine_v5::applyDiskOffset(byte &track, byte §or) const { - sector += _diskOffsets[_curDisk].sector; - if (sector >= 16) { - sector -= 16; - ++track; - } - - track += _diskOffsets[_curDisk].track; -} - -void AdlEngine_v5::adjustDataBlockPtr(byte &track, byte §or, byte &offset, byte &size) const { - applyDiskOffset(track, sector); -} - -typedef Common::Functor1Mem<ScriptEnv &, int, AdlEngine_v5> OpcodeV4; +typedef Common::Functor1Mem<ScriptEnv &, int, AdlEngine_v5> OpcodeV5; #define SetOpcodeTable(x) table = &x; -#define Opcode(x) table->push_back(new OpcodeV4(this, &AdlEngine_v5::x)) -#define OpcodeUnImpl() table->push_back(new OpcodeV4(this, 0)) +#define Opcode(x) table->push_back(new OpcodeV5(this, &AdlEngine_v5::x)) +#define OpcodeUnImpl() table->push_back(new OpcodeV5(this, 0)) void AdlEngine_v5::setupOpcodeTables() { Common::Array<const Opcode *> *table = 0; @@ -76,14 +57,14 @@ void AdlEngine_v5::setupOpcodeTables() { OpcodeUnImpl(); Opcode(o2_isFirstTime); Opcode(o2_isRandomGT); - Opcode(o5_isItemInRoom); + Opcode(o4_isItemInRoom); // 0x04 Opcode(o5_isNounNotInRoom); Opcode(o1_isMovesGT); Opcode(o1_isVarEQ); Opcode(o2_isCarryingSomething); // 0x08 - Opcode(o5_isVarGT); + Opcode(o4_isVarGT); Opcode(o1_isCurPicEQ); Opcode(o5_skipOneCommand); @@ -95,7 +76,7 @@ void AdlEngine_v5::setupOpcodeTables() { Opcode(o1_varSet); // 0x04 Opcode(o1_listInv); - Opcode(o5_moveItem); + Opcode(o4_moveItem); Opcode(o1_setRoom); Opcode(o2_setCurPic); // 0x08 @@ -111,7 +92,7 @@ void AdlEngine_v5::setupOpcodeTables() { // 0x10 Opcode(o2_restore); Opcode(o1_restart); - Opcode(o5_setDisk); + Opcode(o5_setRegionRoom); Opcode(o5_dummy); // 0x14 Opcode(o1_resetPic); @@ -126,45 +107,12 @@ void AdlEngine_v5::setupOpcodeTables() { // 0x1c Opcode(o1_dropItem); Opcode(o1_setRoomPic); - Opcode(o5_sound); + Opcode(o_winGame); OpcodeUnImpl(); // 0x20 Opcode(o2_initDisk); } -int AdlEngine_v5::o5_isVarGT(ScriptEnv &e) { - OP_DEBUG_2("\t&& VARS[%d] > %d", e.arg(1), e.arg(2)); - - if (getVar(e.arg(1)) > e.arg(2)) - return 2; - - return -1; -} - -int AdlEngine_v5::o5_skipOneCommand(ScriptEnv &e) { - OP_DEBUG_0("\t&& SKIP_ONE_COMMAND()"); - - _skipOneCommand = true; - setVar(2, 0); - - return -1; -} - -// FIXME: Rename "isLineArt" and look at code duplication -int AdlEngine_v5::o5_isItemInRoom(ScriptEnv &e) { - OP_DEBUG_2("\t&& GET_ITEM_ROOM(%s) == %s", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str()); - - const Item &item = getItem(e.arg(1)); - - if (e.arg(2) != IDI_ANY && item.isLineArt != _curDisk) - return -1; - - if (item.room == roomArg(e.arg(2))) - return 2; - - return -1; -} - int AdlEngine_v5::o5_isNounNotInRoom(ScriptEnv &e) { OP_DEBUG_1("\t&& NO_SUCH_ITEMS_IN_ROOM(%s)", itemRoomStr(e.arg(1)).c_str()); @@ -183,23 +131,13 @@ int AdlEngine_v5::o5_isNounNotInRoom(ScriptEnv &e) { return 1; } -int AdlEngine_v5::o5_moveItem(ScriptEnv &e) { - OP_DEBUG_2("\tSET_ITEM_ROOM(%s, %s)", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str()); - - byte room = roomArg(e.arg(2)); - - Item &item = getItem(e.arg(1)); - - if (item.room == _roomOnScreen) - _picOnScreen = 0; +int AdlEngine_v5::o5_skipOneCommand(ScriptEnv &e) { + OP_DEBUG_0("\t&& SKIP_ONE_COMMAND()"); - // Set items that move from inventory to a room to state "dropped" - if (item.room == IDI_ANY && room != IDI_VOID_ROOM) - item.state = IDI_ITEM_DROPPED; + _skipOneCommand = true; + setVar(2, 0); - item.room = room; - item.isLineArt = _curDisk; - return 2; + return -1; } int AdlEngine_v5::o5_dummy(ScriptEnv &e) { @@ -225,18 +163,15 @@ int AdlEngine_v5::o5_setTextMode(ScriptEnv &e) { return 1; } -int AdlEngine_v5::o5_setDisk(ScriptEnv &e) { - OP_DEBUG_2("\tSET_DISK(%d, %d)", e.arg(1), e.arg(2)); +int AdlEngine_v5::o5_setRegionRoom(ScriptEnv &e) { + OP_DEBUG_2("\tSET_REGION_ROOM(%d, %d)", e.arg(1), e.arg(2)); // TODO - // Arg 1: disk - // Arg 2: room - return 2; } -int AdlEngine_v5::o5_sound(ScriptEnv &e) { - OP_DEBUG_0("\tSOUND()"); +int AdlEngine_v5::o_winGame(ScriptEnv &e) { + OP_DEBUG_0("\tWIN_GAME()"); // TODO diff --git a/engines/adl/adl_v5.h b/engines/adl/adl_v5.h index 377fe45e20..bb1cc3015a 100644 --- a/engines/adl/adl_v5.h +++ b/engines/adl/adl_v5.h @@ -23,21 +23,11 @@ #ifndef ADL_ADL_V5_H #define ADL_ADL_V5_H -#include "adl/adl_v3.h" - -namespace Common { -class RandomSource; -} - -struct DiskOffset { - byte track; - byte sector; -}; +#include "adl/adl_v4.h" namespace Adl { -// FIXME: Subclass _v4 when it is done -class AdlEngine_v5 : public AdlEngine_v3 { +class AdlEngine_v5 : public AdlEngine_v4 { public: virtual ~AdlEngine_v5() { } @@ -46,26 +36,16 @@ protected: // AdlEngine virtual void setupOpcodeTables(); - virtual Common::String loadMessage(uint idx) const; - Common::String getItemDescription(const Item &item) const; - // AdlEngine_v2 - virtual void adjustDataBlockPtr(byte &track, byte §or, byte &offset, byte &size) const; + // AdlEngine_v4 + virtual RegionChunkType getRegionChunkType(const uint16 addr) const; - void applyDiskOffset(byte &track, byte §or) const; - - int o5_isVarGT(ScriptEnv &e); - int o5_isItemInRoom(ScriptEnv &e); int o5_isNounNotInRoom(ScriptEnv &e); int o5_skipOneCommand(ScriptEnv &e); - int o5_moveItem(ScriptEnv &e); int o5_dummy(ScriptEnv &e); int o5_setTextMode(ScriptEnv &e); - int o5_setDisk(ScriptEnv &e); - int o5_sound(ScriptEnv &e); - - byte _curDisk; - Common::Array<DiskOffset> _diskOffsets; + int o5_setRegionRoom(ScriptEnv &e); + int o_winGame(ScriptEnv &e); }; } // End of namespace Adl diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp index 431395d054..66bbe84ea2 100644 --- a/engines/adl/detection.cpp +++ b/engines/adl/detection.cpp @@ -188,9 +188,9 @@ static const AdlGameDescription gameDescriptions[] = { "hires6", 0, { { "DARK1A.DSK", 0, "00c2646d6943d1405717332a6f42d493", 143360 }, - { "DARK2A.NIB", 0, "271eb92db107e8d5829437f8ba77991e", 232960 }, - { "DARK1B.NIB", 0, "dbedd736617343ade0e6bead8bf2b10c", 232960 }, - { "DARK2B.NIB", 0, "cb72044a9b391c4285f4752f746bea2e", 232960 }, + { "DARK1B.NIB", 3, "dbedd736617343ade0e6bead8bf2b10c", 232960 }, + { "DARK2A.NIB", 4, "271eb92db107e8d5829437f8ba77991e", 232960 }, + { "DARK2B.NIB", 5, "cb72044a9b391c4285f4752f746bea2e", 232960 }, AD_LISTEND }, Common::EN_ANY, diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp index 77b0cb64ee..91ab16313b 100644 --- a/engines/adl/hires6.cpp +++ b/engines/adl/hires6.cpp @@ -34,44 +34,19 @@ namespace Adl { -#define IDI_HR6_NUM_ROOMS 35 -#define IDI_HR6_NUM_MESSAGES 256 -#define IDI_HR6_NUM_VARS 40 -#define IDI_HR6_NUM_ITEM_DESCS 15 -#define IDI_HR6_NUM_ITEM_PICS 15 -#define IDI_HR6_NUM_ITEM_OFFSETS 16 - -// Messages used outside of scripts -#define IDI_HR6_MSG_CANT_GO_THERE 249 -#define IDI_HR6_MSG_DONT_UNDERSTAND 247 -#define IDI_HR6_MSG_ITEM_DOESNT_MOVE 253 -#define IDI_HR6_MSG_ITEM_NOT_HERE 254 -#define IDI_HR6_MSG_THANKS_FOR_PLAYING 252 - -struct DiskDataDesc { - byte track; - byte sector; - byte offset; - byte volume; -}; - class HiRes6Engine : public AdlEngine_v5 { public: HiRes6Engine(OSystem *syst, const AdlGameDescription *gd) : AdlEngine_v5(syst, gd), - _boot(nullptr), _currVerb(0), _currNoun(0) { } - ~HiRes6Engine() { delete _boot; } - private: // AdlEngine void runIntro(); void init(); void initGameState(); - void printRoomDescription(); void showRoom(); Common::String formatVerbError(const Common::String &verb) const; Common::String formatNounError(const Common::String &verb, const Common::String &noun) const; @@ -79,15 +54,12 @@ private: // AdlEngine_v2 void printString(const Common::String &str); - void loadDisk(byte disk); + static const uint kRegions = 3; + static const uint kItems = 15; - DiskImage *_boot; byte _currVerb, _currNoun; - Common::Array<DiskDataDesc> _diskDataDesc; }; -static const char *disks[] = { "DARK1A.DSK", "DARK1B.NIB", "DARK2A.NIB", "DARK2B.NIB" }; - #define SECTORS_PER_TRACK 16 #define BYTES_PER_SECTOR 256 @@ -121,12 +93,9 @@ static Common::MemoryReadStream *loadSectors(DiskImage *disk, byte track, byte s } void HiRes6Engine::runIntro() { - DiskImage *boot(new DiskImage()); - - if (!boot->open(disks[0])) - error("Failed to open disk image '%s'", disks[0]); + insertDisk(0); - StreamPtr stream(loadSectors(boot, 11, 1, 96)); + StreamPtr stream(loadSectors(_disk, 11, 1, 96)); _display->setMode(DISPLAY_MODE_HIRES); _display->loadFrameBuffer(*stream); @@ -139,13 +108,11 @@ void HiRes6Engine::runIntro() { _display->loadFrameBuffer(*stream); - delete boot; - // Load copyright string from boot file Files_DOS33 *files(new Files_DOS33()); - if (!files->open(disks[0])) - error("Failed to open disk image '%s'", disks[0]); + if (!files->open(getDiskImageName(0))) + error("Failed to open disk volume 0"); stream.reset(files->createReadStream("\010\010\010\010\010\010")); Common::String copyright(readStringAt(*stream, 0x103, APPLECHAR('\r'))); @@ -161,20 +128,22 @@ void HiRes6Engine::runIntro() { } void HiRes6Engine::init() { - _boot = new DiskImage(); - _graphics = new Graphics_v2(*_display); + _graphics = new Graphics_v3(*_display); + + insertDisk(0); - if (!_boot->open(disks[0])) - error("Failed to open disk image '%s'", disks[0]); + StreamPtr stream(_disk->createReadStream(0x3, 0xf, 0x05)); + loadRegionLocations(*stream, kRegions); - StreamPtr stream(loadSectors(_boot, 0x7)); + stream.reset(_disk->createReadStream(0x5, 0xa, 0x07)); + loadRegionInitDataOffsets(*stream, kRegions); + + stream.reset(loadSectors(_disk, 0x7)); - // Read parser messages _strings.verbError = readStringAt(*stream, 0x666); _strings.nounError = readStringAt(*stream, 0x6bd); _strings.enterCommand = readStringAt(*stream, 0x6e9); - // Read line feeds _strings.lineFeeds = readStringAt(*stream, 0x408); // Read opcode strings (TODO) @@ -185,137 +154,38 @@ void HiRes6Engine::init() { // _strings_v2.restoreReplace _strings.playAgain = readStringAt(*stream, 0xcdf, 0xff); - _messageIds.cantGoThere = IDI_HR6_MSG_CANT_GO_THERE; - _messageIds.dontUnderstand = IDI_HR6_MSG_DONT_UNDERSTAND; - _messageIds.itemDoesntMove = IDI_HR6_MSG_ITEM_DOESNT_MOVE; - _messageIds.itemNotHere = IDI_HR6_MSG_ITEM_NOT_HERE; - _messageIds.thanksForPlaying = IDI_HR6_MSG_THANKS_FOR_PLAYING; + _messageIds.cantGoThere = 249; + _messageIds.dontUnderstand = 247; + _messageIds.itemDoesntMove = 253; + _messageIds.itemNotHere = 254; + _messageIds.thanksForPlaying = 252; - // Item descriptions - stream.reset(loadSectors(_boot, 0x6, 0xb, 2)); + stream.reset(loadSectors(_disk, 0x6, 0xb, 2)); stream->seek(0x16); - loadItemDescriptions(*stream, IDI_HR6_NUM_ITEM_DESCS); - - // Load dropped item offsets - stream.reset(_boot->createReadStream(0x8, 0x9, 0x16)); - loadDroppedItemOffsets(*stream, IDI_HR6_NUM_ITEM_OFFSETS); - - // Location of game data for each disc - stream.reset(_boot->createReadStream(0x5, 0xa, 0x03)); - for (uint i = 0; i < sizeof(disks); ++i) { - DiskDataDesc desc; - desc.track = stream->readByte(); - desc.sector = stream->readByte(); - desc.offset = stream->readByte(); - desc.volume = stream->readByte(); - _diskDataDesc.push_back(desc); - } - - // DataBlockPtr offsets for each disk - stream.reset(_boot->createReadStream(0x3, 0xf, 0x03)); - for (uint i = 0; i < sizeof(disks); ++i) { - DiskOffset offset; - offset.track = stream->readByte(); - offset.sector = stream->readByte(); - _diskOffsets.push_back(offset); - } -} - -void HiRes6Engine::loadDisk(byte disk) { - delete _disk; - _disk = new DiskImage(); - - if (!_disk->open(disks[disk])) - error("Failed to open disk image '%s'", disks[disk]); - - _curDisk = 0; - - // Load item picture data (indexed on boot disk) - StreamPtr stream(_boot->createReadStream(0xb, 0xd, 0x08)); - _itemPics.clear(); - loadItemPictures(*stream, IDI_HR6_NUM_ITEM_PICS); - - _curDisk = disk; + loadItemDescriptions(*stream, kItems); - byte track = _diskDataDesc[disk].track; - byte sector = _diskDataDesc[disk].sector; - uint offset = _diskDataDesc[disk].offset; + stream.reset(_disk->createReadStream(0x8, 0x9, 0x16)); + loadDroppedItemOffsets(*stream, 16); - applyDiskOffset(track, sector); - - for (uint block = 0; block < 7; ++block) { - stream.reset(_disk->createReadStream(track, sector, offset, 1)); - - uint16 addr = stream->readUint16LE(); - uint16 size = stream->readUint16LE(); - - stream.reset(_disk->createReadStream(track, sector, offset, size / 256 + 1)); - stream->skip(4); - - switch (addr) { - case 0x9000: { - // Messages - _messages.clear(); - uint count = size / 4; - loadMessages(*stream, count); - break; - } - case 0x4a80: { - // Global pics - _pictures.clear(); - loadPictures(*stream); - break; - } - case 0x4000: - // Verbs - loadWords(*stream, _verbs, _priVerbs); - break; - case 0x1800: - // Nouns - loadWords(*stream, _nouns, _priNouns); - break; - case 0x0e00: { - // Rooms - uint count = size / 14 - 1; - stream->skip(14); // Skip invalid room 0 - - _state.rooms.clear(); - loadRooms(*stream, count); - break; - } - case 0x7b00: - // Global commands - readCommands(*stream, _globalCommands); - break; - case 0x9500: - // Room commands - readCommands(*stream, _roomCommands); - break; - default: - error("Unknown data block found (addr %04x; size %04x)", addr, size); - } - - offset += 4 + size; - while (offset >= 256) { - offset -= 256; - ++sector; - if (sector >= 16) { - sector = 0; - ++track; - } - } - } + stream.reset(_disk->createReadStream(0xb, 0xd, 0x08)); + loadItemPicIndex(*stream, kItems); } void HiRes6Engine::initGameState() { - _state.vars.resize(IDI_HR6_NUM_VARS); + _state.vars.resize(40); - loadDisk(1); - - StreamPtr stream(_boot->createReadStream(0x3, 0xe, 0x03)); + insertDisk(0); + StreamPtr stream(_disk->createReadStream(0x3, 0xe, 0x03)); loadItems(*stream); + // A combined total of 91 rooms + static const byte rooms[kRegions] = { 35, 29, 27 }; + + initRegions(rooms, kRegions); + + loadRegion(1); + _currVerb = _currNoun = 0; } @@ -425,11 +295,11 @@ void HiRes6Engine::printString(const Common::String &str) { } if (getVar(2) != 0xff) { - AdlEngine_v2::printString(s); + AdlEngine_v5::printString(s); } else { if (getVar(26) == 0) { if (str.size() != 1 || APPLECHAR(str[0]) != APPLECHAR(' ')) - return AdlEngine_v2::printString(s); + return AdlEngine_v5::printString(s); setVar(2, APPLECHAR(' ')); } else if (getVar(26) != 0xff) { setVar(2, 'P'); diff --git a/engines/agi/appleIIgs_timedelay_overwrite.h b/engines/agi/appleIIgs_timedelay_overwrite.h index c24d7cb5bd..06b94bf3fc 100644 --- a/engines/agi/appleIIgs_timedelay_overwrite.h +++ b/engines/agi/appleIIgs_timedelay_overwrite.h @@ -28,46 +28,50 @@ namespace Agi { struct AgiAppleIIgsDelayOverwriteRoomEntry { int16 fromRoom; int16 toRoom; - int16 timeDelayOverwrite; // time delay here is like on PC, so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles - bool onlyWhenPlayerNotInControl; + int16 activePictureNr; // resource number of current active background picture + int16 timeDelayOverwrite; // time delay here is like on PC + // so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles, -1 means do not touch speed set by scripts + bool onlyWhenPlayerNotInControl; // only sets spee, when play is not in control }; struct AgiAppleIIgsDelayOverwriteGameEntry { uint32 gameId; - int16 defaultTimeDelayOverwrite; // time delay here is like on PC, so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles - const AgiAppleIIgsDelayOverwriteRoomEntry *roomTable; + int16 defaultTimeDelayOverwrite; // time delay here is like on PC + // so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles, -1 means do not touch speed set by scripts + const AgiAppleIIgsDelayOverwriteRoomEntry *roomTable; // pointer to room table (optional) }; static const AgiAppleIIgsDelayOverwriteRoomEntry appleIIgsDelayOverwriteKQ4[] = { - { 120, 121, -1, true }, // Part of the intro: Graham gets his hat, throws it and breaks down, don't touch speed (3 is set) - { 128, 128, -1, true }, // Part of the intro: first actual room for gameplay, but during intro, don't touch speed (3 is set) - { 92, 92, -1, true }, // Part of caught by gargoyle w/ Lolotte cutscene (3 is set) + { 120, 121, -1, -1, true }, // Part of the intro: Graham gets his hat, throws it and breaks down, don't touch speed (3 is set) + { 128, 128, -1, -1, true }, // Part of the intro: first actual room for gameplay, but during intro, don't touch speed (3 is set) + { 92, 92, -1, -1, true }, // Part of caught by gargoyle w/ Lolotte cutscene (3 is set) // room 54 sets the speed for a short time to 3 right after entering "clean" command. It doesn't seem to hurt that we switch it down to 2 // room 92 is dual use, part of cutscenes, part of gameplay, that's why we only stop touching it, when player is not in control - { 135, 135, -1, true }, // Part of ending cutscene. Don't touch speed (3 is set) - { -1, -1, -1, false } + { 135, 135, -1, -1, true }, // Part of ending cutscene. Don't touch speed (3 is set) + { -1, -1, -1, -1, false } }; static const AgiAppleIIgsDelayOverwriteRoomEntry appleIIgsDelayOverwriteMH1[] = { - //{ 153, 153, 2, false }, // Intro w/ credits - //{ 104, 104, 2, false }, // Intro cutscene - //{ 117, 117, 2, false }, // Intro cutscene (ego waking up) - { 114, 114, -1, false }, // interactive MAD map - { 124, 125, -1, false }, // MAD during intro (tracking), seem to work properly at given speed - { 132, 133, -1, false }, // MAD day 2 intro (tracking) - { 137, 137, -1, false }, // Night Club 4th arcade game - game sets speed to 7 - { 115, 116, -1, false }, // MAD day 3 intro (tracking) - { 148, 148, -1, false }, // day 3: arcade sequence under pawn shop (game sets speed to 6) - { 103, 103, -1, false }, // MAD day 4 intro (tracking) - { 105, 105, -1, false }, // day 4 tracking mini game right at the start (game sets speed to 3) - { 107, 107, -1, false }, // MAD day 4 intro (tracking) - { 112, 112, -1, false }, // MAD day 4 intro (tracking) - { -1, -1, -1, false } + //{ 153, 153, -1, 2, false }, // Intro w/ credits + //{ 104, 104, -1, 2, false }, // Intro cutscene + //{ 117, 117, -1, 2, false }, // Intro cutscene (ego waking up) + { 114, 114, -1, -1, false }, // interactive MAD map + { 124, 125, -1, -1, false }, // MAD during intro (tracking), seem to work properly at given speed + { 132, 133, -1, -1, false }, // MAD day 2 intro (tracking) + { 137, 137, 17, -1, false }, // Night Club 4th arcade game - game sets speed to 7, needs to run that slow to be playable + { 137, 137, -1, 4, false }, // Night Club first few arcade games - game sets speed to 0, we need to fix it + { 115, 116, -1, -1, false }, // MAD day 3 intro (tracking) + { 148, 148, -1, -1, false }, // day 3: arcade sequence under pawn shop (game sets speed to 6) + { 103, 103, -1, -1, false }, // MAD day 4 intro (tracking) + { 105, 105, -1, -1, false }, // day 4 tracking mini game right at the start (game sets speed to 3) + { 107, 107, -1, -1, false }, // MAD day 4 intro (tracking) + { 112, 112, -1, -1, false }, // MAD day 4 intro (tracking) + { -1, -1, -1, -1, false } }; static const AgiAppleIIgsDelayOverwriteRoomEntry appleIIgsDelayOverwriteSQ2[] = { - { 1, 1, -1, false }, // Intro: space ship entering space port, don't touch speed - { -1, -1, -1, false } + { 1, 1, -1, -1, false }, // Intro: space ship entering space port, don't touch speed + { -1, -1, -1, -1, false } }; static const AgiAppleIIgsDelayOverwriteGameEntry appleIIgsDelayOverwriteGameTable[] = { diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index 4148306de2..d09a9501d6 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -377,19 +377,22 @@ int AgiEngine::playGame() { // Now check, if we got a time delay overwrite entry for current room if (appleIIgsDelayOverwrite->roomTable) { byte curRoom = getVar(VM_VAR_CURRENT_ROOM); + int16 curPictureNr = _picture->getResourceNr(); appleIIgsDelayRoomOverwrite = appleIIgsDelayOverwrite->roomTable; while (appleIIgsDelayRoomOverwrite->fromRoom >= 0) { if ((appleIIgsDelayRoomOverwrite->fromRoom <= curRoom) && (appleIIgsDelayRoomOverwrite->toRoom >= curRoom)) { - if (appleIIgsDelayRoomOverwrite->onlyWhenPlayerNotInControl) { - if (_game.playerControl) { - // Player is actually currently in control? -> then skip this entry - appleIIgsDelayRoomOverwrite++; - continue; + if ((appleIIgsDelayRoomOverwrite->activePictureNr == curPictureNr) || (appleIIgsDelayRoomOverwrite->activePictureNr == -1)) { + if (appleIIgsDelayRoomOverwrite->onlyWhenPlayerNotInControl) { + if (_game.playerControl) { + // Player is actually currently in control? -> then skip this entry + appleIIgsDelayRoomOverwrite++; + continue; + } } + timeDelayOverwrite = appleIIgsDelayRoomOverwrite->timeDelayOverwrite; + break; } - timeDelayOverwrite = appleIIgsDelayRoomOverwrite->timeDelayOverwrite; - break; } appleIIgsDelayRoomOverwrite++; } diff --git a/engines/agi/picture.h b/engines/agi/picture.h index dfc505d8d0..2cb5bfabc8 100644 --- a/engines/agi/picture.h +++ b/engines/agi/picture.h @@ -64,6 +64,8 @@ class PictureMgr { public: PictureMgr(AgiBase *agi, GfxMgr *gfx); + int16 getResourceNr() { return _resourceNr; }; + private: void draw_xCorner(bool skipOtherCoords = false); void yCorner(bool skipOtherCoords = false); diff --git a/engines/cryo/configure.engine b/engines/cryo/configure.engine new file mode 100644 index 0000000000..a0f5a044e9 --- /dev/null +++ b/engines/cryo/configure.engine @@ -0,0 +1,3 @@ +# This file is included from the main "configure" script +# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] +add_engine cryo "Lost Eden" no "" "" "" diff --git a/engines/cryo/cryo.cpp b/engines/cryo/cryo.cpp new file mode 100644 index 0000000000..3574105053 --- /dev/null +++ b/engines/cryo/cryo.cpp @@ -0,0 +1,85 @@ +/* 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. + * + */ + +#include "common/scummsys.h" + +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/debug-channels.h" +#include "common/error.h" +#include "graphics/surface.h" +#include "graphics/screen.h" +#include "graphics/palette.h" +#include "common/system.h" + +#include "engines/util.h" + +#include "cryo/cryo.h" +#include "cryo/eden.h" + +namespace Cryo { + +CryoEngine *g_ed = nullptr; + +CryoEngine::CryoEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + _rnd = new Common::RandomSource("cryo"); + _debugger = nullptr; + + _game = nullptr; + _video = nullptr; + _screenView = nullptr; + + _showHotspots = false; + _timerTicks = 0; + + g_ed = this; +} + +CryoEngine::~CryoEngine() { + delete _rnd; + delete _game; + delete _video; + delete _screenView; + delete _debugger; + + DebugMan.clearAllDebugChannels(); +} + +Common::Error CryoEngine::run() { + _game = new EdenGame(this); + _video = new HnmPlayer(this); + _screenView = new View(320, 200); + _debugger = new Debugger(this); + + ///// CLTimer + _timerTicks = 0; // incremented in realtime + + // Initialize graphics using following: + initGraphics(320, 200, false); + _screen.create(320, 200, Graphics::PixelFormat::createFormatCLUT8()); + + _game->run(); + + return Common::kNoError; +} + +} // End of namespace Cryo diff --git a/engines/cryo/cryo.h b/engines/cryo/cryo.h new file mode 100644 index 0000000000..515849ffea --- /dev/null +++ b/engines/cryo/cryo.h @@ -0,0 +1,100 @@ +/* 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. + * + */ + +#ifndef CRYO_CRYO_H +#define CRYO_CRYO_H + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "engines/advancedDetector.h" +#include "common/debug.h" +#include "common/debug-channels.h" +#include "common/error.h" +#include "common/random.h" +#include "engines/engine.h" +#include "gui/debugger.h" +#include "graphics/surface.h" +#include "graphics/screen.h" + +#include "cryo/eden.h" +#include "cryo/video.h" +#include "cryo/debugger.h" + +namespace Cryo { + +class Console; + +// our engine debug channels +enum { + kCryoDebugExample = 1 << 0, + kCryoDebugExample2 = 1 << 1 + // next new channel must be 1 << 2 (4) + // the current limitation is 32 debug channels (1 << 31 is the last one) +}; + +class CryoEngine : public Engine { +public: + CryoEngine(OSystem *syst, const ADGameDescription *gameDesc); + ~CryoEngine(); + + virtual Common::Error run(); + + // Detection related functions + const ADGameDescription *_gameDescription; + const char *getGameId() const; + Common::Platform getPlatform() const; + bool isDemo() const; + + // We need random numbers + Common::RandomSource *_rnd; + + Graphics::Surface _screen; + EdenGame *_game; + HnmPlayer *_video; + Debugger *_debugger; + + View *_screenView; + volatile int32 _timerTicks; + + bool _showHotspots; + + void pollEvents(); + + void hideMouse(); + void showMouse(); + void getMousePosition(int16 *x, int16 *y); + void setMousePosition(int16 x, int16 y); + bool isMouseButtonDown(); +}; + +extern CryoEngine *g_ed; + +// Example console class +class Console : public GUI::Debugger { +public: + Console(CryoEngine *vm) {} + virtual ~Console(void) {} +}; + +} // End of namespace Cryo + +#endif diff --git a/engines/cryo/cryolib.cpp b/engines/cryo/cryolib.cpp new file mode 100644 index 0000000000..8b8efad588 --- /dev/null +++ b/engines/cryo/cryolib.cpp @@ -0,0 +1,433 @@ +/* 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. + * + */ + +#include "common/system.h" +#include "common/events.h" +#include "common/timer.h" + +#include "graphics/palette.h" + +#include "cryo/cryo.h" +#include "cryo/cryolib.h" + +namespace Cryo { + +///// Mac APIs + +void SysBeep(int x) { +} + +void FlushEvents(int16 arg1, int16 arg2) { +} + +///// CLView + +View::View(int w, int h) { + void *buffer = (byte *)malloc(w * h); + if (buffer) + initDatas(w, h, buffer); + else + error("Unable to allocate view buffer"); +} + +View::~View() { + if (_bufferPtr) + free(_bufferPtr); +} + +// Original name: CLView_SetSrcZoomValues +void View::setSrcZoomValues(int x, int y) { + _zoom._srcLeft = x; + _zoom._srcTop = y; +} + +// Original name: CLView_SetDisplayZoomValues +void View::setDisplayZoomValues(int w, int h) { + _zoom._width = w; + _zoom._height = h; +} + +// Original name: CLView_InitDatas +void View::initDatas(int w, int h, void *buffer) { + _bufferPtr = (byte *)buffer; + _width = w; + _height = h; + _pitch = w; + _normal._srcLeft = 0; + _normal._srcTop = 0; + _normal._dstLeft = 0; + _normal._dstTop = 0; + _normal._width = w; + _normal._height = h; + _zoom._srcLeft = 0; + _zoom._srcTop = 0; + _zoom._dstLeft = 0; + _zoom._dstTop = 0; + _zoom._width = w; + _zoom._height = h; +} + +// Original name: CLView_CenterIn +void View::centerIn(View *parent) { + _normal._dstLeft = (parent->_width - _normal._width) / 2; + _normal._dstTop = (parent->_height - _normal._height) / 2; + _zoom._dstLeft = (parent->_width - _zoom._width) / 2; + _zoom._dstTop = (parent->_height - _zoom._height) / 2; +} + +///// CLPalette +uint16 gIntervalLast, gIntervalFirst, gIntervalSet; +int16 gMacintize = 0; +color_t black_palette[256]; +color_t last_palette[256]; + +void CLPalette_Init() { + for (int16 i = 0; i < 256; i++) + black_palette[i].r = black_palette[i].g = black_palette[i].b = 0; +} + +void CLPalette_SetLastPalette(color_t *palette, int16 first, int16 count) { + for (int16 i = first; i < first + count; i++) + last_palette[i] = palette[i]; +} + +void CLPalette_GetLastPalette(color_t *palette) { + for (int16 i = 0; i < 256; i++) + palette[i] = last_palette[i]; +} + +void CLPalette_SetRGBColor(color_t *palette, uint16 index, color3_t *rgb) { + palette[index].r = rgb->r; + palette[index].g = rgb->g; + palette[index].b = rgb->b; + palette[index].a = 0; +} + +void CLPalette_Macintize(int16 macintize) { + gMacintize = macintize; +} + +void CLPalette_SetInterval(uint16 first, uint16 last) { + gIntervalFirst = first; + gIntervalSet = 1; + gIntervalLast = last; +} + +void CLPalette_DeactivateInterval() { + gIntervalSet = 0; +} + +void CLPalette_Send2Screen(struct color_t *palette, uint16 first, uint16 count) { + if (gMacintize) { + palette[0].r = palette[0].g = palette[0].b = 0xFFFF; + palette[255].r = palette[255].g = palette[255].b = 0; + } + if (gIntervalSet) { + if (first < gIntervalFirst) + first = gIntervalFirst; + if (first + count > gIntervalLast) + count = gIntervalLast - first; + } + + byte buffer[256 * 3]; + for (int i = 0; i < 256; i++) { + buffer[i * 3] = palette[i].r >> 8; + buffer[i * 3 + 1] = palette[i].g >> 8; + buffer[i * 3 + 2] = palette[i].b >> 8; + } + + g_system->getPaletteManager()->setPalette(buffer, first, count); + g_system->updateScreen(); + + CLPalette_SetLastPalette(palette, first, count); +} + +void CLPalette_BeSystem() { +} + +///// CLBlitter +static uint16 newPaletteCount, newPaletteFirst; +static color_t *pNewPalette; +static bool useNewPalette; + +void CLBlitter_CopyViewRect(View *view1, View *view2, Common::Rect *rect1, Common::Rect *rect2) { + int dy = rect2->top; + int w = rect1->right - rect1->left + 1; + // debug("- Copy rect %3d:%3d-%3d:%3d -> %3d:%3d-%3d:%3d - %s", + // rect1->sx, rect1->sy, rect1->ex, rect1->ey, + // rect2->sx, rect2->sy, rect2->ex, rect2->ey, + // (rect1->ex - rect1->sx == rect2->ex - rect2->sx && rect1->ey - rect1->sy == rect2->ey - rect2->sy) ? "ok" : "BAD"); + assert(rect1->right - rect1->left == rect2->right - rect2->left && rect1->bottom - rect1->top == rect2->bottom - rect2->top); + for (int sy = rect1->top; sy <= rect1->bottom; sy++, dy++) { + byte *s = view1->_bufferPtr + sy * view1->_pitch + rect1->left; + byte *d = view2->_bufferPtr + dy * view2->_pitch + rect2->left; + for (int x = 0; x < w; x++) + *d++ = *s++; + } +} + +void CLBlitter_Send2ScreenNextCopy(color_t *palette, uint16 first, uint16 count) { + pNewPalette = palette; + useNewPalette = true; + newPaletteFirst = first; + newPaletteCount = count; +} + +void CLBlitter_OneBlackFlash() { +} + +void CLBlitter_CopyView2ViewSimpleSize(byte *src, int16 srcw, int16 srcp, int16 srch, + byte *dst, int16 dstw, int16 dstp, int16 dsth) { + for (int16 y = 0; y < srch; y++) { + for (int16 x = 0; x < srcw; x++) + *dst++ = *src++; + src += srcp - srcw; + dst += dstp - dstw; + } +} + +void CLBlitter_CopyView2ScreenCUSTOM(View *view) { + View *dest = g_ed->_screenView; + int16 srcpitch = view->_pitch; + int16 dstpitch = dest->_pitch; + + CLBlitter_CopyView2ViewSimpleSize(view->_bufferPtr + view->_normal._srcTop * srcpitch + view->_normal._srcLeft, + view->_normal._width, srcpitch, view->_normal._height, + dest->_bufferPtr + (dest->_normal._dstTop + view->_normal._dstTop) * dstpitch + dest->_normal._dstLeft + view->_normal._dstLeft, + dest->_normal._width, dstpitch, dest->_normal._height); +} + +void CLBlitter_CopyView2Screen(View *view) { + if (useNewPalette) { + color_t palette[256]; + CLPalette_GetLastPalette(palette); + CLPalette_Send2Screen(pNewPalette, newPaletteFirst, newPaletteCount); + useNewPalette = false; + } + + //HACK: Quick hack to force screen update + if (view) + CLBlitter_CopyView2ScreenCUSTOM(view); + + g_system->copyRectToScreen(g_ed->_screenView->_bufferPtr, g_ed->_screenView->_pitch, 0, 0, g_ed->_screenView->_width, g_ed->_screenView->_height); + g_system->updateScreen(); +} + +void CLBlitter_UpdateScreen() { + CLBlitter_CopyView2Screen(nullptr); +} + +void CLBlitter_FillView(View *view, unsigned int fill) { + byte *d = view->_bufferPtr; + assert((fill & 0xFF) * 0x01010101 == fill); + + for (int16 y = 0; y < view->_height; y++) { + for (int16 x = 0; x < view->_width; x++) + *d++ = fill; + d += view->_pitch - view->_width; + } +} + +void CLBlitter_FillScreenView(unsigned int fill) { + CLBlitter_FillView(g_ed->_screenView, fill); +} + +///// events wrapper +int _mouseButton; +byte _keyState[256]; + +void CryoEngine::pollEvents() { + g_system->delayMillis(10); + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + // Handle keypress + switch (event.type) { + case Common::EVENT_QUIT: + case Common::EVENT_RTL: + return; + + case Common::EVENT_KEYDOWN: + // Check for debugger + if ((event.kbd.keycode == Common::KEYCODE_d) && (event.kbd.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _debugger->attach(); + _debugger->onFrame(); + } + return; + case Common::EVENT_KEYUP: + // _keyState[(byte)toupper(event.kbd.ascii)] = false; + return; + case Common::EVENT_LBUTTONDOWN: + _mouseButton = 1; + return; + case Common::EVENT_RBUTTONDOWN: + _mouseButton = 2; + return; + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + _mouseButton = 0; + return; + default: + break; + } + } +} + +void CryoEngine::hideMouse() { +} + +void CryoEngine::showMouse() { +} + +void CryoEngine::getMousePosition(int16 *x, int16 *y) { + *x = g_system->getEventManager()->getMousePos().x; + *y = g_system->getEventManager()->getMousePos().y; +} + +void CryoEngine::setMousePosition(int16 x, int16 y) { + g_system->warpMouse(x, y); +} + +bool CryoEngine::isMouseButtonDown() { + pollEvents(); + return _mouseButton != 0; +} + +///// CLSound +// base sound + +Sound::Sound(int16 length, float rate, int16 sampleSize, int16 mode) { + _sndHandle = nullptr; + _headerLen = 0; + _headerOffset = 0; + + _length = 0; + _mode = 0; + _volume = 0; + + _maxLength = length; + _rate = rate; + _sampleSize = sampleSize; + _buffer = nullptr; + // sndHandle = CLMemory_AllocHandle(arg1 + 100); + // if(!sndHandle) + // error("CLSoundRaw_New - Not enough memory"); + // else + prepareSample(mode); +} + +Sound::~Sound() { +} + +void CLSoundRaw_AssignBuffer(Sound *sound, void *buffer, int bufferOffs, int length) { + sound->_length = length; + char *buf = bufferOffs + (char *)buffer; + // if(CLSound_GetWantsDesigned()) + // CLSound_Signed2NonSigned(buf, length); + sound->_buffer = buf; + // if(sound->reversed && sound->sampleSize == 16) + // ReverseBlock16(buf, length); +} + +void Sound::prepareSample(int16 mode) { + _mode = mode; + _volume = 255; +} + +void Sound::setWantsDesigned(int16 designed) { +} + +///// CLSoundChannel +/// sound output device that plays queue of sounds +SoundChannel::SoundChannel(int arg1) { + _volumeLeft = _volumeRight = 255; + _numSounds = 0; + + for (int16 i = 0; i < kCryoMaxChSounds; i++) + _sounds[i] = nullptr; +} + +SoundChannel::~SoundChannel() { +} + +void SoundChannel::stop() { + // _vm->_mixer->stopHandle(this); +} + +void SoundChannel::play(Sound *sound) { +} + +int16 SoundChannel::getVolume() { + return (_volumeLeft + _volumeRight) / 2; +} + +void SoundChannel::setVolume(int16 volume) { + if (volume < 0 || volume > 255) + return; + + _volumeLeft = volume; + _volumeRight = volume; +} + +void SoundChannel::setVolumeRight(int16 volume) { + if (volume < 0 || volume > 255) + return; + + _volumeRight = volume; +} + +void SoundChannel::setVolumeLeft(int16 volume) { + if (volume < 0 || volume > 255) + return; + + _volumeLeft = volume; +} + +///// CLTimer +void CLTimer_Action(void *arg) { + // long& counter = *((long*)arg); + // counter++; + g_ed->_timerTicks++; +} + +///// CRYOLib +void CRYOLib_ManagersInit() { + g_system->getTimerManager()->installTimerProc(CLTimer_Action, 10000, nullptr, "100hz timer"); + g_ed->_screenView->initDatas(g_ed->_screen.w, g_ed->_screen.h, g_ed->_screen.getPixels()); +} + +void CRYOLib_ManagersDone() { + g_system->getTimerManager()->removeTimerProc(CLTimer_Action); +} + +PakHeaderNode::PakHeaderNode(int count) { + _count = count; + _files = new PakHeaderItem[count]; +} + +PakHeaderNode::~PakHeaderNode() { + _count = 0; + delete[] _files; +} + +} // End of namespace Cryo diff --git a/engines/cryo/cryolib.h b/engines/cryo/cryolib.h new file mode 100644 index 0000000000..83fdfee236 --- /dev/null +++ b/engines/cryo/cryolib.h @@ -0,0 +1,175 @@ +/* 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. + * + */ + +#ifndef CRYO_CRYOLIB_H +#define CRYO_CRYOLIB_H + +#include "audio/mixer.h" +#include "common/system.h" + +#include "cryo/platdefs.h" + +namespace Cryo { + +class CryoEngine; + +#define SW16(n) ( (((n) & 0xFF) << 8) | (((n) >> 8) & 0xFF) ) +#define SW32(n) ( (((n) & 0xFF) << 24) | (((n) >> 24) & 0xFF) | (((n) & 0xFF00) << 8) | (((n) >> 8) & 0xFF00)) +#ifdef SCUMM_BIG_ENDIAN +//big-endian host +#define LE16(n) SW16(n) +#define LE32(n) SW32(n) +#define BE16(n) (n) +#define BE32(n) (n) +#else +//little-endian host +#define LE16(n) (n) +#define LE32(n) (n) +#define BE16(n) SW16(n) +#define BE32(n) SW32(n) +#endif + +enum { + fsFromStart = 1 +}; + +struct BlitView{ + int _srcLeft; + int _srcTop; + int _dstLeft; + int _dstTop; + int _width; + int _height; +}; + +class View { +public: + View(int w, int h); + ~View(); + + void setSrcZoomValues(int x, int y); + void setDisplayZoomValues(int w, int h); + void initDatas(int w, int h, void *buffer); + void centerIn(View *parent); + + int _width; + int _height; + byte *_bufferPtr; + int16 _pitch; + BlitView _normal; + BlitView _zoom; +}; + +struct color3_t { + uint16 r, g, b; +}; + +struct color_t { + uint16 a, r, g, b; +}; + +struct HNMHeader { + int32 _signature; + uint16 _width; + uint16 _height; + int32 _numbFrame; + int32 _bufferSize; +}; + +class Sound { +private: + int32 _headerOffset; + int16 _mode; + int16 _volume; + +public: + Sound(int16 length, float rate, int16 sampleSize, int16 mode); + ~Sound(); + + void assignBuffer(void *buffer, int bufferOffs, int length); + void prepareSample(int16 mode); + void setWantsDesigned(int16 designed); + + char *_sndHandle; + char *_buffer; + + float _rate; + + int16 _maxLength; + int16 _headerLen; + int16 _sampleSize; + + int _length; +}; + +#define kCryoMaxChSounds 10 + +class SoundChannel { +private: + int16 _volumeLeft; + int16 _volumeRight; + int16 _numSounds; + + Sound *_sounds[kCryoMaxChSounds]; + +public: + SoundChannel(int arg1); + ~SoundChannel(); + + void stop(); + void play(Sound *sound); + int16 getVolume(); + void setVolume(int16 volume); + void setVolumeRight(int16 volume); + void setVolumeLeft(int16 volume); +}; + +void SysBeep(int x); +void FlushEvents(int16 arg1, int16 arg2); + +void CLBlitter_CopyViewRect(View *view1, View *view2, Common::Rect *rect1, Common::Rect *rect2); +void CLBlitter_Send2ScreenNextCopy(color_t *palette, uint16 first, uint16 count); +void CLBlitter_OneBlackFlash(); +void CLBlitter_CopyView2ViewSimpleSize(byte *src, int16 srcw, int16 srcp, int16 srch, + byte *dst, int16 dstw, int16 dstp, int16 dsth); +void CLBlitter_CopyView2ScreenCUSTOM(View *view); +void CLBlitter_CopyView2Screen(View *view); +void CLBlitter_UpdateScreen(); +void CLBlitter_FillView(View *view, unsigned int fill); +void CLBlitter_FillScreenView(unsigned int fill); + +void CLPalette_Init(); +void CLPalette_SetLastPalette(color_t *palette, int16 first, int16 count); +void CLPalette_GetLastPalette(color_t *palette); +void CLPalette_SetRGBColor(color_t *palette, uint16 index, color3_t *rgb); +void CLPalette_Macintize(int16 macintize); +void CLPalette_SetInterval(uint16 first, uint16 last); +void CLPalette_DeactivateInterval(); +void CLPalette_Send2Screen(struct color_t *palette, uint16 first, uint16 count); +void CLPalette_BeSystem(); + +void CRYOLib_ManagersInit(); +void CRYOLib_ManagersDone(); + +} // End of namespace Cryo + +#endif diff --git a/engines/cryo/debugger.cpp b/engines/cryo/debugger.cpp new file mode 100644 index 0000000000..f19c616b72 --- /dev/null +++ b/engines/cryo/debugger.cpp @@ -0,0 +1,64 @@ +/* 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. + * + */ + +#include "common/coroutines.h" +#include "cryo/debugger.h" +#include "cryo/cryo.h" + +namespace Cryo { + +Debugger::Debugger(CryoEngine *vm) : GUI::Debugger(), _vm(vm) { + registerCmd("showHotspots", WRAP_METHOD(Debugger, Cmd_ShowHotspots)); + registerCmd("fullInventory", WRAP_METHOD(Debugger, Cmd_FullInventory)); +} + +/** + * This command enables/disables hotspot display + */ +bool Debugger::Cmd_ShowHotspots(int argc, const char **argv) { + if (argc != 1) { + debugPrintf("Usage: %s\n", argv[0]); + return true; + } + + _vm->_showHotspots ^= 1; + + return false; +} + +bool Debugger::Cmd_FullInventory(int argc, const char **argv) { + if (argc != 1) { + debugPrintf("Usage: %s\n", argv[0]); + return true; + } + + for (int i = 0; i < MAX_OBJECTS; i++) { + object_t *object = _vm->_game->getObjectPtr(i); + object->_flags |= ObjectFlags::ofFlag1; + object->_count++; + } + + _vm->_game->showObjects(); + + return false; +} +} // End of namespace Cryo diff --git a/engines/cryo/debugger.h b/engines/cryo/debugger.h new file mode 100644 index 0000000000..ee765128ce --- /dev/null +++ b/engines/cryo/debugger.h @@ -0,0 +1,48 @@ +/* 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. + * + */ + +#ifndef CRYO_DEBUGGER_H +#define CRYO_DEBUGGER_H + +#include "common/scummsys.h" +#include "gui/debugger.h" + +namespace Cryo { + +class CryoEngine; + +class Debugger : public GUI::Debugger { +private: + CryoEngine *_vm; + +public: + Debugger(CryoEngine *vm); + virtual ~Debugger() {} + +protected: + bool Cmd_ShowHotspots(int argc, const char **argv); + bool Cmd_FullInventory(int argc, const char **argv); +}; + +} // End of namespace Cryo + +#endif diff --git a/engines/cryo/defs.h b/engines/cryo/defs.h new file mode 100644 index 0000000000..b7206dc7e4 --- /dev/null +++ b/engines/cryo/defs.h @@ -0,0 +1,852 @@ +/* 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. + * + */ + +#include "cryo/cryolib.h" + +#ifndef CRYO_DEFS_H +#define CRYO_DEFS_H + +namespace Cryo { + +#define getElem(array, idx) \ + ( (char *)(array) + READ_LE_UINT16((idx) * 2 + (char *)(array)) ) + +///////////////// Game defs + +#define FONT_HEIGHT 9 + +/* +Glossary + room - a single game world's screen. referenced by 16-bit number 0xAALL, where AA - area# and LL - location# + area - geographic area - Mo, Chamaar, etc + location - coordinates of particular room in an area. usually in form of 0xXY, where X - map row, Y - map column + character - an unique character (human or dino.) Has their own voice/dialog lines + person - instance of a character. Usually tied to specific room, but some may travel with you + party - a group of characters that travel with you + object - inventory item + icon - clickable rectangle with some action tied to it + dialog - a set of of dialog lines for character. further divided by categories and each entry may have associated + condition to be validated + global - game-wide storage area. must be preserved when saving/loading + phase - current story progress. Incremented by 1 for minor events, by 0x10 for major advancements +*/ + +enum Phases { + phNewGame = 0 +}; + +namespace Areas { +enum Areas { + arMo = 1, + arTausCave, + arChamaar, + arUluru, + arKoto, + arTamara, + arCantura, + arShandovra, + arNarimsCave, + arEmbalmersCave, + arWhiteArch, + arMoorkusLair +}; +} + +#define MKRM(a,l) (((a) << 8) | (l)) + +enum OBJECT { + OBJ_0, + OBJ_1, + OBJ_2, + OBJ_3, + OBJ_4, + OBJ_PRISME, // 5 + OBJ_6, + OBJ_7, + OBJ_OEUF, // 8 + OBJ_9, + OBJ_10, + OBJ_CHAMPB, // 11 + OBJ_CHAMPM, // 12 + OBJ_COUTEAU, // 13 + OBJ_NIDV, // 14 + OBJ_NIDO, // 15 + OBJ_OR, // 16 + OBJ_17, + OBJ_18, + OBJ_SOLEIL, // 19 + OBJ_CORNE, // 20 + OBJ_21, + OBJ_22, + OBJ_23, + OBJ_24, + OBJ_25, + OBJ_26, + OBJ_27, + OBJ_28, + OBJ_29, + OBJ_30, + OBJ_31, + OBJ_32, + OBJ_33, + OBJ_34, + OBJ_35, + OBJ_36, // 36 is 1st plaque, 6 total + OBJ_37, + OBJ_PLAQUE, // 38 + OBJ_39, + OBJ_40, + OBJ_41 +}; + +namespace Objects { +enum Objects { + obNone, + obWayStone, + obShell, + obTalisman, + obTooth, + obPrism, // 5 + obFlute, + obApple, + obEgg, // 8 + obRoot, + obUnused10, + obShroom, // 11 + obBadShroom, // 12 + obKnife, // 13 + obNest, // 14 + obFullNest, // 15 + obGold, // 16 + obMoonStone, + obBag, + obSunStone, // 19 + obHorn, // 20 + obSword, + + obMaskOfDeath, + obMaskOfBonding, + obMaskOfBirth, + + obEyeInTheStorm, // 25 + obSkyHammer, + obFireInTheClouds, + obWithinAndWithout, + obEyeInTheCyclone, + obRiverThatWinds, + + obTrumpet, // 31 + obUnused32, + obDrum, + obUnused34, + obUnused35, + obRing, + + obTablet1, // 37 is 1st plaque, 6 total + obTablet2, + obTablet3, // 39 + obTablet4, + obTablet5, + obTablet6 +}; +} + +enum PERSO { + PER_KING = 0, + PER_DINA, // 0x12 + PER_TAU, // 0x24 + PER_MONK, // 0x36 + PER_JABBER, // 0x48 + PER_ELOI, // 0x5A + PER_MUNGO, // 0x6C + PER_EVE, // 0x7E + PER_SHAZIA, // 0x90 + PER_MAMMI, // 0xA2 + PER_MAMMI_1, // 0xB4 + PER_MAMMI_2, // 0xC6 + PER_MAMMI_3, // 0xD8 + PER_MAMMI_4, // 0xEA + PER_MAMMI_5, // 0xFC + PER_MAMMI_6, // 0x10E + PER_BAMBOO, // 0x120 + PER_KABUKA, // 0x132 + PER_GUARDS, // 0x144 + PER_UNKN_156, // 0x156 + PER_FISHER, // 0x168 + PER_MORKUS, // 0x17A + PER_UNKN_18C, // 0x18C + PER_UNKN_19E, // 0x19E + PER_UNKN_1B0, // 0x1B0 + PER_UNKN_1C2, // 0x1C2 + PER_UNKN_1D4, // 0x1D4 + PER_UNKN_1E6, // 0x1E6 + PER_UNKN_1F8, // 0x1F8 + PER_UNKN_20A, // 0x20A + PER_UNKN_21C, // 0x21C + PER_UNKN_22E, // 0x22E + PER_UNKN_240, // 0x240 + PER_UNKN_252, // 0x252 + PER_UNKN_264, // 0x264 + PER_UNKN_276, // 0x276 + PER_UNKN_288, // 0x288 + PER_UNKN_29A, // 0x29A + PER_UNKN_2AC, // 0x2AC + PER_UNKN_2BE, // 0x2BE + PER_UNKN_2D0, // 0x2D0 + PER_UNKN_2E2, // 0x2E2 + PER_UNKN_2F4, // 0x2F4 + PER_UNKN_306, // 0x306 + PER_UNKN_318, // 0x318 + PER_UNKN_32A, // 0x32A + PER_UNKN_33C, // 0x33C + PER_UNKN_34E, // 0x34E + PER_UNKN_360, // 0x360 + PER_UNKN_372, // 0x372 + PER_UNKN_384, // 0x384 + PER_UNKN_396, // 0x396 + PER_UNKN_3A8, // 0x3A8 + PER_UNKN_3BA, // 0x3BA + PER_UNKN_3CC, // 0x3CC + PER_UNKN_3DE, // 0x3DE + PER_UNKN_3F0, // 0x3F0 + PER_UNKN_402 // 0x402 +}; + +namespace PersonId { +enum PersonId { + pidGregor = 0, // The King + pidDina, // Pink dino + pidTau, // Late grandpa + pidMonk, // Old wizard + pidJabber, // Executioner + pidEloi, // Evergreen ptero + pidMungo, // Dina's husband + pidEve, // Blonde girl + pidShazia, // Big boobs sis + pidLeadersBegin, // 9 + pidChongOfChamaar = pidLeadersBegin, // Dogface + pidKommalaOfKoto, // Clones + pidUlanOfUlele, // Shaman + pidCabukaOfCantura, // Stone people + pidMarindaOfEmbalmers, // Gods + pidFuggOfTamara, // Boar-like + pidThugg, // Bodyguard + pidNarrator, // 16, Old Eloi, also BGM + pidNarrim, // Sea snake + pidMorkus, // Vicious tyran + pidDinosaur, // different species of friendly dino + pidEnemy // different species of enemy dino +}; +} + +// person in room mask bits +namespace PersonMask { +enum PersonMask { + pmGregor = 1, + pmDina = 2, + pmTau = 4, + pmMonk = 8, + pmJabber = 0x10, + pmEloi = 0x20, + pmMungo = 0x40, + pmEve = 0x80, + pmShazia = 0x100, + pmLeader = 0x200, // valley tribe leader + pmThugg = 0x400, + pmQuest = 0x800, // special quest person + pmDino = 0x1000, + pmEnemy = 0x2000, + pmMorkus = 0x4000 +}; +} + +namespace PersonFlags { +enum PersonFlags { + pfType0 = 0, + pftTyrann, + pfType2, + pfType3, + pfType4, + pfType5, + pfType6, + pfType7, + pfType8, + pftMosasaurus, + pftTriceraptor, + pftVelociraptor, + pfType12, + pfType13, + pfType14, + pfType15, + pfTypeMask = 0xF, + pf10 = 0x10, + pf20 = 0x20, + pfInParty = 0x40, + pf80 = 0x80 +}; +} + +#pragma pack(push, 1) +struct perso_t { + uint16 _roomNum; // room this person currently in + uint16 _actionId; // TODO: checkme + uint16 _partyMask; // party bit mask + byte _id; // character + byte _flags; // flags and kind + byte _roomBankId;// index in kPersoRoomBankTable for specific room banks + byte _spriteBank; // sprite bank + uint16 _items; // inventory + uint16 _powers; // obj of power bitmask + byte _targetLoc; // For party member this is mini sprite index + byte _lastLoc; // For party member this is mini sprite x offset + byte _speed; // num ticks per step + byte _steps; // current ticks +}; + +class EdenGame; + +struct phase_t { + int16 _id; + void (EdenGame::*disp)(); +}; + +namespace ObjectFlags { +enum ObjectFlags { + ofFlag1 = 1, + ofInHands = 2 // Currently holding this object in hands +}; +} + +#define MAX_OBJECTS 42 +struct object_t { + byte _id; + byte _flags; + int _locations; // index in kObjectLocations + uint16 _itemMask; + uint16 _powerMask; // object of power bitmask + int16 _count; +}; + +namespace DialogFlags { +enum DialogFlags { + df20 = 0x20, + dfRepeatable = 0x40, + dfSpoken = 0x80 +}; +} + +namespace DialogType { +enum DialogType { + dtTalk = 0, + dtDinoAction, + dtDinoItem, + dtItem, + dtEvent, + dtInspect, + dtHint +}; +} + +struct Dialog { + char _flags; // 0-3 - action index, 4 - highest bit of contidion index, rest is DialogFlags + char _condNumLow; // condition index low bits + char _textCondHiMask; // 0-1 text index hi bits, 2-5 - perso mask num, 6-7 condition index hi bits + char _textNumLow; // text line index low bits +}; + +struct tape_t { + int16 _textNum; + perso_t *_perso; + int16 _party; + int16 _roomNum; + int16 _backgroundBankNum; + Dialog *_dialog; +}; + +struct Follower { // Characters on Mirror screen + char _id; // character + char _spriteNum; // sprite number + int16 sx; + int16 sy; + int16 ex; + int16 ey; + int16 _spriteBank; + int16 ff_C; + int16 ff_E; +}; + +struct Icon { + int16 sx; + int16 sy; + int16 ex; + int16 ey; + uint16 _cursorId; // & 0x8000 - inactive/hidden + uint32 _actionId; + uint32 _objectId; +}; + +struct Goto { + byte _areaNum; // target area + byte _curAreaNum; // current area + byte _enterVideoNum; + byte _travelTime; // time to skip while in travel + byte _arriveVideoNum; +}; + +namespace RoomFlags { +enum RoomFlags { + rf01 = 1, + rf02 = 2, + rf04 = 4, + rf08 = 8, + rfPanable = 0x10, + rfHasCitadel = 0x20, + rf40 = 0x40, + rf80 = 0x80 +}; +} + +struct Room { + byte _id; + byte _exits[4]; //TODO: signed? + byte _flags; + uint16 _bank; + uint16 _party; + byte _level; // Citadel level + byte _video; + byte _location; + byte _backgroundBankNum; // bg/mirror image number (relative) +}; + +namespace AreaFlags { +enum AreaFlags { + afFlag1 = 1, + afFlag2 = 2, + afFlag4 = 4, + afFlag8 = 8, + afGaveGold = 0x10, + afFlag20 = 0x20, + + HasTriceraptors = 0x100, + HasVelociraptors = 0x200, + HasTyrann = 0x400, + + TyrannSighted = 0x4000, + afFlag8000 = 0x8000 +}; +} + +namespace AreaType { +enum AreaType { + atCitadel = 1, + atValley = 2, + atCave = 3 +}; +} + +struct Area { + byte _num; + byte _type; + uint16 _flags; + uint16 _firstRoomIdx; + byte _citadelLevel; + byte _placeNum; + Room *_citadelRoomPtr; + int16 _visitCount; +}; + +namespace ValleyNews { +enum ValleyNews { + vnAreaMask = 0xF, + + vnTriceraptorsIn = 0x10, + vnVelociraptorsIn = 0x20, + vnTyrannIn = 0x30, + vnTyrannLost = 0x40, + vnCitadelLost = 0x50, + vnVelociraptorsLost = 0x60, + + vnFree = 0, + vnHidden = 0x80, + vnEnd = 0xFF +}; +} + +namespace DisplayFlags { +enum DisplayFlags { + dfFlag1 = 1, + dfFlag2 = 2, + dfMirror = 4, + dfPerson = 8, + dfFrescoes = 0x10, + dfPanable = 0x20, + dfFlag40 = 0x40, + dfFlag80 = 0x80 +}; +} + +namespace DrawFlags { +enum DrawFlags { + drDrawInventory = 1, + drDrawFlag2 = 2, + drDrawTopScreen = 4, + drDrawFlag8 = 8, + drDrawMenu = 0x10, + drDrawFlag20 = 0x20 +}; +} + +namespace MenuFlags { +enum MenuFlags { + mfFlag1 = 1, + mfFlag2 = 2, + mfFlag4 = 4, + mfFlag8 = 8, + mfFlag10 = 0x10 +}; +} + +namespace MusicType { +enum MusicType { //TODO: same as DialogType? + mtDontChange = 0, + mtNormal = 1, + mt2 = 2, + mtEvent = 4, + mtFF = 0xFF +}; +} + +namespace EventType { +enum EventType { + etEvent1 = 1, + etEvent2 = 2, + etEvent3 = 3, + etEvent4 = 4, + etEvent5 = 5, + etEvent6 = 6, + etEvent7 = 7, + etEvent8 = 8, + etEvent9 = 9, + etEventB = 11, + etEventC = 12, + etEventD = 13, + etEventE = 14, + etEventF = 15, + etEvent10 = 16, + etEvent12 = 18, + etGotoArea = 0x80 // + area id +}; +} + +namespace GameFlags { +enum GameFlags { + gfNone = 0, + gfMummyOpened = 1, + gfFlag2 = 2, + gfFlag4 = 4, + gfFlag8 = 8, + gfFlag10 = 0x10, + gfFlag20 = 0x20, + gfFlag40 = 0x40, + gfFlag80 = 0x80, + gfFlag100 = 0x100, + gfFlag200 = 0x200, + gfFlag400 = 0x400, + gfPrismAndMonk = 0x800, + gfFlag1000 = 0x1000, + gfFlag2000 = 0x2000, + gfFlag4000 = 0x4000, + gfFlag8000 = 0x8000 +}; +} + +struct global_t { + byte _areaNum; + byte _areaVisitCount; + byte _menuItemIdLo; + byte _menuItemIdHi; //TODO: pad? + uint16 _randomNumber; //TODO: this is randomized in pc ver and used by some conds. always zero on mac + uint16 _gameTime; + uint16 _gameDays; + uint16 _chrono; + uint16 _eloiDepartureDay; + uint16 _roomNum; // current room number + uint16 _newRoomNum; // target room number selected on world map + uint16 _phaseNum; + uint16 _metPersonsMask1; + uint16 _party; + uint16 _partyOutside; + uint16 _metPersonsMask2; + uint16 _var1C; //TODO: write-only? + uint16 _phaseActionsCount; + uint16 _curAreaFlags; + uint16 _curItemsMask; + uint16 _curPowersMask; + uint16 _curPersoItems; + uint16 _curCharacterPowers; + uint16 _wonItemsMask; + uint16 _wonPowersMask; + uint16 _stepsToFindAppleFast; + uint16 _stepsToFindAppleNormal; + uint16 _roomPersoItems; //TODO: write-only? + uint16 _roomCharacterPowers; //TODO: write-only? + uint16 _gameFlags; + uint16 _curVideoNum; + uint16 _morkusSpyVideoNum1; //TODO: pad? + uint16 _morkusSpyVideoNum2; //TODO: pad? + uint16 _morkusSpyVideoNum3; //TODO: pad? + uint16 _morkusSpyVideoNum4; //TODO: pad? + byte _newMusicType; + byte _var43; + byte _videoSubtitleIndex; + byte _partyInstruments; // &1 - Bell for Monk, &2 - Drum for Thugg + byte _monkGotRing; + byte _chronoFlag; + byte _curRoomFlags; + byte _endGameFlag; + byte _lastInfo; + bool _autoDialog; + byte _worldTyranSighted; + byte _var4D; + byte _var4E; + byte _worldGaveGold; + byte _worldHasTriceraptors; + byte _worldHasVelociraptors; + byte _worldHasTyran; + byte _var53; + byte _var54; //CHEKME: Used? + byte _var55; //TODO: pad? + byte _gameHours; + byte _textToken1; + byte _textToken2; //TODO: pad? + byte _eloiHaveNews; + byte _dialogFlags; + byte _curAreaType; + byte _curCitadelLevel; + byte _newLocation; + byte _prevLocation; + byte _curPersoFlags; + byte _var60; + byte _eventType; + byte _var62; //TODO: pad? + byte _curObjectId; + byte _curObjectFlags; + byte _var65; //TODO: pad? + byte _roomCharacterType; + byte _roomCharacterFlags; + byte _narratorSequence; + byte _var69; + byte _var6A; + byte _frescoNumber; + byte _var6C; //TODO: pad? + byte _var6D; //TODO: pad? + byte _labyrinthDirections; + byte _labyrinthRoom; + Dialog *_dialogPtr; + tape_t *_tapePtr; + Dialog *_nextDialogPtr; + Dialog *_narratorDialogPtr; + Dialog *_lastDialogPtr; + Icon *_nextRoomIcon; + byte *_sentenceBufferPtr; + Room *_roomPtr; + Area *_areaPtr; + Area *_lastAreaPtr; + Area *_curAreaPtr; + Room *_citaAreaFirstRoom; + perso_t *_characterPtr; + perso_t *_roomCharacterPtr; + byte _lastInfoIdx; + byte _nextInfoIdx; + byte *_persoSpritePtr; + byte *_persoSpritePtr2; + byte *_curCharacterAnimPtr; + byte *_varC2; //TODO: image desc arr + int16 _iconsIndex; + int16 _curObjectCursor; // TODO: useless? + int16 _varCA; + int16 _varCC; //TODO: unused/pad + int16 _characterImageBank; //TODO: unsigned? + uint16 _roomImgBank; + uint16 _characterBackgroundBankIdx; + uint16 _varD4; //TODO: unsigned? + uint16 _frescoeWidth; + uint16 _frescoeImgBank; + uint16 _varDA; //TODO: pad? + uint16 _varDC; //TODO: pad? + uint16 _roomBaseX; + uint16 _varE0; //TODO: pad? + uint16 _dialogType; + uint16 _varE4; //TODO: pad? + uint16 _currMusicNum; + int16 _textNum; + uint16 _travelTime; + uint16 _varEC; //TODO: pad? + byte _displayFlags; + byte _oldDisplayFlags; + byte _drawFlags; + byte _varF1; + byte _varF2; + byte _menuFlags; + byte _varF4; //TODO: write-only? + byte _varF5; + byte _varF6; + byte _varF7; + byte _varF8; //TODO: pad? + byte _varF9; //TODO: pad? + byte _varFA; //TODO: pad? + byte _animationFlags; + byte _giveObj1; + byte _giveObj2; + byte _giveObj3; + byte _var100; + byte _roomVidNum; + byte _mirrorEffect; + byte _var103; + byte _roomBackgroundBankNum; + byte _valleyVidNum; + byte _updatePaletteFlag; + byte _inventoryScrollPos; + byte _objCount; + byte _textBankIndex; + byte _prefLanguage; + byte _prefMusicVol[2]; + byte _prefVoiceVol[2]; + byte _prefSoundVolume[2]; + byte _citadelAreaNum; + byte _var113; + byte _lastPlaceNum; + byte _saveEnd; // TODO: This has to be removed + int16 _textWidthLimit; + byte _numGiveObjs; + byte _var119; // unused +}; + +struct PakHeaderItem { + Common::String _name; //[16]; + int32 _size; + int32 _offs; + char _flag; +}; + +class PakHeaderNode { +public: + PakHeaderNode(int count); + ~PakHeaderNode(); + + uint16 _count; + PakHeaderItem* _files; +}; +#pragma pack(pop) + +struct Citadel { + int16 _id; + int16 _bank[8]; + int16 _video[8]; +}; + +/////////////// vars + +extern Follower followerList[]; + + +/* + Labyrinth of Mo + + | | | | | | | | + +*/ + +enum { + LAB_N = 1, + LAB_E, + LAB_S, + LAB_W +}; + +extern byte kLabyrinthPath[]; + +extern char kDinoSpeedForCitaLevel[16]; + +extern char kTabletView[]; + +// special character backgrounds for specific rooms +extern char kPersoRoomBankTable[]; + +// area transition descriptors +extern Goto gotos[]; +extern object_t _objects[]; +extern uint16 kObjectLocations[100]; +extern perso_t kPersons[]; +extern Citadel _citadelList[]; + +struct prect_t { + int16 left, top, right, bottom; +}; + +extern prect_t _characterRects[]; +extern byte _characterArray[][5]; +extern Area kAreasTable[]; +extern int16 tab_2CEF0[64]; +extern int16 tab_2CF70[64]; +extern int16 kActionCursors[299]; + +struct CubeFace { + int tri; + char ff_4; + char ff_5; + + byte *_texturePtr; + uint16 *_indices; + int16 *_uv; +}; + +struct Point3D { + int16 x; + int16 y; + int16 z; +}; + +struct Cube { + int _num; + CubeFace **_faces; + Point3D *_projection; // projected XYZ coords + Point3D *_vertices; +}; + +extern float _translationZ; +extern float flt_2DF80; +extern float flt_2DF84; + +struct XYZ { + signed short x, y, z; +}; + +struct CubeCursor { + uint8 _sides[6]; // spr idx for each side + uint8 _kind; + int8 _speed; +}; + +} // End of namespace Cryo + +#endif diff --git a/engines/cryo/detection.cpp b/engines/cryo/detection.cpp new file mode 100644 index 0000000000..2ae01f41dd --- /dev/null +++ b/engines/cryo/detection.cpp @@ -0,0 +1,166 @@ +/* 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. + * + */ + +#include "base/plugins.h" + +#include "engines/advancedDetector.h" +#include "common/file.h" + +#include "cryo/cryo.h" + + +namespace Cryo { + +const char *CryoEngine::getGameId() const { return _gameDescription->gameId; } +bool CryoEngine::isDemo() const { return _gameDescription->flags & ADGF_DEMO; } +Common::Platform CryoEngine::getPlatform() const { return _gameDescription->platform; } + +} + +static const PlainGameDescriptor cryoGames[] = { + {"losteden", "Lost Eden"}, + {0, 0} +}; + +namespace Cryo { + +static const ADGameDescription gameDescriptions[] = { + + // Lost Eden PC non-interactive demo version + // Probably not worth it + { + "losteden", + 0, + AD_ENTRY1s("EDEN6.HSQ", 0, 17093), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_DEMO, + GUIO1(GUIO_NONE) + }, + + // Lost Eden PC interactive demo version + { + "losteden", + 0, + AD_ENTRY1s("EDEN.DAT", 0, 205473728), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_DEMO, + GUIO1(GUIO_NONE) + }, + + // Lost Eden PC version + { + "losteden", + 0, + AD_ENTRY1s("EDEN.DAT", 0, 449853776), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_UNSTABLE, + GUIO1(GUIO_NONE) + }, + + // Lost Eden EN PC version + // Added by Strangerke + { + "losteden", + 0, + AD_ENTRY1s("EDEN.DAT", "2126f14fe38b47c7a132f7937c79a2f0", 451205552), + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_UNSTABLE, + GUIO1(GUIO_NONE) + }, + + // Lost Eden FR PC version + // Added by Strangerke + { + "losteden", + 0, + AD_ENTRY1s("EDEN.DAT", "378b1260ac400ecf35f8843357adcca6", 448040496), + Common::FR_FRA, + Common::kPlatformDOS, + ADGF_UNSTABLE, + GUIO1(GUIO_NONE) + }, + + // Lost Eden DE PC version + { + "losteden", + 0, + AD_ENTRY1s("EDEN.DAT", 0, 457719104), + Common::DE_DEU, + Common::kPlatformDOS, + ADGF_UNSTABLE, + GUIO1(GUIO_NONE) + }, + + // Lost Eden Mac version + { + "losteden", + 0, + AD_ENTRY1s("EDEN.DAT", 0, 489739536), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_UNSTABLE, + GUIO1(GUIO_NONE) + }, + + AD_TABLE_END_MARKER +}; + +} // End of namespace Cryo + +class CryoMetaEngine : public AdvancedMetaEngine { +public: + CryoMetaEngine() : AdvancedMetaEngine(Cryo::gameDescriptions, sizeof(ADGameDescription), cryoGames) { + _singleId = "losteden"; + } + + virtual const char *getName() const { + return "Cryo Engine"; + } + + virtual const char *getOriginalCopyright() const { + return "Cryo Engine (C) Cryo Interactive"; + } + + virtual bool hasFeature(MetaEngineFeature f) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; +}; + +bool CryoMetaEngine::hasFeature(MetaEngineFeature f) const { + return false; +} + +bool CryoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + if (desc) { + *engine = new Cryo::CryoEngine(syst, desc); + } + return desc != 0; +} + +#if PLUGIN_ENABLED_DYNAMIC(CRYO) +REGISTER_PLUGIN_DYNAMIC(CRYO, PLUGIN_TYPE_ENGINE, CryoMetaEngine); +#else +REGISTER_PLUGIN_STATIC(CRYO, PLUGIN_TYPE_ENGINE, CryoMetaEngine); +#endif diff --git a/engines/cryo/eden.cpp b/engines/cryo/eden.cpp new file mode 100644 index 0000000000..b8e191c50b --- /dev/null +++ b/engines/cryo/eden.cpp @@ -0,0 +1,9363 @@ +/* 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. + * + */ + +#include "common/scummsys.h" + +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/debug-channels.h" +#include "common/error.h" +#include "gui/EventRecorder.h" +#include "common/file.h" +#include "common/savefile.h" +#include "common/fs.h" +#include "common/system.h" +#include "graphics/surface.h" +#include "graphics/screen.h" +#include "graphics/palette.h" +#include "common/timer.h" + +//#include "audio/audiostream.h" +#include "audio/mixer.h" + +#include "cryo/defs.h" +#include "cryo/cryo.h" +#include "cryo/platdefs.h" +#include "cryo/cryolib.h" +#include "cryo/eden.h" +#include "cryo/sound.h" + +namespace Cryo { + +int16 _torchTick = 0; +int16 _glowIndex = 0; +int16 _torchCurIndex = 0; + +bool _allowDoubled = true; +int _cursCenter = 11; + +EdenGame::EdenGame(CryoEngine *vm) : _vm(vm), kMaxMusicSize(2200000) { + static uint8 statTab2CB1E[8][4] = { + { 0x10, 0x81, 1, 0x90}, + { 0x90, 1, 0x81, 0x10}, + { 1, 0x90, 0x10, 0x81}, + { 1, 0x10, 0x90, 0x81}, + { 1, 0x90, 0x10, 0x81}, + { 0x81, 0x10, 0x90, 1}, + { 0x81, 0x10, 0x90, 1}, + { 0x81, 0x90, 1, 0x10} + }; + + _adamMapMarkPos = Common::Point(-1, -1); + + _scrollPos = _oldScrollPos = 0; + _frescoTalk = false; + _torchCursor = false; + _curBankNum = 0; + _glowH = _glowW = _glowY = _glowX = 0; + _paletteUpdateRequired = false; + _cursorSaved = false; + _showBlackBars = false; + _backgroundSaved = false; + _bankData = nullptr; + _tyranPtr = nullptr; + _lastAnimFrameNumb = _curAnimFrameNumb = 0; + _lastAnimTicks = 0; + _curCharacterRect = nullptr; + _numAnimFrames = _maxPersoDesc = _numImgDesc = 0; + _restartAnimation = _animationActive = false; + _animationDelay = _animationIndex = _lastAnimationIndex = 0; + dword_30724 = dword_30728 = _mouthAnimations = _animationTable = nullptr; + _characterBankData = nullptr; + _savedUnderSubtitles = false; + _numTextLines = 0; + _textOutPtr = textout = nullptr; + _curSpecialObject = nullptr; + _lastDialogChoice = false; + parlemoiNormalFlag = false; + _closeCharacterDialog = false; + dword_30B04 = 0; + _lastPhrasesFile = 0; + _dialogSkipFlags = 0; + _voiceSamplesBuffer = nullptr; + _needToFade = false; + _mainBankBuf = nullptr; + _musicBuf = nullptr; + _gameLipsync = nullptr; + _gamePhrases = nullptr; + _gameDialogs = nullptr; + _gameConditions = nullptr; + _placeRawBuf = nullptr; + _bankDataBuf = nullptr; + _gameIcons = nullptr; + _gameRooms = nullptr; + _glowBuffer = nullptr; + _gameFont = nullptr; + _globals = nullptr; + _mouseCenterY = _mouseCenterX = 0; + _bufferAllocationErrorFl = _quitFlag2 = _quitFlag3 = false; + _gameStarted = false; + _soundAllocated = false; + _musicChannel = _voiceChannel = nullptr; + _hnmSoundChannel = nullptr; + _voiceSound = nullptr; + _view2 = _underSubtitlesView = _subtitlesView = _underBarsView = _mainView = _hnmView = nullptr; + _cirsorPanX = 0; + _inventoryScrollDelay = 0; + _cursorPosY = _cursorPosX = 0; + _currCursor = 0; + _currSpot = _curSpot2 = nullptr; + _keyboardHeld = false; + _mouseHeld = false; + _normalCursor = false; + _showVideoSubtitle = false; + _specialTextMode = false; + _voiceSamplesSize = 0; + _animateTalking = false; + _personTalking = false; + _musicFadeFlag = 0; + _musicPlayingFlag = false; + _musicSamplesPtr = _musicPatternsPtr = _musSequencePtr = nullptr; + _musicEnabledFlag = false; + _currentObjectLocation = nullptr; + byte_31D64 = false; + _noPalette = false; + _gameLoaded = false; + memset(_tapes, 0, sizeof(_tapes)); + _confirmMode = 0; + _curSliderValuePtr = nullptr; + _lastMenuItemIdLo = 0; + _lastTapeRoomNum = 0; + _curSliderX = _curSliderY = 0; + _destinationRoom = 0; + word_31E7A = 0; + word_378CC = 0; //TODO: set by CLComputer_Init to 0 + word_378CE = 0; + + _rotationAngleY = _rotationAngleX = _rotationAngleZ = 0; + _translationY = _translationX = 0.0; //TODO: never changed, make consts? + _cursorOldTick = 0; + + _invIconsBase = 19; +// invIconsCount = (_vm->getPlatform() == Common::kPlatformMacintosh) ? 9 : 11; + _invIconsCount = 11; + _roomIconsBase = _invIconsBase + _invIconsCount; + + _codePtr = nullptr; + + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 4; j++) + tab_2CB1E[i][j] = statTab2CB1E[i][j]; + } +} + +void EdenGame::removeConsole() { +} + +void EdenGame::scroll() { + restoreFriezes(); + _mainView->_normal._srcLeft = _scrollPos; + _mainView->_zoom._srcLeft = _scrollPos; +} + +void EdenGame::resetScroll() { + _oldScrollPos = _scrollPos; + _scrollPos = 0; + restoreFriezes(); //TODO: inlined scroll() ? + _mainView->_normal._srcLeft = 0; + _mainView->_zoom._srcLeft = 0; +} + +void EdenGame::scrollFrescoes() { + if (_cursorPosY > 16 && _cursorPosY < 176) { + if (_cursorPosX >= 0 && _cursorPosX < 32 && _scrollPos > 3) + _scrollPos -= 4; + else if (_cursorPosX > 288 && _cursorPosX < 320 && _scrollPos < _globals->_frescoeWidth) + _scrollPos += 4; + } + scroll(); +} + +// Original name: afffresques +void EdenGame::displayFrescoes() { + useBank(_globals->_frescoeImgBank); + noclipax(0, 0, 16); + useBank(_globals->_frescoeImgBank + 1); + noclipax(0, 320, 16); + _paletteUpdateRequired = true; +} + +void EdenGame::gametofresques() { + _frescoTalk = false; + rundcurs(); + saveFriezes(); + displayFrescoes(); + _globals->_displayFlags = DisplayFlags::dfFrescoes; +} + +// Original name: dofresques +void EdenGame::doFrescoes() { + _cursorSaved = false; + _torchCursor = true; + _glowX = -1; + _glowY = -1; + _globals->_gameFlags |= GameFlags::gfFlag20; + _globals->_varD4 = 0; + _globals->_curObjectId = 0; + _globals->_iconsIndex = 13; + _globals->_autoDialog = false; + gametofresques(); + _globals->_frescoNumber = 3; +} + +// Original name: finfresques +void EdenGame::actionEndFrescoes() { + _torchCursor = false; + _cursorSaved = true; + _globals->_displayFlags = DisplayFlags::dfFlag1; + resetScroll(); + _globals->_var100 = 0xFF; + updateRoom(_globals->_roomNum); + if (_globals->_phaseNum == 114) + _globals->_narratorSequence = 1; + _globals->_eventType = EventType::etEvent8; + showEvents(); +} + +void EdenGame::scrollMirror() { + if (_cursorPosY > 16 && _cursorPosY < 165) { + if (_cursorPosX >= 0 && _cursorPosX < 16) { + if (_scrollPos > 3) { + _scrollPos--; + scroll(); + } + } else if (_cursorPosX > 290 && _cursorPosX < 320) { + if (_scrollPos < 320) { + _scrollPos++; + scroll(); + } + } + } +} + +// Original name: scrollpano +void EdenGame::scrollPanel() { + if (_cursorPosY > 16 && _cursorPosY < 165) { + if (_cursorPosX >= 0 && _cursorPosX < 16 && _scrollPos > 3) + _scrollPos--; + else if (_cursorPosX > 290 && _cursorPosX < 320 && _scrollPos < 320) + _scrollPos++; + } + scroll(); +} + +// Original name: affsuiveur +void EdenGame::displayFollower(Follower *follower, int16 x, int16 y) { + useBank(follower->_spriteBank); + noclipax(follower->_spriteNum, x, y + 16); +} + +// Original name: persoinmiroir +void EdenGame::characterInMirror() { + Icon *icon1 = &_gameIcons[3]; + Icon *icon = &_gameIcons[_roomIconsBase]; + Follower *suiveur = followerList; + int16 num = 1; + for (int i = 0; i < 16; i++) { + if (_globals->_party & (1 << i)) + num++; + } + icon += num; + icon->sx = -1; + icon--; + icon->sx = icon1->sx; + icon->sy = icon1->sy; + icon->ex = icon1->ex; + icon->ey = 170; + icon->_cursorId = icon1->_cursorId; + icon->_actionId = icon1->_actionId; + icon->_objectId = icon1->_objectId; + icon--; + displayFollower(suiveur, suiveur->sx, suiveur->sy); + for (; suiveur->_id != -1; suiveur++) { + perso_t *perso; + for (perso = kPersons; perso != &kPersons[PER_UNKN_156]; perso++) { + if (perso->_id != suiveur->_id) + continue; + + if (perso->_flags & PersonFlags::pf80) + continue; + + if ((perso->_flags & PersonFlags::pfInParty) == 0) + continue; + + if (perso->_roomNum != _globals->_roomNum) + continue; + + icon->sx = suiveur->sx; + icon->sy = suiveur->sy; + icon->ex = suiveur->ex; + icon->ey = suiveur->ey; + icon->_cursorId = 8; + icon->_actionId = perso->_actionId; + icon--; + displayFollower(suiveur, suiveur->sx, suiveur->sy); + break; + } + } +} + +// Original name: gametomiroir +void EdenGame::gameToMirror(byte arg1) { + if (_globals->_displayFlags != DisplayFlags::dfFlag2) { + rundcurs(); + restoreFriezes(); + drawTopScreen(); + showObjects(); + saveFriezes(); + } + int16 bank = _globals->_roomBackgroundBankNum; + uint16 resNum = bank + 326; + if ((_vm->getPlatform() == Common::kPlatformMacintosh) && (bank == 76 || bank == 128)) + resNum = 2487; // PCIMG.HSQ + + useBank(resNum); + noclipax(0, 0, 16); + useBank(resNum + 1); + noclipax(0, 320, 16); + characterInMirror(); + _paletteUpdateRequired = true; + _globals->_iconsIndex = 16; + _globals->_autoDialog = false; + _globals->_displayFlags = DisplayFlags::dfMirror; + _globals->_mirrorEffect = arg1; +} + +void EdenGame::flipMode() { + if (_personTalking) { + endCharacterSpeech(); + if (_globals->_displayFlags == DisplayFlags::dfPerson) { + if (_globals->_characterPtr == &kPersons[PER_TAU] && _globals->_phaseNum >= 80) + displaySubtitles(); + else { + getDataSync(); + loadCurrCharacter(); + addanim(); + _restartAnimation = true; + animCharacter(); + } + } else + displaySubtitles(); + persovox(); + } else { + if (_globals->_displayFlags != DisplayFlags::dfFrescoes && _globals->_displayFlags != DisplayFlags::dfFlag2) { + closeRoom(); + if (_globals->_displayFlags & DisplayFlags::dfFlag1) + gameToMirror(1); + else { + quitMirror(); + updateRoom(_globals->_roomNum); + if (byte_31D64) { + dialautoon(); + parle_moi(); + byte_31D64 = false; + } + } + } + } +} + +// Original name: quitmiroir +void EdenGame::quitMirror() { + rundcurs(); + display(); + resetScroll(); + saveFriezes(); + _globals->_displayFlags = DisplayFlags::dfFlag1; + _globals->_var100 = 0xFF; + _globals->_eventType = EventType::etEventC; + _globals->_mirrorEffect = 1; +} + +void EdenGame::clictimbre() { + flipMode(); +} + +// Original name: clicplanval +void EdenGame::actionClickValleyPlan() { + if ((_globals->_partyOutside & PersonMask::pmDina) && _globals->_phaseNum == 371) { + quitMirror(); + updateRoom(_globals->_roomNum); + return; + } + if (_globals->_roomNum == 8 || _globals->_roomNum < 16) + return; + + rundcurs(); + display(); + if (_globals->_displayFlags == DisplayFlags::dfMirror) + quitMirror(); + deplaval((_globals->_roomNum & 0xFF00) | 1); //TODO: check me +} + +// Original name: gotolieu +void EdenGame::gotoPlace(Goto *go) { + _globals->_valleyVidNum = go->_arriveVideoNum; + _globals->_travelTime = go->_travelTime * 256; + _globals->_stepsToFindAppleFast = 0; + _globals->_eventType = EventType::etEvent2; + setChoiceYes(); + showEvents(); + if (!isAnswerYes()) + return; + + if (_globals->_var113) { + waitEndSpeak(); + if (!_vm->shouldQuit()) + closeCharacterScreen(); + } + if (go->_enterVideoNum) { + hideBars(); + playHNM(go->_enterVideoNum); + _needToFade = true; + } + initPlace(_globals->_newRoomNum); + specialoutside(); + faire_suivre(_globals->_newRoomNum); + closeRoom(); + _adamMapMarkPos.x = -1; + _adamMapMarkPos.y = -1; + addTime(_globals->_travelTime); + _globals->_var100 = _globals->_roomPtr->_id; + _globals->_roomNum = _globals->_newRoomNum; + _globals->_areaNum = _globals->_roomNum >> 8; + _globals->_eventType = EventType::etEvent5; + _globals->_newMusicType = MusicType::mt2; + setCharacterHere(); + musique(); + updateRoom1(_globals->_roomNum); + drawTopScreen(); + _adamMapMarkPos.x = -1; + _adamMapMarkPos.y = -1; +} + +void EdenGame::deplaval(uint16 roomNum) { + _globals->_newLocation = roomNum & 0xFF; + _globals->_valleyVidNum = 0; + _globals->_phaseActionsCount++; + closeRoom(); + endCharacterSpeech(); + byte c1 = roomNum & 0xFF; + if (c1 == 0) + return; + + if (c1 < 0x80) { + _globals->_displayFlags = DisplayFlags::dfFlag1; + setChoiceYes(); + _globals->_eventType = EventType::etEvent1; + showEvents(); + if (!isAnswerYes()) + return; + + if (_globals->_var113) { + waitEndSpeak(); + if (!_vm->shouldQuit()) + closeCharacterScreen(); + } + specialout(); + if (_globals->_areaPtr->_type == AreaType::atValley) { + addTime(32); + _globals->_stepsToFindAppleFast++; + _globals->_stepsToFindAppleNormal++; + } + faire_suivre((roomNum & 0xFF00) | _globals->_newLocation); + _globals->_var100 = _globals->_roomPtr->_id; + _globals->_roomNum = roomNum; + _globals->_areaNum = roomNum >> 8; + _globals->_eventType = EventType::etEvent5; + setCharacterHere(); + _globals->_newMusicType = MusicType::mtNormal; + musique(); + updateRoom1(roomNum); + _globals->_chronoFlag = 0; + _globals->_chrono = 0; + _globals->_var54 = 0; + if (_globals->_roomCharacterType == PersonFlags::pftTyrann) + setChrono(3000); + return; + } + if (c1 == 0xFF) { + _globals->_eventType = EventType::etEventE; + showEvents(); + if (!kPersons[PER_ELOI]._roomNum && checkEloiReturn()) + setChrono(800); + return; + } + _globals->_stepsToFindAppleFast = 0; + byte newAreaNum = c1 & 0x7F; + byte curAreaNum = _globals->_roomNum >> 8; + int16 newRoomNum = newAreaNum << 8; + if (curAreaNum == Areas::arTausCave && newAreaNum == Areas::arMo) + newRoomNum |= 0x16; + else if (curAreaNum == Areas::arMoorkusLair) + newRoomNum |= 4; + else + newRoomNum |= 1; + _globals->_newRoomNum = newRoomNum; + if (newAreaNum == Areas::arTausCave) + gotoPlace(&gotos[0]); + else { + for (Goto *go = gotos + 1; go->_curAreaNum != 0xFF; go++) { + if (go->_curAreaNum == curAreaNum) { + gotoPlace(go); + break; + } + } + } +} + +// Original name: deplacement +void EdenGame::move(Direction dir) { + Room *room = _globals->_roomPtr; + int16 roomNum = _globals->_roomNum; + debug("move: from room %4X", roomNum); + char newLoc = 0; + rundcurs(); + display(); + _globals->_prevLocation = roomNum & 0xFF; + switch (dir) { + case kCryoNorth: + newLoc = room->_exits[0]; + break; + case kCryoEast: + newLoc = room->_exits[1]; + break; + case kCryoSouth: + newLoc = room->_exits[2]; + break; + case kCryoWest: + newLoc = room->_exits[3]; + break; + } + deplaval((roomNum & 0xFF00) | newLoc); +} + +// Original name: deplacement2 +void EdenGame::move2(Direction dir) { + Room *room = _globals->_roomPtr; + int16 roomNum = _globals->_roomNum; + char newLoc = 0; + _globals->_prevLocation = roomNum & 0xFF; + switch (dir) { + case kCryoNorth: + newLoc = room->_exits[0]; + break; + case kCryoEast: + newLoc = room->_exits[1]; + break; + case kCryoSouth: + newLoc = room->_exits[2]; + break; + case kCryoWest: + newLoc = room->_exits[3]; + break; + } + deplaval((roomNum & 0xFF00) | newLoc); +} + +// Original name: dinosoufle +void EdenGame::actionDinoBlow() { + if (_globals->_curObjectId == 0) { + hideBars(); + playHNM(148); + maj2(); + } +} + +// Original name: plaquemonk +void EdenGame::actionPlateMonk() { + if (_globals->_curObjectId != 0) { + if (_globals->_curObjectId == Objects::obPrism) { + loseObject(Objects::obPrism); + hideBars(); + _specialTextMode = true; + playHNM(89); + // CHECKME: Unused code + // word_2F514 |= 0x8000; + maj2(); + _globals->_eventType = EventType::etEventB; + showEvents(); + } + } else { + hideBars(); + playHNM(7); + maj2(); + _globals->_eventType = EventType::etEvent4; + showEvents(); + } +} + +// Original name: fresquesgraa +void EdenGame::actionGraaFrescoe() { + if (_globals->_curObjectId == 0) { + _globals->_frescoeWidth = 320; + _globals->_frescoeImgBank = 113; + doFrescoes(); + handleDinaDialog(); + } +} + +// Original name: fresqueslasc +void EdenGame::actionLascFrescoe() { + if (_globals->_curObjectId == 0) { + _globals->_frescoeWidth = 112; + _globals->_frescoeImgBank = 315; + doFrescoes(); + } +} + +// Original name: pushpierre +void EdenGame::actionPushStone() { + if (_globals->_curObjectId == 0) { + _gameRooms[22]._exits[0] = 17; + _gameRooms[26]._exits[2] = 9; + move(kCryoNorth); + } +} + +// Original name: tetemomie +void EdenGame::actionMummyHead() { + if (_globals->_curObjectId == Objects::obTooth) { + _globals->_gameFlags |= GameFlags::gfMummyOpened; + move(kCryoNorth); + } else if (_globals->_curObjectId == 0) { + if (_globals->_gameFlags & GameFlags::gfMummyOpened) + move(kCryoNorth); + else { + _globals->_eventType = EventType::etEvent6; + handleCharacterDialog(PersonId::pidMonk); + _globals->_eventType = 0; + } + } +} + +// Original name: tetesquel +void EdenGame::actionSkelettonHead() { + if (_globals->_curObjectId == Objects::obTooth) { + _gameRooms[22]._exits[0] = 16; + _gameRooms[26]._exits[2] = 13; + _gameIcons[16]._cursorId |= 0x8000; + loseObject(Objects::obTooth); + move(kCryoNorth); + } +} + +// Original name: squelmoorkong +void EdenGame::actionSkelettonMoorkong() { + _globals->_eventType = EventType::etEvent9; + showEvents(); +} + +// Original name: choisir +void EdenGame::actionChoose() { + byte objid = _curSpot2->_objectId; + byte obj; + switch (objid) { + case 0: + obj = _globals->_giveObj1; + break; + case 1: + obj = _globals->_giveObj2; + break; + case 2: + obj = _globals->_giveObj3; + break; + default: + warning("Unexpected objid in actionChoose()"); + return; + } + objectmain(obj); + winObject(obj); + _globals->_iconsIndex = 16; + _globals->_autoDialog = false; + _globals->_var60 = 0; + parle_moi(); +} + +// Original name: dinaparle +void EdenGame::handleDinaDialog() { + perso_t *perso = &kPersons[PER_DINA]; + if (perso->_partyMask & (_globals->_party | _globals->_partyOutside)) { + if (_globals->_frescoNumber < 3) + _globals->_frescoNumber = 3; + _globals->_frescoNumber++; + if (_globals->_frescoNumber < 15) { + endCharacterSpeech(); + if (_globals->_frescoNumber == 7 && _globals->_phaseNum == 113) + incPhase(); + _globals->_characterPtr = perso; + _globals->_dialogType = DialogType::dtInspect; + int16 num = (perso->_id << 3) | DialogType::dtInspect; //TODO: combine + bool res = dialoscansvmas((Dialog *)getElem(_gameDialogs, num)); + _frescoTalk = false; + if (res) { + restoreUnderSubtitles(); + _frescoTalk = true; + persovox(); + } + _globals->_varCA = 0; + _globals->_dialogType = DialogType::dtTalk; + } else + actionEndFrescoes(); + } +} + +// Original name: roiparle +void EdenGame::handleKingDialog() { + if (_globals->_phaseNum <= 400) + handleCharacterDialog(0); +} + +// Original name: roiparle1 +void EdenGame::actionKingDialog1() { + if (_globals->_curObjectId == Objects::obSword) { + _globals->_gameFlags |= GameFlags::gfFlag80; + hideBars(); + playHNM(76); + move2(kCryoNorth); + } else { + _globals->_frescoNumber = 1; + handleKingDialog(); + } +} + +// Original name: roiparle2 +void EdenGame::actionKingDialog2() { + _globals->_frescoNumber = 2; + handleKingDialog(); +} + +// Original name: roiparle3 +void EdenGame::actionKingDialog3() { + _globals->_frescoNumber = 3; + handleKingDialog(); +} + +// Original name: getcouteau +void EdenGame::actionGetKnife() { + if (_globals->_phaseNum >= 80) { + _gameRooms[113]._video = 0; + getObject(Objects::obKnife); + } + _globals->_eventType = EventType::etEvent7; + showEvents(); +} + +// Original name: getprisme +void EdenGame::actionGetPrism() { + getObject(Objects::obPrism); + _globals->_eventType = EventType::etEvent7; + showEvents(); +} + +// Original name: getchampb +void EdenGame::actionGetMushroom() { + getObject(Objects::obShroom); +} + +// Original name: getchampm +void EdenGame::actionGetBadMushroom() { + getObject(Objects::obBadShroom); +} + +// Original name: getor +void EdenGame::actionGetGold() { + getObject(Objects::obGold); +} + +// Original name: getnido +void EdenGame::actionGetFullNest() { + if (_globals->_curObjectId != 0) + return; + _globals->_roomPtr->_bank = 282; //TODO: fix me + _globals->_roomPtr--; + _globals->_roomPtr->_bank = 281; //TODO: fix me + _globals->_roomPtr->_id = 3; + getObject(Objects::obFullNest); +} + +// Original name: getnidv +void EdenGame::actionGetEmptyNest() { + if (_globals->_curObjectId != 0) + return; + _globals->_roomPtr->_bank = 282; //TODO: fix me + _globals->_roomPtr--; + _globals->_roomPtr->_bank = 281; //TODO: fix me + _globals->_roomPtr->_id = 3; + getObject(Objects::obNest); +} + +// Original name: getcorne +void EdenGame::actionGetHorn() { + if (_globals->_curObjectId != 0) + return; + getObject(Objects::obHorn); + _globals->_eventType = EventType::etEvent7; + showEvents(); + bigphase1(); + setCharacterHere(); + _globals->_roomPtr = getRoom(_globals->_roomNum); +} + +// Original name: getsoleil +void EdenGame::actionGetSunStone() { + if (_globals->_curObjectId != 0) + return; + _gameRooms[238]._video = 0; + _gameRooms[238]._flags = RoomFlags::rf80; + getObject(Objects::obSunStone); +} + +// Original name: getoueuf +void EdenGame::actionGetEgg() { + if (_globals->_curObjectId != 0) + return; + _globals->_roomPtr->_flags = 0; + _globals->_roomPtr->_video = 0; + getObject(Objects::obEgg); +} + +// Original name: getplaque +void EdenGame::actionGetTablet() { + if (_globals->_curObjectId != 0 && _globals->_curObjectId < Objects::obTablet1) + return; + _globals->_curObjectId = 0; + getObject(Objects::obTablet2); + putObject(); + for (int i = 0; i < 6; i++) + _objects[Objects::obTablet1 - 1 + i]._count = 0; + _globals->_curObjectFlags = 0; + _globals->_inventoryScrollPos = 0; + _globals->_curObjectCursor = 9; + _gameIcons[16]._cursorId |= 0x8000; + showObjects(); + _gameRooms[131]._video = 0; + hideBars(); + playHNM(149); + _globals->_varF1 = RoomFlags::rf04; + _globals->_drawFlags = DrawFlags::drDrawFlag20; + _normalCursor = true; + maj2(); +} + +// Original name: voirlac +void EdenGame::actionLookLake() { + perso_t *perso = &kPersons[PER_MORKUS]; + Room *room = _globals->_roomPtr; + Area *area = _globals->_areaPtr; + int16 vid = _globals->_curObjectId == Objects::obApple ? 81 : 54; + for (++perso; perso->_roomNum != 0xFFFF; perso++) { + if (perso->_roomNum != _globals->_roomNum) + continue; + vid++; + if (_globals->_curObjectId != Objects::obApple) + continue; //TODO: pc breaks here + if ((perso->_flags & PersonFlags::pfTypeMask) != PersonFlags::pftMosasaurus) + continue; + if (!(perso->_flags & PersonFlags::pf80)) + return; + perso->_flags &= ~PersonFlags::pf80; //TODO: useless? see above + area->_flags |= AreaFlags::afFlag8; + _globals->_curAreaFlags |= AreaFlags::afFlag8; + room->_id = 3; + } + debug("sea monster: room = %X, d0 = %X\n", _globals->_roomNum, _globals->_roomImgBank); + hideBars(); + playHNM(vid); + updateRoom(_globals->_roomNum); //TODO: getting memory trashed here? + if (_globals->_curObjectId == Objects::obApple) + loseObject(Objects::obApple); + _globals->_eventType = EventType::etEventF; + showEvents(); +} + +// Original name: gotohall +void EdenGame::actionGotoHall() { + _globals->_prevLocation = _globals->_roomNum & 0xFF; + deplaval((_globals->_roomNum & 0xFF00) | 6); +} + +// Original name: demitourlabi +void EdenGame::actionLabyrinthTurnAround() { + _globals->_prevLocation = _globals->_roomNum & 0xFF; + _globals->_var100 = 0xFF; + uint16 target = (_globals->_roomNum & 0xFF00) | _globals->_roomPtr->_exits[2]; + faire_suivre(target); + _globals->_roomNum = target; + _globals->_eventType = EventType::etEvent5; + updateRoom(_globals->_roomNum); +} + +// Original name: gotonido +void EdenGame::actionGotoFullNest() { + _globals->_roomPtr++; + _globals->_eventType = 0; + _globals->_roomImgBank = _globals->_roomPtr->_bank; + _globals->_roomVidNum = _globals->_roomPtr->_video; + _globals->_curRoomFlags = _globals->_roomPtr->_flags; + _globals->_varF1 = _globals->_roomPtr->_flags; + animpiece(); + _globals->_var100 = 0; + maj2(); +} + +// Original name: gotoval +void EdenGame::actionGotoVal() { + uint16 target = _globals->_roomNum; + rundcurs(); + display(); + _scrollPos = 0; + char obj = _curSpot2->_objectId - 14; //TODO + _globals->_prevLocation = target & 0xFF; + deplaval((target & 0xFF00) | obj); +} + +// Original name: visiter +void EdenGame::actionVisit() { + hideBars(); + playHNM(144); + _globals->_varF1 = RoomFlags::rf04; + maj2(); +} + +// Original name: final +void EdenGame::actionFinal() { + if (_globals->_curObjectId != 0) + return; + + hideBars(); + *(int16 *)(_gameRooms + 0x6DC) = 319; //TODO + _globals->_roomImgBank = 319; + playHNM(97); + maj2(); + _globals->_eventType = EventType::etEvent12; + showEvents(); + _globals->_narratorSequence = 54; +} + +// Original name: goto_nord +void EdenGame::actionMoveNorth() { + if (_globals->_curObjectId == 0) + move(kCryoNorth); +} + +// Original name: goto_est +void EdenGame::actionMoveEast() { + if (_globals->_curObjectId == 0) + move(kCryoEast); +} + +// Original name: goto_sud +void EdenGame::actionMoveSouth() { + if (_globals->_curObjectId == 0) + move(kCryoSouth); +} + +// Original name: goto_ouest +void EdenGame::actionMoveWest() { + if (_globals->_curObjectId == 0) + move(kCryoWest); +} + +// Original name: afficher +void EdenGame::display() { + if (!_globals->_mirrorEffect && !_globals->_var103) { + if (_paletteUpdateRequired) { + _paletteUpdateRequired = false; + CLPalette_Send2Screen(_globalPalette, 0, 256); + } + CLBlitter_CopyView2Screen(_mainView); + } else { + if (_globals->_mirrorEffect) + displayEffect3(); + else + displayEffect2(); + + _globals->_var103 = 0; + _globals->_mirrorEffect = 0; + } +} + +void EdenGame::afficher128() { + if (_globals->_updatePaletteFlag == 16) { + CLPalette_Send2Screen(_globalPalette, 0, 129); + CLBlitter_CopyView2Screen(_mainView); + _globals->_updatePaletteFlag = 0; + } else { + clearScreen(); + fadeToBlackLowPalette(1); + if (_showBlackBars) + drawBlackBars(); + CLBlitter_CopyView2Screen(_mainView); + fadeFromBlackLowPalette(1); + } +} + +// Original name: sauvefrises +void EdenGame::saveFriezes() { + saveTopFrieze(0); + saveBottomFrieze(); +} + +// Original name: sauvefriseshaut +void EdenGame::saveTopFrieze(int16 x) { // Save top bar + _underTopBarScreenRect = Common::Rect(x, 0, x + 320 - 1, 15); + _underTopBarBackupRect = Common::Rect(0, 0, 320 - 1, 15); + CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underTopBarScreenRect, &_underTopBarBackupRect); +} + +// Original name: sauvefrisesbas +void EdenGame::saveBottomFrieze() { // Save bottom bar + _underBottomBarScreenRect.left = 0; + _underBottomBarScreenRect.right = 320 - 1; + CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underBottomBarScreenRect, &_underBottomBarBackupRect); +} + +// Original name: restaurefrises +void EdenGame::restoreFriezes() { + restoreTopFrieze(); + restoreBottomFrieze(); +} + +// Original name: restaurefriseshaut +void EdenGame::restoreTopFrieze() { + _underTopBarScreenRect.left = _scrollPos; + _underTopBarScreenRect.right = _scrollPos + 320 - 1; + CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarBackupRect, &_underTopBarScreenRect); +} + +// Original name: restaurefrisesbas +void EdenGame::restoreBottomFrieze() { + _underBottomBarScreenRect.left = _scrollPos; + _underBottomBarScreenRect.right = _scrollPos + 320 - 1; + CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underBottomBarBackupRect, &_underBottomBarScreenRect); +} + +void EdenGame::useMainBank() { + _bankData = _mainBankBuf; +} + +void EdenGame::useCharacterBank() { + _bankData = _characterBankData; +} + +// Original name: use_bank +void EdenGame::useBank(int16 bank) { + if (bank > 2500) + error("attempt to load bad bank %d", bank); + + _bankData = _bankDataBuf; + if (_curBankNum != bank) { + loadRawFile(bank, _bankDataBuf); + verifh(_bankDataBuf); + _curBankNum = bank; + } +} + +void EdenGame::sundcurs(int16 x, int16 y) { + byte *keep = _cursKeepBuf; + x = CLIP<int16>(x - 4, 0, 640 - 48); + y = CLIP<int16>(y - 4, 0, 200 - 48); + _cursKeepPos = Common::Point(x, y); + byte *scr = _mainViewBuf + _cursKeepPos.x + _cursKeepPos.y * 640; + for (int16 h = 48; h--;) { + for (int16 w = 48; w--;) + *keep++ = *scr++; + scr += 640 - 48; + } + _cursorSaved = true; +} + +void EdenGame::rundcurs() { + byte *keep = _cursKeepBuf; + byte *scr = _mainViewBuf + _cursKeepPos.x + _cursKeepPos.y * 640; + if (!_cursorSaved || (_cursKeepPos == Common::Point(-1, -1))) //TODO ... + return; + + for (int16 h = 48; h--;) { + for (int16 w = 48; w--;) + *scr++ = *keep++; + scr += 640 - 48; + } + +} + +void EdenGame::noclipax(int16 index, int16 x, int16 y) { + byte *pix = _bankData; + byte *scr = _mainViewBuf + x + y * 640; + if (_curBankNum != 117 && !_noPalette) { + if (READ_LE_UINT16(pix) > 2) + readPalette(pix + 2); + } + pix += READ_LE_UINT16(pix); + pix += READ_LE_UINT16(pix + index * 2); + // int16 height:9 + // int16 pad:6; + // int16 flag:1; + byte h0 = *pix++; + byte h1 = *pix++; + int16 w = ((h1 & 1) << 8) | h0; + int16 h = *pix++; + byte mode = *pix++; + debug("- draw sprite %d at %d:%d, %dx%d", index, x, y, w, h); + if (mode != 0xFF && mode != 0xFE) + return; + if (y + h > 200) + h -= (y + h - 200); + if (h1 & 0x80) { + // compressed + for (; h-- > 0;) { + for (int16 ww = w; ww > 0;) { + byte c = *pix++; + if (c >= 0x80) { + if (c == 0x80) { + byte fill = *pix++; + if (fill == 0) { + scr += 128 + 1; + ww -= 128 + 1; + } else { + byte runVal; + *scr++ = fill; //TODO: wha? + *scr++ = fill; + ww -= 128 + 1; + for (runVal = 127; runVal--;) + *scr++ = fill; + } + } else { + byte fill = *pix++; + byte runVal = 255 - c + 2; + ww -= runVal; + if (fill == 0) + scr += runVal; + else + for (; runVal--;) + *scr++ = fill; + } + } else { + byte runVal = c + 1; + ww -= runVal; + for (; runVal--;) { + byte p = *pix++; + if (p == 0) + scr++; + else + *scr++ = p; + } + } + } + scr += 640 - w; + } + } else { + // uncompressed + for (; h--;) { + for (int16 ww = w; ww--;) { + byte p = *pix++; + if (p == 0) + scr++; + else + *scr++ = p; + } + scr += 640 - w; + } + } +} + +void EdenGame::noclipax_avecnoir(int16 index, int16 x, int16 y) { + byte *pix = _bankData; + byte *scr = _mainViewBuf + x + y * 640; + if (_curBankNum != 117) { + if (READ_LE_UINT16(pix) > 2) + readPalette(pix + 2); + } + pix += READ_LE_UINT16(pix); + pix += READ_LE_UINT16(pix + index * 2); + // int16 height:9 + // int16 pad:6; + // int16 flag:1; + byte h0 = *pix++; + byte h1 = *pix++; + int16 w = ((h1 & 1) << 8) | h0; + int16 h = *pix++; + byte mode = *pix++; + if (mode != 0xFF && mode != 0xFE) + return; + if (y + h > 200) + h -= (y + h - 200); + if (h1 & 0x80) { + // compressed + for (; h-- > 0;) { + for (int16 ww = w; ww > 0;) { + byte c = *pix++; + if (c >= 0x80) { + if (c == 0x80) { + byte fill = *pix++; + byte runVal; + *scr++ = fill; //TODO: wha? + *scr++ = fill; + ww -= 128 + 1; + for (runVal = 127; runVal--;) + *scr++ = fill; + } else { + byte fill = *pix++; + byte runVal = 255 - c + 2; + ww -= runVal; + for (; runVal--;) + *scr++ = fill; + } + } else { + byte runVal = c + 1; + ww -= runVal; + for (; runVal--;) { + byte p = *pix++; + *scr++ = p; + } + } + } + scr += 640 - w; + } + } else { + // uncompressed + for (; h--;) { + for (int16 ww = w; ww--;) { + byte p = *pix++; + *scr++ = p; + } + scr += 640 - w; + } + } +} + +void EdenGame::getglow(int16 x, int16 y, int16 w, int16 h) { + byte *scr = _mainViewBuf + x + y * 640; + byte *gl = _glowBuffer; + _glowX = x; + _glowY = y; + _glowW = w; + _glowH = h; + for (; h--;) { + for (int16 ww = w; ww--;) + *gl++ = *scr++; + scr += 640 - w; + } +} + +void EdenGame::unglow() { + byte *gl = _glowBuffer; + byte *scr = _mainViewBuf + _glowX + _glowY * 640; + if (_glowX < 0 || _glowY < 0) //TODO: move it up + return; + for (; _glowH--;) { + for (int16 ww = _glowW; ww--;) + *scr++ = *gl++; + scr += 640 - _glowW; + } +} + +void EdenGame::glow(int16 index) { + // byte pixbase; + byte *pix = _bankData; + + index += 9; + pix += READ_LE_UINT16(pix); + pix += READ_LE_UINT16(pix + index * 2); + // int16 height:9 + // int16 pad:6; + // int16 flag:1; + byte h0 = *pix++; + byte h1 = *pix++; + int16 w = ((h1 & 1) << 8) | h0; + int16 h = *pix++; + byte mode = *pix++; + if (mode != 0xFF && mode != 0xFE) + return; + + int16 x = _cursorPosX + _scrollPos - 38; + int16 y = _cursorPosY - 28; + int16 ex = _globals->_frescoeWidth + 320; + + if (x + w <= 0 || x >= ex || y + h <= 0 || y >= 176) + return; + + int16 dx; + if (x < 0) { + dx = -x; + x = 0; + } else if (x + w > ex) + dx = x + w - ex; + else + dx = 0; + + int16 dy = 0; + if (y < 16) { + dy = 16 - y; + y = 16; + } else if (y + h > 175) + dy = y + h - 175; + + int16 pstride = dx; + int16 sstride = 640 - (w - dx); + if (y == 16) + pix += w * dy; + if (x == 0) + pix += dx; + + byte *scr = _mainViewBuf + x + y * 640; + + w -= dx; + h -= dy; + + getglow(x, y, w, h); + + for (; h--;) { + for (int16 ww = w; ww--;) { + byte p = *pix++; + if (p == 0) + scr++; + else + *scr++ += p << 4; + } + pix += pstride; + scr += sstride; + } +} + +void EdenGame::readPalette(byte *ptr) { + bool doit = true; + color3_t pal_entry; + while (doit) { + uint16 idx = *ptr++; + if (idx != 0xFF) { + uint16 cnt = *ptr++; + while (cnt--) { + if (idx == 0) { + pal_entry.r = 0; + pal_entry.g = 0; + pal_entry.b = 0; + ptr += 3; + } else { + pal_entry.r = *ptr++ << 10; + pal_entry.g = *ptr++ << 10; + pal_entry.b = *ptr++ << 10; + } + CLPalette_SetRGBColor(_globalPalette, idx, &pal_entry); + idx++; + } + } else + doit = false; + } +} + +// Original name: spritesurbulle +void EdenGame::spriteOnSubtitle(int16 index, int16 x, int16 y) { + byte *pix = _bankData; + byte *scr = _subtitlesViewBuf + x + y * _subtitlesXWidth; + if ((_curBankNum != 117) && (READ_LE_UINT16(pix) > 2)) + readPalette(pix + 2); + + pix += READ_LE_UINT16(pix); + pix += READ_LE_UINT16(pix + index * 2); + // int16 height:9 + // int16 pad:6; + // int16 flag:1; + byte h0 = *pix++; + byte h1 = *pix++; + int16 w = ((h1 & 1) << 8) | h0; + int16 h = *pix++; + byte mode = *pix++; + if (mode != 0xFF && mode != 0xFE) + return; + if (h1 & 0x80) { + // compressed + for (; h-- > 0;) { + for (int16 ww = w; ww > 0;) { + byte c = *pix++; + if (c >= 0x80) { + if (c == 0x80) { + byte fill = *pix++; + if (fill == 0) { + scr += 128 + 1; + ww -= 128 + 1; + } else { + byte runVal; + *scr++ = fill; //TODO: wha? + *scr++ = fill; + ww -= 128 + 1; + for (runVal = 127; runVal--;) + *scr++ = fill; + } + } else { + byte fill = *pix++; + byte runVal = 255 - c + 2; + ww -= runVal; + if (fill == 0) + scr += runVal; + else { + for (; runVal--;) + *scr++ = fill; + } + } + } else { + byte runVal = c + 1; + ww -= runVal; + for (; runVal--;) { + byte p = *pix++; + if (p == 0) + scr++; + else + *scr++ = p; + } + } + } + scr += _subtitlesXWidth - w; + } + } else { + // uncompressed + for (; h--;) { + for (int16 ww = w; ww--;) { + byte p = *pix++; + if (p == 0) + scr++; + else + *scr++ = p; + } + scr += _subtitlesXWidth - w; + } + } +} + +// Original name: bars_out +void EdenGame::hideBars() { + if (_showBlackBars) + return; + + display(); + _underTopBarScreenRect.left = _scrollPos; + _underTopBarScreenRect.right = _scrollPos + 320 - 1; + CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underTopBarScreenRect, &_underTopBarBackupRect); + _underBottomBarScreenRect.left = _underTopBarScreenRect.left; + _underBottomBarScreenRect.right = _underTopBarScreenRect.right; + CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underBottomBarScreenRect, &_underBottomBarBackupRect); + int16 r19 = 14; // TODO - init in decl? + int16 r20 = 176; + int16 r25 = 14; + int16 r24 = 21; + _underTopBarScreenRect.left = 0; + _underTopBarScreenRect.right = 320 - 1; + _underTopBarBackupRect.left = _scrollPos; + _underTopBarBackupRect.right = _scrollPos + 320 - 1; + unsigned int *scr40, *scr41, *scr42; + while (r24 > 0) { + if (r25 > 0) { + _underTopBarScreenRect.top = 16 - r25; + _underTopBarScreenRect.bottom = 16 - 1; + _underTopBarBackupRect.top = 0; + _underTopBarBackupRect.bottom = r25 - 1; + CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect); + scr40 = ((unsigned int *)_mainViewBuf) + r19 * 640 / 4; + scr41 = scr40 + 640 / 4; + for (int i = 0; i < 320; i += 4) { + *scr40++ = 0; + *scr41++ = 0; + } + } + _underTopBarScreenRect.top = 16; + _underTopBarScreenRect.bottom = r24 + 16 - 1; + _underTopBarBackupRect.top = 200 - r24; + _underTopBarBackupRect.bottom = 200 - 1; + CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect); + scr40 = ((unsigned int *)_mainViewBuf) + r20 * 640 / 4; + scr41 = scr40 + 640 / 4; + scr42 = scr41 + 640 / 4; + for (int i = 0; i < 320; i += 4) { + *scr40++ = 0; + *scr41++ = 0; + *scr42++ = 0; + } + r19 -= 2; + r20 += 3; + r25 -= 2; + r24 -= 3; + display(); + } + scr40 = (unsigned int *)_mainViewBuf; + scr41 = scr40 + 640 / 4; + for (int i = 0; i < 320; i += 4) { + *scr40++ = 0; + *scr41++ = 0; + } + scr40 = ((unsigned int *)_mainViewBuf) + r20 * 640 / 4; + scr41 = scr40 + 640 / 4; + scr42 = scr41 + 640 / 4; + for (int i = 0; i < 320; i += 4) { + *scr40++ = 0; + *scr41++ = 0; + *scr42++ = 0; + } + display(); + initRects(); + _showBlackBars = true; +} + +// Original name: bars_in +void EdenGame::showBars() { + if (!_showBlackBars) + return; + + drawBlackBars(); + int16 r29 = 2; + int16 r28 = 2; + _underTopBarScreenRect.left = 0; + _underTopBarScreenRect.right = 320 - 1; + _underTopBarBackupRect.left = _scrollPos; + _underTopBarBackupRect.right = _scrollPos + 320 - 1; + while (r28 < 24) { + if (r29 <= 16) { + _underTopBarScreenRect.top = 16 - r29; + _underTopBarScreenRect.bottom = 16 - 1; + _underTopBarBackupRect.top = 0; + _underTopBarBackupRect.bottom = r29 - 1; + CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect); + } + _underTopBarScreenRect.top = 16; + _underTopBarScreenRect.bottom = 16 + r28; + _underTopBarBackupRect.top = 200 - 1 - r28; + _underTopBarBackupRect.bottom = 200 - 1; + CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect); + r29 += 2; + r28 += 3; + display(); + } + initRects(); + _showBlackBars = false; +} + +// Original name: sauvefondbouche +void EdenGame::saveMouthBackground() { + rect_src.left = _curCharacterRect->left; + rect_src.top = _curCharacterRect->top; + rect_src.right = _curCharacterRect->right; + rect_src.bottom = _curCharacterRect->bottom; + rect_dst.left = _curCharacterRect->left + 320; + rect_dst.top = _curCharacterRect->top; + rect_dst.right = _curCharacterRect->right + 320; + rect_dst.bottom = _curCharacterRect->bottom; + CLBlitter_CopyViewRect(_mainView, _mainView, &rect_src, &rect_dst); + _backgroundSaved = true; +} + +// Original name: restaurefondbouche +void EdenGame::restoreMouthBackground() { + rect_src.left = _curCharacterRect->left; + rect_src.top = _curCharacterRect->top; + rect_src.right = _curCharacterRect->right; + rect_src.bottom = _curCharacterRect->bottom; + rect_dst.left = _curCharacterRect->left + 320; + rect_dst.top = _curCharacterRect->top; + rect_dst.right = _curCharacterRect->right + 320; + rect_dst.bottom = _curCharacterRect->bottom; + CLBlitter_CopyViewRect(_mainView, _mainView, &rect_dst, &rect_src); +} + +// Original name : blackbars +void EdenGame::drawBlackBars() { + byte *scr = _mainViewBuf; + for (int16 y = 0; y < 16; y++) { + for (int16 x = 0; x < 640; x++) + *scr++ = 0; + } + + scr += 640 * (200 - 16 - 24); + for (int16 y = 0; y < 24; y++) { + for (int16 x = 0; x < 640; x++) + *scr++ = 0; + } +} + +void EdenGame::drawTopScreen() { // Draw top bar (location / party / map) + _globals->_drawFlags &= ~DrawFlags::drDrawTopScreen; + useBank(314); + noclipax(36, 83, 0); + noclipax(_globals->_areaPtr->_num - 1, 0, 0); + noclipax(23, 145, 0); + for (perso_t *perso = &kPersons[PER_DINA]; perso != &kPersons[PER_UNKN_156]; perso++) { + if ((perso->_flags & PersonFlags::pfInParty) && !(perso->_flags & PersonFlags::pf80)) + noclipax(perso->_targetLoc + 18, perso->_lastLoc + 120, 0); + } + _adamMapMarkPos.x = -1; + _adamMapMarkPos.y = -1; + displayValleyMap(); + _paletteUpdateRequired = true; +} + +// Original name: affplanval +void EdenGame::displayValleyMap() { // Draw mini-map + if (_globals->_areaPtr->_type == AreaType::atValley) { + noclipax(_globals->_areaPtr->_num + 9, 266, 1); + for (perso_t *perso = &kPersons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) { + if (((perso->_roomNum >> 8) == _globals->_areaNum) + && !(perso->_flags & PersonFlags::pf80) && (perso->_flags & PersonFlags::pf20)) + displayMapMark(33, perso->_roomNum & 0xFF); + } + if (_globals->_areaPtr->_citadelLevel) + displayMapMark(34, _globals->_areaPtr->_citadelRoomPtr->_location); + saveTopFrieze(0); + int16 loc = _globals->_roomNum & 0xFF; + if (loc >= 16) + displayAdamMapMark(loc); + restoreTopFrieze(); + } else { + saveTopFrieze(0); + restoreTopFrieze(); + } +} + +// Original name: affrepere +void EdenGame::displayMapMark(int16 index, int16 location) { + noclipax(index, 269 + location % 16 * 4, 2 + (location - 16) / 16 * 3); +} + +// Original name: affrepereadam +void EdenGame::displayAdamMapMark(int16 location) { + int16 x = 269; + int16 y = 2; + restoreAdamMapMark(); + if (location > 15 && location < 76) { + x += (location & 15) * 4; + y += ((location - 16) >> 4) * 3; + saveAdamMapMark(x, y); + byte *pix = _underBarsView->_bufferPtr; + int16 w = _underBarsView->_width; + pix += x + w * y; + pix[1] = 0xC3; + pix[2] = 0xC3; + pix += w; + pix[0] = 0xC3; + pix[1] = 0xC3; + pix[2] = 0xC3; + pix[3] = 0xC3; + pix += w; + pix[1] = 0xC3; + pix[2] = 0xC3; + } +} + +// Original name: rest_repadam +void EdenGame::restoreAdamMapMark() { + if (_adamMapMarkPos.x == -1 && _adamMapMarkPos.y == -1) + return; + + int16 x = _adamMapMarkPos.x; + int16 y = _adamMapMarkPos.y; + byte *pix = _underBarsView->_bufferPtr; + int16 w = _underBarsView->_width; + pix += x + w * y; + pix[1] = _oldPix[0]; + pix[2] = _oldPix[1]; + pix += w; + pix[0] = _oldPix[2]; + pix[1] = _oldPix[3]; + pix[2] = _oldPix[4]; + pix[3] = _oldPix[5]; + pix += w; + pix[1] = _oldPix[6]; + pix[2] = _oldPix[7]; +} + +// Original name: save_repadam +void EdenGame::saveAdamMapMark(int16 x, int16 y) { + _adamMapMarkPos.x = x; + _adamMapMarkPos.y = y; + byte *pix = _underBarsView->_bufferPtr; + int16 w = _underBarsView->_width; + pix += x + w * y; + _oldPix[0] = pix[1]; + _oldPix[1] = pix[2]; + pix += w; + _oldPix[2] = pix[0]; + _oldPix[3] = pix[1]; + _oldPix[4] = pix[2]; + _oldPix[5] = pix[3]; + pix += w; + _oldPix[6] = pix[1]; + _oldPix[7] = pix[2]; +} + +bool EdenGame::istrice(int16 roomNum) { + char loc = roomNum & 0xFF; + int16 area = roomNum & 0xFF00; + for (perso_t *perso = &kPersons[PER_UNKN_18C]; perso != &kPersons[PER_UNKN_372]; perso++) { + if ((perso->_flags & PersonFlags::pf80) || (perso->_flags & PersonFlags::pfTypeMask) != PersonFlags::pftTriceraptor) + continue; + if (perso->_roomNum == (area | (loc - 16))) + return true; + if (perso->_roomNum == (area | (loc + 16))) + return true; + if (perso->_roomNum == (area | (loc - 1))) + return true; + if (perso->_roomNum == (area | (loc + 1))) + return true; + } + return false; +} + +bool EdenGame::istyran(int16 roomNum) { + char loc = roomNum & 0xFF; + int16 area = roomNum & 0xFF00; + // TODO: orig bug: this ptr is not initialized when first called from getsalle + // PC version scans kPersons[] directly and is not affected + if (!_tyranPtr) + return false; + + for (; _tyranPtr->_roomNum != 0xFFFF; _tyranPtr++) { + if (_tyranPtr->_flags & PersonFlags::pf80) + continue; + if (_tyranPtr->_roomNum == (area | (loc - 16))) + return true; + if (_tyranPtr->_roomNum == (area | (loc + 16))) + return true; + if (_tyranPtr->_roomNum == (area | (loc - 1))) + return true; + if (_tyranPtr->_roomNum == (area | (loc + 1))) + return true; + } + return false; +} + +void EdenGame::istyranval(Area *area) { + byte areaNum = area->_num; + area->_flags &= ~AreaFlags::HasTyrann; + for (perso_t *perso = &kPersons[PER_UNKN_372]; perso->_roomNum != 0xFFFF; perso++) { + if (perso->_flags & PersonFlags::pf80) + continue; + + if ((perso->_roomNum >> 8) == areaNum) { + area->_flags |= AreaFlags::HasTyrann; + break; + } + } +} + +char EdenGame::getDirection(perso_t *perso) { + char dir = -1; + byte trgLoc = perso->_targetLoc; + byte curLoc = perso->_roomNum & 0xFF; //TODO name + if (curLoc != trgLoc) { + curLoc &= 0xF; + trgLoc &= 0xF; + if (curLoc != trgLoc) { + dir = 2; + if (curLoc > trgLoc) + dir = 5; + } + trgLoc = perso->_targetLoc; + curLoc = perso->_roomNum & 0xFF; + curLoc &= 0xF0; + trgLoc &= 0xF0; + if (curLoc != trgLoc) { + if (curLoc > trgLoc) + dir++; + dir++; + } + } + return dir; +} + +// Original name: caselibre +bool EdenGame::canMoveThere(char loc, perso_t *perso) { + Room *room = _globals->_citaAreaFirstRoom; + if (loc <= 0x10 || loc > 76 || (loc & 0xF) >= 12 || loc == perso->_lastLoc) + return false; + + int16 roomNum = (perso->_roomNum & ~0xFF) | loc; //TODO: danger! signed + if (roomNum == _globals->_roomNum) + return false; + + for (; room->_id != 0xFF; room++) { + if (room->_location != loc) + continue; + if (!(room->_flags & RoomFlags::rf01)) + return false; + for (perso = &kPersons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) { + if (perso->_flags & PersonFlags::pf80) + continue; + if (perso->_roomNum == roomNum) + break; + } + if (perso->_roomNum != 0xFFFF) + return false; + return true; + } + return false; +} + +// Original name: melange1 +void EdenGame::scramble1(uint8 elem[4]) { + if (_vm->_rnd->getRandomNumber(1) & 1) + SWAP(elem[1], elem[2]); +} + +// Original name melange2 +void EdenGame::scramble2(uint8 elem[4]) { + if (_vm->_rnd->getRandomNumber(1) & 1) + SWAP(elem[0], elem[1]); + + if (_vm->_rnd->getRandomNumber(1) & 1) + SWAP(elem[2], elem[3]); +} + +// Original name: melangedir +void EdenGame::scrambleDirections() { + scramble1(tab_2CB1E[0]); + scramble1(tab_2CB1E[1]); + scramble1(tab_2CB1E[2]); + scramble2(tab_2CB1E[3]); + scramble2(tab_2CB1E[4]); + scramble1(tab_2CB1E[5]); + scramble2(tab_2CB1E[6]); + scramble2(tab_2CB1E[7]); +} + +bool EdenGame::naitredino(char persoType) { + for (perso_t *perso = &kPersons[PER_MORKUS]; (++perso)->_roomNum != 0xFFFF;) { + char areaNum = perso->_roomNum >> 8; + if (areaNum != _globals->_citadelAreaNum) + continue; + if ((perso->_flags & PersonFlags::pf80) && (perso->_flags & PersonFlags::pfTypeMask) == persoType) { + perso->_flags &= ~PersonFlags::pf80; + return true; + } + } + return false; +} + +// Original name: newcita +void EdenGame::newCitadel(char area, int16 level, Room *room) { + Citadel *cita = _citadelList; + while (cita->_id < level) + cita++; + + uint16 index = ((room->_flags & 0xC0) >> 6); //TODO: this is very wrong + if (area == 4 || area == 6) + index++; + + room->_bank = cita->_bank[index]; + room->_video = cita->_video[index]; + room->_flags |= RoomFlags::rf02; +} + +// Original name: citaevol +void EdenGame::evolveCitadel(int16 level) { + Room *room = _globals->_curAreaPtr->_citadelRoomPtr; + perso_t *perso = &kPersons[PER_UNKN_372]; + byte loc = room->_location; + if (level >= 80 && !istrice((_globals->_citadelAreaNum << 8) | loc)) { + room->_level = 79; + return; + } + + if (level > 160) + level = 160; + + if (room->_level < 64 && level >= 64 && naitredino(PersonFlags::pftTriceraptor)) { + _globals->_curAreaPtr->_flags |= AreaFlags::HasTriceraptors; + addInfo(_globals->_citadelAreaNum + ValleyNews::vnTriceraptorsIn); + } + if (room->_level < 40 && level >= 40 && naitredino(PersonFlags::pftVelociraptor)) { + _globals->_curAreaPtr->_flags |= AreaFlags::HasVelociraptors; + addInfo(_globals->_citadelAreaNum + ValleyNews::vnVelociraptorsIn); + } + room->_level = level; + newCitadel(_globals->_citadelAreaNum, level, room); + byte speed = kDinoSpeedForCitaLevel[room->_level >> 4]; + for (; perso->_roomNum != 0xFFFF; perso++) { + if (perso->_flags & PersonFlags::pf80) + continue; + if ((perso->_roomNum >> 8) == _globals->_citadelAreaNum && perso->_targetLoc == loc) + perso->_speed = speed; + } +} + +// Original name: citacapoute +void EdenGame::destroyCitadelRoom(int16 roomNum) { + perso_t *perso = &kPersons[PER_UNKN_18C]; + Room *room = _globals->_curAreaPtr->_citadelRoomPtr; + room->_flags |= RoomFlags::rf01; + room->_flags &= ~RoomFlags::rfHasCitadel; + room->_bank = 193; + room->_video = 0; + room->_level = 0; + _globals->_curAreaPtr->_citadelLevel = 0; + _globals->_curAreaPtr->_citadelRoomPtr = 0; + roomNum = (roomNum & ~0xFF) | room->_location; + for (; perso->_roomNum != 0xFFFF; perso++) { + if (perso->_roomNum == roomNum) { + perso->_flags &= ~PersonFlags::pf80; + removeInfo((roomNum >> 8) + ValleyNews::vnTyrannIn); + break; + } + } +} + +// Original name: buildcita +void EdenGame::narratorBuildCitadel() { + Area *area = _globals->_areaPtr; + _globals->_curAreaPtr = _globals->_areaPtr; + if (area->_citadelRoomPtr) + destroyCitadelRoom(_globals->_roomNum); + _globals->_var6A = _globals->_var69; + _globals->_narratorSequence = _globals->_var69 | 0x80; + area->_citadelRoomPtr = _globals->_roomPtr; + _globals->_roomPtr->_flags &= ~RoomFlags::rf01; + _globals->_roomPtr->_flags |= RoomFlags::rfHasCitadel; + _globals->_roomPtr->_level = 32; + newCitadel(_globals->_areaNum, 32, _globals->_roomPtr); + area->_flags &= ~AreaFlags::TyrannSighted; + if (!(area->_flags & AreaFlags::afFlag8000)) { + if (_globals->_phaseNum == 304 || _globals->_phaseNum != 384) //TODO: wha + handleEloiReturn(); + area->_flags |= AreaFlags::afFlag8000; + } + _globals->_roomCharacterPtr->_flags |= PersonFlags::pf80; + _globals->_citadelAreaNum = _globals->_areaNum; + naitredino(1); + removeInfo(_globals->_areaNum + ValleyNews::vnCitadelLost); + removeInfo(_globals->_areaNum + ValleyNews::vnTyrannLost); + if (_globals->_phaseNum == 193 && _globals->_areaNum == Areas::arUluru) + bigphase1(); +} + +// Original name: citatombe +void EdenGame::citadelFalls(char level) { + if (level) + newCitadel(_globals->_citadelAreaNum, level, _globals->_curAreaPtr->_citadelRoomPtr); + else { + destroyCitadelRoom(_globals->_citadelAreaNum << 8); + addInfo(_globals->_citadelAreaNum + ValleyNews::vnCitadelLost); + } +} + +// Original name: constcita +void EdenGame::buildCitadel() { + if (!_globals->_curAreaPtr->_citadelLevel || !_globals->_curAreaPtr->_citadelRoomPtr) + return; + + Room *room = _globals->_curAreaPtr->_citadelRoomPtr; + byte loc = room->_location; + _tyranPtr = &kPersons[PER_UNKN_372]; + if (istyran((_globals->_citadelAreaNum << 8) | loc)) { + if (!(_globals->_curAreaPtr->_flags & AreaFlags::TyrannSighted)) { + addInfo(_globals->_citadelAreaNum + ValleyNews::vnTyrannIn); + _globals->_curAreaPtr->_flags |= AreaFlags::TyrannSighted; + } + byte level = room->_level - 1; + if (level < 32) + level = 32; + room->_level = level; + citadelFalls(level); + } else { + _globals->_curAreaPtr->_flags &= ~AreaFlags::TyrannSighted; + evolveCitadel(room->_level + 1); + } +} + +// Original name: depladino +void EdenGame::moveDino(perso_t *perso) { + int dir = getDirection(perso); + if (dir != -1) { + scrambleDirections(); + uint8 *dirs = tab_2CB1E[dir]; + byte loc = perso->_roomNum & 0xFF; + uint8 dir2 = dirs[0]; + if (dir2 & 0x80) + dir2 = -(dir2 & ~0x80); + dir2 += loc; + if (!canMoveThere(dir2, perso)) { + dir2 = dirs[1]; + if (dir2 & 0x80) + dir2 = -(dir2 & ~0x80); + dir2 += loc; + if (!canMoveThere(dir2, perso)) { + dir2 = dirs[2]; + if (dir2 & 0x80) + dir2 = -(dir2 & ~0x80); + dir2 += loc; + if (!canMoveThere(dir2, perso)) { + dir2 = dirs[3]; + if (dir2 & 0x80) + dir2 = -(dir2 & ~0x80); + dir2 += loc; + if (!canMoveThere(dir2, perso)) { + dir2 = perso->_lastLoc; + perso->_lastLoc = 0; + if (!canMoveThere(dir2, perso)) + return; + } + } + } + } + + perso->_lastLoc = perso->_roomNum & 0xFF; + perso->_roomNum &= ~0xFF; + perso->_roomNum |= dir2 & 0xFF; + if ((perso->_targetLoc - 16 == (perso->_roomNum & 0xFF)) + || (perso->_targetLoc + 16 == (perso->_roomNum & 0xFF)) + || (perso->_targetLoc - 1 == (perso->_roomNum & 0xFF)) + || (perso->_targetLoc + 1 == (perso->_roomNum & 0xFF))) + perso->_targetLoc = 0; + } else + perso->_targetLoc = 0; +} + +// Original name: deplaalldino +void EdenGame::moveAllDino() { + for (perso_t *perso = &kPersons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) { + if (((perso->_roomNum >> 8) & 0xFF) != _globals->_citadelAreaNum) + continue; + if ((perso->_flags & PersonFlags::pf80) || !perso->_targetLoc) + continue; + if (--perso->_steps) + continue; + perso->_steps = 1; + if (perso->_roomNum == _globals->_roomNum) + continue; + perso->_steps = perso->_speed; + moveDino(perso); + } +} + +// Original name: newvallee +void EdenGame::newValley() { + static int16 roomNumList[] = { 2075, 2080, 2119, -1}; + + perso_t *perso = &kPersons[PER_UNKN_372]; + int16 *ptr = roomNumList; + int16 roomNum = *ptr++; + while (roomNum != -1) { + perso->_roomNum = roomNum; + perso->_flags &= ~PersonFlags::pf80; + perso->_flags &= ~PersonFlags::pf20; + perso++; + roomNum = *ptr++; + } + perso->_roomNum = 0xFFFF; + kAreasTable[7]._flags |= AreaFlags::HasTyrann; + _globals->_worldHasTyran = 32; +} + +char EdenGame::whereIsCita() { + char res = (char)-1; + for (Room *room = _globals->_citaAreaFirstRoom; room->_id != 0xFF; room++) { + if (!(room->_flags & RoomFlags::rfHasCitadel)) + continue; + res = room->_location; + break; + } + return res; +} + +bool EdenGame::isCita(int16 loc) { + loc &= 0xFF; + for (Room *room = _globals->_citaAreaFirstRoom; room->_id != 0xFF; room++) { + if (!(room->_flags & RoomFlags::rfHasCitadel)) + continue; + + if ((room->_location == loc + 16) + || (room->_location == loc - 16) + || (room->_location == loc - 1) + || (room->_location == loc + 1)) + return true; + } + return false; +} + +// Original name: lieuvava +void EdenGame::placeVava(Area *area) { + if (area->_type == AreaType::atValley) { + istyranval(area); + area->_citadelLevel = 0; + if (area->_citadelRoomPtr) + area->_citadelLevel = _globals->_citaAreaFirstRoom->_level; //TODO: no search? + byte mask = ~(1 << (area->_num - Areas::arChamaar)); + _globals->_worldTyranSighted &= mask; + _globals->_var4E &= mask; + _globals->_worldGaveGold &= mask; + _globals->_worldHasVelociraptors &= mask; + _globals->_worldHasTriceraptors &= mask; + _globals->_worldHasTyran &= mask; + _globals->_var53 &= mask; + mask = ~mask; + if (area->_flags & AreaFlags::TyrannSighted) + _globals->_worldTyranSighted |= mask; + if (area->_flags & AreaFlags::afFlag4) + _globals->_var4E |= mask; + if (area->_flags & AreaFlags::HasTriceraptors) + _globals->_worldHasTriceraptors |= mask; + if (area->_flags & AreaFlags::afGaveGold) + _globals->_worldGaveGold |= mask; + if (area->_flags & AreaFlags::HasVelociraptors) + _globals->_worldHasVelociraptors |= mask; + if (area->_flags & AreaFlags::HasTyrann) + _globals->_worldHasTyran |= mask; + if (area->_flags & AreaFlags::afFlag20) + _globals->_var53 |= mask; + if (area == _globals->_areaPtr) { + _globals->_curAreaFlags = area->_flags; + _globals->_curCitadelLevel = area->_citadelLevel; + } + } + _globals->_var4D &= _globals->_worldTyranSighted; +} + +void EdenGame::vivredino() { + for (perso_t *perso = &kPersons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) { + if (((perso->_roomNum >> 8) & 0xFF) != _globals->_citadelAreaNum) + continue; + if (perso->_flags & PersonFlags::pf80) + continue; + switch (perso->_flags & PersonFlags::pfTypeMask) { + case PersonFlags::pftTyrann: + if (isCita(perso->_roomNum)) + perso->_targetLoc = 0; + else if (!perso->_targetLoc) { + char cita = whereIsCita(); + if (cita != (char)-1) { + perso->_targetLoc = cita; + perso->_speed = 2; + perso->_steps = 1; + } + } + break; + case PersonFlags::pftTriceraptor: + if (perso->_flags & PersonFlags::pfInParty) { + if (isCita(perso->_roomNum)) + perso->_targetLoc = 0; + else if (!perso->_targetLoc) { + char cita = whereIsCita(); + if (cita != (char)-1) { + perso->_targetLoc = cita; + perso->_speed = 3; + perso->_steps = 1; + } + } + } + break; + case PersonFlags::pftVelociraptor: + if (perso->_flags & PersonFlags::pf10) { + if (perso->_roomNum == _globals->_roomNum) { + perso_t *perso2 = &kPersons[PER_UNKN_372]; + bool found = false; + for (; perso2->_roomNum != 0xFFFF; perso2++) { + if ((perso->_roomNum & ~0xFF) == (perso2->_roomNum & ~0xFF)) { + if (perso2->_flags & PersonFlags::pf80) + continue; + perso->_targetLoc = perso2->_roomNum & 0xFF; + perso->_steps = 1; + found = true; + break; + } + } + if (found) + continue; + } else { + _tyranPtr = &kPersons[PER_UNKN_372]; + if (istyran(perso->_roomNum)) { + if (_globals->_phaseNum < 481 && (perso->_powers & (1 << (_globals->_citadelAreaNum - 3)))) { + _tyranPtr->_flags |= PersonFlags::pf80; + _tyranPtr->_roomNum = 0; + perso->_flags &= ~PersonFlags::pf10; + perso->_flags |= PersonFlags::pfInParty; + addInfo(_globals->_citadelAreaNum + ValleyNews::vnTyrannLost); + removeInfo(_globals->_citadelAreaNum + ValleyNews::vnTyrannIn); + if (naitredino(PersonFlags::pftTriceraptor)) + addInfo(_globals->_citadelAreaNum + ValleyNews::vnTriceraptorsIn); + buildCitadel(); + _globals->_curAreaPtr->_flags &= ~AreaFlags::TyrannSighted; + } else { + perso->_flags &= ~PersonFlags::pf10; + perso->_flags &= ~PersonFlags::pfInParty; + addInfo(_globals->_citadelAreaNum + ValleyNews::vnVelociraptorsLost); + } + continue; + } + } + } + if (!perso->_targetLoc) { + int16 loc; + perso->_lastLoc = 0; + do { + loc = (_vm->_rnd->getRandomNumber(63) & 63) + 16; + if ((loc & 0xF) >= 12) + loc &= ~4; //TODO: ??? same as -= 4 + } while (!canMoveThere(loc, perso)); + perso->_targetLoc = loc; + perso->_steps = 1; + } + break; + } + } +} + +void EdenGame::vivreval(int16 areaNum) { + _globals->_citadelAreaNum = areaNum; + _globals->_curAreaPtr = &kAreasTable[areaNum - 1]; + _globals->_citaAreaFirstRoom = &_gameRooms[_globals->_curAreaPtr->_firstRoomIdx]; + moveAllDino(); + buildCitadel(); + vivredino(); + newMushroom(); + newNestWithEggs(); + newEmptyNest(); + if (_globals->_phaseNum >= 226) + newGold(); + placeVava(_globals->_curAreaPtr); +} + +// Original name: chaquejour +void EdenGame::handleDay() { + vivreval(3); + vivreval(4); + vivreval(5); + vivreval(6); + vivreval(7); + vivreval(8); + _globals->_drawFlags |= DrawFlags::drDrawTopScreen; +} + +// Original name: temps_passe +void EdenGame::addTime(int16 t) { + int16 days = _globals->_gameDays; + int16 lo = _globals->_gameHours + t; + if (lo > 255) { + days++; + lo &= 0xFF; + } + + _globals->_gameHours = lo; + t = ((t >> 8) & 0xFF) + days; + t -= _globals->_gameDays; + if (t) { + _globals->_gameDays += t; + while (t--) + handleDay(); + } +} + +// Original name: anim_perso +void EdenGame::animCharacter() { + if (_curBankNum != _globals->_characterImageBank) + loadCharacter(_globals->_characterPtr); + restoreUnderSubtitles(); + if (_restartAnimation) { + _lastAnimTicks = _vm->_timerTicks; + _restartAnimation = false; + } + _curAnimFrameNumb = (_vm->_timerTicks - _lastAnimTicks) >> 2; // TODO: check me!!! + if (_curAnimFrameNumb > _numAnimFrames) // TODO: bug? + _animateTalking = false; + if (_globals->_curCharacterAnimPtr && !_globals->_animationFlags && _curAnimFrameNumb != _lastAnimFrameNumb) { + _lastAnimFrameNumb = _curAnimFrameNumb; + if (*_globals->_curCharacterAnimPtr == 0xFF) + getanimrnd(); + useCharacterBank(); + _numImgDesc = 0; + setCharacterSprite(_globals->_curCharacterAnimPtr); + _globals->_curCharacterAnimPtr += _numImgDesc + 1; + _mouthAnimations = _imageDesc + 200; + removeMouthSprite(); + if (*_mouthAnimations) + displayImage(); + _animationDelay--; + if (!_animationDelay) { + _globals->_animationFlags = 1; + _animationDelay = 8; + } + } + + _animationDelay--; + if (!_animationDelay) { + getanimrnd(); + //TODO: no reload? + } + if (_animateTalking) { + if (!_animationTable) { + _animationTable = _gameLipsync + 7262; //TODO: fix me + if (!_backgroundSaved) + saveMouthBackground(); + } + if (!_personTalking) + _curAnimFrameNumb = _numAnimFrames - 1; + _animationIndex = _animationTable[_curAnimFrameNumb]; + if (_animationIndex == 0xFF) + _animateTalking = false; + else if (_animationIndex != _lastAnimationIndex) { + useCharacterBank(); + restoreMouthBackground(); +// debug("perso spr %d", animationIndex); + setCharacterSprite(_globals->_persoSpritePtr2 + _animationIndex * 2); //TODO: int16s? + _mouthAnimations = _imageDesc + 200; + if (*_mouthAnimations) + displayImage(); + _lastAnimationIndex = _animationIndex; + } + } + displaySubtitles(); +} + +void EdenGame::getanimrnd() { + _animationDelay = 8; + int16 rnd = _vm->_rnd->getRandomNumber(65535) & (byte)~0x18; //TODO + dword_30724 = _globals->_persoSpritePtr + 16; //TODO + _globals->_curCharacterAnimPtr = _globals->_persoSpritePtr + ((dword_30724[1] << 8) + dword_30724[0]); + _globals->_animationFlags = 1; + if (rnd >= 8) + return; + _globals->_animationFlags = 0; + if (rnd <= 0) + return; + for (rnd *= 8; rnd > 0; rnd--) { + while (*_globals->_curCharacterAnimPtr) + _globals->_curCharacterAnimPtr++; + _globals->_curCharacterAnimPtr++; + } +} + +void EdenGame::addanim() { + _lastAnimationIndex = 0xFF; + _lastAnimTicks = 0; + _globals->_animationFlags = 0xC0; + _globals->_curCharacterAnimPtr = _globals->_persoSpritePtr; + getanimrnd(); + _animationActive = true; + if (_globals->_characterPtr == &kPersons[PER_KING]) + return; + setCharacterSprite(_globals->_persoSpritePtr + READ_LE_UINT16(_globals->_persoSpritePtr)); //TODO: GetElem(0) + _mouthAnimations = _imageDesc + 200; + if (_globals->_characterPtr->_id != PersonId::pidCabukaOfCantura && _globals->_characterPtr->_targetLoc != 7) //TODO: targetLoc is minisprite idx + removeMouthSprite(); + if (*_mouthAnimations) + displayImage(); +} + +// Original name: virespritebouche +void EdenGame::removeMouthSprite() { + byte *src = _mouthAnimations + 2; + byte *dst = src; + char cnt = _mouthAnimations[0]; + while (cnt--) { + byte a = *src++; + byte b = *src++; + byte c = *src++; + dst[0] = a; + dst[1] = b; + dst[2] = c; + if (dword_30728[0] != 0xFF) { + if ((a < dword_30728[0] || a > dword_30728[1]) + && (a < dword_30728[2] || a > dword_30728[3])) + dst += 3; + else + _mouthAnimations[0]--; + } else + dst += 3; + } +} + +// Original name: anim_perfin +void EdenGame::AnimEndCharacter() { + _globals->_animationFlags &= ~0x80; + _animationDelay = 0; + _animationActive = false; +} + +// Original name: perso_spr +void EdenGame::setCharacterSprite(byte *spr) { + byte *img = _imageDesc + 200 + 2; + int16 count = 0; + byte c; + while ((c = *spr++)) { + byte *src; + int16 index = 0; + byte cc = 0; + if (c == 1) { + cc = index; + c = *spr++; + } + _numImgDesc++; + index = (cc << 8) | c; + index -= 2; + + if (index > _maxPersoDesc) + index = _maxPersoDesc; + index *= 2; //TODO: src = GetElem(ff_C2, index) + src = _globals->_varC2; + src += READ_LE_UINT16(src + index); + while ((c = *src++)) { + *img++ = c; + *img++ = *src++; + *img++ = *src++; + count++; + } + } + _imageDesc[200] = count & 0xFF; + _imageDesc[201] = count >> 8; +} + +// Original name: af_image +void EdenGame::displayImage() { + byte *img = _imageDesc + 200; + + int16 count = READ_LE_UINT16(img); + if (!count) + return; + + byte *img_start = img; + byte *curimg = _imageDesc; + + img += 2; + count *= 3; + while (count--) + *curimg++ = *img++; + img = img_start; + count = READ_LE_UINT16(img); + img += 2; + /////// draw it + while (count--) { + uint16 index = *img++; + uint16 x = *img++ + _gameIcons[0].sx; + uint16 y = *img++ + _gameIcons[0].sy; + byte *pix = _bankData; + byte *scr = _mainViewBuf + x + y * 640; + index--; + if (READ_LE_UINT16(pix) > 2) + readPalette(pix + 2); + pix += READ_LE_UINT16(pix); + pix += READ_LE_UINT16(pix + index * 2); + // int16 height:9 + // int16 pad:6; + // int16 flag:1; + byte h0 = *pix++; + byte h1 = *pix++; + int16 w = ((h1 & 1) << 8) | h0; + int16 h = *pix++; + byte mode = *pix++; + if (mode != 0xFF && mode != 0xFE) + continue; //TODO: enclosing block? + if (h1 & 0x80) { + // compressed + for (; h-- > 0;) { + for (int16 ww = w; ww > 0;) { + byte c = *pix++; + if (c >= 0x80) { + if (c == 0x80) { + byte fill = *pix++; + if (fill == 0) { + scr += 128 + 1; + ww -= 128 + 1; + } else { + byte runVal; + *scr++ = fill; //TODO: wha? + *scr++ = fill; + ww -= 128 + 1; + for (runVal = 127; runVal--;) + *scr++ = fill; + } + } else { + byte fill = *pix++; + byte runVal = 255 - c + 2; + ww -= runVal; + if (fill == 0) + scr += runVal; + else { + for (; runVal--;) + *scr++ = fill; + } + } + } else { + byte runVal = c + 1; + ww -= runVal; + for (; runVal--;) { + byte p = *pix++; + if (p == 0) + scr++; + else + *scr++ = p; + } + } + } + scr += 640 - w; + } + } else { + // uncompressed + for (; h--;) { + for (int16 ww = w; ww--;) { + byte p = *pix++; + if (p == 0) + scr++; + else + *scr++ = p; + } + scr += 640 - w; + } + } + } +} + +// Original name: af_perso1 +void EdenGame::displayCharacter1() { + setCharacterSprite(_globals->_persoSpritePtr + READ_LE_UINT16(_globals->_persoSpritePtr)); + displayImage(); +} + +// Original name: af_perso +void EdenGame::displayCharacter() { + loadCurrCharacter(); + displayCharacter1(); +} + +void EdenGame::ef_perso() { + _globals->_animationFlags &= 0x3F; +} + +// Original name: load_perso +void EdenGame::loadCharacter(perso_t *perso) { + _characterBankData = nullptr; + if (!perso->_spriteBank) + return; + + if (perso->_spriteBank != _globals->_characterImageBank) { + _curCharacterRect = &_characterRects[perso->_id]; //TODO: array of int16? + dword_30728 = _characterArray[perso->_id]; + ef_perso(); + _globals->_characterImageBank = perso->_spriteBank; + useBank(_globals->_characterImageBank); + _characterBankData = _bankData; + byte *ptr = _bankData; + ptr += READ_LE_UINT16(ptr); + byte *baseptr = ptr; + ptr += READ_LE_UINT16(ptr) - 2; + ptr = baseptr + READ_LE_UINT16(ptr) + 4; + _gameIcons[0].sx = READ_LE_UINT16(ptr); + _gameIcons[0].sy = READ_LE_UINT16(ptr + 2); + _gameIcons[0].ex = READ_LE_UINT16(ptr + 4); + _gameIcons[0].ey = READ_LE_UINT16(ptr + 6); + ptr += 8; + _globals->_varC2 = ptr + 2; + _maxPersoDesc = READ_LE_UINT16(ptr) / 2; + ptr += READ_LE_UINT16(ptr); + baseptr = ptr; + ptr += READ_LE_UINT16(ptr) - 2; + _globals->_persoSpritePtr = baseptr; + _globals->_persoSpritePtr2 = baseptr + READ_LE_UINT16(ptr); + debug("load perso: b6 len is %ld", _globals->_persoSpritePtr2 - _globals->_persoSpritePtr); + } else { + useBank(_globals->_characterImageBank); + _characterBankData = _bankData; + } +} + +// Original name: load_perso_cour +void EdenGame::loadCurrCharacter() { + loadCharacter(_globals->_characterPtr); +} + +void EdenGame::fin_perso() { + _globals->_animationFlags &= 0x3F; + _globals->_curCharacterAnimPtr = nullptr; + _globals->_varCA = 0; + _globals->_characterImageBank = -1; + AnimEndCharacter(); +} + +void EdenGame::no_perso() { + if (_globals->_displayFlags == DisplayFlags::dfPerson) { + _globals->_displayFlags = _globals->_oldDisplayFlags; + fin_perso(); + } + endCharacterSpeech(); +} + +// Original name: close_perso +void EdenGame::closeCharacterScreen() { + endCharacterSpeech(); + if (_globals->_displayFlags == DisplayFlags::dfPerson && _globals->_characterPtr->_id != PersonId::pidNarrator && _globals->_eventType != EventType::etEventE) { + rundcurs(); + _savedUnderSubtitles = true; + restoreUnderSubtitles(); + display(); + _globals->_var103 = 16; + } + if (_globals->_characterPtr->_id == PersonId::pidNarrator) + _globals->_var103 = 69; + _globals->_eloiHaveNews &= 1; + _globals->_varCA = 0; + _globals->_varF6 = 0; + if (_globals->_displayFlags == DisplayFlags::dfPerson) { + _globals->_displayFlags = _globals->_oldDisplayFlags; + _globals->_animationFlags &= 0x3F; + _globals->_curCharacterAnimPtr = nullptr; + AnimEndCharacter(); + if (_globals->_displayFlags & DisplayFlags::dfMirror) { + gameToMirror(1); + _scrollPos = _oldScrollPos; + scroll(); + return; + } + if (_globals->_numGiveObjs) { + if (!(_globals->_displayFlags & DisplayFlags::dfFlag2)) + showObjects(); + _globals->_numGiveObjs = 0; + } + if (_globals->_varF2 & 1) { + _globals->_mirrorEffect = 6; // CHECKME: Verify the value + _globals->_varF2 &= ~1; + } + char oldLoc = _globals->_newLocation; + _globals->_newLocation = 0; + if (!(_globals->_narratorSequence & 0x80)) + _globals->_var100 = 0xFF; + updateRoom(_globals->_roomNum); + _globals->_newLocation = oldLoc; + } + + if (_globals->_chrono) + _globals->_chronoFlag = 1; +} + +// Original name: af_fondsuiveur +void EdenGame::displayBackgroundFollower() { + char id = _globals->_characterPtr->_id; + for (Follower *follower = followerList; follower->_id != -1; follower++) { + if (follower->_id == id) { + int bank = 326; + if (follower->sx >= 320) + bank = 327; + useBank(bank + _globals->_roomBackgroundBankNum); + noclipax_avecnoir(0, 0, 16); + break; + } + } +} + +void EdenGame::displayNoFollower(int16 bank) { + if (bank) { + useBank(bank); + if (_globals->_characterPtr == &kPersons[PER_UNKN_156]) + noclipax_avecnoir(0, 0, 16); + else + noclipax(0, 0, 16); + } +} + +// Original name: af_fondperso1 +void EdenGame::displayCharacterBackground1() { + byte bank; + char *ptab; + if (_globals->_characterPtr == &kPersons[PER_ELOI]) { + _gameIcons[0].sx = 0; + _characterRects[PER_ELOI].left = 2; + bank = _globals->_characterBackgroundBankIdx; + if (_globals->_eventType == EventType::etEventE) { + _globals->_var103 = 1; + displayNoFollower(bank); + return; + } + _gameIcons[0].sx = 60; + _characterRects[PER_ELOI].left = 62; + } + if (_globals->_characterPtr == &kPersons[PER_TAU]) { + bank = 37; + if (_globals->_curObjectId == Objects::obShell) { + displayNoFollower(bank); + return; + } + } + ptab = kPersoRoomBankTable + _globals->_characterPtr->_roomBankId; + bank = *ptab++; + if (!(_globals->_characterPtr->_partyMask & _globals->_party)) { + while ((bank = *ptab++) != 0xFF) { + if (bank == (_globals->_roomNum & 0xFF)) { //TODO: signed vs unsigned - chg bank to uns? + bank = *ptab; + break; + } + ptab++; + } + if (bank == 0xFF) { + ptab = kPersoRoomBankTable + _globals->_characterPtr->_roomBankId; + bank = *ptab++; + } + } + displayBackgroundFollower(); + displayNoFollower(bank); +} + +// Original name: af_fondperso +void EdenGame::displayCharacterBackground() { + if (_globals->_characterPtr->_spriteBank) { + _backgroundSaved = false; + displayCharacterBackground1(); + } +} + +// Original name: setpersoicon +void EdenGame::setCharacterIcon() { + if (_globals->_iconsIndex == 4) + return; + + if (_globals->_characterPtr == &kPersons[PER_ELOI] && _globals->_eventType == EventType::etEventE) { + _globals->_iconsIndex = 123; + return; + } + Icon *icon = _gameIcons; + Icon *icon2 = &_gameIcons[_roomIconsBase]; + + *icon2++ = *icon++; //TODO: is this ok? + *icon2++ = *icon++; + icon2->sx = -1; +} + +// Original name: show_perso +void EdenGame::showCharacter() { + perso_t *perso = _globals->_characterPtr; + if (perso->_spriteBank) { + closeRoom(); + if (_globals->_displayFlags != DisplayFlags::dfPerson) { + if (_globals->_displayFlags & DisplayFlags::dfMirror) + resetScroll(); + _globals->_oldDisplayFlags = _globals->_displayFlags; + _globals->_displayFlags = DisplayFlags::dfPerson; + loadCharacter(perso); + setCharacterIcon(); + displayCharacterBackground(); + if (perso == &kPersons[PER_TAU] && _globals->_curObjectId == Objects::obShell) { + displaySubtitles(); + updateCursor(); + _paletteUpdateRequired = true; + display(); + rundcurs(); + return; + } + } + loadCurrCharacter(); + addanim(); + if (!_globals->_curCharacterAnimPtr) { + displayCharacter(); + displaySubtitles(); + } + _restartAnimation = true; + animCharacter(); + if (perso != &kPersons[PER_UNKN_156]) + updateCursor(); + _paletteUpdateRequired = true; + if (perso != &kPersons[PER_UNKN_156]) + rundcurs(); + display(); + } else { + displayPlace(); + displaySubtitles(); + } +} + +// Original name: showpersopanel +void EdenGame::displayCharacterPanel() { + perso_t *perso = _globals->_characterPtr; + loadCurrCharacter(); + addanim(); + if (!_globals->_curCharacterAnimPtr) { + displayCharacter(); + displaySubtitles(); + } + _restartAnimation = true; + _paletteUpdateRequired = true; + if (_globals->_drawFlags & DrawFlags::drDrawFlag8) + return; + animCharacter(); + if (perso != &kPersons[PER_UNKN_156]) + updateCursor(); + display(); + if (perso != &kPersons[PER_UNKN_156]) + rundcurs(); + _globals->_drawFlags |= DrawFlags::drDrawFlag8; + _globals->_iconsIndex = 112; +} + +void EdenGame::getDataSync() { + int16 num = _globals->_textNum; + if (_globals->_textBankIndex != 1) + num += 565; + if (_globals->_textBankIndex == 3) + num += 707; + if (num == 144) + num = 142; + _animateTalking = ReadDataSync(num - 1); + if (_animateTalking) + _numAnimFrames = readFrameNumber(); + else + _numAnimFrames = 0; + if (_globals->_textNum == 144) + _numAnimFrames = 48; + _animationTable = 0; +} + +// Original name: ReadNombreFrames +int16 EdenGame::readFrameNumber() { + int16 num = 0; + _animationTable = _gameLipsync + 7260 + 2; //TODO: fix me + while (*_animationTable++ != 0xFF) + num++; + return num; +} + +void EdenGame::waitEndSpeak() { + for (;;) { + if (_animationActive) + animCharacter(); + musicspy(); + display(); + _vm->pollEvents(); + if (_vm->shouldQuit()) { + closeCharacterScreen(); + edenShudown(); + break; + } + if (!_mouseHeld) + if (_vm->isMouseButtonDown()) + break; + if (_mouseHeld) + if (!_vm->isMouseButtonDown()) + _mouseHeld = false; + } + _mouseHeld = true; +} + +void EdenGame::my_bulle() { + if (!_globals->_textNum) + return; + + byte *icons = phraseIconsBuffer; + byte *linesp = _sentenceCoordsBuffer; + byte *sentencePtr = _sentenceBuffer; + _globals->_numGiveObjs = 0; + _globals->_giveObj1 = 0; + _globals->_giveObj2 = 0; + _globals->_giveObj3 = 0; + _globals->_textWidthLimit = _subtitlesXWidth; + byte *textPtr = getPhrase(_globals->_textNum); + _numTextLines = 0; + int16 wordsOnLine = 0; + int16 wordWidth = 0; + int16 lineWidth = 0; + byte c; + while ((c = *textPtr++) != 0xFF) { + if (c == 0x11 || c == 0x13) { + if (_globals->_phaseNum <= 272 || _globals->_phaseNum == 386) { + _globals->_eloiHaveNews = c & 0xF; + _globals->_var4D = _globals->_worldTyranSighted; + } + } else if (c >= 0x80 && c < 0x90) + SysBeep(1); + else if (c >= 0x90 && c < 0xA0) { + while (*textPtr++ != 0xFF) ; + textPtr--; + } else if (c >= 0xA0 && c < 0xC0) + _globals->_textToken1 = c & 0xF; + else if (c >= 0xC0 && c < 0xD0) + _globals->_textToken2 = c & 0xF; + else if (c >= 0xD0 && c < 0xE0) { + byte c1 = *textPtr++; + if (c == 0xD2) +#ifdef FAKE_DOS_VERSION + _globals->_textWidthLimit = c1 + 160; +#else + _globals->_textWidthLimit = c1 + _subtitlesXCenter; //TODO: signed? 160 in pc ver +#endif + else { + byte c2 = *textPtr++; + switch (_globals->_numGiveObjs) { + case 0: + _globals->_giveObj1 = c2; + break; + case 1: + _globals->_giveObj2 = c2; + break; + case 2: + _globals->_giveObj3 = c2; + break; + } + _globals->_numGiveObjs++; + *icons++ = *textPtr++; + *icons++ = *textPtr++; + *icons++ = c2; + } + } else if (c >= 0xE0 && c < 0xFF) + SysBeep(1); + else if (c != '\r') { + *sentencePtr++ = c; + byte width = _gameFont[c]; +#ifdef FAKE_DOS_VERSION + if (c == ' ') + width = _spaceWidth; +#endif + wordWidth += width; + lineWidth += width; + int16 overrun = lineWidth - _globals->_textWidthLimit; + if (overrun > 0) { + _numTextLines++; + if (c != ' ') { + *linesp++ = wordsOnLine; + *linesp++ = wordWidth + _spaceWidth - overrun; + lineWidth = wordWidth; + } else { + *linesp++ = wordsOnLine + 1; + *linesp++ = _spaceWidth - overrun; //TODO: checkme + lineWidth = 0; + } + wordWidth = 0; + wordsOnLine = 0; + } else { + if (c == ' ') { + wordsOnLine++; + wordWidth = 0; + } + } + } + } + _numTextLines++; + *linesp++ = wordsOnLine + 1; + *linesp++ = wordWidth; + *sentencePtr = c; + if (_globals->_textBankIndex == 2 && _globals->_textNum == 101 && _globals->_prefLanguage == 1) + patchSentence(); + my_pr_bulle(); + if (!_globals->_numGiveObjs) + return; + useMainBank(); + if (_numTextLines < 3) + _numTextLines = 3; + icons = phraseIconsBuffer; + for (byte i = 0; i < _globals->_numGiveObjs; i++) { + byte x = *icons++; + byte y = *icons++; + byte s = *icons++; + spriteOnSubtitle(52, x + _subtitlesXCenter, y - 1); + spriteOnSubtitle(s + 9, x + _subtitlesXCenter + 1, y); + } +} + +void EdenGame::my_pr_bulle() { + CLBlitter_FillView(_subtitlesView, 0); + if (_globals->_prefLanguage == 0) + return; + + byte *coo = _sentenceCoordsBuffer; + bool done = false; + textout = _subtitlesViewBuf; + byte *textPtr = _sentenceBuffer; + int16 lines = 1; + while (!done) { + int16 numWords = *coo++; // num words on line + int16 padSize = *coo++; // amount of extra spacing + byte *currOut = textout; + int16 extraSpacing = numWords > 1 ? padSize / (numWords - 1) + 1 : 0; + if (lines == _numTextLines) + extraSpacing = 0; + byte c = *textPtr++; + while (!done && (numWords > 0)) { + if (c < 0x80 && c != '\r') { + if (c == ' ') { + numWords--; + if (padSize >= extraSpacing) { + textout += extraSpacing + _spaceWidth; + padSize -= extraSpacing; + } else { + textout += padSize + _spaceWidth; + padSize = 0; + } + } else { + int16 charWidth = _gameFont[c]; + if (!(_globals->_drawFlags & DrawFlags::drDrawMenu)) { + textout += _subtitlesXWidth; + if (!_specialTextMode) + drawSubtitleChar(c, 195, charWidth); + textout++; + if (!_specialTextMode) + drawSubtitleChar(c, 195, charWidth); + textout -= _subtitlesXWidth + 1; + } + if (_specialTextMode) + drawSubtitleChar(c, 250, charWidth); + else + drawSubtitleChar(c, 230, charWidth); + textout += charWidth; + } + } else + error("my_pr_bulle: Unexpected format"); + + c = *textPtr++; + if (c == 0xFF) + done = true; + } + textout = currOut + _subtitlesXWidth * FONT_HEIGHT; + lines++; + textPtr--; + } +} + +// Original name: charsurbulle +void EdenGame::drawSubtitleChar(byte c, byte color, int16 width) { + byte *glyph = _gameFont + 256 + c * FONT_HEIGHT; + _textOutPtr = textout; + for (int16 h = 0; h < FONT_HEIGHT; h++) { + byte bits = *glyph++; + int16 mask = 0x80; + for (int16 w = 0; w < width; w++) { + if (bits & mask) + *_textOutPtr = color; + _textOutPtr++; + mask >>= 1; + } + _textOutPtr += _subtitlesXWidth - width; + } +} + +// Original name: af_subtitle +void EdenGame::displaySubtitles() { + byte *src = _subtitlesViewBuf; + byte *dst = _mainViewBuf; + int16 y; + if (_globals->_displayFlags & DisplayFlags::dfFlag2) { + y = 174; + if ((_globals->_drawFlags & DrawFlags::drDrawMenu) && _numTextLines == 1) + y = 167; + dst += 640 * (y - _numTextLines * FONT_HEIGHT) + _subtitlesXScrMargin; + } else { + y = 174; + dst += 640 * (y - _numTextLines * FONT_HEIGHT) + _scrollPos + _subtitlesXScrMargin; + } + if (_animationActive && !_personTalking) + return; + saveUnderSubtitles(y); + for (int16 h = 0; h < _numTextLines * FONT_HEIGHT + 1; h++) { + for (int16 w = 0; w < _subtitlesXWidth; w++) { + byte c = *src++; + if (c) + *dst = c; + dst++; + } + dst += 640 - _subtitlesXWidth; + } +} + +// Original name: sauvefondbulle +void EdenGame::saveUnderSubtitles(int16 y) { + _underSubtitlesScreenRect.top = y - _numTextLines * FONT_HEIGHT; + _underSubtitlesScreenRect.left = _scrollPos + _subtitlesXScrMargin; + _underSubtitlesScreenRect.right = _scrollPos + _subtitlesXScrMargin + _subtitlesXWidth - 1; + _underSubtitlesScreenRect.bottom = y; + _underSubtitlesBackupRect.top = 0; + _underSubtitlesBackupRect.bottom = _numTextLines * FONT_HEIGHT; + CLBlitter_CopyViewRect(_mainView, _underSubtitlesView, &_underSubtitlesScreenRect, &_underSubtitlesBackupRect); + _savedUnderSubtitles = true; +} + +// Original name: restaurefondbulle +void EdenGame::restoreUnderSubtitles() { + if (!_savedUnderSubtitles) + return; + CLBlitter_CopyViewRect(_underSubtitlesView, _mainView, &_underSubtitlesBackupRect, &_underSubtitlesScreenRect); + _savedUnderSubtitles = false; +} + +// Original name: af_subtitlehnm +void EdenGame::displayHNMSubtitle() { + byte *src = _subtitlesViewBuf; + byte *dst = _hnmViewBuf + _subtitlesXScrMargin + (158 - _numTextLines * FONT_HEIGHT) * 320; + for (int16 y = 0; y < _numTextLines * FONT_HEIGHT; y++) { + for (int16 x = 0; x < _subtitlesXWidth; x++) { + char c = *src++; + if (c) + *dst = c; + dst++; + } + dst += 320 - _subtitlesXWidth; + } +} + +// Original name: patchPhrase +void EdenGame::patchSentence() { + _sentenceBuffer[36] = 'c'; +} + +void EdenGame::vavapers() { + perso_t *perso = _globals->_characterPtr; + _globals->_curPersoFlags = perso->_flags; + _globals->_curPersoItems = perso->_items; + _globals->_curCharacterPowers = perso->_powers; +} + +void EdenGame::citadelle() { + _globals->_var69++; + _globals->_varF6++; + parlemoiNormalFlag = true; + _closeCharacterDialog = true; +} + +// Original name: choixzone +void EdenGame::selectZone() { + if (_globals->_giveObj3) + _globals->_iconsIndex = 6; + else + _globals->_iconsIndex = 10; + _globals->_autoDialog = false; + putObject(); +} + +void EdenGame::showEvents1() { + _globals->_var113 = 0; + perso_ici(3); +} + +void EdenGame::showEvents() { + if (_globals->_eventType && _globals->_displayFlags != DisplayFlags::dfPerson) + showEvents1(); +} + +void EdenGame::parle_mfin() { + perso_t *perso = _globals->_characterPtr; + if (_globals->_curObjectId) { + char curobj = _globals->_curObjectId; + if (_globals->_dialogType == DialogType::dtHint) + return; + object_t *obj = getObjectPtr(_globals->_curObjectId); + if (_globals->_dialogType == DialogType::dtDinoItem) + perso = _globals->_roomCharacterPtr; + if (isAnswerYes()) { + loseObject(_globals->_curObjectId); + perso->_powers |= obj->_powerMask; + } + perso->_items |= obj->_itemMask; + specialObjects(perso, curobj); + return; + } + if (!isAnswerYes()) + return; + nextInfo(); + if (!_globals->_lastInfo) + _closeCharacterDialog = true; + else { + _globals->_nextDialogPtr = nullptr; + _closeCharacterDialog = false; + } +} + +void EdenGame::parlemoi_normal() { + Dialog *dial; + if (!_globals->_nextDialogPtr) { + perso_t *perso = _globals->_characterPtr; + if (perso) { + int16 num = (perso->_id << 3) | _globals->_dialogType; + dial = (Dialog *)getElem(_gameDialogs, num); + } else { + closeCharacterScreen(); + return; + } + } else { + if (_closeCharacterDialog) { + closeCharacterScreen(); + return; + } + dial = _globals->_nextDialogPtr; + } + char ok = dial_scan(dial); + _globals->_nextDialogPtr = _globals->_dialogPtr; + _closeCharacterDialog = false; + if (!ok) + closeCharacterScreen(); + else + parle_mfin(); +} + +void EdenGame::parle_moi() { + endCharacterSpeech(); + byte r28 = _globals->_varF6; + _globals->_varF6 = 0; + if (!r28) { + setChoiceNo(); + if (_globals->_drawFlags & DrawFlags::drDrawInventory) + showObjects(); + if (_globals->_drawFlags & DrawFlags::drDrawTopScreen) + drawTopScreen(); + if (_globals->_curObjectId) { + if (_globals->_dialogType == DialogType::dtTalk) { + _globals->_dialogType = DialogType::dtItem; + _globals->_nextDialogPtr = nullptr; + _closeCharacterDialog = false; + } + parlemoi_normal(); + return; + } + if (_globals->_dialogType == DialogType::dtItem) { + _globals->_dialogType = DialogType::dtTalk; + if (!_closeCharacterDialog) + _globals->_nextDialogPtr = nullptr; + } + if (parlemoiNormalFlag) { + parlemoi_normal(); + return; + } + Dialog *dial; + + if (!_globals->_lastDialogPtr) { + int16 num = 160; + if (_globals->_phaseNum >= 400) + num++; + dial = (Dialog *)getElem(_gameDialogs, num); + } else + dial = _globals->_lastDialogPtr; + char ok = dial_scan(dial); + _globals->_lastDialogPtr = _globals->_dialogPtr; + parlemoiNormalFlag = false; + if (!ok) { + parlemoiNormalFlag = true; + if (_globals->_var60) { + if (_globals->_characterPtr == &kPersons[PER_ELOI]) { + _globals->_dialogType = DialogType::dtTalk; + if (_globals->_eloiHaveNews) + parlemoi_normal(); + else + closeCharacterScreen(); + } else + closeCharacterScreen(); + } else + parlemoi_normal(); + } else + parle_mfin(); + } else + closeCharacterScreen(); +} + +// Original name: init_perso_ptr +void EdenGame::initCharacterPointers(perso_t *perso) { + _globals->_metPersonsMask1 |= perso->_partyMask; + _globals->_metPersonsMask2 |= perso->_partyMask; + _globals->_nextDialogPtr = nullptr; + _closeCharacterDialog = false; + _dialogSkipFlags = DialogFlags::dfSpoken; + _globals->_var60 = 0; + _globals->_textToken1 = 0; +} + +void EdenGame::perso1(perso_t *perso) { + _globals->_phaseActionsCount++; + if (perso == &kPersons[PER_TAU]) + _globals->_phaseActionsCount--; + _globals->_characterPtr = perso; + initCharacterPointers(perso); + parle_moi(); +} + +void EdenGame::perso_normal(perso_t *perso) { + _globals->_lastDialogPtr = nullptr; + _globals->_dialogType = DialogType::dtTalk; + parlemoiNormalFlag = false; + perso1(perso); +} + +// Original name: persoparle +void EdenGame::handleCharacterDialog(int16 pers) { + perso_t *perso = &kPersons[pers]; + _globals->_characterPtr = perso; + _globals->_dialogType = DialogType::dtInspect; + uint16 idx = perso->_id * 8 | _globals->_dialogType; + dialoscansvmas((Dialog *)getElem(_gameDialogs, idx)); + displayPlace(); + displaySubtitles(); + persovox(); + _globals->_varCA = 0; + _globals->_dialogType = DialogType::dtTalk; +} + +// Original name: roi +void EdenGame::actionKing() { + perso_normal(&kPersons[PER_KING]); +} + +// Original name: dina +void EdenGame::actionDina() { + perso_normal(&kPersons[PER_DINA]); +} + +// Original name: thoo +void EdenGame::actionThoo() { + perso_normal(&kPersons[PER_TAU]); +} + +// Original name: monk +void EdenGame::actionMonk() { + perso_normal(&kPersons[PER_MONK]); +} + +// Original name: bourreau +void EdenGame::actionTormentor() { + perso_normal(&kPersons[PER_JABBER]); +} + +// Original name: messager +void EdenGame::actionMessenger() { + perso_normal(&kPersons[PER_ELOI]); +} + +// Original name: mango +void EdenGame::actionMango() { + perso_normal(&kPersons[PER_MUNGO]); +} + +// Original name: eve +void EdenGame::actionEve() { + perso_normal(&kPersons[PER_EVE]); +} + +// Original name: azia +void EdenGame::actionAzia() { + perso_normal(&kPersons[PER_SHAZIA]); +} + +// Original name: mammi +void EdenGame::actionMammi() { + perso_t *perso; + for (perso = &kPersons[PER_MAMMI]; perso->_partyMask == PersonMask::pmLeader; perso++) { + if (perso->_roomNum == _globals->_roomNum) { + perso_normal(perso); + break; + } + } +} + +// Original name: gardes +void EdenGame::actionGuards() { + perso_normal(&kPersons[PER_GUARDS]); +} + +// Original name: bambou +void EdenGame::actionBamboo() { + perso_normal(&kPersons[PER_BAMBOO]); +} + +// Original name: kabuka +void EdenGame::actionKabuka() { + if (_globals->_roomNum == 0x711) perso_normal(&kPersons[PER_KABUKA]); + else actionBamboo(); +} + +// Original name: fisher +void EdenGame::actionFisher() { + if (_globals->_roomNum == 0x902) perso_normal(&kPersons[PER_FISHER]); + else actionKabuka(); +} + +// Original name: dino +void EdenGame::actionDino() { + perso_t *perso = _globals->_roomCharacterPtr; + if (!perso) + return; + parlemoiNormalFlag = true; + _globals->_dialogType = DialogType::dtTalk; + _globals->_roomCharacterFlags = perso->_flags; + _globals->_roomPersoItems = perso->_items; + _globals->_roomCharacterPowers = perso->_powers; + _globals->_characterPtr = perso; + initCharacterPointers(perso); + debug("beg dino talk"); + parle_moi(); + debug("end dino talk"); + if (_globals->_areaNum == Areas::arWhiteArch) + return; + if (_globals->_var60) + waitEndSpeak(); + if (_vm->shouldQuit()) + return; + perso = &kPersons[PER_MUNGO]; + if (!(_globals->_party & PersonMask::pmMungo)) { + perso = &kPersons[PER_DINA]; + if (!(_globals->_party & PersonMask::pmDina)) { + perso = &kPersons[PER_EVE]; + if (!(_globals->_party & PersonMask::pmEve)) { + perso = &kPersons[PER_GUARDS]; + } + } + } + _globals->_dialogType = DialogType::dtDinoAction; + if (_globals->_curObjectId) + _globals->_dialogType = DialogType::dtDinoItem; + perso1(perso); + if (_globals->_roomCharacterType == PersonFlags::pftMosasaurus && !_globals->_curObjectId) { + _globals->_areaPtr->_flags |= AreaFlags::afFlag20; + placeVava(_globals->_areaPtr); + } +} + +// Original name: tyran +void EdenGame::actionTyran() { + perso_t *perso = _globals->_roomCharacterPtr; + if (!perso) + return; + + parlemoiNormalFlag = true; + _globals->_dialogType = DialogType::dtTalk; + _globals->_roomCharacterFlags = perso->_flags; + _globals->_characterPtr = perso; + initCharacterPointers(perso); + perso = &kPersons[PER_MUNGO]; + if (!(_globals->_party & PersonMask::pmMungo)) { + perso = &kPersons[PER_DINA]; + if (!(_globals->_party & PersonMask::pmDina)) { + perso = &kPersons[PER_EVE]; + if (!(_globals->_party & PersonMask::pmEve)) { + perso = &kPersons[PER_GUARDS]; + } + } + } + _globals->_dialogType = DialogType::dtDinoAction; + if (_globals->_curObjectId) + _globals->_dialogType = DialogType::dtDinoItem; + perso1(perso); +} + +// Original name: morkus +void EdenGame::actionMorkus() { + perso_normal(&kPersons[PER_MORKUS]); +} + +void EdenGame::comment() { + perso_t *perso = &kPersons[PER_DINA]; + if (!(_globals->_party & PersonMask::pmDina)) { + perso = &kPersons[PER_EVE]; + if (!(_globals->_party & PersonMask::pmEve)) { + perso = &kPersons[PER_GUARDS]; + if (!(_globals->_party & PersonMask::pmThugg)) + return; + } + } + _globals->_dialogType = DialogType::dtHint; + perso1(perso); +} + +// Original name: adam +void EdenGame::actionAdam() { + resetScroll(); + switch (_globals->_curObjectId) { + case Objects::obNone: + gotoPanel(); + break; + case Objects::obRoot: + if (_globals->_roomNum == 2817 + && _globals->_phaseNum > 496 && _globals->_phaseNum < 512) { + bigphase1(); + loseObject(Objects::obRoot); + _globals->_var100 = 0xFF; + quitMirror(); + updateRoom(_globals->_roomNum); + removeFromParty(PER_ELOI); + _globals->_eventType = EventType::etEvent3; + showEvents(); + waitEndSpeak(); + if (_vm->shouldQuit()) + return; + closeCharacterScreen(); + removeFromParty(PER_ELOI); + _globals->_roomNum = 2818; + _globals->_areaNum = Areas::arWhiteArch; + _globals->_eventType = EventType::etEvent5; + _globals->_valleyVidNum = 0; + _globals->_mirrorEffect = 6; // CHECKME: Verify the value + _globals->_newMusicType = MusicType::mtNormal; + updateRoom(_globals->_roomNum); + } else { + _globals->_dialogType = DialogType::dtHint; + perso1(&kPersons[PER_EVE]); + } + break; + case Objects::obShell: + _globals->_dialogType = DialogType::dtHint; + perso1(&kPersons[PER_TAU]); + break; + case Objects::obFlute: + case Objects::obTrumpet: + if (_globals->_roomCharacterType) { + quitMirror(); + updateRoom(_globals->_roomNum); + actionDino(); + } else + comment(); + break; + case Objects::obTablet1: + case Objects::obTablet2: + case Objects::obTablet3: + case Objects::obTablet4: + case Objects::obTablet5: + case Objects::obTablet6: { + if ((_globals->_partyOutside & PersonMask::pmDina) + && _globals->_curObjectId == Objects::obTablet1 && _globals->_phaseNum == 370) + incPhase(); + char *objvid = &kTabletView[(_globals->_curObjectId - Objects::obTablet1) * 2]; + object_t *object = getObjectPtr(*objvid++); + int16 vid = 84; + if (!object->_count) + vid = *objvid; + hideBars(); + _specialTextMode = true; + playHNM(vid); + _paletteUpdateRequired = true; + _globals->_mirrorEffect = 16; // CHECKME: Verify the value + showBars(); + gameToMirror(0); + } + break; + case Objects::obApple: + case Objects::obShroom: + case Objects::obBadShroom: + case Objects::obNest: + case Objects::obFullNest: + case Objects::obDrum: + if (_globals->_party & PersonMask::pmThugg) { + _globals->_dialogType = DialogType::dtHint; + perso1(&kPersons[PER_GUARDS]); + } + break; + default: + comment(); + } +} + +// Original name: oui and init_oui +void EdenGame::setChoiceYes() { + _lastDialogChoice = true; +} + +// Original name: non and init_non +void EdenGame::setChoiceNo() { + _lastDialogChoice = false; +} + +// Original name: verif_oui +bool EdenGame::isAnswerYes() { + return _lastDialogChoice; +} + +// Original name: SpcChampi +void EdenGame::specialMushroom(perso_t *perso) { + perso->_flags |= PersonFlags::pf10; + _globals->_areaPtr->_flags |= AreaFlags::afFlag2; + _globals->_curAreaFlags |= AreaFlags::afFlag2; +} + +// Original name: SpcNidv +void EdenGame::specialEmptyNest(perso_t *perso) { + if (!isAnswerYes()) + return; + perso->_flags |= PersonFlags::pf10; + _globals->_roomCharacterFlags |= PersonFlags::pf10; + _globals->_gameFlags |= GameFlags::gfFlag400; + if (_globals->_characterPtr == &kPersons[PER_EVE]) { + _globals->_areaPtr->_flags |= AreaFlags::afFlag4; + _globals->_curAreaFlags |= AreaFlags::afFlag4; + perso->_flags |= PersonFlags::pfInParty; + _globals->_roomCharacterFlags |= PersonFlags::pfInParty; + placeVava(_globals->_areaPtr); + } else { + perso->_flags &= ~PersonFlags::pf10; + _globals->_roomCharacterFlags &= ~PersonFlags::pf10; + } +} + +// Original name: SpcNido +void EdenGame::specialNestWithEggs(perso_t *perso) { + if (perso == &kPersons[PER_GUARDS]) + giveObject(); +} + +// Original name: SpcPomme +void EdenGame::specialApple(perso_t *perso) { + perso->_flags |= PersonFlags::pf10; + _globals->_areaPtr->_flags |= AreaFlags::afFlag8; + _globals->_curAreaFlags |= AreaFlags::afFlag8; + _globals->_gameFlags |= GameFlags::gfFlag200; +} + +// Original name: SpcOr +void EdenGame::specialGold(perso_t *perso) { + if (!isAnswerYes()) + return; + perso->_items = _curSpecialObject->_itemMask; + _globals->_roomPersoItems = _curSpecialObject->_itemMask; + perso->_flags |= PersonFlags::pf10; + perso->_flags &= ~PersonFlags::pfInParty; + perso->_targetLoc = 0; + _globals->_areaPtr->_flags |= AreaFlags::afGaveGold; + _globals->_curAreaFlags |= AreaFlags::afGaveGold; + if (_globals->_phaseNum == 226) + incPhase(); +} + +// Original name: SpcPrisme +void EdenGame::specialPrism(perso_t *perso) { + if (perso == &kPersons[PER_DINA]) { + if (_globals->_partyOutside & PersonMask::pmMonk) + _globals->_gameFlags |= GameFlags::gfPrismAndMonk; + } +} + +// Original name: SpcTalisman +void EdenGame::specialTalisman(perso_t *perso) { + if (perso == &kPersons[PER_DINA]) + addToParty(PER_DINA); +} + +// Original name: SpcMasque +void EdenGame::specialMask(perso_t *perso) { + if (perso == &kPersons[PER_BAMBOO]) { + dialautoon(); + parlemoiNormalFlag = true; + } +} + +// Original name: SpcSac +void EdenGame::specialBag(perso_t *perso) { + if (_globals->_textToken1 != 3) + return; + if (perso == &kPersons[PER_KABUKA] || perso == &kPersons[PER_MAMMI_3]) + loseObject(_curSpecialObject->_id); +} + +// Original name: SpcTrompet +void EdenGame::specialTrumpet(perso_t *perso) { + if (!isAnswerYes()) + return; + _globals->_var54 = 4; + winObject(Objects::obTrumpet); + _globals->_drawFlags |= DrawFlags::drDrawInventory; + _closeCharacterDialog = true; + tyranDies(_globals->_roomCharacterPtr); +} + +// Original name: SpcArmes +void EdenGame::specialWeapons(perso_t *perso) { + if (!isAnswerYes()) + return; + perso->_powers = _curSpecialObject->_powerMask; + _globals->_roomCharacterPowers = _curSpecialObject->_powerMask; + giveObject(); +} + +// Original name: SpcInstru +void EdenGame::specialInstrument(perso_t *perso) { + if (!isAnswerYes()) + return; + if (perso == &kPersons[PER_MONK]) { + _globals->_partyInstruments &= ~1; //TODO: check me + if (_curSpecialObject->_id == Objects::obRing) { + _globals->_partyInstruments |= 1; + _globals->_monkGotRing++; //TODO: |= 1 ? + } + } + if (perso == &kPersons[PER_GUARDS]) { + _globals->_partyInstruments &= ~2; + if (_curSpecialObject->_id == Objects::obDrum) + _globals->_partyInstruments |= 2; + } + perso->_powers = _curSpecialObject->_powerMask; + _globals->_curCharacterPowers = _curSpecialObject->_powerMask; + giveObject(); +} + +// Original name: SpcOeuf +void EdenGame::specialEgg(perso_t *perso) { + if (!isAnswerYes()) + return; + _gameIcons[131]._cursorId &= ~0x8000; + _globals->_characterBackgroundBankIdx = 62; + dialautoon(); +} + +// Original name: TyranMeurt +void EdenGame::tyranDies(perso_t *perso) { + perso->_flags |= PersonFlags::pf80; + perso->_roomNum = 0; + removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn); + _globals->_roomCharacterType = 0; + _globals->_roomCharacterFlags = 0; + _globals->_chronoFlag = 0; +} + +void EdenGame::specialObjects(perso_t *perso, char objid) { +#pragma pack(push, 1) + struct SpecialObject { + int8 _characterType; + int8 _objectId; + void (EdenGame::*dispFct)(perso_t *perso); + }; +#pragma pack(pop) + + static SpecialObject kSpecialObjectActions[] = { + // persoType, objectId, dispFct + { PersonFlags::pfType8, Objects::obShroom, &EdenGame::specialMushroom }, + { PersonFlags::pftTriceraptor, Objects::obNest, &EdenGame::specialEmptyNest }, + { PersonFlags::pfType0, Objects::obFullNest, &EdenGame::specialNestWithEggs }, + { PersonFlags::pftMosasaurus, Objects::obApple, &EdenGame::specialApple }, + { PersonFlags::pftVelociraptor, Objects::obGold, &EdenGame::specialGold }, + { PersonFlags::pfType0, Objects::obPrism, &EdenGame::specialPrism }, + { PersonFlags::pfType0, Objects::obTalisman, &EdenGame::specialTalisman }, + { PersonFlags::pfType2, Objects::obMaskOfDeath, &EdenGame::specialMask }, + { PersonFlags::pfType2, Objects::obMaskOfBonding, &EdenGame::specialMask }, + { PersonFlags::pfType2, Objects::obMaskOfBirth, &EdenGame::specialMask }, + { PersonFlags::pfType0, Objects::obBag, &EdenGame::specialBag }, + { PersonFlags::pfType2, Objects::obBag, &EdenGame::specialBag }, + { PersonFlags::pftTyrann, Objects::obTrumpet, &EdenGame::specialTrumpet }, + { PersonFlags::pftVelociraptor, Objects::obEyeInTheStorm, &EdenGame::specialWeapons }, + { PersonFlags::pftVelociraptor, Objects::obSkyHammer, &EdenGame::specialWeapons }, + { PersonFlags::pftVelociraptor, Objects::obFireInTheClouds, &EdenGame::specialWeapons }, + { PersonFlags::pftVelociraptor, Objects::obWithinAndWithout, &EdenGame::specialWeapons }, + { PersonFlags::pftVelociraptor, Objects::obEyeInTheCyclone, &EdenGame::specialWeapons }, + { PersonFlags::pftVelociraptor, Objects::obRiverThatWinds, &EdenGame::specialWeapons }, + { PersonFlags::pfType0, Objects::obTrumpet, &EdenGame::specialInstrument }, + { PersonFlags::pfType0, Objects::obDrum, &EdenGame::specialInstrument }, + { PersonFlags::pfType0, Objects::obRing, &EdenGame::specialInstrument }, + { PersonFlags::pfType0, Objects::obEgg, &EdenGame::specialEgg }, + { -1, -1, nullptr } + }; + + char characterType = perso->_flags & PersonFlags::pfTypeMask; + _curSpecialObject = &_objects[objid - 1]; + for (SpecialObject *spcObj = kSpecialObjectActions; spcObj->_characterType != -1; spcObj++) { + if (spcObj->_objectId == objid && spcObj->_characterType == characterType) { + (this->*spcObj->dispFct)(perso); + break; + } + } +} + +void EdenGame::dialautoon() { + _globals->_iconsIndex = 4; + _globals->_autoDialog = true; + putObject(); +} + +void EdenGame::dialautooff() { + _globals->_iconsIndex = 0x10; + _globals->_autoDialog = false; +} + +void EdenGame::follow() { + if (_globals->_roomCharacterType == PersonFlags::pfType12) { + debug("follow: hiding person %ld", _globals->_roomCharacterPtr - kPersons); + _globals->_roomCharacterPtr->_flags |= PersonFlags::pf80; + _globals->_roomCharacterPtr->_roomNum = 0; + _globals->_gameFlags |= GameFlags::gfFlag8; + _gameIcons[123]._objectId = 18; + _gameIcons[124]._objectId = 35; + _gameIcons[125]._cursorId &= ~0x8000; + _globals->_characterBackgroundBankIdx = 56; + } else + AddCharacterToParty(); +} + +void EdenGame::dialonfollow() { + _globals->_iconsIndex = 4; + _globals->_autoDialog = true; + follow(); +} + +// Original name: abortdial +void EdenGame::abortDialogue() { + _globals->_varF6++; + if (_globals->_roomCharacterType != PersonFlags::pftTriceraptor || _globals->_characterPtr != &kPersons[PER_EVE]) + return; + _globals->_areaPtr->_flags |= AreaFlags::afFlag4; + _globals->_curAreaFlags |= AreaFlags::afFlag4; + _globals->_roomCharacterPtr->_flags |= PersonFlags::pfInParty; + _globals->_roomCharacterFlags |= PersonFlags::pfInParty; + placeVava(_globals->_areaPtr); +} + +void EdenGame::subHandleNarrator() { + _globals->_varF2 &= ~1; //TODO: check me + if (_globals->_narratorSequence > 50 && _globals->_narratorSequence <= 80) + _globals->_endGameFlag = 50; + if (_globals->_narratorSequence == 3) + setChrono(1200); + _globals->_narratorSequence = 0; +} + +// Original name: narrateur +void EdenGame::handleNarrator() { + if (!(_globals->_displayFlags & DisplayFlags::dfFlag1)) + return; + if (!_globals->_narratorSequence) { + if (_globals->_var6A == _globals->_var69) { + subHandleNarrator(); + return; + } + + narratorBuildCitadel(); + } + _globals->_varF5 |= 0x80; + _globals->_varF2 &= ~1; //TODO: check me + _globals->_characterPtr = &kPersons[PER_UNKN_156]; + _globals->_var60 = 0; + _globals->_eventType = 0; + _globals->_var103 = 69; + if (dialogEvent(&kPersons[PER_UNKN_156])) { + _globals->_narratorDialogPtr = _globals->_dialogPtr; + dialautoon(); + _globals->_varF2 |= 1; + waitEndSpeak(); + if (_vm->shouldQuit()) + return; + endCharacterSpeech(); + while (dialoscansvmas(_globals->_narratorDialogPtr)) { + _globals->_narratorDialogPtr = _globals->_dialogPtr; + waitEndSpeak(); + if (_vm->shouldQuit()) + return; + endCharacterSpeech(); + } + _globals->_narratorDialogPtr = _globals->_dialogPtr; + _globals->_mirrorEffect = 0; + _globals->_var103 = 0; + closeCharacterScreen(); + placeVava(_globals->_areaPtr); + if (_globals->_narratorSequence == 8) + deplaval(134); + } + _globals->_var103 = 0; + if (_globals->_narratorSequence == 10) { + addToParty(PER_ELOI); + addToParty(PER_EVE); + addToParty(PER_MONK); + addToParty(PER_GUARDS); + removeFromParty(PER_MUNGO); + _globals->_eloiHaveNews = 0; + deplaval(139); + } + _globals->_eventType = EventType::etEventD; + showEvents(); + _globals->_varF5 &= ~0x80; + + subHandleNarrator(); +} + +// Original name: vrf_phrases_file +void EdenGame::checkPhraseFile() { + int16 num = 3; + if (_globals->_dialogPtr < (Dialog *)getElem(_gameDialogs, 48)) + num = 1; + else if (_globals->_dialogPtr < (Dialog *)getElem(_gameDialogs, 128)) + num = 2; + _globals->_textBankIndex = num; + if (_globals->_prefLanguage) + num += (_globals->_prefLanguage - 1) * 3; + if (num == _lastPhrasesFile) + return; + _lastPhrasesFile = num; + num += 404; + loadRawFile(num, _gamePhrases); + verifh(_gamePhrases); +} + +// Original name: gettxtad +byte *EdenGame::getPhrase(int16 id) { + checkPhraseFile(); + return (byte *)getElem(_gamePhrases, id - 1); +} + +// Original name: gotocarte +void EdenGame::actionGotoMap() { + Goto *go = &gotos[_curSpot2->_objectId]; + endCharacterSpeech(); + byte newArea = go->_areaNum; + _globals->_newRoomNum = (go->_areaNum << 8) | 1; + _globals->_newLocation = 1; + _globals->_prevLocation = _globals->_roomNum & 0xFF; + char curArea = _globals->_roomNum >> 8; + if (curArea == go->_areaNum) + newArea = 0; + else { + for (; go->_curAreaNum != 0xFF; go++) { + if (go->_curAreaNum == curArea) + break; + } + + if (go->_areaNum == 0xFF) + return; + } + _globals->_eventType = EventType::etGotoArea | newArea; + setChoiceYes(); + showEvents1(); + waitEndSpeak(); + if (_vm->shouldQuit()) + return; + + closeCharacterScreen(); + if (isAnswerYes()) + gotoPlace(go); +} + +void EdenGame::record() { + if (_globals->_curObjectId) + return; + + if (_globals->_characterPtr >= &kPersons[PER_UNKN_18C]) + return; + + if (_globals->_eventType == EventType::etEventE || _globals->_eventType >= EventType::etGotoArea) + return; + + for (tape_t *tape = _tapes; tape != _tapes + MAX_TAPES; tape++) { + if (tape->_textNum == _globals->_textNum) + return; + } + + tape_t *tape = _tapes; + for (int16 i = 0; i < MAX_TAPES - 1; i++) { + tape->_textNum = tape[+1]._textNum; + tape->_perso = tape[+1]._perso; + tape->_party = tape[+1]._party; + tape->_roomNum = tape[+1]._roomNum; + tape->_backgroundBankNum = tape[+1]._backgroundBankNum; + tape->_dialog = tape[+1]._dialog; + tape++; + } + + perso_t *perso = _globals->_characterPtr; + if (perso == &kPersons[PER_EVE]) + perso = _globals->_phaseNum >= 352 ? &kPersons[PER_UNKN_372] + : &kPersons[PER_UNKN_402]; + tape->_textNum = _globals->_textNum; + tape->_perso = perso; + tape->_party = _globals->_party; + tape->_roomNum = _globals->_roomNum; + tape->_backgroundBankNum = _globals->_roomBackgroundBankNum; + tape->_dialog = _globals->_dialogPtr; +} + +bool EdenGame::dial_scan(Dialog *dial) { + if (_globals->_numGiveObjs) { + if (!(_globals->_displayFlags & DisplayFlags::dfFlag2)) + showObjects(); + _globals->_numGiveObjs = 0; + } + _globals->_dialogPtr = dial; + vavapers(); + _globals->_sentenceBufferPtr = _sentenceBuffer; + byte hidx, lidx; + uint16 mask = 0; + bool skipFl = false; + for (;; _globals->_dialogPtr++) { + for (;; _globals->_dialogPtr++) { + if (_globals->_dialogPtr->_flags == -1 && _globals->_dialogPtr->_condNumLow == -1) + return false; + byte flags = _globals->_dialogPtr->_flags; + _globals->_dialogFlags = flags; + if (!(flags & DialogFlags::dfSpoken) || (flags & DialogFlags::dfRepeatable)) { + hidx = (_globals->_dialogPtr->_textCondHiMask >> 6) & 3; + lidx = _globals->_dialogPtr->_condNumLow; + if (flags & 0x10) + hidx |= 4; + if (testCondition(((hidx << 8) | lidx) & 0x7FF)) + break; + } else { + if (flags & _dialogSkipFlags) + continue; + hidx = (_globals->_dialogPtr->_textCondHiMask >> 6) & 3; + lidx = _globals->_dialogPtr->_condNumLow; + if (flags & 0x10) + hidx |= 4; + if (testCondition(((hidx << 8) | lidx) & 0x7FF)) + break; + } + } + char bidx = (_globals->_dialogPtr->_textCondHiMask >> 2) & 0xF; + if (!bidx) { + skipFl = true; + break; + } + + mask = (_globals->_party | _globals->_partyOutside) & (1 << (bidx - 1)); + if (mask) + break; + } + + if (!skipFl) { + perso_t *perso; + for (perso = kPersons; !(perso->_partyMask == mask && perso->_roomNum == _globals->_roomNum); perso++) + ; //Find matching + + _globals->_characterPtr = perso; + initCharacterPointers(perso); + no_perso(); + } + + hidx = _globals->_dialogPtr->_textCondHiMask; + lidx = _globals->_dialogPtr->_textNumLow; + _globals->_textNum = ((hidx << 8) | lidx) & 0x3FF; + if (_globals->_sentenceBufferPtr != _sentenceBuffer) { + for (int16 i = 0; i < 32; i++) + SysBeep(1); + } else + my_bulle(); + if (!dword_30B04) { + static void (EdenGame::*talk_subject[])() = { + &EdenGame::setChoiceYes, + &EdenGame::setChoiceNo, + &EdenGame::handleEloiDeparture, + &EdenGame::dialautoon, + &EdenGame::dialautooff, + &EdenGame::characterStayHere, + &EdenGame::follow, + &EdenGame::citadelle, + &EdenGame::dialonfollow, + &EdenGame::abortDialogue, + &EdenGame::incPhase, + &EdenGame::bigphase, + &EdenGame::giveObject, + &EdenGame::selectZone, + &EdenGame::lostObject + }; + char pnum = _globals->_dialogPtr->_flags & 0xF; + if (pnum) + (this->*talk_subject[pnum - 1])(); + _globals->_var60 = 1; + _globals->_dialogPtr->_flags |= DialogFlags::dfSpoken; + _globals->_dialogPtr++; + } + if (_globals->_dialogType != DialogType::dtInspect) { + record(); + getDataSync(); + showCharacter(); + persovox(); + } + return true; +} + +bool EdenGame::dialoscansvmas(Dialog *dial) { + byte oldFlag = _dialogSkipFlags; + _dialogSkipFlags = DialogFlags::df20; + bool res = dial_scan(dial); + _dialogSkipFlags = oldFlag; + return res; +} + +// Original name: dialo_even +bool EdenGame::dialogEvent(perso_t *perso) { + _globals->_characterPtr = perso; + int num = (perso->_id << 3) | DialogType::dtEvent; + Dialog *dial = (Dialog *)getElem(_gameDialogs, num); + bool retVal = dialoscansvmas(dial); + _globals->_lastDialogPtr = nullptr; + parlemoiNormalFlag = false; + return retVal; +} + +// Original name: stay_here +void EdenGame::characterStayHere() { + if (_globals->_characterPtr == &kPersons[PER_DINA] && _globals->_roomNum == 260) + _globals->_gameFlags |= GameFlags::gfFlag1000; + removeCharacterFromParty(); +} + +// Original name: mort +void EdenGame::endDeath(int16 vid) { + hideBars(); + playHNM(vid); + fadeToBlack(2); + CLBlitter_FillScreenView(0); + CLBlitter_FillView(_mainView, 0); + showBars(); + _globals->_narratorSequence = 51; + _globals->_newMusicType = MusicType::mtNormal; + musique(); + musicspy(); +} + +// Original name: evenchrono +void EdenGame::chronoEvent() { + if (!(_globals->_displayFlags & DisplayFlags::dfFlag1)) + return; + + uint16 oldGameTime = _globals->_gameTime; + _currentTime = _vm->_timerTicks / 100; + _globals->_gameTime = _currentTime; + if (_globals->_gameTime <= oldGameTime) + return; + addTime(5); + if (!(_globals->_chronoFlag & 1)) + return; + _globals->_chrono -= 200; + if (_globals->_chrono == 0) + _globals->_chronoFlag |= 2; + if (!(_globals->_chronoFlag & 2)) + return; + _globals->_chronoFlag = 0; + _globals->_chrono = 0; + if (_globals->_roomCharacterType == PersonFlags::pftTyrann) { + int16 vid = 272; + if (_globals->_curRoomFlags & 0xC0) { + vid += 2; + if ((_globals->_curRoomFlags & 0xC0) != 0x80) { + vid += 2; + endDeath(vid); + return; + } + } + if (_globals->_areaNum == Areas::arUluru || _globals->_areaNum == Areas::arTamara) + endDeath(vid); + else + endDeath(vid + 1); + return; + } + if (_globals->_roomNum == 2817) { + addToParty(PER_ELOI); + _globals->_gameFlags |= GameFlags::gfFlag40; + dialautoon(); + } else + handleEloiReturn(); + _globals->_eventType = EventType::etEvent10; + showEvents(); +} + +// Original name: chronoon +void EdenGame::setChrono(int16 t) { + _globals->_chrono = t; + _globals->_chronoFlag = 1; +} + +// Original name: prechargephrases +void EdenGame::preloadDialogs(int16 vid) { + perso_t *perso = &kPersons[PER_MORKUS]; + if (vid == 170) + perso = &kPersons[PER_UNKN_156]; + _globals->_characterPtr = perso; + _globals->_dialogType = DialogType::dtInspect; + int num = (perso->_id << 3) | _globals->_dialogType; + Dialog *dial = (Dialog *)getElem(_gameDialogs, num); + dialoscansvmas(dial); +} + +// Original name: effet1 +void EdenGame::displayEffect1() { + blackRect32(); + setSrcRect(0, 0, 16 - 1, 4 - 1); + int y = _mainView->_normal._dstTop; + for (int16 i = 16; i <= 96; i += 4) { + for (int x = _mainView->_normal._dstLeft; x < _mainView->_normal._dstLeft + 320; x += 16) { + setDestRect(x, y + i, x + 16 - 1, y + i + 4 - 1); + CLBlitter_CopyViewRect(_view2, _vm->_screenView, &rect_src, &rect_dst); + setDestRect(x, y + 192 - i, x + 16 - 1, y + 192 - i + 4 - 1); + CLBlitter_CopyViewRect(_view2, _vm->_screenView, &rect_src, &rect_dst); + } + CLBlitter_UpdateScreen(); + wait(1); + } + CLPalette_Send2Screen(_globalPalette, 0, 256); + _mainView->_normal._height = 2; + _mainView->_zoom._height = 4; + int16 ny = _mainView->_normal._dstTop; + int16 dy = _mainView->_zoom._dstTop; + for (int16 i = 0; i < 100; i += 2) { + _mainView->_normal._srcTop = 99 - i; + _mainView->_zoom._srcTop = 99 - i; + _mainView->_normal._dstTop = 99 - i + ny; + _mainView->_zoom._dstTop = (99 - i) * 2 + dy; + CLBlitter_CopyView2Screen(_mainView); + _mainView->_normal._srcTop = 100 + i; + _mainView->_zoom._srcTop = 100 + i; + _mainView->_normal._dstTop = 100 + i + ny; + _mainView->_zoom._dstTop = (100 + i) * 2 + dy; + CLBlitter_CopyView2Screen(_mainView); + CLBlitter_UpdateScreen(); + wait(1); + } + _mainView->_normal._height = 200; + _mainView->_zoom._height = 400; + _mainView->_normal._srcTop = 0; + _mainView->_zoom._srcTop = 0; + _mainView->_normal._dstTop = ny; + _mainView->_zoom._dstTop = dy; + _globals->_varF1 = 0; +} + +// Original name: effet2 +void EdenGame::displayEffect2() { + static int16 pattern1[] = {0, 1, 2, 3, 7, 11, 15, 14, 13, 12, 8, 4, 5, 6, 10, 9}; + static int16 pattern2[] = {0, 15, 1, 14, 2, 13, 3, 12, 7, 8, 11, 4, 5, 10, 6, 9}; + static int16 pattern3[] = {0, 2, 5, 7, 8, 10, 13, 15, 1, 3, 4, 6, 9, 11, 12, 14}; + static int16 pattern4[] = {0, 3, 15, 12, 1, 7, 14, 8, 2, 11, 13, 4, 5, 6, 10, 9}; + + static int eff2pat = 0; + if (_globals->_var103 == 69) { + displayEffect4(); + return; + } + switch (++eff2pat) { + case 1: + colimacon(pattern1); + break; + case 2: + colimacon(pattern2); + break; + case 3: + colimacon(pattern3); + break; + case 4: + colimacon(pattern4); + eff2pat = 0; + break; + } +} + +// Original name: effet3 +void EdenGame::displayEffect3() { + CLPalette_GetLastPalette(oldPalette); + for (uint16 i = 0; i < 6; i++) { + for (uint16 c = 0; c < 256; c++) { + newColor.r = oldPalette[c].r >> i; + newColor.g = oldPalette[c].g >> i; + newColor.b = oldPalette[c].b >> i; + CLPalette_SetRGBColor(newPalette, c, &newColor); + } + CLPalette_Send2Screen(newPalette, 0, 256); + wait(1); + } + CLBlitter_CopyView2Screen(_mainView); + for (uint16 i = 0; i < 6; i++) { + for (uint16 c = 0; c < 256; c++) { + newColor.r = _globalPalette[c].r >> (5 - i); + newColor.g = _globalPalette[c].g >> (5 - i); + newColor.b = _globalPalette[c].b >> (5 - i); + CLPalette_SetRGBColor(newPalette, c, &newColor); + } + CLPalette_Send2Screen(newPalette, 0, 256); + wait(1); + } +} + +// Original name: effet4 +void EdenGame::displayEffect4() { + byte *scr, *pix, *r24, *r25, *r30, c; + int16 r17, r23, r16, r18, r19, r22, r27, r31; + CLPalette_Send2Screen(_globalPalette, 0, 256); + + int16 ww = _vm->_screenView->_pitch; + int16 x = _mainView->_normal._dstLeft; + int16 y = _mainView->_normal._dstTop; + for (int16 i = 32; i > 0; i -= 2) { + scr = _vm->_screenView->_bufferPtr; + scr += (y + 16) * ww + x; + pix = _mainView->_bufferPtr + 16 * 640; + r17 = 320 / i; + r23 = 320 - 320 / i * i; //TODO: 320 % i ? + r16 = 160 / i; + r18 = 160 - 160 / i * i; //TODO: 160 % i ? + for (r19 = r16; r19 > 0; r19--) { + r24 = scr; + r25 = pix; + for (r22 = r17; r22 > 0; r22--) { + c = *r25; + r25 += i; + r30 = r24; + for (r27 = i; r27 > 0; r27--) { + for (r31 = i; r31 > 0; r31--) + *r30++ = c; + r30 += ww - i; + } + r24 += i; + } + if (r23) { + c = *r25; + r30 = r24; + for (r27 = i; r27 > 0; r27--) { + for (r31 = r23; r31 > 0; r31--) + *r30++ = c; + r30 += ww - r23; + } + } + scr += i * ww; + pix += i * 640; + } + if (r18) { + r24 = scr; + r25 = pix; + for (r22 = r17; r22 > 0; r22--) { + c = *r25; + r25 += i; + r30 = r24; + for (r27 = r18; r27 > 0; r27--) { + for (r31 = i; r31 > 0; r31--) + *r30++ = c; + r30 += ww - i; + } + r24 += i; + } + if (r23) { + c = *r25; + r30 = r24; + for (r27 = r18; r27 > 0; r27--) { + for (r31 = r23; r31 > 0; r31--) + *r30++ = c; + r30 += ww - r23; + } + } + } + CLBlitter_UpdateScreen(); + wait(3); + } + CLBlitter_CopyView2Screen(_mainView); +} + +void EdenGame::clearScreen() { + int16 ww = _vm->_screenView->_pitch; + int16 x = _mainView->_normal._dstLeft; + int16 y = _mainView->_normal._dstTop; + byte *scr = _vm->_screenView->_bufferPtr; + scr += (y + 16) * ww + x; + for (int16 yy = 0; yy < 160; yy++) { + for (int16 xx = 0; xx < 320; xx++) + *scr++ = 0; + scr += ww - 320; + } + CLBlitter_UpdateScreen(); +} + +void EdenGame::colimacon(int16 pattern[16]) { + int16 p, r27, r25; + + int16 ww = _vm->_screenView->_pitch; + int16 x = _mainView->_normal._dstLeft; + int16 y = _mainView->_normal._dstTop; + byte *scr = _vm->_screenView->_bufferPtr; + scr += (y + 16) * ww + x; + for (int16 i = 0; i < 16; i++) { + p = pattern[i]; + r27 = p % 4 + p / 4 * ww; + for (int16 j = 0; j < 320 * 160 / 16; j++) + scr[j / (320 / 4) * ww * 4 + j % (320 / 4) * 4 + r27] = 0; + CLBlitter_UpdateScreen(); + wait(1); + } + CLPalette_Send2Screen(_globalPalette, 0, 256); + byte *pix = _mainView->_bufferPtr; + x = _mainView->_normal._dstLeft; + y = _mainView->_normal._dstTop; + pix += 640 * 16; + scr = _vm->_screenView->_bufferPtr; + scr += (y + 16) * ww + x; + for (int16 i = 0; i < 16; i++) { + p = pattern[i]; + r25 = p % 4 + p / 4 * 640; + r27 = p % 4 + p / 4 * ww; + for (int16 j = 0; j < 320 * 160 / 16; j++) + scr[j / (320 / 4) * ww * 4 + j % (320 / 4) * 4 + r27] = + pix[j / (320 / 4) * 640 * 4 + j % (320 / 4) * 4 + r25]; + CLBlitter_UpdateScreen(); + wait(1); + } +} + +void EdenGame::fadeToBlack(int delay) { + CLPalette_GetLastPalette(oldPalette); + for (int16 i = 0; i < 6; i++) { + for (int16 j = 0; j < 256; j++) { + newColor.r = oldPalette[j].r >> i; + newColor.g = oldPalette[j].g >> i; + newColor.b = oldPalette[j].b >> i; + CLPalette_SetRGBColor(newPalette, j, &newColor); + } + CLPalette_Send2Screen(newPalette, 0, 256); + wait(delay); + } +} + +// Original name: fadetoblack128 +void EdenGame::fadeToBlackLowPalette(int delay) { + CLPalette_GetLastPalette(oldPalette); + for (int16 i = 0; i < 6; i++) { + for (int16 j = 0; j < 129; j++) { //CHECKME: Should be 128? + newColor.r = oldPalette[j].r >> i; + newColor.g = oldPalette[j].g >> i; + newColor.b = oldPalette[j].b >> i; + CLPalette_SetRGBColor(newPalette, j, &newColor); + } + CLPalette_Send2Screen(newPalette, 0, 128); + wait(delay); + } +} + +// Original name: fadefromblack128 +void EdenGame::fadeFromBlackLowPalette(int delay) { + for (int16 i = 0; i < 6; i++) { + for (int16 j = 0; j < 129; j++) { //CHECKME: Should be 128? + newColor.r = _globalPalette[j].r >> (5 - i); + newColor.g = _globalPalette[j].g >> (5 - i); + newColor.b = _globalPalette[j].b >> (5 - i); + CLPalette_SetRGBColor(newPalette, j, &newColor); + } + CLPalette_Send2Screen(newPalette, 0, 128); + wait(delay); + } +} + +// Original name: rectanglenoir32 +void EdenGame::blackRect32() { + // blacken 32x32 rectangle + int *pix = (int *)_view2Buf; + for (int16 i = 0; i < 32; i++) { + pix[0] = 0; + pix[1] = 0; + pix[2] = 0; + pix[3] = 0; + pix[4] = 0; + pix[5] = 0; + pix[6] = 0; + pix[7] = 0; + pix += 32 / 4; + } +} + +void EdenGame::setSrcRect(int16 sx, int16 sy, int16 ex, int16 ey) { + rect_src = Common::Rect(sx, sy, ex, ey); +} + +void EdenGame::setDestRect(int16 sx, int16 sy, int16 ex, int16 ey) { + rect_dst = Common::Rect(sx, sy, ex, ey); +} + +void EdenGame::wait(int howlong) { + int t = g_system->getMillis(); + + for (int t2 = t; t2 - t < howlong; t2 = g_system->getMillis()) + g_system->delayMillis(10); // waste time +} + +void EdenGame::effetpix() { + uint16 r25, r18, r31, r30; //TODO: change to xx/yy + + uint16 ww = _vm->_screenView->_pitch; + r25 = ww * 80; + r18 = 640 * 80; + byte *pix = _mainView->_bufferPtr + 16 * 640; + int x = _mainView->_normal._dstLeft; + int y = _mainView->_normal._dstTop; + byte *scr = _vm->_screenView->_bufferPtr; + scr += (y + 16) * ww + x; + int16 r20 = 0x4400; //TODO + int16 r27 = 1; + int16 r26 = 0; + do { + char r8 = r27 & 1; + r27 >>= 1; + if (r8) + r27 ^= r20; + if (r27 < 320 * 80) { + r31 = r27 / 320; + r30 = r27 % 320; + scr[r31 * ww + r30] = 0; + scr[r31 * ww + r25 + r30] = 0; + if (++r26 == 960) { + CLBlitter_UpdateScreen(); + wait(1); + r26 = 0; + } + } + } while (r27 != 1); + CLPalette_Send2Screen(_globalPalette, 0, 256); + r20 = 0x4400; + r27 = 1; + r26 = 0; + do { + char r8 = r27 & 1; + r27 >>= 1; + if (r8) + r27 ^= r20; + if (r27 < 320 * 80) { + r31 = r27 / 320; + r30 = r27 % 320; + byte p0 = pix[r31 * 640 + r30]; + byte p1 = pix[r31 * 640 + r18 + r30]; + scr[r31 * ww + r30] = p0; + scr[r31 * ww + r25 + r30] = p1; + if (++r26 == 960) { + CLBlitter_UpdateScreen(); + wait(1); + r26 = 0; + } + } + } while (r27 != 1); + assert(_vm->_screenView->_pitch == 320); +} + +////// datfile.c +void EdenGame::verifh(byte *ptr) { + byte sum = 0; + byte *head = ptr; + + for (int8 i = 0; i < 6; i++) + sum += *head++; + + if (sum != 0xAB) + return; + + debug("* Begin unpacking resource"); + head -= 6; + uint16 h0 = READ_LE_UINT16(head); + // 3 = 2 bytes for the uint16 and 1 byte for an unused char + head += 3; + uint16 h3 = READ_LE_UINT16(head); + head += 2; + byte *data = h0 + head + 26; + h3 -= 6; + head += h3; + for (; h3; h3--) + *data-- = *head--; + head = data + 1; + data = ptr; + expandHSQ(head, data); +} + +void EdenGame::openbigfile() { + _bigfile.open("EDEN.DAT"); + + char buf[16]; + int count = _bigfile.readUint16LE(); + _bigfileHeader = new PakHeaderNode(count); + for (int j = 0; j < count; j++) { + for (int k = 0; k < 16; k++) + buf[k] = _bigfile.readByte(); + _bigfileHeader->_files[j]._name = Common::String(buf); + _bigfileHeader->_files[j]._size = _bigfile.readUint32LE(); + _bigfileHeader->_files[j]._offs = _bigfile.readUint32LE(); + _bigfileHeader->_files[j]._flag = _bigfile.readByte(); + } + + _vm->_video->resetInternals(); + _vm->_video->setFile(&_bigfile); +} + +void EdenGame::closebigfile() { + _bigfile.close(); +} + +void EdenGame::loadRawFile(uint16 num, byte *buffer) { + if (_vm->getPlatform() == Common::kPlatformDOS) { + if ((_vm->isDemo() && num > 2204) || num > 2472) + error("Trying to read invalid game resource"); + } + + assert(num < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[num]; + int32 size = file->_size; + int32 offs = file->_offs; + + _bigfile.seek(offs, SEEK_SET); + _bigfile.read(buffer, size); +} + +void EdenGame::loadIconFile(uint16 num, Icon *buffer) { + if (_vm->getPlatform() == Common::kPlatformDOS) { + if ((_vm->isDemo() && num > 2204) || num > 2472) + error("Trying to read invalid game resource"); + } + + assert(num < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[num]; + int32 size = file->_size; + int32 offs = file->_offs; + debug("* Loading icon - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size); + _bigfile.seek(offs, SEEK_SET); + + int count = size / sizeof(Icon); + for (int i = 0; i < count; i++) { + if (_vm->getPlatform() == Common::kPlatformMacintosh) { + buffer[i].sx = _bigfile.readSint16BE(); + buffer[i].sy = _bigfile.readSint16BE(); + buffer[i].ex = _bigfile.readSint16BE(); + buffer[i].ey = _bigfile.readSint16BE(); + buffer[i]._cursorId = _bigfile.readUint16BE();; + buffer[i]._actionId= _bigfile.readUint32BE();; + buffer[i]._objectId= _bigfile.readUint32BE();; + } else { + buffer[i].sx = _bigfile.readSint16LE(); + buffer[i].sy = _bigfile.readSint16LE(); + buffer[i].ex = _bigfile.readSint16LE(); + buffer[i].ey = _bigfile.readSint16LE(); + buffer[i]._cursorId = _bigfile.readUint16LE();; + buffer[i]._actionId= _bigfile.readUint32LE();; + buffer[i]._objectId= _bigfile.readUint32LE();; + } + } +} + +void EdenGame::loadRoomFile(uint16 num, Room *buffer) { + if (_vm->getPlatform() == Common::kPlatformDOS) { + if ((_vm->isDemo() && num > 2204) || num > 2472) + error("Trying to read invalid game resource"); + } + + assert(num < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[num]; + int32 size = file->_size; + int32 offs = file->_offs; + debug("* Loading room - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size); + _bigfile.seek(offs, SEEK_SET); + + int count = size / sizeof(Room); + for (int i = 0; i < count; i++) { + buffer[i]._id = _bigfile.readByte(); + for (int j = 0; j < 4; j++) + buffer[i]._exits[j] = _bigfile.readByte(); + buffer[i]._flags = _bigfile.readByte(); + if (_vm->getPlatform() == Common::kPlatformMacintosh) { + buffer[i]._bank = _bigfile.readUint16BE(); + buffer[i]._party = _bigfile.readUint16BE(); + } else { + buffer[i]._bank = _bigfile.readUint16LE(); + buffer[i]._party = _bigfile.readUint16LE(); + } + buffer[i]._level = _bigfile.readByte(); + buffer[i]._video = _bigfile.readByte(); + buffer[i]._location = _bigfile.readByte(); + buffer[i]._backgroundBankNum = _bigfile.readByte(); + } +} + +// Original name: shnmfl +void EdenGame::loadHnm(uint16 num) { + unsigned int resNum = num - 1 + 485; + assert(resNum < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[resNum]; + int size = file->_size; + int offs = file->_offs; + debug("* Loading movie %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), (uint)offs, size); + _vm->_video->_file->seek(offs, SEEK_SET); +} + +// Original name: ssndfl +int EdenGame::loadSound(uint16 num) { + unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661); + assert(resNum < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[resNum]; + int32 size = file->_size; + int32 offs = file->_offs; + debug("* Loading sound %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), (uint)offs, size); + if (_soundAllocated) { + free(_voiceSamplesBuffer); + _voiceSamplesBuffer = nullptr; + _soundAllocated = false; //TODO: bug??? no alloc + } else { + _voiceSamplesBuffer = (byte *)malloc(size); + _soundAllocated = true; + } + + _bigfile.seek(offs, SEEK_SET); + //For PC loaded data is a VOC file, on Mac version this is a raw samples + if (_vm->getPlatform() == Common::kPlatformMacintosh) + _bigfile.read(_voiceSamplesBuffer, size); + else { + // VOC files also include extra information for lipsync + // 1. Standard VOC header + _bigfile.read(_voiceSamplesBuffer, 0x1A); + + // 2. Lipsync? + unsigned char chunkType = _bigfile.readByte(); + + uint32 val = 0; + _bigfile.read(&val, 3); + unsigned int chunkLen = LE32(val); + + if (chunkType == 5) { + _bigfile.read(_gameLipsync + 7260, chunkLen); + chunkType = _bigfile.readByte(); + _bigfile.read(&val, 3); + chunkLen = LE32(val); + } + + // 3. Normal sound data + if (chunkType == 1) { + _bigfile.readUint16LE(); + size = chunkLen - 2; + _bigfile.read(_voiceSamplesBuffer, size); + } + } + + return size; +} + +void EdenGame::convertMacToPC() { + // Convert all mac (big-endian) resources to native format + // Array of longs + int *p = (int *)_gameLipsync; + for (int i = 0; i < 7240 / 4; i++) + p[i] = BE32(p[i]); +} + +void EdenGame::loadpermfiles() { + switch (_vm->getPlatform()) { + case Common::kPlatformDOS: + { + // Since PC version stores hotspots and rooms info in the executable, load them from premade resource file + Common::File f; + + if (f.open("led.dat")) { + const int kNumIcons = 136; + const int kNumRooms = 424; + if (f.size() != kNumIcons * sizeof(Icon) + kNumRooms * sizeof(Room)) + error("Mismatching aux data"); + for (int i = 0; i < kNumIcons; i++) { + _gameIcons[i].sx = f.readSint16LE(); + _gameIcons[i].sy = f.readSint16LE(); + _gameIcons[i].ex = f.readSint16LE(); + _gameIcons[i].ey = f.readSint16LE(); + _gameIcons[i]._cursorId = f.readUint16LE(); + _gameIcons[i]._actionId = f.readUint32LE(); + _gameIcons[i]._objectId = f.readUint32LE(); + } + + for (int i = 0; i <kNumRooms; i++) { + _gameRooms[i]._id = f.readByte(); + for (int j = 0; j < 4; j++) + _gameRooms[i]._exits[j] = f.readByte(); + _gameRooms[i]._flags = f.readByte(); + _gameRooms[i]._bank = f.readUint16LE(); + _gameRooms[i]._party = f.readUint16LE(); + _gameRooms[i]._level = f.readByte(); + _gameRooms[i]._video = f.readByte(); + _gameRooms[i]._location = f.readByte(); + _gameRooms[i]._backgroundBankNum = f.readByte(); + } + + f.close(); + } else + error("Can not load aux data"); + } + break; + case Common::kPlatformMacintosh: + loadIconFile(2498, _gameIcons); + loadRoomFile(2497, _gameRooms); + loadRawFile(2486, _gameLipsync); + convertMacToPC(); + break; + default: + error("Unsupported platform"); + } + + loadRawFile(0, _mainBankBuf); + loadRawFile(402, _gameFont); + loadRawFile(404, _gameDialogs); + loadRawFile(403, _gameConditions); +} + +bool EdenGame::ReadDataSyncVOC(unsigned int num) { + unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661); + unsigned char vocHeader[0x1A]; + int filePos = 0; + loadpartoffile(resNum, vocHeader, filePos, sizeof(vocHeader)); + filePos += sizeof(vocHeader); + unsigned char chunkType = 0; + loadpartoffile(resNum, &chunkType, sizeof(vocHeader), 1); + filePos++; + if (chunkType == 5) { + uint32 chunkLen = 0; + loadpartoffile(resNum, &chunkLen, filePos, 3); + filePos += 3; + chunkLen = LE32(chunkLen); + loadpartoffile(resNum, _gameLipsync + 7260, filePos, chunkLen); + return true; + } + return false; +} + +bool EdenGame::ReadDataSync(uint16 num) { + if (_vm->getPlatform() == Common::kPlatformMacintosh) { + long pos = READ_LE_UINT32(_gameLipsync + num * 4); + if (pos != -1) { + long len = 1024; + loadpartoffile(1936, _gameLipsync + 7260, pos, len); + return true; + } + } else + return ReadDataSyncVOC(num + 1); //TODO: remove -1 in caller + return false; +} + +void EdenGame::loadpartoffile(uint16 num, void *buffer, int32 pos, int32 len) { + assert(num < _bigfileHeader->_count); + PakHeaderItem *file = &_bigfileHeader->_files[num]; + int32 offs = READ_LE_UINT32(&file->_offs); + debug("* Loading partial resource %d (%s) at 0x%X(+0x%X), %d bytes", num, file->_name.c_str(), offs, pos, len); + _bigfile.seek(offs + pos, SEEK_SET); + _bigfile.read(buffer, len); +} + +void EdenGame::expandHSQ(byte *input, byte *output) { + byte *src = input; + byte *dst = output; + byte *ptr; + uint16 bit; // bit + uint16 queue = 0; // queue + uint16 len = 0; + int16 ofs; +#define GetBit \ + bit = queue & 1; \ + queue >>= 1; \ + if (!queue) { \ + queue = (src[1] << 8) | src[0]; src += 2; \ + bit = queue & 1; \ + queue = (queue >> 1) | 0x8000; \ + } + + for (;;) { + GetBit; + if (bit) + *dst++ = *src++; + else { + len = 0; + GetBit; + if (!bit) { + GetBit; + len = (len << 1) | bit; + GetBit; + len = (len << 1) | bit; + ofs = 0xFF00 | *src++; //TODO: -256 + } else { + ofs = (src[1] << 8) | src[0]; + src += 2; + len = ofs & 7; + ofs = (ofs >> 3) | 0xE000; + if (!len) { + len = *src++; + if (!len) + break; + } + } + ptr = dst + ofs; + len += 2; + while (len--) + *dst++ = *ptr++; + } + } +} + +////// + +// Original name: ajouinfo +void EdenGame::addInfo(byte info) { + byte idx = _globals->_nextInfoIdx; + if (kPersons[PER_ELOI]._roomNum) + info |= 0x80; + _infoList[idx] = info; + if (idx == _globals->_lastInfoIdx) + _globals->_lastInfo = info; + idx++; + if (idx == 16) + idx = 0; + _globals->_nextInfoIdx = idx; +} + +void EdenGame::unlockInfo() { + for (byte idx = 0; idx < 16; idx++) { + if (_infoList[idx] != 0xFF) + _infoList[idx] &= ~0x80; + } + _globals->_lastInfo &= ~0x80; +} + +void EdenGame::nextInfo() { + do { + byte idx = _globals->_lastInfoIdx; + _infoList[idx] = 0; + idx++; + if (idx == 16) + idx = 0; + _globals->_lastInfoIdx = idx; + _globals->_lastInfo = _infoList[idx]; + } while (_globals->_lastInfo == 0xFF); +} + +// Original name: delinfo +void EdenGame::removeInfo(byte info) { + for (byte idx = 0; idx < 16; idx++) { + if ((_infoList[idx] & ~0x80) == info) { + _infoList[idx] = 0xFF; + if (idx == _globals->_lastInfoIdx) + nextInfo(); + break; + } + } +} + +void EdenGame::updateInfoList() { + for (int idx = 0; idx < 16; idx++) + _infoList[idx] = 0; +} + +void EdenGame::initGlobals() { + _gameIcons[16]._cursorId |= 0x8000; + + _globals->_areaNum = Areas::arMo; + _globals->_areaVisitCount = 1; + _globals->_menuItemIdLo = 0; + _globals->_menuItemIdHi = 0; + _globals->_randomNumber = 0; + _globals->_gameTime = 0; + _globals->_gameDays = 0; + _globals->_chrono = 0; + _globals->_eloiDepartureDay = 0; + _globals->_roomNum = 259; + _globals->_newRoomNum = 0; + _globals->_phaseNum = 0; + _globals->_metPersonsMask1 = 0; + _globals->_party = 0; + _globals->_partyOutside = 0; + _globals->_metPersonsMask2 = 0; + _globals->_phaseActionsCount = 0; + _globals->_curAreaFlags = 0; + _globals->_curItemsMask = 0; + _globals->_curPowersMask = 0; + _globals->_curPersoItems = 0; + _globals->_curCharacterPowers = 0; + _globals->_wonItemsMask = 0; + _globals->_wonPowersMask = 0; + _globals->_stepsToFindAppleFast = 0; + _globals->_stepsToFindAppleNormal = 0; + _globals->_roomPersoItems = 0; + _globals->_roomCharacterPowers = 0; + _globals->_gameFlags = GameFlags::gfNone; + _globals->_curVideoNum = 0; + _globals->_morkusSpyVideoNum1 = 89; + _globals->_morkusSpyVideoNum2 = 88; + _globals->_morkusSpyVideoNum3 = 83; + _globals->_morkusSpyVideoNum4 = 94; + _globals->_newMusicType = MusicType::mtDontChange; + _globals->_var43 = 0; + _globals->_videoSubtitleIndex = 0; + _globals->_partyInstruments = 0; + _globals->_monkGotRing = 0; + _globals->_chronoFlag = 0; + _globals->_curRoomFlags = 0; + _globals->_endGameFlag = 0; + _globals->_lastInfo = 0; + _globals->_autoDialog = false; + _globals->_worldTyranSighted = 0; + _globals->_var4D = 0; + _globals->_var4E = 0; + _globals->_worldGaveGold = 0; + _globals->_worldHasTriceraptors = 0; + _globals->_worldHasVelociraptors = 0; + _globals->_worldHasTyran = 0; + _globals->_var53 = 0; + _globals->_var54 = 0; + _globals->_var55 = 0; + _globals->_gameHours = 0; + _globals->_textToken1 = 0; + _globals->_textToken2 = 0; + _globals->_eloiHaveNews = 0; + _globals->_dialogFlags = 0; + _globals->_curAreaType = 0; + _globals->_curCitadelLevel = 0; + _globals->_newLocation = 0; + _globals->_prevLocation = 0; + _globals->_curPersoFlags = 0; + _globals->_var60 = 0; + _globals->_eventType = EventType::etEvent5; + _globals->_var62 = 0; + _globals->_curObjectId = 0; + _globals->_curObjectFlags = 0; + _globals->_var65 = 1; + _globals->_roomCharacterType = 0; + _globals->_roomCharacterFlags = 0; + _globals->_narratorSequence = 0; + _globals->_var69 = 0; + _globals->_var6A = 0; + _globals->_frescoNumber = 0; + _globals->_var6C = 0; + _globals->_var6D = 0; + _globals->_labyrinthDirections = 0; + _globals->_labyrinthRoom = 0; + _globals->_curCharacterAnimPtr = nullptr; + _globals->_characterImageBank = 0; + _globals->_roomImgBank = 0; + _globals->_characterBackgroundBankIdx = 55; + _globals->_varD4 = 0; + _globals->_frescoeWidth = 0; + _globals->_frescoeImgBank = 0; + _globals->_varDA = 0; + _globals->_varDC = 0; + _globals->_roomBaseX = 0; + _globals->_varE0 = 0; + _globals->_dialogType = DialogType::dtTalk; + _globals->_varE4 = 0; + _globals->_currMusicNum = 0; + _globals->_textNum = 0; + _globals->_travelTime = 0; + _globals->_varEC = 0; + _globals->_displayFlags = DisplayFlags::dfFlag1; + _globals->_oldDisplayFlags = 1; + _globals->_drawFlags = 0; + _globals->_varF1 = 0; + _globals->_varF2 = 0; + _globals->_menuFlags = 0; + _globals->_varF5 = 0; + _globals->_varF6 = 0; + _globals->_varF7 = 0; + _globals->_varF8 = 0; + _globals->_varF9 = 0; + _globals->_varFA = 0; + _globals->_animationFlags = 0; + _globals->_giveObj1 = 0; + _globals->_giveObj2 = 0; + _globals->_giveObj3 = 0; + _globals->_var100 = 0; + _globals->_roomVidNum = 0; + _globals->_mirrorEffect = 0; + _globals->_var103 = 0; + _globals->_roomBackgroundBankNum = 0; + _globals->_valleyVidNum = 0; + _globals->_updatePaletteFlag = 0; + _globals->_inventoryScrollPos = 0; + _globals->_objCount = 0; + _globals->_textBankIndex = 69; + _globals->_citadelAreaNum = 0; + _globals->_var113 = 0; + _globals->_lastPlaceNum = 0; + _globals->_dialogPtr = nullptr; + _globals->_tapePtr = _tapes; + _globals->_nextDialogPtr = nullptr; + _globals->_narratorDialogPtr = nullptr; + _globals->_lastDialogPtr = nullptr; + _globals->_nextRoomIcon = nullptr; + _globals->_sentenceBufferPtr = nullptr; + _globals->_roomPtr = nullptr; + _globals->_areaPtr = nullptr; + _globals->_lastAreaPtr = nullptr; + _globals->_curAreaPtr = nullptr; + _globals->_citaAreaFirstRoom = 0; + _globals->_characterPtr = nullptr; + _globals->_roomCharacterPtr = 0; + _globals->_lastInfoIdx = 0; + _globals->_nextInfoIdx = 0; + _globals->_iconsIndex = 16; + _globals->_persoSpritePtr = nullptr; + _globals->_numGiveObjs = 0; + + initRects(); + + _underSubtitlesScreenRect.top = 0; + _underSubtitlesScreenRect.left = _subtitlesXScrMargin; + _underSubtitlesScreenRect.right = _subtitlesXScrMargin + _subtitlesXWidth - 1; + _underSubtitlesScreenRect.bottom = 176 - 1; + + _underSubtitlesBackupRect.top = 0; + _underSubtitlesBackupRect.left = _subtitlesXScrMargin; + _underSubtitlesBackupRect.right = _subtitlesXScrMargin + _subtitlesXWidth - 1; + _underSubtitlesBackupRect.bottom = 60 - 1; +} + +void EdenGame::initRects() { + _underTopBarScreenRect = Common::Rect(0, 0, 320 - 1, 16 - 1); + _underTopBarBackupRect = Common::Rect(0, 0, 320 - 1, 16 - 1); + _underBottomBarScreenRect = Common::Rect(0, 176, 320 - 1, 200 - 1); //TODO: original bug? this cause crash in copyrect (this, underBottomBarBackupRect) + _underBottomBarBackupRect = Common::Rect(0, 16, 320 - 1, 40 - 1); +} + +// Original name: closesalle +void EdenGame::closeRoom() { + if (_globals->_displayFlags & DisplayFlags::dfPanable) { + _globals->_displayFlags &= ~DisplayFlags::dfPanable; + resetScroll(); + } +} + +// Original name afsalle1 +void EdenGame::displaySingleRoom(Room *room) { + byte *ptr = (byte *)getElem(_placeRawBuf, room->_id - 1); + ptr++; + for (;;) { + byte b0 = *ptr++; + byte b1 = *ptr++; + int16 index = (b1 << 8) | b0; + if (index == -1) + break; + if (index > 0) { + int16 x = *ptr++ | (((b1 & 0x2) >> 1) << 8); //TODO: check me + int16 y = *ptr++; + ptr++; + index &= 0x1FF; + if (!(_globals->_displayFlags & 0x80)) { + if (index == 1 || _globals->_varF7) + noclipax_avecnoir(index - 1, x, y); + } + _globals->_varF7 = 0; + continue; + } + if (b1 & 0x40) { + if (b1 & 0x20) { + bool addIcon = false; + Icon *icon = _globals->_nextRoomIcon; + if (b0 < 4) { + if (_globals->_roomPtr->_exits[b0]) + addIcon = true; + } else if (b0 > 229) { + if (_globals->_partyOutside & (1 << (b0 - 230))) + addIcon = true; + } else if (b0 >= 100) { + debug("add object %d", b0 - 100); + if (isObjectHere(b0 - 100)) { + addIcon = true; + _globals->_varF7 = 1; + } + } else + addIcon = true; + if (addIcon) { + icon->_actionId = b0; + icon->_objectId = b0; + icon->_cursorId = kActionCursors[b0]; + int16 x = READ_LE_UINT16(ptr); + ptr += 2; + int16 y = READ_LE_UINT16(ptr); + ptr += 2; + int16 ex = READ_LE_UINT16(ptr); + ptr += 2; + int16 ey = READ_LE_UINT16(ptr); + ptr += 2; + x += _globals->_roomBaseX; + ex += _globals->_roomBaseX; + debug("add hotspot at %3d:%3d - %3d:%3d, action = %d", x, y, ex, ey, b0); + + if (_vm->_showHotspots) { + for (int iii = x; iii < ex; iii++) + _mainViewBuf[y * 640 + iii] = _mainViewBuf[ey * 640 + iii] = (iii % 2) ? 0 : 255; + for (int iii = y; iii < ey; iii++) + _mainViewBuf[iii * 640 + x] = _mainViewBuf[iii * 640 + ex] = (iii % 2) ? 0 : 255; + } + + icon->sx = x; + icon->sy = y; + icon->ex = ex; + icon->ey = ey; + _globals->_nextRoomIcon = ++icon; + icon->sx = -1; + } else + ptr += 8; + } else + ptr += 8; + } else + ptr += 8; + } +} + +// Original name: afsalle +void EdenGame::displayRoom() { + Room *room = _globals->_roomPtr; + _globals->_displayFlags = DisplayFlags::dfFlag1; + _globals->_roomBaseX = 0; + _globals->_roomBackgroundBankNum = room->_backgroundBankNum; + if (room->_flags & RoomFlags::rf08) { + _globals->_displayFlags |= DisplayFlags::dfFlag80; + if (room->_flags & RoomFlags::rfPanable) { + // Scrollable room on 2 screens + _globals->_displayFlags |= DisplayFlags::dfPanable; + _globals->_varF4 = 0; + rundcurs(); + saveFriezes(); + useBank(room->_bank - 1); + noclipax_avecnoir(0, 0, 16); + useBank(room->_bank); + noclipax_avecnoir(0, 320, 16); + displaySingleRoom(room); + _globals->_roomBaseX = 320; + displaySingleRoom(room + 1); + } else + displaySingleRoom(room); + } else { + //TODO: roomImgBank is garbage here! + debug("displayRoom: room 0x%X using bank %d", _globals->_roomNum, _globals->_roomImgBank); + useBank(_globals->_roomImgBank); + displaySingleRoom(room); + assert(_vm->_screenView->_pitch == 320); + } +} + +// Original name: aflieu +void EdenGame::displayPlace() { + no_perso(); + if (!_vm->shouldQuit()) { + _globals->_iconsIndex = 16; + _globals->_autoDialog = false; + } + _globals->_nextRoomIcon = &_gameIcons[_roomIconsBase]; + displayRoom(); + _paletteUpdateRequired = true; +} + +// Original name: loadsal +void EdenGame::loadPlace(int16 num) { + if (num == _globals->_lastPlaceNum) + return; + _globals->_lastPlaceNum = num; + loadRawFile(num + 419, _placeRawBuf); +} + +void EdenGame::specialoutside() { + if (_globals->_lastAreaPtr->_type == AreaType::atValley && (_globals->_party & PersonMask::pmLeader)) + perso_ici(5); +} + +void EdenGame::specialout() { + if (_globals->_gameDays - _globals->_eloiDepartureDay > 2) { + if (checkEloiReturn()) + handleEloiReturn(); + } + + if (_globals->_phaseNum >= 32 && _globals->_phaseNum < 48) { + if (_globals->_newLocation == 9 || _globals->_newLocation == 4 || _globals->_newLocation == 24) { + kPersons[PER_ELOI]._roomNum = 263; + return; + } + } + + if ((_globals->_phaseNum == 434) && (_globals->_newLocation == 5)) { + removeFromParty(PER_JABBER); + kPersons[PER_JABBER]._roomNum = 264; + return; + } + + if (_globals->_phaseNum < 400) { + if ((_globals->_gameFlags & GameFlags::gfFlag4000) && _globals->_prevLocation == 1 + && (_globals->_party & PersonMask::pmEloi) && _globals->_curAreaType == AreaType::atValley) + handleEloiDeparture(); + } + + if (_globals->_phaseNum == 386) { + if (_globals->_prevLocation == 1 + && (_globals->_party & PersonMask::pmEloi) && _globals->_areaNum == Areas::arCantura) + handleEloiDeparture(); + } +} + +void EdenGame::specialin() { + if (!(_globals->_party & PersonMask::pmEloi) && (_globals->_partyOutside & PersonMask::pmEloi) && (_globals->_roomNum & 0xFF) == 1) { + addToParty(PER_ELOI); + _globals->_eloiHaveNews = 1; + } + if (_globals->_roomNum == 288) + _globals->_gameFlags |= GameFlags::gfFlag100 | GameFlags::gfFlag2000; + if (_globals->_roomNum == 3075 && _globals->_phaseNum == 546) { + incPhase(); + if (_globals->_curItemsMask & 0x2000) { // Morkus' tablet + hideBars(); + playHNM(92); + _gameRooms[129]._exits[0] = 0; + _gameRooms[129]._exits[2] = 1; + _globals->_roomNum = 3074; + kPersons[PER_MUNGO]._roomNum = 3074; + _globals->_eventType = EventType::etEvent5; + updateRoom(_globals->_roomNum); + return; + } + _globals->_narratorSequence = 53; + } + if (_globals->_roomNum == 1793 && _globals->_phaseNum == 336) + handleEloiDeparture(); + if (_globals->_roomNum == 259 && _globals->_phaseNum == 129) + _globals->_narratorSequence = 12; + if (_globals->_roomNum >= 289 && _globals->_roomNum < 359) + _globals->_labyrinthDirections = kLabyrinthPath[(_globals->_roomNum & 0xFF) - 33]; + if (_globals->_roomNum == 305 && _globals->_prevLocation == 103) + _globals->_gameFlags &= ~GameFlags::gfFlag2000; + if (_globals->_roomNum == 304 && _globals->_prevLocation == 105) + _globals->_gameFlags &= ~GameFlags::gfFlag2000; + if (_globals->_phaseNum < 226) { + if (_globals->_roomNum == 842) + _globals->_gameFlags |= GameFlags::gfFlag2; + if (_globals->_roomNum == 1072) + _globals->_gameFlags |= GameFlags::gfFlag4; + if (_globals->_roomNum == 1329) + _globals->_gameFlags |= GameFlags::gfFlag8000; + } +} + +void EdenGame::animpiece() { + Room *room = _globals->_roomPtr; + if (_globals->_roomVidNum && _globals->_var100 != 0xFF) { + if (_globals->_valleyVidNum || !room->_level || (room->_flags & RoomFlags::rfHasCitadel) + || room->_level == _globals->_var100) { + hideBars(); + _globals->_updatePaletteFlag = 16; + if (!(_globals->_narratorSequence & 0x80)) //TODO: bug? !() @ 100DC + _globals->_mirrorEffect = 0; + if (!_needToFade) + _needToFade = room->_flags & RoomFlags::rf02; + playHNM(_globals->_roomVidNum); + return; + } + } + _globals->_varF1 &= ~RoomFlags::rf04; +} + +void EdenGame::getdino(Room *room) { + assert(tab_2CEF0[4] == 0x25); + + room->_flags &= ~0xC; + for (perso_t *perso = &kPersons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) { + if (perso->_flags & PersonFlags::pf80) + continue; + if (perso->_roomNum != _globals->_roomNum) + continue; + byte persoType = perso->_flags & PersonFlags::pfTypeMask; + if (persoType == PersonFlags::pftVelociraptor) + removeInfo(_globals->_citadelAreaNum + ValleyNews::vnVelociraptorsIn); + if (persoType == PersonFlags::pftTriceraptor) + removeInfo(_globals->_citadelAreaNum + ValleyNews::vnTriceraptorsIn); + perso->_flags |= PersonFlags::pf20; + int16 *tab = tab_2CF70; + if (_globals->_areaNum != Areas::arUluru && _globals->_areaNum != Areas::arTamara) + tab = tab_2CEF0; + byte r27 = (room->_flags & 0xC0) >> 2; //TODO: check me (like pc) + persoType = perso->_flags & PersonFlags::pfTypeMask; + if (persoType == PersonFlags::pftTyrann) + persoType = 13; + r27 |= (persoType & 7) << 1; //TODO: check me 13 & 7 = ??? + tab += r27; + _globals->_roomVidNum = *tab++; + int16 bank = *tab; + if (bank & 0x8000) { + bank &= ~0x8000; + room->_flags |= RoomFlags::rf08; + } + room->_flags |= RoomFlags::rf04 | RoomFlags::rf02; + _globals->_roomImgBank = bank; + break; + } +} + +// Original name: getsalle +Room *EdenGame::getRoom(int16 loc) { //TODO: byte? + debug("get room for %X, starting from %d, looking for %X", loc, _globals->_areaPtr->_firstRoomIdx, _globals->_partyOutside); + Room *room = &_gameRooms[_globals->_areaPtr->_firstRoomIdx]; + loc &= 0xFF; + for (;; room++) { + for (; room->_location != loc; room++) { + if (room->_id == 0xFF) + return nullptr; + } + if (_globals->_partyOutside == room->_party || room->_party == 0xFFFF) + break; + } + debug("found room: party = %X, bank = %X", room->_party, room->_bank); + _globals->_roomImgBank = room->_bank; + _globals->_labyrinthRoom = 0; + if (_globals->_roomImgBank > 104 && _globals->_roomImgBank <= 112) + _globals->_labyrinthRoom = _globals->_roomImgBank - 103; + if (_globals->_valleyVidNum) + _globals->_roomVidNum = _globals->_valleyVidNum; + else + _globals->_roomVidNum = room->_video; + if ((room->_flags & 0xC0) == RoomFlags::rf40 || (room->_flags & RoomFlags::rf01)) + getdino(room); + if (room->_flags & RoomFlags::rfHasCitadel) { + removeInfo(_globals->_areaNum + ValleyNews::vnCitadelLost); + removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn); + removeInfo(_globals->_areaNum + ValleyNews::vnTyrannLost); + removeInfo(_globals->_areaNum + ValleyNews::vnVelociraptorsLost); + } + if (istyran(_globals->_roomNum)) + _globals->_gameFlags |= GameFlags::gfFlag10; + else + _globals->_gameFlags &= ~GameFlags::gfFlag10; + return room; +} + +// Original name: initlieu +void EdenGame::initPlace(int16 roomNum) { + _globals->_gameFlags |= GameFlags::gfFlag4000; + _gameIcons[18]._cursorId |= 0x8000; + _globals->_lastAreaPtr = _globals->_areaPtr; + _globals->_areaPtr = &kAreasTable[((roomNum >> 8) & 0xFF) - 1]; + Area *area = _globals->_areaPtr; + area->_visitCount++; + _globals->_areaVisitCount = area->_visitCount; + _globals->_curAreaFlags = area->_flags; + _globals->_curAreaType = area->_type; + _globals->_curCitadelLevel = area->_citadelLevel; + if (_globals->_curAreaType == AreaType::atValley) + _gameIcons[18]._cursorId &= ~0x8000; + loadPlace(area->_placeNum); +} + +void EdenGame::maj2() { + displayPlace(); + assert(_vm->_screenView->_pitch == 320); + if (_globals->_roomNum == 273 && _globals->_prevLocation == 18) + _globals->_mirrorEffect = 1; + if (_globals->_eventType == EventType::etEventC) { + drawTopScreen(); + showObjects(); + } + FRDevents(); + assert(_vm->_screenView->_pitch == 320); + bool r30 = false; + if (_globals->_curAreaType == AreaType::atValley && !(_globals->_displayFlags & DisplayFlags::dfPanable)) + r30 = true; + //TODO: ^^ inlined func? + + if (_globals->_mirrorEffect || _globals->_var103) + display(); + else if (_globals->_varF1 == (RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01)) { + drawBlackBars(); + displayEffect1(); + } else if (_globals->_varF1 && !(_globals->_varF1 & RoomFlags::rf04) && !r30) { + if (!(_globals->_displayFlags & DisplayFlags::dfPanable)) + drawBlackBars(); + else if (_globals->_valleyVidNum) + drawBlackBars(); + displayEffect1(); + } else if (r30 && !(_globals->_varF1 & RoomFlags::rf04)) + effetpix(); + else + afficher128(); + musique(); + if (_globals->_eventType != EventType::etEventC) { + drawTopScreen(); + showObjects(); + } + showBars(); + showEvents(); + _globals->_labyrinthDirections = 0; + specialin(); +} + +// Original name: majsalle1 +void EdenGame::updateRoom1(int16 roomNum) { + Room *room = getRoom(roomNum & 0xFF); + _globals->_roomPtr = room; + debug("DrawRoom: room 0x%X, arg = 0x%X", _globals->_roomNum, roomNum); + _globals->_curRoomFlags = room->_flags; + _globals->_varF1 = room->_flags; + animpiece(); + _globals->_var100 = 0; + maj2(); +} + +// Original name: maj_salle +void EdenGame::updateRoom(uint16 roomNum) { + setCharacterHere(); + updateRoom1(roomNum); +} + +// Original name: initbuf +void EdenGame::allocateBuffers() { +#define ALLOC(ptr, size, typ) if (!((ptr) = (typ*)malloc(size))) _bufferAllocationErrorFl = true; + ALLOC(_gameRooms, 0x4000, Room); + ALLOC(_gameIcons, 0x4000, Icon); + ALLOC(_bankDataBuf, 0x10000, byte); + ALLOC(_globals, sizeof(*_globals), global_t); + ALLOC(_placeRawBuf, 2048, byte); + ALLOC(_gameConditions, 0x4800, byte); + ALLOC(_gameDialogs, 0x2800, byte); + ALLOC(_gamePhrases, 0x10000, byte); + ALLOC(_mainBankBuf, 0x9400, byte); + ALLOC(_glowBuffer, 0x2800, byte); + ALLOC(_gameFont, 0x900, byte); + ALLOC(_gameLipsync, 0x205C, byte); + ALLOC(_musicBuf, kMaxMusicSize, byte); +#undef ALLOC +} + +void EdenGame::freebuf() { + delete(_bigfileHeader); + _bigfileHeader = nullptr; + + free(_gameRooms); + free(_gameIcons); + free(_bankDataBuf); + free(_globals); + free(_placeRawBuf); + free(_gameConditions); + free(_gameDialogs); + free(_gamePhrases); + free(_mainBankBuf); + free(_glowBuffer); + free(_gameFont); + free(_gameLipsync); + free(_musicBuf); +} + +void EdenGame::openWindow() { + _underBarsView = new View(320, 40); + _underBarsView->_normal._width = 320; + + _view2 = new View(32, 32); + _view2Buf = _view2->_bufferPtr; + + _subtitlesView = new View(_subtitlesXWidth, 60); + _subtitlesViewBuf = _subtitlesView->_bufferPtr; + + _underSubtitlesView = new View(_subtitlesXWidth, 60); + _underSubtitlesViewBuf = _underSubtitlesView->_bufferPtr; + + _mainView = new View(640, 200); + _mainView->_normal._width = 320; + CLBlitter_FillView(_mainView, 0xFFFFFFFF); + _mainView->setSrcZoomValues(0, 0); + _mainView->setDisplayZoomValues(640, 400); + _mainView->centerIn(_vm->_screenView); + _mainViewBuf = _mainView->_bufferPtr; + + _mouseCenterX = _mainView->_normal._dstLeft + _mainView->_normal._width / 2; + _mouseCenterY = _mainView->_normal._dstTop + _mainView->_normal._height / 2; + _vm->setMousePosition(_mouseCenterX, _mouseCenterY); + _vm->hideMouse(); + + _cursorPosX = 320 / 2; + _cursorPosY = 200 / 2; +} + +void EdenGame::EmergencyExit() { + SysBeep(1); +} + +void EdenGame::run() { + _invIconsCount = (_vm->getPlatform() == Common::kPlatformMacintosh) ? 9 : 11; + _roomIconsBase = _invIconsBase + _invIconsCount; + + word_378CE = 0; + CRYOLib_ManagersInit(); + _vm->_video->setupSound(11025, false, false); + _vm->_video->setForceZero2Black(true); + _vm->_video->setupTimer(12.5); + _voiceSound = new Sound(0, 11025 * 65536.0, 8, 0); + _hnmSoundChannel = _vm->_video->getSoundChannel(); + _voiceSound->setWantsDesigned(1); // CHECKME: Used? + + _musicChannel = new CSoundChannel(_vm->_mixer, 11025, false); + _voiceChannel = new CSoundChannel(_vm->_mixer, 11025, false); + + allocateBuffers(); + openbigfile(); + openWindow(); + loadpermfiles(); + + if (!_bufferAllocationErrorFl) { + LostEdenMac_InitPrefs(); + if (_vm->getPlatform() == Common::kPlatformMacintosh) + initCubeMac(); + else + initCubePC(); + + while (!_quitFlag2) { + initGlobals(); + _quitFlag3 = false; + _normalCursor = true; + _torchCursor = false; + _cursKeepPos = Common::Point(-1, -1); + if (!_gameLoaded) + intro(); + edmain(); + startmusique(1); + drawBlackBars(); + display(); + fadeToBlack(3); + clearScreen(); + playHNM(95); + if (_globals->_endGameFlag == 50) { + loadrestart(); + _gameLoaded = false; + } + fademusica0(2); + _musicChannel->stop(); + _musicPlayingFlag = false; + _musicEnabledFlag = false; + } + // LostEdenMac_SavePrefs(); + } + + delete _voiceChannel; + delete _musicChannel; + + fadeToBlack(4); + closebigfile(); + freebuf(); + CRYOLib_ManagersDone(); +} + +void EdenGame::edmain() { + //TODO + enterGame(); + while (!_bufferAllocationErrorFl && !_quitFlag3 && _globals->_endGameFlag != 50) { + if (!_gameStarted) { + // if in demo mode, reset game after a while + _demoCurrentTicks = _vm->_timerTicks; + if (_demoCurrentTicks - _demoStartTicks > 3000) { + rundcurs(); + display(); + fademusica0(2); + fadeToBlack(3); + CLBlitter_FillScreenView(0); + CLBlitter_FillView(_mainView, 0); + _musicChannel->stop(); + _musicPlayingFlag = false; + _musicEnabledFlag = false; + intro(); + enterGame(); + } + } + rundcurs(); + musicspy(); + FRDevents(); + handleNarrator(); + chronoEvent(); + if (_globals->_drawFlags & DrawFlags::drDrawInventory) + showObjects(); + if (_globals->_drawFlags & DrawFlags::drDrawTopScreen) + drawTopScreen(); + if ((_globals->_displayFlags & DisplayFlags::dfPanable) && (_globals->_displayFlags != DisplayFlags::dfPerson)) + scrollPanel(); + if ((_globals->_displayFlags & DisplayFlags::dfMirror) && (_globals->_displayFlags != DisplayFlags::dfPerson)) + scrollMirror(); + if ((_globals->_displayFlags & DisplayFlags::dfFrescoes) && (_globals->_displayFlags != DisplayFlags::dfPerson)) + scrollFrescoes(); + if (_globals->_displayFlags & DisplayFlags::dfFlag2) + noclicpanel(); + if (_animationActive) + animCharacter(); + updateCursor(); + display(); + } +} + +void EdenGame::intro() { + if (_vm->getPlatform() == Common::kPlatformMacintosh) { + // Play intro videos in HQ + _hnmSoundChannel->stop(); + _vm->_video->closeSound(); + _vm->_video->setupSound(22050, false, true); + _hnmSoundChannel = _vm->_video->getSoundChannel(); + playHNM(2012); + playHNM(171); + CLBlitter_FillScreenView(0); + _specialTextMode = false; + playHNM(2001); + _hnmSoundChannel->stop(); + _vm->_video->closeSound(); + _vm->_video->setupSound(11025, false, false); + _hnmSoundChannel = _vm->_video->getSoundChannel(); + } else { + if (_vm->isDemo()) { + playHNM(171); // Virgin logo + playHNM(98); // Cryo logo + } + else { + playHNM(98); // Cryo logo + playHNM(171); // Virgin logo + } + CLBlitter_FillScreenView(0); + _specialTextMode = false; + startmusique(2); // INTRO.MUS is played during intro video + playHNM(170); // Intro video + } +} + +void EdenGame::enterGame() { + char flag = 0; + _currentTime = _vm->_timerTicks / 100; + _globals->_gameTime = _currentTime; + _demoStartTicks = _vm->_timerTicks; + _gameStarted = false; + if (!_gameLoaded) { + _globals->_roomNum = 279; + _globals->_areaNum = Areas::arMo; + _globals->_var100 = 0xFF; + initPlace(_globals->_roomNum); + _globals->_currMusicNum = 0; + startmusique(1); + } else { + flag = _globals->_autoDialog; //TODO + initafterload(); + byte lastMusicNum = _globals->_currMusicNum; //TODO: ??? + _globals->_currMusicNum = 0; + startmusique(lastMusicNum); + _globals->_inventoryScrollPos = 0; + _gameStarted = true; + } + showObjects(); + drawTopScreen(); + saveFriezes(); + _showBlackBars = true; + _globals->_mirrorEffect = 1; + updateRoom(_globals->_roomNum); + if (flag) { + _globals->_iconsIndex = 4; + _globals->_autoDialog = true; + parle_moi(); + } +} + +void EdenGame::signon(const char *s) { +} + +void EdenGame::FRDevents() { + _vm->pollEvents(); + if (_allowDoubled) { +#if 0 // CLKeyboard_IsScanCodeDown currently always returns false + if (_vm->isScanCodeDown(0x30)) { //TODO: const + if (!_keyboardHeld) { + _doubledScreen = !_doubledScreen; + _mainView->_doubled = _doubledScreen; + CLBlitter_FillScreenView(0); + _keyboardHeld = true; + } + } else +#endif + _keyboardHeld = false; + } + + int16 mouseY; + int16 mouseX; + _vm->getMousePosition(&mouseX, &mouseY); + mouseX -= _mouseCenterX; + mouseY -= _mouseCenterY; + _vm->setMousePosition(_mouseCenterX , _mouseCenterY); + _cursorPosX += mouseX; + _cursorPosX = CLIP<int16>(_cursorPosX, 4, 292); + _cursorPosY += mouseY; + + int16 maxY = _globals->_displayFlags == DisplayFlags::dfFlag2 ? 190 : 170; + _cursorPosY = CLIP<int16>(_cursorPosY, 4, maxY); + _cirsorPanX = _cursorPosX; + + if (_cursorPosY >= 10 && _cursorPosY <= 164 && !(_globals->_displayFlags & DisplayFlags::dfFrescoes)) + _cirsorPanX += _scrollPos; + if (_normalCursor) { + _currCursor = 0; + _currSpot = scan_icon_list(_cirsorPanX + _cursCenter, _cursorPosY + _cursCenter, _globals->_iconsIndex); + if (_currSpot) + _currCursor = _currSpot->_cursorId; + } + if (_cursCenter == 0 && _currCursor != 53) { + _cursCenter = 11; + _cursorPosX -= 11; + } + if (_cursCenter == 11 && _currCursor == 53) { + _cursCenter = 0; + _cursorPosX += 11; + } + if (_globals->_displayFlags & DisplayFlags::dfPanable) { + //TODO: _currSpot may be zero (due to scan_icon_list failure) if cursor slips between hot areas. + //fix me here or above? + if (_currSpot) { // ok, plug it here + _curSpot2 = _currSpot; + displayAdamMapMark(_curSpot2->_actionId - 14); + } + } + if (_globals->_displayFlags == DisplayFlags::dfFlag2 && _currSpot) + _curSpot2 = _currSpot; + if (_globals->_displayFlags & DisplayFlags::dfFrescoes) { + if (_frescoTalk) + restoreUnderSubtitles(); + if (_currCursor == 9 && !_torchCursor) { + rundcurs(); + _torchCursor = true; + _glowX = -1; + } + if (_currCursor != 9 && _torchCursor) { + unglow(); + _torchCursor = false; + _cursorSaved = false; + } + } + if (_vm->isMouseButtonDown()) { + if (!_mouseHeld) { + _mouseHeld = true; + _gameStarted = true; + mouse(); + } + } else + _mouseHeld = false; + if (_globals->_displayFlags != DisplayFlags::dfFlag2) { + if (--_inventoryScrollDelay <= 0) { + if (_globals->_objCount > _invIconsCount && _cursorPosY > 164) { + if (_cursorPosX > 284 && _globals->_inventoryScrollPos + _invIconsCount < _globals->_objCount) { + _globals->_inventoryScrollPos++; + _inventoryScrollDelay = 20; + showObjects(); + } + + if (_cursorPosX < 30 && _globals->_inventoryScrollPos != 0) { + _globals->_inventoryScrollPos--; + _inventoryScrollDelay = 20; + showObjects(); + } + } + } + } + if (_inventoryScrollDelay < 0) + _inventoryScrollDelay = 0; + + if (_vm->shouldQuit()) + edenShudown(); +} + +Icon *EdenGame::scan_icon_list(int16 x, int16 y, int16 index) { + for (Icon *icon = &_gameIcons[index]; icon->sx >= 0; icon++) { + if (icon->_cursorId & 0x8000) + continue; +#if 0 + // MAC version use this check. Same check is present in PC version, but never used + // Because of x >= clause two adjacent rooms has 1-pixel wide dead zone between them + // On valley view screens if cursor slips in this zone a crash in FRDevents occurs + // due to lack of proper checks + if (x < icon->ff_0 || x >= icon->ff_4 + || y < icon->ff_2 || y >= icon->ff_6) +#else + // PC version has this check inlined in FRDevents + // Should we keep it or fix edge coordinates in afroom() instead? + if (x < icon->sx || x > icon->ex + || y < icon->sy || y > icon->ey) +#endif + continue; + return icon; + } + return nullptr; +} + +void EdenGame::updateCursor() { + if (++_torchTick > 3) + _torchTick = 0; + if (!_torchTick) { + _torchCurIndex++; + _glowIndex++; + } + if (_torchCurIndex > 8) + _torchCurIndex = 0; + if (_glowIndex > 4) + _glowIndex = 0; + + if (!_torchCursor) { + useMainBank(); + sundcurs(_cursorPosX + _scrollPos, _cursorPosY); + if (_currCursor != 53 && _currCursor < 10) { //TODO: cond + if (_vm->getPlatform() == Common::kPlatformMacintosh) + engineMac(); + else + enginePC(); + } else + noclipax(_currCursor, _cursorPosX + _scrollPos, _cursorPosY); + _glowX = 1; + } else { + useBank(117); + if (_cursorPosX > 294) + _cursorPosX = 294; + unglow(); + glow(_glowIndex); + noclipax(_torchCurIndex, _cursorPosX + _scrollPos, _cursorPosY); + if (_frescoTalk) + displaySubtitles(); + } +} + +void EdenGame::mouse() { + static void (EdenGame::*mouse_actions[])() = { + &EdenGame::actionMoveNorth, + &EdenGame::actionMoveEast, + &EdenGame::actionMoveSouth, + &EdenGame::actionMoveWest, + &EdenGame::actionPlateMonk, + &EdenGame::actionGraaFrescoe, + &EdenGame::actionPushStone, + &EdenGame::actionSkelettonHead, + &EdenGame::actionMummyHead, + &EdenGame::actionMoveNorth, + &EdenGame::actionKingDialog1, + &EdenGame::actionKingDialog2, + &EdenGame::actionKingDialog3, + &EdenGame::actionGotoHall, + &EdenGame::actionLabyrinthTurnAround, + &EdenGame::actionSkelettonMoorkong, + &EdenGame::actionGotoFullNest, + &EdenGame::actionLookLake, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionFinal, + &EdenGame::actionMoveNorth, + &EdenGame::actionMoveSouth, + &EdenGame::actionVisit, + &EdenGame::actionDinoBlow, + &EdenGame::actionLascFrescoe, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + nullptr, + nullptr, + nullptr, + nullptr, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + nullptr, + nullptr, + nullptr, + nullptr, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + nullptr, + nullptr, + nullptr, + nullptr, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + &EdenGame::actionGotoVal, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionGetPrism, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionGetEgg, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionGetMushroom, + &EdenGame::actionGetBadMushroom, + &EdenGame::actionGetKnife, + &EdenGame::actionGetEmptyNest, + &EdenGame::actionGetFullNest, + &EdenGame::actionGetGold, + nullptr, + &EdenGame::actionNop, + &EdenGame::actionGetSunStone, + &EdenGame::actionGetHorn, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + &EdenGame::actionNop, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &EdenGame::actionGetTablet, + &EdenGame::actionClickValleyPlan, + &EdenGame::actionEndFrescoes, + &EdenGame::actionChoose, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &EdenGame::actionKing, + &EdenGame::actionDina, + &EdenGame::actionThoo, + &EdenGame::actionMonk, + &EdenGame::actionTormentor, + &EdenGame::actionMessenger, + &EdenGame::actionMango, + &EdenGame::actionEve, + &EdenGame::actionAzia, + &EdenGame::actionMammi, + &EdenGame::actionGuards, + &EdenGame::actionFisher, + &EdenGame::actionDino, + &EdenGame::actionTyran, + &EdenGame::actionMorkus, + &EdenGame::actionNop, + &EdenGame::parle_moi, + &EdenGame::actionAdam, + &EdenGame::actionTakeObject, + &EdenGame::putObject, + &EdenGame::clictimbre, + &EdenGame::handleDinaDialog, + &EdenGame::closeCharacterScreen, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &EdenGame::generique, + &EdenGame::choseSubtitleOption, + &EdenGame::edenQuit, + &EdenGame::restart, + &EdenGame::cancel2, + &EdenGame::testvoice, + &EdenGame::changeVolume, + &EdenGame::load, + &EdenGame::save, + &EdenGame::cliccurstape, + &EdenGame::playtape, + &EdenGame::stoptape, + &EdenGame::rewindtape, + &EdenGame::forwardtape, + &EdenGame::confirmYes, + &EdenGame::confirmNo, + &EdenGame::actionGotoMap + }; + + if (!(_currSpot = scan_icon_list(_cirsorPanX + _cursCenter, + _cursorPosY + _cursCenter, _globals->_iconsIndex))) + return; + _curSpot2 = _currSpot; + debug("invoking mouse action %d", _currSpot->_actionId); + if (mouse_actions[_currSpot->_actionId]) + (this->*mouse_actions[_currSpot->_actionId])(); +} + +////// film.c +// Original name: showfilm +void EdenGame::showMovie(char arg1) { + _vm->_video->readHeader(); + if (_globals->_curVideoNum == 92) { + // _hnmContext->_header._unusedFlag2 = 0; CHECKME: Useless? + _hnmSoundChannel->setVolumeLeft(0); + _hnmSoundChannel->setVolumeRight(0); + } + + if (_vm->_video->getVersion() != 4) + return; + + bool playing = true; + _vm->_video->allocMemory(); + _hnmView = new View(_vm->_video->_header._width, _vm->_video->_header._height); + _hnmView->setSrcZoomValues(0, 0); + _hnmView->setDisplayZoomValues(_vm->_video->_header._width * 2, _vm->_video->_header._height * 2); + _hnmView->centerIn(_vm->_screenView); + _hnmViewBuf = _hnmView->_bufferPtr; + if (arg1) { + _hnmView->_normal._height = 160; + _hnmView->_zoom._height = 320; //TODO: width?? + _hnmView->_normal._dstTop = _mainView->_normal._dstTop + 16; + _hnmView->_zoom._dstTop = _mainView->_zoom._dstTop + 32; + } + _vm->_video->setFinalBuffer(_hnmView->_bufferPtr); + do { + _hnmFrameNum = _vm->_video->getFrameNum(); + _vm->_video->waitLoop(); + playing = _vm->_video->nextElement(); + if (_specialTextMode) + handleHNMSubtitles(); + else + musicspy(); + CLBlitter_CopyView2Screen(_hnmView); + assert(_vm->_screenView->_pitch == 320); + _vm->pollEvents(); + if (_allowDoubled) { +#if 0 // CLKeyboard_IsScanCodeDown currently always returns false + if (_vm->isScanCodeDown(0x30)) { //TODO: const + if (!_keyboardHeld) { + _doubledScreen = !_doubledScreen; + _hnmView->_doubled = _doubledScreen; //TODO: but mainview ? + CLBlitter_FillScreenView(0); + _keyboardHeld = true; + } + } else +#endif + _keyboardHeld = false; + } + if (arg1) { + if (_vm->isMouseButtonDown()) { + if (!_mouseHeld) { + _mouseHeld = true; + _videoCanceledFlag = true; + } + } else + _mouseHeld = false; + } + } while (playing && !_videoCanceledFlag); + delete _hnmView; + _vm->_video->deallocMemory(); +} + +void EdenGame::playHNM(int16 num) { + perso_t *perso = nullptr; + int16 oldDialogType = -1; + _globals->_curVideoNum = num; + if (num != 2001 && num != 2012 && num != 98 && num != 171) { + byte oldMusicType = _globals->_newMusicType; + _globals->_newMusicType = MusicType::mtEvent; + musique(); + musicspy(); + _globals->_newMusicType = oldMusicType; + } + _globals->_videoSubtitleIndex = 1; + if (_specialTextMode) { + perso = _globals->_characterPtr; + oldDialogType = _globals->_dialogType; + preloadDialogs(num); + fademusica0(1); + _musicChannel->stop(); + } + _showVideoSubtitle = false; + _videoCanceledFlag = false; + loadHnm(num); + _vm->_video->reset(); + if (_needToFade) { + fadeToBlack(4); + clearScreen(); + _needToFade = false; + } + if (num == 2012 || num == 98 || num == 171) + showMovie(0); + else + showMovie(1); + _cursKeepPos = Common::Point(-1, -1); + if (_specialTextMode) { + _musicFadeFlag = 3; + musicspy(); + _globals->_characterPtr = perso; + _globals->_dialogType = oldDialogType; + _specialTextMode = false; + } + if (_videoCanceledFlag) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 167) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 104) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 102) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 77) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; + if (_globals->_curVideoNum == 149) + _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01; +} + +// Original name bullehnm +void EdenGame::handleHNMSubtitles() { +#define SUB_LINE(start, end) \ + (start), (end) | 0x8000 + + static uint16 kFramesVid170[] = { + SUB_LINE( 68, 120), + SUB_LINE( 123, 196), + SUB_LINE( 199, 274), + SUB_LINE( 276, 370), + SUB_LINE( 799, 885), + SUB_LINE( 888, 940), + SUB_LINE( 947, 1000), + SUB_LINE(1319, 1378), + SUB_LINE(1380, 1440), + SUB_LINE(1854, 1898), + SUB_LINE(1900, 1960), + SUB_LINE(2116, 2184), + SUB_LINE(2186, 2252), + SUB_LINE(2254, 2320), + SUB_LINE(3038, 3094), + SUB_LINE(3096, 3160), + 0xFFFF + }; + + static uint16 kFramesVid83[] = { + SUB_LINE(99, 155), + SUB_LINE(157, 256), + 0xFFFF + }; + + static uint16 kFramesVid88[] = { + SUB_LINE(106, 173), + SUB_LINE(175, 244), + SUB_LINE(246, 350), + SUB_LINE(352, 467), + 0xFFFF + }; + + static uint16 kFramesVid89[] = { + SUB_LINE(126, 176), + SUB_LINE(178, 267), + SUB_LINE(269, 342), + SUB_LINE(344, 398), + SUB_LINE(400, 458), + SUB_LINE(460, 558), + 0xFFFF + }; + + static uint16 kFramesVid94[] = { + SUB_LINE(101, 213), + SUB_LINE(215, 353), + SUB_LINE(355, 455), + SUB_LINE(457, 518), + SUB_LINE(520, 660), + SUB_LINE(662, 768), + 0xFFFF + }; + +#undef SUB_LINE + + uint16 *frames; + perso_t *perso; + switch (_globals->_curVideoNum) { + case 170: + frames = kFramesVid170; + perso = &kPersons[PER_UNKN_156]; + break; + case 83: + frames = kFramesVid83; + perso = &kPersons[PER_MORKUS]; + break; + case 88: + frames = kFramesVid88; + perso = &kPersons[PER_MORKUS]; + break; + case 89: + frames = kFramesVid89; + perso = &kPersons[PER_MORKUS]; + break; + case 94: + frames = kFramesVid94; + perso = &kPersons[PER_MORKUS]; + break; + default: + return; + } + uint16 *frames_start = frames; + uint16 frame; + while ((frame = *frames++) != 0xFFFF) { + if ((frame & ~0x8000) == _hnmFrameNum) + break; + } + if (frame == 0xFFFF) { + if (_showVideoSubtitle) + displayHNMSubtitle(); + return; + } + if (frame & 0x8000) + _showVideoSubtitle = false; + else { + _globals->_videoSubtitleIndex = (frames - frames_start) / 2 + 1; + _globals->_characterPtr = perso; + _globals->_dialogType = DialogType::dtInspect; + int16 num = (perso->_id << 3) | _globals->_dialogType; + dialoscansvmas((Dialog *)getElem(_gameDialogs, num)); + _showVideoSubtitle = true; + } + if (_showVideoSubtitle) + displayHNMSubtitle(); +} + +////// sound.c +void EdenGame::musique() { + if (_globals->_newMusicType == MusicType::mtDontChange) + return; + + Dialog *dial = (Dialog *)getElem(_gameDialogs, 128); + for (;;dial++) { + if (dial->_flags == -1 && dial->_condNumLow == -1) + return; + byte flag = dial->_flags; + byte hidx = (dial->_textCondHiMask & 0xC0) >> 6; + byte lidx = dial->_condNumLow; //TODO: fixme - unsigned = signed + if (flag & 0x10) + hidx |= 4; + if (testCondition(((hidx << 8) | lidx) & 0x7FF)) + break; + } + byte mus = dial->_textNumLow; + _globals->_newMusicType = MusicType::mtDontChange; + if (mus != 0 && mus != 2 && mus < 50) + startmusique(mus); +} + +void EdenGame::startmusique(byte num) { + if (num == _globals->_currMusicNum) + return; + + if (_musicPlayingFlag) { + fademusica0(1); + _musicChannel->stop(); + } + loadmusicfile(num); + _globals->_currMusicNum = num; + _musSequencePtr = _musicBuf + 32; //TODO: rewrite it properly + int16 seq_size = READ_LE_UINT16(_musicBuf + 30); + _musicPatternsPtr = _musicBuf + 30 + seq_size; + int16 pat_size = READ_LE_UINT16(_musicBuf + 27); + _musicSamplesPtr = _musicBuf + 32 + 4 + pat_size; + int16 freq = READ_LE_UINT16(_musicSamplesPtr - 2); + + delete _musicChannel; + _musicChannel = new CSoundChannel(_vm->_mixer, freq == 166 ? 11025 : 22050, false); + _musicEnabledFlag = true; + + _musicSequencePos = 0; + _musicLeftVol = _globals->_prefMusicVol[0]; + _musicRightVol = _globals->_prefMusicVol[1]; + _musicChannel->setVolume(_musicLeftVol, _musicRightVol); +} + +void EdenGame::musicspy() { + if (!_musicEnabledFlag) + return; + _musicLeftVol = _globals->_prefMusicVol[0]; + _musicRightVol = _globals->_prefMusicVol[1]; + if (_musicFadeFlag & 3) + fademusicup(); + if (_personTalking && !_voiceChannel->numQueued()) + _musicFadeFlag = 3; + if (_musicChannel->numQueued() < 3) { + byte patnum = _musSequencePtr[(int)_musicSequencePos]; + if (patnum == 0xFF) { + // rewind + _musicSequencePos = 0; + patnum = _musSequencePtr[(int)_musicSequencePos]; + } + _musicSequencePos++; + byte *patptr = _musicPatternsPtr + patnum * 6; + int ofs = patptr[0] + (patptr[1] << 8) + (patptr[2] << 16); + int len = patptr[3] + (patptr[4] << 8) + (patptr[5] << 16); + _musicChannel->queueBuffer(_musicSamplesPtr + ofs, len); + _musicPlayingFlag = true; + } +} + +int EdenGame::loadmusicfile(int16 num) { + PakHeaderItem *file = &_bigfileHeader->_files[num + 435]; + int32 size = file->_size; + int32 offs = file->_offs; + _bigfile.seek(offs, SEEK_SET); + uint32 numread = size; + if (numread > kMaxMusicSize) + error("Music file %s is too big", file->_name.c_str()); + _bigfile.read(_musicBuf, numread); + return size; +} + +void EdenGame::persovox() { + int16 num = _globals->_textNum; + if (_globals->_textBankIndex != 1) + num += 565; + if (_globals->_textBankIndex == 3) + num += 707; + _voiceSamplesSize = loadSound(num); + int16 volumeLeft = _globals->_prefSoundVolume[0]; + int16 volumeRight = _globals->_prefSoundVolume[1]; + int16 stepLeft = _musicChannel->_volumeLeft < volumeLeft ? 1 : -1; + int16 stepRight = _musicChannel->_volumeRight < volumeRight ? 1 : -1; + do { + if (volumeLeft != _musicChannel->_volumeLeft) + _musicChannel->setVolumeLeft(_musicChannel->_volumeLeft + stepLeft); + if (volumeRight != _musicChannel->_volumeRight) + _musicChannel->setVolumeRight(_musicChannel->_volumeRight + stepRight); + } while (_musicChannel->_volumeLeft != volumeLeft || _musicChannel->_volumeRight != volumeRight); + volumeLeft = _globals->_prefVoiceVol[0]; + volumeRight = _globals->_prefVoiceVol[1]; + _voiceChannel->setVolume(volumeLeft, volumeRight); + _voiceChannel->queueBuffer(_voiceSamplesBuffer, _voiceSamplesSize, true); + _personTalking = true; + _musicFadeFlag = 0; + _lastAnimTicks = _vm->_timerTicks; +} + +// Original name: endpersovox +void EdenGame::endCharacterSpeech() { + restoreUnderSubtitles(); + if (_personTalking) { + _voiceChannel->stop(); + _personTalking = false; + _musicFadeFlag = 3; + } + + if (_soundAllocated) { + free(_voiceSamplesBuffer); + _voiceSamplesBuffer = nullptr; + _soundAllocated = false; + } +} + +void EdenGame::fademusicup() { + if (_musicFadeFlag & 2) { + int16 vol = _musicChannel->_volumeLeft; + if (vol < _musicLeftVol) { + vol += 8; + if (vol > _musicLeftVol) + vol = _musicLeftVol; + } else { + vol -= 8; + if (vol < _musicLeftVol) + vol = _musicLeftVol; + } + _musicChannel->setVolumeLeft(vol); + if (vol == _musicLeftVol) + _musicFadeFlag &= ~2; + } + if (_musicFadeFlag & 1) { + int16 vol = _musicChannel->_volumeRight; + if (vol < _musicRightVol) { + vol += 8; + if (vol > _musicRightVol) + vol = _musicRightVol; + } else { + vol -= 8; + if (vol < _musicRightVol) + vol = _musicRightVol; + } + _musicChannel->setVolumeRight(vol); + if (vol == _musicRightVol) + _musicFadeFlag &= ~1; + } +} + +void EdenGame::fademusica0(int16 delay) { + int16 volume; + while ((volume = _musicChannel->getVolume()) > 2) { + volume -= 2; + if (volume < 2) + volume = 2; + _musicChannel->setVolume(volume, volume); + wait(delay); + } +} + +//// obj.c + +// Original name: getobjaddr +object_t *EdenGame::getObjectPtr(int16 id) { + int i; + for (i = 0; i < MAX_OBJECTS; i++) { + if (_objects[i]._id == id) + break; + } + + return &_objects[i]; +} + +void EdenGame::countObjects() { + int16 index = 0; + byte total = 0; + for (int i = 0; i < MAX_OBJECTS; i++) { + int16 count = _objects[i]._count; + if (count == 0) + continue; + + if (_objects[i]._flags & ObjectFlags::ofInHands) + count--; + + if (count) { + total += count; + while (count--) + _ownObjects[index++] = _objects[i]._id; + } + } + _globals->_objCount = total; +} + +void EdenGame::showObjects() { + Icon *icon = &_gameIcons[_invIconsBase]; + _globals->_drawFlags &= ~(DrawFlags::drDrawInventory | DrawFlags::drDrawFlag2); + countObjects(); + int16 total = _globals->_objCount; + for (int16 i = _invIconsCount; i--; icon++) { + if (total) { + icon->_cursorId &= ~0x8000; + total--; + } else + icon->_cursorId |= 0x8000; + } + useMainBank(); + noclipax(55, 0, 176); + icon = &_gameIcons[_invIconsBase]; + total = _globals->_objCount; + int16 index = _globals->_inventoryScrollPos; + for (int16 i = _invIconsCount; total-- && i--; icon++) { + char obj = _ownObjects[index++]; + icon->_objectId = obj; + noclipax(obj + 9, icon->sx, 178); + } + _paletteUpdateRequired = true; + if ((_globals->_displayFlags & DisplayFlags::dfMirror) || (_globals->_displayFlags & DisplayFlags::dfPanable)) { + saveBottomFrieze(); + scroll(); + } +} + +void EdenGame::winObject(int16 id) { + object_t *object = getObjectPtr(id); + object->_flags |= ObjectFlags::ofFlag1; + object->_count++; + _globals->_curItemsMask |= object->_itemMask; + _globals->_wonItemsMask |= object->_itemMask; + _globals->_curPowersMask |= object->_powerMask; + _globals->_wonPowersMask |= object->_powerMask; +} + +void EdenGame::loseObject(int16 id) { + object_t *object = getObjectPtr(id); + if (object->_count > 0) + object->_count--; + if (!object->_count) { + object->_flags &= ~ObjectFlags::ofFlag1; + _globals->_curItemsMask &= ~object->_itemMask; + _globals->_curPowersMask &= ~object->_powerMask; + } + _globals->_curObjectId = 0; + _globals->_curObjectFlags = 0; + _globals->_curObjectCursor = 9; + _gameIcons[16]._cursorId |= 0x8000; + object->_flags &= ~ObjectFlags::ofInHands; + _normalCursor = true; + _currCursor = 0; + _torchCursor = false; +} + +void EdenGame::lostObject() { + parlemoiNormalFlag = true; + if (_globals->_curObjectId) + loseObject(_globals->_curObjectId); +} + +// Original name: objecthere +bool EdenGame::isObjectHere(int16 id) { + object_t *object = getObjectPtr(id); + for (_currentObjectLocation = &kObjectLocations[object->_locations]; *_currentObjectLocation != 0xFFFF; _currentObjectLocation++) { + if (*_currentObjectLocation == _globals->_roomNum) + return true; + } + return false; +} + +void EdenGame::objectmain(int16 id) { + object_t *object = getObjectPtr(id); + _gameIcons[16]._cursorId &= ~0x8000; + _globals->_curObjectId = object->_id; + _globals->_curObjectCursor = _globals->_curObjectId + 9; + object->_flags |= ObjectFlags::ofInHands; + _globals->_curObjectFlags = object->_flags; + _currCursor = _globals->_curObjectId + 9; + _normalCursor = false; +} + +void EdenGame::getObject(int16 id) { + Room *room = _globals->_roomPtr; + if (_globals->_curObjectId) + return; + if (!isObjectHere(id)) + return; + *_currentObjectLocation |= 0x8000; + objectmain(id); + winObject(id); + showObjects(); + _globals->_roomImgBank = room->_bank; + _globals->_roomVidNum = room->_video; + displayPlace(); +} + +void EdenGame::putObject() { + if (!_globals->_curObjectId) + return; + _gameIcons[16]._cursorId |= 0x8000; + object_t *object = getObjectPtr(_globals->_curObjectId); + _globals->_curObjectCursor = 9; + _globals->_curObjectId = 0; + _globals->_curObjectFlags = 0; + object->_flags &= ~ObjectFlags::ofInHands; + _globals->_nextDialogPtr = nullptr; + _closeCharacterDialog = false; + _globals->_dialogType = DialogType::dtTalk; + showObjects(); + _normalCursor = true; +} + +void EdenGame::newObject(int16 id, int16 arg2) { + object_t *object = getObjectPtr(id); + uint16 e, *t = &kObjectLocations[object->_locations]; + while ((e = *t) != 0xFFFF) { + e &= ~0x8000; + if ((e >> 8) == arg2) + *t = e; + t++; + } +} + +void EdenGame::giveobjectal(int16 id) { + if (id == Objects::obKnife) + kObjectLocations[2] = 0; + if (id == Objects::obApple) + _globals->_stepsToFindAppleNormal = 0; + if (id >= Objects::obEyeInTheStorm && id < (Objects::obRiverThatWinds + 1) && _globals->_roomCharacterType == PersonFlags::pftVelociraptor) { + //TODO: fix that cond above + object_t *object = getObjectPtr(id); + _globals->_roomCharacterPtr->_powers &= ~object->_powerMask; + } + winObject(id); +} + +void EdenGame::giveObject() { + byte id = _globals->_giveObj1; + if (id) { + _globals->_giveObj1 = 0; + giveobjectal(id); + } + id = _globals->_giveObj2; + if (id) { + _globals->_giveObj2 = 0; + giveobjectal(id); + } + id = _globals->_giveObj3; + if (id) { + _globals->_giveObj3 = 0; + giveobjectal(id); + } +} + +// Original name: takeObject +void EdenGame::actionTakeObject() { + objectmain(_curSpot2->_objectId); + _globals->_nextDialogPtr = nullptr; + _closeCharacterDialog = false; + _globals->_dialogType = DialogType::dtTalk; + if (_globals->_inventoryScrollPos) + _globals->_inventoryScrollPos--; + showObjects(); +} +//// + +// Original name: newchampi +void EdenGame::newMushroom() { + if (_objects[Objects::obShroom - 1]._count == 0) { + newObject(Objects::obShroom, _globals->_citadelAreaNum); + newObject(Objects::obBadShroom, _globals->_citadelAreaNum); + } +} + +// Original name: newnidv +void EdenGame::newEmptyNest() { + Room *room = _globals->_citaAreaFirstRoom; + if (_objects[Objects::obNest - 1]._count) + return; + object_t *obj = getObjectPtr(Objects::obNest); + for (uint16 *ptr = kObjectLocations + obj->_locations; *ptr != 0xFFFF; ptr++) { + if ((*ptr & ~0x8000) >> 8 != _globals->_citadelAreaNum) + continue; + *ptr &= ~0x8000; + for (; room->_id != 0xFF; room++) { + if (room->_location == (*ptr & 0xFF)) { + room->_bank = 279; + room->_id = 9; + room++; + room->_bank = 280; + return; + } + } + } +} + +// Original name: newnido +void EdenGame::newNestWithEggs() { + Room *room = _globals->_citaAreaFirstRoom; + if (_objects[Objects::obFullNest - 1]._count) + return; + if (_objects[Objects::obNest - 1]._count) + return; + object_t *obj = getObjectPtr(Objects::obFullNest); + for (uint16 *ptr = kObjectLocations + obj->_locations; *ptr != 0xFFFF; ptr++) { + if ((*ptr & ~0x8000) >> 8 != _globals->_citadelAreaNum) + continue; + *ptr &= ~0x8000; + for (; room->_id != 0xFF; room++) { + if (room->_location == (*ptr & 0xFF)) { + room->_bank = 277; + room->_id = 9; + room++; + room->_bank = 278; + return; + } + } + } +} + +// Original name: newor +void EdenGame::newGold() { + if (_objects[Objects::obGold - 1]._count == 0) + newObject(Objects::obGold, _globals->_citadelAreaNum); +} + +void EdenGame::gotoPanel() { + if (_vm->shouldQuit()) + byte_31D64 = _globals->_autoDialog; //TODO: check me + _noPalette = false; + _globals->_iconsIndex = 85; + _globals->_characterPtr = nullptr; + _globals->_drawFlags |= DrawFlags::drDrawMenu; + _globals->_displayFlags = DisplayFlags::dfFlag2; + _globals->_menuFlags = 0; + displayPanel(); + fadeToBlack(3); + displayTopPanel(); + CLBlitter_CopyView2Screen(_mainView); + CLPalette_Send2Screen(_globalPalette, 0, 256); + _cursorPosX = 320 / 2; + _cursorPosY = 200 / 2; + _vm->setMousePosition(_mouseCenterX, _mouseCenterY); +} + +void EdenGame::noclicpanel() { + if (_globals->_menuFlags & MenuFlags::mfFlag4) { + depcurstape(); + return; + } + if (_globals->_drawFlags & DrawFlags::drDrawFlag8) + return; + if (_globals->_menuFlags & MenuFlags::mfFlag1) { + changervol(); + return; + } + byte num; + if (_curSpot2 >= &_gameIcons[119]) { + debug("noclic: objid = %p, glob3,2 = %2X %2X", (void *)_curSpot2, _globals->_menuItemIdHi, _globals->_menuItemIdLo); + if (_curSpot2->_objectId == (uint16)((_globals->_menuItemIdLo + _globals->_menuItemIdHi) << 8)) //TODO: check me + return; + } else { + int idx = _curSpot2 - &_gameIcons[105]; + if (idx == 0) { + _globals->_menuItemIdLo = 1; + num = 1; + goto skip; + } + num = (idx & 0x7F) + 1; + if (num >= 5) + num = 1; + if (num == _globals->_var43) + return; + _globals->_var43 = 0; + } + num = _globals->_menuItemIdLo; + _globals->_menuItemIdLo = _curSpot2->_objectId & 0xFF; +skip: + ; + _globals->_menuItemIdHi = (_curSpot2->_objectId & 0xFF00) >> 8; + debug("noclic: new glob3,2 = %2X %2X", _globals->_menuItemIdHi, _globals->_menuItemIdLo); + displayResult(); + num &= 0xF0; + if (num != 0x30) + num = _globals->_menuItemIdLo & 0xF0; + if (num == 0x30) + displayCursors(); +} + +void EdenGame::generique() { + drawBlackBars(); + display(); + fadeToBlack(3); + clearScreen(); + int oldmusic = _globals->_currMusicNum; + playHNM(95); + displayPanel(); + displayTopPanel(); + _paletteUpdateRequired = true; + startmusique(oldmusic); +} + +void EdenGame::cancel2() { + drawTopScreen(); + showObjects(); + _globals->_iconsIndex = 16; + _globals->_drawFlags &= ~DrawFlags::drDrawMenu; + gameToMirror(1); +} + +void EdenGame::testvoice() { + _globals->_frescoNumber = 0; + _globals->_characterPtr = kPersons; + _globals->_dialogType = DialogType::dtInspect; + int16 num = (kPersons[PER_KING]._id << 3) | _globals->_dialogType; + dialoscansvmas((Dialog *)getElem(_gameDialogs, num)); + restoreUnderSubtitles(); + displaySubtitles(); + persovox(); + waitEndSpeak(); + endCharacterSpeech(); + _globals->_varCA = 0; + _globals->_dialogType = DialogType::dtTalk; +} + +void EdenGame::load() { + char name[132]; + _gameLoaded = false; + byte oldMusic = _globals->_currMusicNum; //TODO: from uint16 to byte?! + fademusica0(1); + desktopcolors(); + FlushEvents(-1, 0); +// if(OpenDialog(0, 0)) //TODO: write me + { + // TODO + strcpy(name, "edsave1.000"); + loadgame(name); + } + _vm->hideMouse(); + CLBlitter_FillScreenView(0xFFFFFFFF); + fadeToBlack(3); + CLBlitter_FillScreenView(0); + if (!_gameLoaded) { + _musicFadeFlag = 3; + musicspy(); + _paletteUpdateRequired = true; + return; + } + if ((oldMusic & 0xFF) != _globals->_currMusicNum) { //TODO: r30 is uns char/bug??? + oldMusic = _globals->_currMusicNum; + _globals->_currMusicNum = 0; + startmusique(oldMusic); + } else { + _musicFadeFlag = 3; + musicspy(); + } + bool talk = _globals->_autoDialog; //TODO check me + initafterload(); + fadeToBlack(3); + CLBlitter_FillScreenView(0); + CLBlitter_FillView(_mainView, 0); + drawTopScreen(); + _globals->_inventoryScrollPos = 0; + showObjects(); + updateRoom(_globals->_roomNum); + if (talk) { + _globals->_iconsIndex = 4; + _globals->_autoDialog = true; + parle_moi(); + } + +} + +void EdenGame::initafterload() { + _globals->_characterImageBank = 0; + _globals->_lastPlaceNum = 0; + loadPlace(_globals->_areaPtr->_placeNum); + _gameIcons[18]._cursorId |= 0x8000; + if (_globals->_curAreaType == AreaType::atValley) + _gameIcons[18]._cursorId &= ~0x8000; + kPersoRoomBankTable[30] = 27; + if (_globals->_phaseNum >= 352) + kPersoRoomBankTable[30] = 26; + _animateTalking = false; + _animationActive = false; + _globals->_var100 = 0; + _globals->_eventType = EventType::etEventC; + _globals->_valleyVidNum = 0; + _globals->_drawFlags &= ~DrawFlags::drDrawMenu; + _currentTime = _vm->_timerTicks / 100; + _globals->_gameTime = _currentTime; + if (_globals->_roomCharacterType == PersonFlags::pftTyrann) + setChrono(3000); + _adamMapMarkPos.x = -1; + _adamMapMarkPos.y = -1; +} + +void EdenGame::save() { + char name[260]; + fademusica0(1); + desktopcolors(); + FlushEvents(-1, 0); + //SaveDialog(byte_37150, byte_37196->ff_A); + //TODO + strcpy(name, "edsave1.000"); + savegame(name); + _vm->hideMouse(); + CLBlitter_FillScreenView(0xFFFFFFFF); + fadeToBlack(3); + CLBlitter_FillScreenView(0); + _musicFadeFlag = 3; + musicspy(); + _paletteUpdateRequired = true; +} + +void EdenGame::desktopcolors() { + fadeToBlack(3); + CLBlitter_FillScreenView(0xFFFFFFFF); + CLPalette_BeSystem(); + _vm->showMouse(); +} + +void EdenGame::panelrestart() { + _gameLoaded = false; + byte curmus = _globals->_currMusicNum; + byte curlng = _globals->_prefLanguage; + loadrestart(); + _globals->_prefLanguage = curlng; + if (!_gameLoaded) //TODO always? + return; + _globals->_characterImageBank = 0; + _globals->_lastPlaceNum = 0; + loadPlace(_globals->_areaPtr->_placeNum); + _globals->_displayFlags = DisplayFlags::dfFlag1; + _gameIcons[18]._cursorId |= 0x8000; + if (_globals->_curAreaType == AreaType::atValley) + _gameIcons[18]._cursorId &= ~0x8000; + kPersoRoomBankTable[30] = 27; + if (_globals->_phaseNum >= 352) + kPersoRoomBankTable[30] = 26; + _animateTalking = false; + _animationActive = false; + _globals->_var100 = 0; + _globals->_eventType = 0; + _globals->_valleyVidNum = 0; + _globals->_drawFlags &= ~DrawFlags::drDrawMenu; + _globals->_inventoryScrollPos = 0; + _adamMapMarkPos.x = -1; + _adamMapMarkPos.y = -1; + if (curmus != _globals->_currMusicNum) { + curmus = _globals->_currMusicNum; + _globals->_currMusicNum = 0; + startmusique(curmus); + } + fadeToBlack(3); + CLBlitter_FillScreenView(0); + CLBlitter_FillView(_mainView, 0); + drawTopScreen(); + showObjects(); + saveFriezes(); + _showBlackBars = true; + updateRoom(_globals->_roomNum); +} + +void EdenGame::reallyquit() { + _quitFlag3 = true; + _quitFlag2 = true; +} + +void EdenGame::confirmer(char mode, char yesId) { + _globals->_iconsIndex = 119; + _gameIcons[119]._objectId = yesId; + _confirmMode = mode; + useBank(65); + noclipax(12, 117, 74); + _cursorPosX = 156; + if (_vm->shouldQuit()) + _cursorPosX = 136; + _cursorPosY = 88; +} + +void EdenGame::confirmYes() { + displayPanel(); + _globals->_iconsIndex = 85; + switch (_confirmMode) { + case 1: + panelrestart(); + break; + case 2: + reallyquit(); + break; + } +} + +void EdenGame::confirmNo() { + displayPanel(); + _globals->_iconsIndex = 85; +// pomme_q = false; +} + +void EdenGame::restart() { + confirmer(1, _curSpot2->_objectId); +} + +void EdenGame::edenQuit() { + confirmer(2, _curSpot2->_objectId); +} + +// Original name: choixsubtitle +void EdenGame::choseSubtitleOption() { + byte lang = _curSpot2->_objectId & 0xF; + if (lang == _globals->_prefLanguage) + return; + if (lang > 5) + return; + _globals->_prefLanguage = lang; + langbuftopanel(); + displayLanguage(); +} + +// Original name: reglervol +void EdenGame::changeVolume() { + byte *valptr = &_globals->_prefMusicVol[_curSpot2->_objectId & 7]; + _cursorPosY = 104 - ((*valptr >> 2) & 0x3F); // TODO: check me + _curSliderValuePtr = valptr; + _globals->_menuFlags |= MenuFlags::mfFlag1; + if (_curSpot2->_objectId & 8) + _globals->_menuFlags |= MenuFlags::mfFlag2; + _curSliderX = _curSpot2->sx; + _curSliderY = _cursorPosY; +} + +void EdenGame::changervol() { + if (_mouseHeld) { + restrictCursorArea(_curSliderX - 1, _curSliderX + 3, 40, 110); + int16 delta = _curSliderY - _cursorPosY; + if (delta == 0) + return; + newvol(_curSliderValuePtr, delta); + if (_globals->_menuFlags & MenuFlags::mfFlag2) + newvol(_curSliderValuePtr + 1, delta); + cursbuftopanel(); + displayCursors(); + _curSliderY = _cursorPosY; + } else + _globals->_menuFlags &= ~(MenuFlags::mfFlag1 | MenuFlags::mfFlag2); +} + +void EdenGame::newvol(byte *volptr, int16 delta) { + int16 vol = *volptr / 4; + vol += delta; + if (vol < 0) + vol = 0; + if (vol > 63) + vol = 63; + *volptr = vol * 4; + _musicChannel->setVolume(_globals->_prefMusicVol[0], _globals->_prefMusicVol[1]); +} + +void EdenGame::playtape() { + if (_globals->_menuItemIdHi & 8) + _globals->_tapePtr++; + for (;; _globals->_tapePtr++) { + if (_globals->_tapePtr == &_tapes[MAX_TAPES]) { + _globals->_tapePtr--; + stoptape(); + return; + } + if (_globals->_tapePtr->_textNum) + break; + } + _globals->_menuFlags |= MenuFlags::mfFlag8; + _globals->_drawFlags &= ~DrawFlags::drDrawMenu; + uint16 oldRoomNum = _globals->_roomNum; + uint16 oldParty = _globals->_party; + byte oldBack = _globals->_roomBackgroundBankNum; + perso_t *oldPerso = _globals->_characterPtr; + _globals->_party = _globals->_tapePtr->_party; + _globals->_roomNum = _globals->_tapePtr->_roomNum; + _globals->_roomBackgroundBankNum = _globals->_tapePtr->_backgroundBankNum; + _globals->_dialogPtr = _globals->_tapePtr->_dialog; + _globals->_characterPtr = _globals->_tapePtr->_perso; + endCharacterSpeech(); + affcurstape(); + if (_globals->_characterPtr != oldPerso + || _globals->_roomNum != _lastTapeRoomNum) { + _lastTapeRoomNum = _globals->_roomNum; + _globals->_curCharacterAnimPtr = nullptr; + _globals->_varCA = 0; + _globals->_characterImageBank = -1; + AnimEndCharacter(); + loadCurrCharacter(); + } + displayCharacterBackground(); + _globals->_textNum = _globals->_tapePtr->_textNum; + my_bulle(); + getDataSync(); + displayCharacterPanel(); + persovox(); + _globals->_roomBackgroundBankNum = oldBack; + _globals->_party = oldParty; + _globals->_roomNum = oldRoomNum; +} + +void EdenGame::rewindtape() { + if (_globals->_tapePtr > _tapes) { + _globals->_tapePtr--; + _globals->_menuFlags &= ~MenuFlags::mfFlag8; + affcurstape(); + } +} + +void EdenGame::depcurstape() { + if (_mouseHeld) { + restrictCursorArea(95, 217, 179, 183); + int idx = (_cursorPosX - 97); + if (idx < 0) + idx = 0; + + idx /= 8; + tape_t *tape = _tapes + idx; + if (tape >= _tapes + 16) + tape = _tapes + 16 - 1; + + if (tape != _globals->_tapePtr) { + _globals->_tapePtr = tape; + affcurstape(); + _globals->_menuFlags &= ~MenuFlags::mfFlag8; + } + } else + _globals->_menuFlags &= ~MenuFlags::mfFlag4; +} + +void EdenGame::affcurstape() { + if (_globals->_drawFlags & DrawFlags::drDrawFlag8) + _noPalette = true; + useBank(65); + noclipax(2, 0, 176); + int x = (_globals->_tapePtr - _tapes) * 8 + 97; + _gameIcons[112].sx = x - 3; + _gameIcons[112].ex = x + 3; + noclipax(5, x, 179); + _noPalette = false; +} + +void EdenGame::forwardtape() { + if (_globals->_tapePtr < _tapes + 16) { + _globals->_tapePtr++; + _globals->_menuFlags &= ~MenuFlags::mfFlag8; + affcurstape(); + } +} + +void EdenGame::stoptape() { + if (!(_globals->_drawFlags & DrawFlags::drDrawFlag8)) + return; + _globals->_menuFlags &= ~MenuFlags::mfFlag8; + _globals->_drawFlags &= ~DrawFlags::drDrawFlag8; + _globals->_menuFlags |= MenuFlags::mfFlag10; + _globals->_iconsIndex = 85; + _globals->_characterPtr = nullptr; + _lastTapeRoomNum = 0; + endCharacterSpeech(); + fin_perso(); + displayPanel(); + displayTopPanel(); + _paletteUpdateRequired = true; +} + +void EdenGame::cliccurstape() { + _globals->_menuFlags |= MenuFlags::mfFlag4; +} + +void EdenGame::paneltobuf() { + setSrcRect(0, 16, 320 - 1, 169 - 1); + setDestRect(320, 16, 640 - 1, 169 - 1); + CLBlitter_CopyViewRect(_mainView, _mainView, &rect_src, &rect_dst); +} + +void EdenGame::cursbuftopanel() { + setSrcRect(434, 40, 525 - 1, 111 - 1); + setDestRect(114, 40, 205 - 1, 111 - 1); + CLBlitter_CopyViewRect(_mainView, _mainView, &rect_src, &rect_dst); +} + +void EdenGame::langbuftopanel() { + setSrcRect(328, 42, 407 - 1, 97 - 1); + setDestRect(8, 42, 87 - 1, 97 - 1); + CLBlitter_CopyViewRect(_mainView, _mainView, &rect_src, &rect_dst); +} + +// Original name: affpanel +void EdenGame::displayPanel() { + useBank(65); + noclipax(0, 0, 16); + paneltobuf(); + displayLanguage(); + displayCursors(); + affcurstape(); +} + +// Original name: afflangue +void EdenGame::displayLanguage() { + useBank(65); + if (_globals->_prefLanguage > 5) + return; + noclipax(6, 8, _globals->_prefLanguage * 9 + 43); //TODO: * FONT_HEIGHT + noclipax(7, 77, _globals->_prefLanguage * 9 + 44); +} + +// Original name: affcursvol +void EdenGame::displayVolCursor(int16 x, int16 vol1, int16 vol2) { + int16 slider = 3; + if (_lastMenuItemIdLo && (_lastMenuItemIdLo & 9) != 1) //TODO check me + slider = 4; + noclipax(slider, x, 104 - vol1); + slider = 3; + if ((_lastMenuItemIdLo & 9) != 0) + slider = 4; + noclipax(slider, x + 12, 104 - vol2); +} + +// Original name: affcurseurs +void EdenGame::displayCursors() { + useBank(65); + if (_globals->_drawFlags & DrawFlags::drDrawFlag8) + return; + selectCursor(48); + displayVolCursor(114, _globals->_prefMusicVol[0] / 4, _globals->_prefMusicVol[1] / 4); + selectCursor(50); + displayVolCursor(147, _globals->_prefVoiceVol[0] / 4, _globals->_prefVoiceVol[1] / 4); + selectCursor(52); + displayVolCursor(179, _globals->_prefSoundVolume[0] / 4, _globals->_prefSoundVolume[1] / 4); +} + +// Original name: curseurselect +void EdenGame::selectCursor(int itemId) { + _lastMenuItemIdLo = _globals->_menuItemIdLo; + if ((_lastMenuItemIdLo & ~9) != itemId) + _lastMenuItemIdLo = 0; +} + +// Original name: afftoppano +void EdenGame::displayTopPanel() { + noclipax(1, 0, 0); +} + +// Original name: affresult +void EdenGame::displayResult() { + restoreUnderSubtitles(); + _globals->_characterPtr = &kPersons[19]; + _globals->_dialogType = DialogType::dtInspect; + int16 num = (kPersons[PER_UNKN_156]._id << 3) | _globals->_dialogType; + if (dialoscansvmas((Dialog *)getElem(_gameDialogs, num))) + displaySubtitles(); + _globals->_varCA = 0; + _globals->_dialogType = DialogType::dtTalk; + _globals->_characterPtr = nullptr; +} + +// Original name: limitezonecurs +void EdenGame::restrictCursorArea(int16 xmin, int16 xmax, int16 ymin, int16 ymax) { + _cursorPosX = CLIP(_cursorPosX, xmin, xmax); + _cursorPosY = CLIP(_cursorPosY, ymin, ymax); +} + +// Original name: PommeQ +void EdenGame::edenShudown() { + Icon *icon = &_gameIcons[85]; + if (_globals->_displayFlags & DisplayFlags::dfFrescoes) { + _torchCursor = false; + _cursorSaved = true; + if (_globals->_displayFlags & DisplayFlags::dfPerson) + closeCharacterScreen(); + _globals->_displayFlags = DisplayFlags::dfFlag1; + resetScroll(); + _globals->_var100 = 0xFF; + updateRoom(_globals->_roomNum); + } + if (_globals->_displayFlags & DisplayFlags::dfPerson) + closeCharacterScreen(); + if (_globals->_displayFlags & DisplayFlags::dfPanable) + resetScroll(); + if (_globals->_displayFlags & DisplayFlags::dfMirror) + resetScroll(); + if (_globals->_drawFlags & DrawFlags::drDrawFlag8) + stoptape(); + if (_personTalking) + endCharacterSpeech(); + _globals->_var103 = 0; + _globals->_mirrorEffect = 0; + putObject(); + _currCursor = 53; + if (_globals->_displayFlags != DisplayFlags::dfFlag2) + gotoPanel(); + _curSpot2 = icon + 7; //TODO + edenQuit(); +} + +void EdenGame::habitants(perso_t *perso) { + char persType = perso->_flags & PersonFlags::pfTypeMask; //TODO rename + if (persType && persType != PersonFlags::pfType2) { + _globals->_roomCharacterPtr = perso; + _globals->_roomCharacterType = persType; + _globals->_roomCharacterFlags = perso->_flags; + _globals->_roomPersoItems = perso->_items; + _globals->_roomCharacterPowers = perso->_powers; + _globals->_partyOutside |= perso->_partyMask; + if (_globals->_roomCharacterType == PersonFlags::pftTriceraptor) + removeInfo(_globals->_areaNum + ValleyNews::vnTriceraptorsIn); + else if (_globals->_roomCharacterType == PersonFlags::pftVelociraptor) + removeInfo(_globals->_areaNum + ValleyNews::vnVelociraptorsIn); + } else if (!(perso->_flags & PersonFlags::pfInParty)) + _globals->_partyOutside |= perso->_partyMask; +} + +void EdenGame::suiveurs(perso_t *perso) { + char persType = perso->_flags & PersonFlags::pfTypeMask; + if (persType == 0 || persType == PersonFlags::pfType2) { + if (perso->_flags & PersonFlags::pfInParty) + _globals->_party |= perso->_partyMask; + } +} + +void EdenGame::evenements(perso_t *perso) { + if (_globals->_var113) + return; + + if (perso >= &kPersons[PER_UNKN_18C]) + return; + + if (!dialogEvent(perso)) + return; + + _globals->_var113++; + _globals->_oldDisplayFlags = 1; + perso = _globals->_characterPtr; + initCharacterPointers(perso); + if (!(perso->_partyMask & PersonMask::pmLeader)) + _globals->_var60 = 1; + _globals->_eventType = 0; +} + +void EdenGame::followme(perso_t *perso) { + if (perso->_flags & PersonFlags::pfTypeMask) + return; + if (perso->_flags & PersonFlags::pfInParty) + perso->_roomNum = _destinationRoom; +} + +void EdenGame::rangermammi(perso_t *perso, Room *room) { + Room *found_room = nullptr; + if (!(perso->_partyMask & PersonMask::pmLeader)) + return; + for (; room->_id != 0xFF; room++) { + if (room->_flags & RoomFlags::rfHasCitadel) { + found_room = room; + break; + } + if (room->_party != 0xFFFF && (room->_party & PersonMask::pmLeader)) + found_room = room; //TODO: no brk? + } + if (!found_room) + return; + perso->_roomNum &= ~0xFF; + perso->_roomNum |= found_room->_location; + perso->_flags &= ~PersonFlags::pfInParty; + _globals->_party &= ~perso->_partyMask; +} + +void EdenGame::perso_ici(int16 action) { + perso_t *perso = &kPersons[PER_UNKN_156]; +// room_t *room = p_global->last_area_ptr->room_ptr; //TODO: compiler opt bug? causes access to zero ptr??? last_area_ptr == 0 + switch (action) { + case 0: + suiveurs(perso); + break; + case 1: + habitants(perso); + break; + case 3: + evenements(perso); + break; + case 4: + followme(perso); + break; + case 5: + rangermammi(perso, _globals->_lastAreaPtr->_citadelRoomPtr); + break; + } + perso = kPersons; + do { + if (perso->_roomNum == _globals->_roomNum && !(perso->_flags & PersonFlags::pf80)) { + switch (action) { + case 0: + suiveurs(perso); + break; + case 1: + habitants(perso); + break; + case 3: + evenements(perso); + break; + case 4: + followme(perso); + break; + case 5: + rangermammi(perso, _globals->_lastAreaPtr->_citadelRoomPtr); + break; + } + } + perso++; + } while (perso->_roomNum != 0xFFFF); +} + +// Original name: setpersohere +void EdenGame::setCharacterHere() { + debug("setCharacterHere, perso is %ld", _globals->_characterPtr - kPersons); + _globals->_partyOutside = 0; + _globals->_party = 0; + _globals->_roomCharacterPtr = nullptr; + _globals->_roomCharacterType = 0; + _globals->_roomCharacterFlags = 0; + perso_ici(1); + perso_ici(0); + if (_globals->_roomCharacterType == PersonFlags::pftTyrann) + removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn); + if (_globals->_roomCharacterType == PersonFlags::pftTriceraptor) + removeInfo(_globals->_areaNum + ValleyNews::vnTriceraptorsIn); + if (_globals->_roomCharacterType == PersonFlags::pftVelociraptor) { + removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn); + removeInfo(_globals->_areaNum + ValleyNews::vnTyrannLost); + removeInfo(_globals->_areaNum + ValleyNews::vnVelociraptorsLost); + } +} + +void EdenGame::faire_suivre(int16 roomNum) { + _destinationRoom = roomNum; + perso_ici(4); +} + +// Original name: suis_moi5 +void EdenGame::AddCharacterToParty() { + debug("adding person %ld to party", _globals->_characterPtr - kPersons); + _globals->_characterPtr->_flags |= PersonFlags::pfInParty; + _globals->_characterPtr->_roomNum = _globals->_roomNum; + _globals->_party |= _globals->_characterPtr->_partyMask; + _globals->_drawFlags |= DrawFlags::drDrawTopScreen; +} + +// Original name: suis_moi +void EdenGame::addToParty(int16 index) { + perso_t *old_perso = _globals->_characterPtr; + _globals->_characterPtr = &kPersons[index]; + AddCharacterToParty(); + _globals->_characterPtr = old_perso; +} + +// Original name: reste_ici5 +void EdenGame::removeCharacterFromParty() { + debug("removing person %ld from party", _globals->_characterPtr - kPersons); + _globals->_characterPtr->_flags &= ~PersonFlags::pfInParty; + _globals->_partyOutside |= _globals->_characterPtr->_partyMask; + _globals->_party &= ~_globals->_characterPtr->_partyMask; + _globals->_drawFlags |= DrawFlags::drDrawTopScreen; +} + +// Original name: reste_ici +void EdenGame::removeFromParty(int16 index) { + perso_t *old_perso = _globals->_characterPtr; + _globals->_characterPtr = &kPersons[index]; + removeCharacterFromParty(); + _globals->_characterPtr = old_perso; +} + +// Original name: eloipart +void EdenGame::handleEloiDeparture() { + removeFromParty(PER_ELOI); + _globals->_gameFlags &= ~GameFlags::gfFlag4000; + kPersons[PER_ELOI]._roomNum = 0; + _globals->_partyOutside &= ~kPersons[PER_ELOI]._partyMask; + if (_globals->_roomNum == 2817) + setChrono(3000); + _globals->_eloiDepartureDay = _globals->_gameDays; + _globals->_eloiHaveNews = 0; + unlockInfo(); +} + +// Original name: eloirevientq +bool EdenGame::checkEloiReturn() { + if (_globals->_phaseNum < 304) + return true; + if ((_globals->_phaseNum <= 353) || (_globals->_phaseNum == 370) || (_globals->_phaseNum == 384)) + return false; + if (_globals->_areaNum != Areas::arShandovra) + return true; + if (_globals->_phaseNum < 480) + return false; + return true; +} + +// Original name: eloirevient +void EdenGame::handleEloiReturn() { + if (_globals->_areaPtr->_type == AreaType::atValley && !kPersons[PER_ELOI]._roomNum) + kPersons[PER_ELOI]._roomNum = (_globals->_roomNum & 0xFF00) + 1; +} +//// phase.c +void EdenGame::incPhase() { + static phase_t phases[] = { + { 65, &EdenGame::dialautoon }, + { 113, &EdenGame::phase113 }, + { 129, &EdenGame::dialautoon }, + { 130, &EdenGame::phase130 }, + { 161, &EdenGame::phase161 }, + { 211, &EdenGame::dialautoon }, + { 226, &EdenGame::phase226 }, + { 257, &EdenGame::phase257 }, + { 353, &EdenGame::phase353 }, + { 369, &EdenGame::phase369 }, + { 371, &EdenGame::phase371 }, + { 385, &EdenGame::phase385 }, + { 386, &EdenGame::dialonfollow }, + { 418, &EdenGame::phase418 }, + { 433, &EdenGame::phase433 }, + { 434, &EdenGame::phase434 }, + { 449, &EdenGame::dialautoon }, + { 497, &EdenGame::dialautoon }, + { 513, &EdenGame::phase513 }, + { 514, &EdenGame::phase514 }, + { 529, &EdenGame::phase529 }, + { 545, &EdenGame::phase545 }, + { 561, &EdenGame::phase561 }, + { -1, nullptr } + }; + + _globals->_phaseNum++; + debug("!!! next phase - %4X , room %4X", _globals->_phaseNum, _globals->_roomNum); + _globals->_phaseActionsCount = 0; + for (phase_t *phase = phases; phase->_id != -1; phase++) { + if (_globals->_phaseNum == phase->_id) { + (this->*phase->disp)(); + break; + } + } +} + +void EdenGame::phase113() { + removeFromParty(PER_DINA); + kPersons[PER_DINA]._roomNum = 274; +} + +void EdenGame::phase130() { + dialautoon(); + removeFromParty(PER_MONK); +} + +void EdenGame::phase161() { + Area *area = _globals->_areaPtr; + addToParty(PER_MAMMI); + kPersons[PER_MAMMI]._flags |= PersonFlags::pf10; + area->_flags |= AreaFlags::afFlag1; + _globals->_curAreaFlags |= AreaFlags::afFlag1; +} + +void EdenGame::phase226() { + newObject(16, 3); + newObject(16, 4); + newObject(16, 5); +} + +void EdenGame::phase257() { + _gameIcons[127]._cursorId &= ~0x8000; + _globals->_characterBackgroundBankIdx = 58; + dialautooff(); +} + +void EdenGame::phase353() { + removeFromParty(PER_DINA); + kPersons[PER_DINA]._roomNum = 0; + kTabletView[1] = 88; +} + +void EdenGame::phase369() { + addToParty(PER_ELOI); + _globals->_narratorSequence = 2; + _gameRooms[334]._exits[0] = 134; + _gameRooms[335]._exits[0] = 134; +} + +void EdenGame::phase371() { + handleEloiReturn(); + _gameIcons[128]._cursorId &= ~0x8000; + _gameIcons[129]._cursorId &= ~0x8000; + _gameIcons[127]._cursorId |= 0x8000; + _globals->_characterBackgroundBankIdx = 59; + _gameRooms[334]._exits[0] = 0xFF; + _gameRooms[335]._exits[0] = 0xFF; + _gameIcons[123]._objectId = 9; + _gameIcons[124]._objectId = 26; + _gameIcons[125]._objectId = 42; + _gameIcons[126]._objectId = 56; +} + +void EdenGame::phase385() { + dialautooff(); + handleEloiReturn(); + _globals->_nextInfoIdx = 0; + _globals->_lastInfoIdx = 0; + updateInfoList(); + _globals->_lastInfo = 0; +} + +void EdenGame::phase418() { + loseObject(Objects::obHorn); + dialautoon(); + addToParty(PER_JABBER); +} + +void EdenGame::phase433() { + dialautoon(); + kPersons[PER_MAMMI_4]._flags &= ~PersonFlags::pf80; + kPersons[PER_JABBER]._flags &= ~PersonFlags::pf80; + setCharacterHere(); + _globals->_chronoFlag = 0; + _globals->_chrono = 0; +} + +void EdenGame::phase434() { + _globals->_roomNum = 275; + _gameRooms[16]._bank = 44; + _gameRooms[18]._bank = 44; + _gameIcons[132]._cursorId &= ~0x8000; + _globals->_characterBackgroundBankIdx = 61; + _gameRooms[118]._exits[2] = 0xFF; + abortDialogue(); + _gameRooms[7]._bank = 322; + removeFromParty(PER_EVE); + removeFromParty(PER_MONK); + removeFromParty(PER_ELOI); + removeFromParty(PER_GUARDS); + removeFromParty(PER_JABBER); + _globals->_drawFlags |= DrawFlags::drDrawTopScreen; +} + +void EdenGame::phase513() { + _globals->_lastDialogPtr = nullptr; + parlemoiNormalFlag = false; + dialautoon(); +} + +void EdenGame::phase514() { + _gameRooms[123]._exits[2] = 1; +} + +void EdenGame::phase529() { + _gameIcons[133]._cursorId &= ~0x8000; + _globals->_characterBackgroundBankIdx = 63; +} + +void EdenGame::phase545() { +} + +void EdenGame::phase561() { + _globals->_narratorSequence = 10; +} + +void EdenGame::bigphase1() { + static void (EdenGame::*bigphases[])() = { + &EdenGame::phase16, + &EdenGame::phase32, + &EdenGame::phase48, + &EdenGame::phase64, + &EdenGame::phase80, + &EdenGame::phase96, + &EdenGame::phase112, + &EdenGame::phase128, + &EdenGame::phase144, + &EdenGame::phase160, + &EdenGame::phase176, + &EdenGame::phase192, + &EdenGame::phase208, + &EdenGame::phase224, + &EdenGame::phase240, + &EdenGame::phase256, + &EdenGame::phase272, + &EdenGame::phase288, + &EdenGame::phase304, + &EdenGame::phase320, + &EdenGame::phase336, + &EdenGame::phase352, + &EdenGame::phase368, + &EdenGame::phase384, + &EdenGame::phase400, + &EdenGame::phase416, + &EdenGame::phase432, + &EdenGame::phase448, + &EdenGame::phase464, + &EdenGame::phase480, + &EdenGame::phase496, + &EdenGame::phase512, + &EdenGame::phase528, + &EdenGame::phase544, + &EdenGame::phase560 + }; + + int16 phase = (_globals->_phaseNum & ~3) + 0x10; //TODO: check me + debug("!!! big phase - %4X", phase); + _globals->_phaseActionsCount = 0; + _globals->_phaseNum = phase; + if (phase > 560) + return; + phase >>= 4; + (this->*bigphases[phase - 1])(); +} + +void EdenGame::bigphase() { + if (!(_globals->_dialogPtr->_flags & DialogFlags::dfSpoken)) + bigphase1(); +} + +void EdenGame::phase16() { + dialautoon(); +} + +void EdenGame::phase32() { + word_31E7A &= ~0x8000; +} + +void EdenGame::phase48() { + _gameRooms[8]._exits[1] = 22; + dialautoon(); +} + +void EdenGame::phase64() { + addToParty(PER_DINA); + kPersons[PER_ELOI]._roomNum = 259; +} + +void EdenGame::phase80() { + kPersons[PER_TAU]._roomNum = 0; +} + +void EdenGame::phase96() { +} + +void EdenGame::phase112() { + giveObject(); +} + +void EdenGame::phase128() { + addToParty(PER_DINA); + giveObject(); +} + +void EdenGame::phase144() { + addToParty(PER_ELOI); + _gameRooms[113]._video = 0; + _gameRooms[113]._bank = 317; +} + +void EdenGame::phase160() { +} + +void EdenGame::phase176() { + dialonfollow(); +} + +void EdenGame::phase192() { + Area *area = _globals->_areaPtr; + addToParty(PER_MAMMI_1); + kPersons[PER_MAMMI_1]._flags |= PersonFlags::pf10; + dialautoon(); + area->_flags |= AreaFlags::afFlag1; + _globals->_curAreaFlags |= AreaFlags::afFlag1; +} + +void EdenGame::phase208() { + handleEloiReturn(); +} + +void EdenGame::phase224() { + _gameIcons[126]._cursorId &= ~0x8000; + _globals->_characterBackgroundBankIdx = 57; + dialautooff(); +} + +void EdenGame::phase240() { + Area *area = _globals->_areaPtr; + addToParty(PER_MAMMI_2); + kPersons[PER_MAMMI_2]._flags |= PersonFlags::pf10; + area->_flags |= AreaFlags::afFlag1; + _globals->_curAreaFlags |= AreaFlags::afFlag1; +} + +void EdenGame::phase256() { + dialautoon(); +} + +void EdenGame::phase272() { + dialautoon(); + _globals->_eloiHaveNews = 0; +} + +void EdenGame::phase288() { + setChoiceYes(); + kPersons[PER_MUNGO]._roomNum = 0; + removeFromParty(PER_MUNGO); + addToParty(PER_ELOI); + _globals->_narratorSequence = 8; +} + +void EdenGame::phase304() { + Area *area = _globals->_areaPtr; + addToParty(PER_EVE); + addToParty(PER_MAMMI_5); + kPersons[PER_MAMMI_5]._flags |= PersonFlags::pf10; + dialautoon(); + area->_flags |= AreaFlags::afFlag1; + _globals->_curAreaFlags |= AreaFlags::afFlag1; +} + +void EdenGame::phase320() { + dialonfollow(); +} + +void EdenGame::phase336() { + _gameRooms[288]._exits[0] = 135; + _gameRooms[289]._exits[0] = 135; + loseObject(_globals->_curObjectId); + dialautoon(); +} + +void EdenGame::phase352() { + kPersoRoomBankTable[30] = 26; + kPersons[PER_EVE]._spriteBank = 9; + kPersons[PER_EVE]._targetLoc = 8; + followerList[13]._spriteNum = 2; + dialautoon(); + _gameRooms[288]._exits[0] = 0xFF; + _gameRooms[289]._exits[0] = 0xFF; + _gameRooms[288]._flags &= ~RoomFlags::rf02; + _gameRooms[289]._flags &= ~RoomFlags::rf02; +} + +void EdenGame::phase368() { + removeFromParty(PER_EVE); + dialautoon(); + kPersons[PER_ELOI]._roomNum = 1811; + kPersons[PER_DINA]._roomNum = 1607; +} + +void EdenGame::phase384() { + Area *area = _globals->_areaPtr; + addToParty(PER_EVE); + removeFromParty(PER_DINA); + dialautoon(); + area->_flags |= AreaFlags::afFlag1; + _globals->_curAreaFlags |= AreaFlags::afFlag1; + handleEloiDeparture(); +} + +void EdenGame::phase400() { + dialonfollow(); + kPersons[PER_KING]._roomNum = 0; + kPersons[PER_MONK]._roomNum = 259; + _globals->_eloiHaveNews = 0; + kObjectLocations[20] = 259; +} + +void EdenGame::phase416() { + addToParty(PER_MONK); + _gameIcons[130]._cursorId &= ~0x8000; + _globals->_characterBackgroundBankIdx = 60; + _gameRooms[0]._exits[0] = 138; +} + +void EdenGame::phase432() { + _globals->_narratorSequence = 3; + kPersons[PER_MAMMI_4]._flags |= PersonFlags::pf80; + kPersons[PER_JABBER]._flags |= PersonFlags::pf80; + kPersons[PER_ELOI]._roomNum = 257; + _gameRooms[0]._exits[0] = 0xFF; + _globals->_drawFlags |= DrawFlags::drDrawTopScreen; +} + +void EdenGame::phase448() { + dialautoon(); + handleEloiDeparture(); +} + +void EdenGame::phase464() { + _globals->_areaPtr->_flags |= AreaFlags::afFlag1; + _globals->_curAreaFlags |= AreaFlags::afFlag1; + kPersons[PER_MAMMI_6]._flags |= PersonFlags::pf10; + addToParty(PER_SHAZIA); + _globals->_citadelAreaNum = _globals->_areaNum; + naitredino(8); +} + +void EdenGame::phase480() { + giveObject(); + newValley(); + handleEloiReturn(); + kTabletView[1] = 94; +} + +void EdenGame::phase496() { + dialautoon(); + _globals->_lastDialogPtr = nullptr; + parlemoiNormalFlag = false; +} + +void EdenGame::phase512() { + removeFromParty(PER_MONK); + removeFromParty(PER_EVE); + removeFromParty(PER_SHAZIA); + removeFromParty(PER_GUARDS); +} + +void EdenGame::phase528() { + _globals->_narratorSequence = 11; + addToParty(PER_MONK); + addToParty(PER_ELOI); + addToParty(PER_EVE); + addToParty(PER_SHAZIA); + addToParty(PER_GUARDS); +} + +void EdenGame::phase544() { + handleEloiDeparture(); + dialautoon(); + removeFromParty(PER_SHAZIA); + removeFromParty(PER_GUARDS); +} + +void EdenGame::phase560() { + kPersons[PER_ELOI]._roomNum = 3073; + _gameRooms[127]._exits[1] = 0; +} + +//// saveload.c +void EdenGame::savegame(char *name) { +// filespec_t fs; +// Common::File handle; + int32 size; +// CLFile_MakeStruct(0, 0, name, &fs); +// CLFile_Create(&fs); +// CLFile_SetFinderInfos(&fs, 'EDNS', 'LEDN'); +// CLFile_Open(&fs, 3, handle); + + Common::OutSaveFile *handle = g_system->getSavefileManager()->openForSaving(name); + if (!handle) + return; + +#define CLFile_Write(h, ptr, size) \ +debug("writing 0x%X bytes", *size); \ +h->write(ptr, *size); + + vavaoffsetout(); + size = (char *)(&_globals->_saveEnd) - (char *)(_globals); + CLFile_Write(handle, _globals, &size); + size = (char *)(&_gameIcons[134]) - (char *)(&_gameIcons[123]); + CLFile_Write(handle, &_gameIcons[123], &size); + lieuoffsetout(); + size = (char *)(&kAreasTable[12]) - (char *)(&kAreasTable[0]); + CLFile_Write(handle, &kAreasTable[0], &size); + size = (char *)(&_gameRooms[423]) - (char *)(&_gameRooms[0]); + CLFile_Write(handle, &_gameRooms[0], &size); + size = (char *)(&_objects[42]) - (char *)(&_objects[0]); + CLFile_Write(handle, &_objects[0], &size); + size = (char *)(&kObjectLocations[45]) - (char *)(&kObjectLocations[0]); + CLFile_Write(handle, &kObjectLocations[0], &size); + size = (char *)(&followerList[14]) - (char *)(&followerList[13]); + CLFile_Write(handle, &followerList[13], &size); + size = (char *)(&kPersons[PER_UNKN_3DE]) - (char *)(&kPersons[PER_KING]); + CLFile_Write(handle, &kPersons[PER_KING], &size); + bandeoffsetout(); + size = (char *)(&_tapes[16]) - (char *)(&_tapes[0]); + CLFile_Write(handle, &_tapes[0], &size); + size = (char *)(&kTabletView[6]) - (char *)(&kTabletView[0]); + CLFile_Write(handle, &kTabletView[0], &size); + size = (char *)(&_gameDialogs[10240]) - (char *)(&_gameDialogs[0]); //TODO: const size 10240 + CLFile_Write(handle, &_gameDialogs[0], &size); + + delete handle; + +#undef CLFile_Write + +// CLFile_Close(handle); + + vavaoffsetin(); + lieuoffsetin(); + bandeoffsetin(); + + debug("* Game saved to %s", name); +} + +void EdenGame::loadrestart() { + assert(0); //TODO: this won't work atm - all snapshots are BE + int32 offs = 0; + int32 size; + size = (char *)(&_globals->_saveEnd) - (char *)(_globals); + loadpartoffile(2495, _globals, offs, size); + offs += size; + vavaoffsetin(); + size = (char *)(&_gameIcons[134]) - (char *)(&_gameIcons[123]); + loadpartoffile(2495, &_gameIcons[123], offs, size); + offs += size; + size = (char *)(&kAreasTable[12]) - (char *)(&kAreasTable[0]); + loadpartoffile(2495, &kAreasTable[0], offs, size); + offs += size; + lieuoffsetin(); + size = (char *)(&_gameRooms[423]) - (char *)(&_gameRooms[0]); + loadpartoffile(2495, &_gameRooms[0], offs, size); + offs += size; + size = (char *)(&_objects[42]) - (char *)(&_objects[0]); + loadpartoffile(2495, &_objects[0], offs, size); + offs += size; + size = (char *)(&kObjectLocations[45]) - (char *)(&kObjectLocations[0]); + loadpartoffile(2495, &kObjectLocations[0], offs, size); + offs += size; + size = (char *)(&followerList[14]) - (char *)(&followerList[13]); + loadpartoffile(2495, &followerList[13], offs, size); + offs += size; + size = (char *)(&kPersons[PER_UNKN_3DE]) - (char *)(&kPersons[PER_KING]); + loadpartoffile(2495, &kPersons[PER_KING], offs, size); + offs += size; + size = (char *)(&_tapes[16]) - (char *)(&_tapes[0]); + loadpartoffile(2495, &_tapes[0], offs, size); + offs += size; + bandeoffsetin(); + size = (char *)(&kTabletView[6]) - (char *)(&kTabletView[0]); + loadpartoffile(2495, &kTabletView[0], offs, size); + offs += size; + size = (char *)(&_gameDialogs[10240]) - (char *)(&_gameDialogs[0]); //TODO: const size 10240 + loadpartoffile(2495, &_gameDialogs[0], offs, size); + _gameLoaded = true; +} + +void EdenGame::loadgame(char *name) { +// filespec_t fs; +// Common::File handle; +// CLFile_MakeStruct(0, 0, name, &fs); +// CLFile_Open(&fs, 3, handle); + + Common::InSaveFile *handle = g_system->getSavefileManager()->openForLoading(name); + if (!handle) + return; + +#define CLFile_Read(h, ptr, size) \ + h->read(ptr, *size); + + int32 size = (char *)(&_globals->_saveEnd) - (char *)(_globals); + CLFile_Read(handle, _globals, &size); + vavaoffsetin(); + size = (char *)(&_gameIcons[134]) - (char *)(&_gameIcons[123]); + CLFile_Read(handle, &_gameIcons[123], &size); + size = (char *)(&kAreasTable[12]) - (char *)(&kAreasTable[0]); + CLFile_Read(handle, &kAreasTable[0], &size); + lieuoffsetin(); + size = (char *)(&_gameRooms[423]) - (char *)(&_gameRooms[0]); + CLFile_Read(handle, &_gameRooms[0], &size); + size = (char *)(&_objects[42]) - (char *)(&_objects[0]); + CLFile_Read(handle, &_objects[0], &size); + size = (char *)(&kObjectLocations[45]) - (char *)(&kObjectLocations[0]); + CLFile_Read(handle, &kObjectLocations[0], &size); + size = (char *)(&followerList[14]) - (char *)(&followerList[13]); + CLFile_Read(handle, &followerList[13], &size); + size = (char *)(&kPersons[55]) - (char *)(&kPersons[0]); + CLFile_Read(handle, &kPersons[0], &size); + size = (char *)(&_tapes[16]) - (char *)(&_tapes[0]); + CLFile_Read(handle, &_tapes[0], &size); + bandeoffsetin(); + size = (char *)(&kTabletView[6]) - (char *)(&kTabletView[0]); + CLFile_Read(handle, &kTabletView[0], &size); + size = (char *)(&_gameDialogs[10240]) - (char *)(&_gameDialogs[0]); //TODO: const size 10240 + CLFile_Read(handle, &_gameDialogs[0], &size); + + delete handle; +#undef CLFile_Read + +// CLFile_Close(handle); + _gameLoaded = true; + debug("* Game loaded from %s", name); +} + +#define NULLPTR (void*)0xFFFFFF +#define OFSOUT(val, base, typ) if (val) (val) = (typ*)((char*)(val) - (size_t)(base)); else (val) = (typ*)NULLPTR; +#define OFSIN(val, base, typ) if ((void*)(val) != NULLPTR) (val) = (typ*)((char*)(val) + (size_t)(base)); else (val) = 0; + +void EdenGame::vavaoffsetout() { + OFSOUT(_globals->_dialogPtr, _gameDialogs, Dialog); + OFSOUT(_globals->_nextDialogPtr, _gameDialogs, Dialog); + OFSOUT(_globals->_narratorDialogPtr, _gameDialogs, Dialog); + OFSOUT(_globals->_lastDialogPtr, _gameDialogs, Dialog); + OFSOUT(_globals->_tapePtr, _tapes, tape_t); + OFSOUT(_globals->_nextRoomIcon, _gameIcons, Icon); + OFSOUT(_globals->_roomPtr, _gameRooms, Room); + OFSOUT(_globals->_citaAreaFirstRoom, _gameRooms, Room); + OFSOUT(_globals->_areaPtr, kAreasTable, Area); + OFSOUT(_globals->_lastAreaPtr, kAreasTable, Area); + OFSOUT(_globals->_curAreaPtr, kAreasTable, Area); + OFSOUT(_globals->_characterPtr, kPersons, perso_t); + OFSOUT(_globals->_roomCharacterPtr, kPersons, perso_t); +} + +void EdenGame::vavaoffsetin() { + OFSIN(_globals->_dialogPtr, _gameDialogs, Dialog); + OFSIN(_globals->_nextDialogPtr, _gameDialogs, Dialog); + OFSIN(_globals->_narratorDialogPtr, _gameDialogs, Dialog); + OFSIN(_globals->_lastDialogPtr, _gameDialogs, Dialog); + OFSIN(_globals->_tapePtr, _tapes, tape_t); + OFSIN(_globals->_nextRoomIcon, _gameIcons, Icon); + OFSIN(_globals->_roomPtr, _gameRooms, Room); + OFSIN(_globals->_citaAreaFirstRoom, _gameRooms, Room); + OFSIN(_globals->_areaPtr, kAreasTable, Area); + OFSIN(_globals->_lastAreaPtr, kAreasTable, Area); + OFSIN(_globals->_curAreaPtr, kAreasTable, Area); + OFSIN(_globals->_characterPtr, kPersons, perso_t); + OFSIN(_globals->_roomCharacterPtr, kPersons, perso_t); +} + +void EdenGame::lieuoffsetout() { + for (int i = 0; i < 12; i++) + OFSOUT(kAreasTable[i]._citadelRoomPtr, _gameRooms, Room); +} + +void EdenGame::lieuoffsetin() { + for (int i = 0; i < 12; i++) + OFSIN(kAreasTable[i]._citadelRoomPtr, _gameRooms, Room); +} + +void EdenGame::bandeoffsetout() { + for (int i = 0; i < 16; i++) { + OFSOUT(_tapes[i]._perso, kPersons, perso_t); + OFSOUT(_tapes[i]._dialog, _gameDialogs, Dialog); + } +} + +void EdenGame::bandeoffsetin() { + for (int i = 0; i < 16; i++) { + OFSIN(_tapes[i]._perso, kPersons, perso_t); + OFSIN(_tapes[i]._dialog, _gameDialogs, Dialog); + } +} + +//// cond.c + +char EdenGame::testCondition(int16 index) { + bool endFl = false; + uint16 stack[32]; + uint16 *sp = stack; + assert(index > 0); + _codePtr = (byte *)getElem(_gameConditions, (index - 1)); + uint16 value; + do { + value = fetchValue(); + for (;;) { + byte op = *_codePtr++; + if (op == 0xFF) { + endFl = true; + break; + } + if ((op & 0x80) == 0) { + uint16 value2 = fetchValue(); + value = operation(op, value, value2); + } else { + assert(sp < stack + 32); + *sp++ = value; + *sp++ = op; + break; + } + } + } while (!endFl); + + if (sp != stack) { + *sp++ = value; + uint16 *sp2 = stack; + value = *sp2++; + do { + byte op = *sp2++; + uint16 value2 = *sp2++; + value = operation(op, value, value2); + } while (sp2 != sp); + } +// if (value) + debug("cond %d(-1) returns %s", index, value ? "TRUE" : "false"); +// if (index == 402) debug("(glob_61.b == %X) & (glob_12.w == %X) & (glob_4C.b == %X) & (glob_4E.b == %X)", p_global->eventType, p_global->phaseNum, p_global->worldTyrannSighted, p_global->ff_4E); + return value != 0; +} + +// Original name: opera_add +uint16 EdenGame::operAdd(uint16 v1, uint16 v2) { + return v1 + v2; +} + +// Original name: opera_sub +uint16 EdenGame::operSub(uint16 v1, uint16 v2) { + return v1 - v2; +} + +// Original name: opera_and +uint16 EdenGame::operLogicalAnd(uint16 v1, uint16 v2) { + return v1 & v2; +} + +// Original name: opera_or +uint16 EdenGame::operLogicalOr(uint16 v1, uint16 v2) { + return v1 | v2; +} + +// Original name: opera_egal +uint16 EdenGame::operIsEqual(uint16 v1, uint16 v2) { + return v1 == v2 ? -1 : 0; +} + +// Original name: opera_petit +uint16 EdenGame::operIsSmaller(uint16 v1, uint16 v2) { + return v1 < v2 ? -1 : 0; //TODO: all comparisons are unsigned! +} + +// Original name: opera_grand +uint16 EdenGame::operIsGreater(uint16 v1, uint16 v2) { + return v1 > v2 ? -1 : 0; +} + +// Original name: opera_diff +uint16 EdenGame::operIsDifferent(uint16 v1, uint16 v2) { + return v1 != v2 ? -1 : 0; +} + +// Original name: opera_petega +uint16 EdenGame::operIsSmallerOrEqual(uint16 v1, uint16 v2) { + return v1 <= v2 ? -1 : 0; +} + +// Original name: opera_graega +uint16 EdenGame::operIsGreaterOrEqual(uint16 v1, uint16 v2) { + return v1 >= v2 ? -1 : 0; +} + +// Original name: opera_faux +uint16 EdenGame::operFalse(uint16 v1, uint16 v2) { + return 0; +} + +uint16 EdenGame::operation(byte op, uint16 v1, uint16 v2) { + static uint16(EdenGame::*operations[16])(uint16, uint16) = { + &EdenGame::operIsEqual, + &EdenGame::operIsSmaller, + &EdenGame::operIsGreater, + &EdenGame::operIsDifferent, + &EdenGame::operIsSmallerOrEqual, + &EdenGame::operIsGreaterOrEqual, + &EdenGame::operAdd, + &EdenGame::operSub, + &EdenGame::operLogicalAnd, + &EdenGame::operLogicalOr, + &EdenGame::operFalse, + &EdenGame::operFalse, + &EdenGame::operFalse, + &EdenGame::operFalse, + &EdenGame::operFalse, + &EdenGame::operFalse + }; + return (this->*operations[(op & 0x1F) >> 1])(v1, v2); +} + +#define VAR(ofs, var) case ofs: return _globals->var; + +uint8 EdenGame::getByteVar(uint16 offset) { + switch (offset) { + VAR(0, _areaNum); + VAR(1, _areaVisitCount); + VAR(2, _menuItemIdLo); + VAR(3, _menuItemIdHi); //TODO: pad? + VAR(0x42, _newMusicType); + VAR(0x43, _var43); + VAR(0x44, _videoSubtitleIndex); + VAR(0x45, _partyInstruments); // &1 - Bell for Monk, &2 - Drum for Thugg + VAR(0x46, _monkGotRing); + VAR(0x47, _chronoFlag); + VAR(0x48, _curRoomFlags); + VAR(0x49, _endGameFlag); + VAR(0x4A, _lastInfo); + VAR(0x4B, _autoDialog); + VAR(0x4C, _worldTyranSighted); + VAR(0x4D, _var4D); + VAR(0x4E, _var4E); + VAR(0x4F, _worldGaveGold); + VAR(0x50, _worldHasTriceraptors); + VAR(0x51, _worldHasVelociraptors); + VAR(0x52, _worldHasTyran); + VAR(0x53, _var53); + VAR(0x54, _var54); //CHEKME: Used? + VAR(0x55, _var55); //TODO: pad? + VAR(0x56, _gameHours); + VAR(0x57, _textToken1); + VAR(0x58, _textToken2); //TODO: pad? + VAR(0x59, _eloiHaveNews); + VAR(0x5A, _dialogFlags); + VAR(0x5B, _curAreaType); + VAR(0x5C, _curCitadelLevel); + VAR(0x5D, _newLocation); + VAR(0x5E, _prevLocation); + VAR(0x5F, _curPersoFlags); + VAR(0x60, _var60); + VAR(0x61, _eventType); + VAR(0x62, _var62); //TODO: pad? + VAR(0x63, _curObjectId); + VAR(0x64, _curObjectFlags); + VAR(0x65, _var65); //TODO: pad? + VAR(0x66, _roomCharacterType); + VAR(0x67, _roomCharacterFlags); + VAR(0x68, _narratorSequence); + VAR(0x69, _var69); + VAR(0x6A, _var6A); + VAR(0x6B, _frescoNumber); + VAR(0x6C, _var6C); //TODO: pad? + VAR(0x6D, _var6D); //TODO: pad? + VAR(0x6E, _labyrinthDirections); + VAR(0x6F, _labyrinthRoom); + default: + error("Undefined byte variable access (0x%X)", offset); + } + return 0; +} + +uint16 EdenGame::getWordVar(uint16 offset) { + switch (offset) { + VAR(4, _randomNumber); //TODO: this is randomized in pc ver and used by some conds. always zero on mac + VAR(6, _gameTime); + VAR(8, _gameDays); + VAR(0xA, _chrono); + VAR(0xC, _eloiDepartureDay); + VAR(0xE, _roomNum); // current room number + VAR(0x10, _newRoomNum); // target room number selected on world map + VAR(0x12, _phaseNum); + VAR(0x14, _metPersonsMask1); + VAR(0x16, _party); + VAR(0x18, _partyOutside); + VAR(0x1A, _metPersonsMask2); + VAR(0x1C, _var1C); //TODO: write-only? + VAR(0x1E, _phaseActionsCount); + VAR(0x20, _curAreaFlags); + VAR(0x22, _curItemsMask); + VAR(0x24, _curPowersMask); + VAR(0x26, _curPersoItems); + VAR(0x28, _curCharacterPowers); + VAR(0x2A, _wonItemsMask); + VAR(0x2C, _wonPowersMask); + VAR(0x2E, _stepsToFindAppleFast); + VAR(0x30, _stepsToFindAppleNormal); + VAR(0x32, _roomPersoItems); //TODO: write-only? + VAR(0x34, _roomCharacterPowers); //TODO: write-only? + VAR(0x36, _gameFlags); + VAR(0x38, _curVideoNum); + VAR(0x3A, _morkusSpyVideoNum1); //TODO: pad? + VAR(0x3C, _morkusSpyVideoNum2); //TODO: pad? + VAR(0x3E, _morkusSpyVideoNum3); //TODO: pad? + VAR(0x40, _morkusSpyVideoNum4); //TODO: pad? + default: + error("Undefined word variable access (0x%X)", offset); + } + return 0; +} + +#undef VAR + +// Original name: cher_valeur +uint16 EdenGame::fetchValue() { + uint16 val; + byte typ = *_codePtr++; + if (typ < 0x80) { + byte ofs = *_codePtr++; + val = (typ == 1) ? getByteVar(ofs) : getWordVar(ofs); + } else if (typ == 0x80) + val = *_codePtr++; + else { + val = READ_LE_UINT16(_codePtr); + _codePtr += 2; + } + return val; +} + +// Original name: ret +void EdenGame::actionNop() { +} + +//// cube.c +// Original name: make_tabcos +void EdenGame::initSinCosTable() { + for (int i = 0; i < 361; i++) { + _cosTable[i] = (int)(cos(3.1416 * i / 180.0) * 255.0); + _sinTable[i] = (int)(sin(3.1416 * i / 180.0) * 255.0); + } +} + +void EdenGame::makeMatriceFix() { + int16 rotAngleTheta = _rotationAngleX; + int16 rotAnglePhi = _rotationAngleY; + int16 rotAnglePsi = _rotationAngleZ; + + _passMat31 = (_cosTable[rotAnglePhi] * _cosTable[rotAngleTheta]) >> 8; + _passMat32 = (_sinTable[rotAnglePhi] * _cosTable[rotAngleTheta]) >> 8; + _passMat33 = -_sinTable[rotAngleTheta]; + _passMat21 = ((-_sinTable[rotAnglePhi] * _cosTable[rotAnglePsi]) >> 8) + + ((_sinTable[rotAnglePsi] * ((_cosTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8); + _passMat22 = ((_cosTable[rotAnglePhi] * _cosTable[rotAnglePsi]) >> 8) + + ((_sinTable[rotAnglePsi] * ((_sinTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8); + _passMat23 = (_cosTable[rotAngleTheta] * _sinTable[rotAnglePsi]) >> 8; + _passMat11 = ((_sinTable[rotAnglePhi] * _sinTable[rotAnglePsi]) >> 8) + + ((_cosTable[rotAnglePsi] * ((_cosTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8); + _passMat12 = ((-_cosTable[rotAnglePhi] * _sinTable[rotAnglePsi]) >> 8) + + ((_cosTable[rotAnglePsi] * ((_sinTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8); + _passMat13 = (_cosTable[rotAngleTheta] * _cosTable[rotAnglePsi]) >> 8; +} + +void EdenGame::projectionFix(Cube *cubep, int n) { + for (int i = 0; i < n; i++) { + int x = cubep->_vertices[i].x; + int y = cubep->_vertices[i].y; + int z = cubep->_vertices[i].z; + + int transformX = _passMat31 * x + _passMat21 * y + _passMat11 * z + (int)(_translationX * 256.0f); + int transformY = _passMat32 * x + _passMat22 * y + _passMat12 * z + (int)(_translationY * 256.0f); + int transformZ = _passMat33 * x + _passMat23 * y + _passMat13 * z + (int)(_translationZ * 256.0f); + + transformZ >>= 8; + if (transformZ == -256) + transformZ++; + cubep->_projection[i].x = transformX / (transformZ + 256) + _cursorPosX + 14 + _scrollPos; + cubep->_projection[i].y = transformY / (transformZ + 256) + _cursorPosY + 14; + cubep->_projection[i].z = transformZ; + } +} + +// Original name init_cube +void EdenGame::initCubeMac() { + loadMap(2493, _cubeTexture); + NEWcharge_objet_mob(&_cube, 2494, _cubeTexture); + initSinCosTable(); +} + +void EdenGame::engineMac() { + Eden_dep_and_rot(); + makeMatriceFix(); + projectionFix(&_cube, _cubeFaces); + displayObject(&_cube); +} + +// Original name: affiche_objet +void EdenGame::displayObject(Cube *cubep) { + for (int i = 0; i < cubep->_num; i++) + displayPolygoneMapping(cubep, cubep->_faces[i]); +} + +// Original name: NEWcharge_map +void EdenGame::loadMap(int file_id, byte *buffer) { + if (_vm->getPlatform() == Common::kPlatformMacintosh) { + loadpartoffile(file_id, buffer, 32, 256 * 3); + + for (int i = 0; i < 256; i++) { + color3_t color; + color.r = buffer[i * 3] << 8; + color.g = buffer[i * 3 + 1] << 8; + color.b = buffer[i * 3 + 2] << 8; + CLPalette_SetRGBColor(_globalPalette, i, &color); + } + CLPalette_Send2Screen(_globalPalette, 0, 256); + + loadpartoffile(file_id, buffer, 32 + 256 * 3, 0x4000); + } else { +#if 0 +// Fake Mac cursor on PC + Common::File f; + if (f.open("curs.raw")) { + f.seek(32); + f.read(buffer, 256 * 3); + + for (i = 0; i < 256; i++) { + color3_t color; + color.r = buffer[i * 3] << 8; + color.g = buffer[i * 3 + 1] << 8; + color.b = buffer[i * 3 + 2] << 8; + CLPalette_SetRGBColor(global_palette, i, &color); + } + CLPalette_Send2Screen(global_palette, 0, 256); + + f.read(buffer, 0x4000); + + f.close(); + } + else + error("can not load cursor texture"); +#endif + } +} + +void EdenGame::NEWcharge_objet_mob(Cube *cubep, int fileNum, byte *texturePtr) { + char *tmp1 = (char *)malloc(454); + if (_vm->getPlatform() == Common::kPlatformMacintosh) + loadpartoffile(fileNum, tmp1, 0, 454); + else { +#if 0 +// Fake Mac cursor on PC + Common::File f; + if (f.open("curseden.mob")) { + f.read(tmp1, 454); + f.close(); + } + else + ::error("can not load cursor model"); +#endif + } + + char *next = tmp1; + char error; + _cubeFaces = nextVal(&next, &error); + Point3D *vertices = (Point3D *)malloc(_cubeFaces * sizeof(*vertices)); + Point3D *projection = (Point3D *)malloc(_cubeFaces * sizeof(*projection)); + for (int i = 0; i < _cubeFaces; i++) { + vertices[i].x = nextVal(&next, &error); + vertices[i].y = nextVal(&next, &error); + vertices[i].z = nextVal(&next, &error); + } + int count2 = nextVal(&next, &error); + CubeFace **tmp4 = (CubeFace **)malloc(count2 * sizeof(*tmp4)); + for (int i = 0; i < count2; i++) { + tmp4[i] = (CubeFace *)malloc(sizeof(CubeFace)); + tmp4[i]->tri = 3; + char textured = nextVal(&next, &error); + tmp4[i]->ff_5 = nextVal(&next, &error); + tmp4[i]->_indices = (uint16 *)malloc(3 * sizeof(*tmp4[i]->_indices)); + tmp4[i]->_uv = (int16 *)malloc(3 * 2 * sizeof(*tmp4[i]->_uv)); + for (int j = 0; j < 3; j++) { + tmp4[i]->_indices[j] = nextVal(&next, &error); + if (textured) { + tmp4[i]->_uv[j * 2] = nextVal(&next, &error); + tmp4[i]->_uv[j * 2 + 1] = nextVal(&next, &error); + } + } + if (textured) { + tmp4[i]->ff_4 = 3; + tmp4[i]->_texturePtr = texturePtr; + } else + tmp4[i]->ff_4 = 0; + } + free(tmp1); + cubep->_num = count2; + cubep->_faces = tmp4; + cubep->_projection = projection; + cubep->_vertices = vertices; +} + +int EdenGame::nextVal(char **ptr, char *error) { + char c = 0; + char *p = *ptr; + int val = strtol(p, 0, 10); + while ((*p >= '0' && *p <= '9' && *p != 0) || *p == '-') + p++; + while ((*p == 13 || *p == 10 || *p == ',' || *p == ' ') && *p) + c = *p++; + *error = c == 10; + *ptr = p; + return val; +} + +void EdenGame::selectMap(int16 num) { + static const char mapMode[12] = { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 2, 0 }; + // Cube faces to texture coords mapping + // each entry is num_polys(6) * num_faces_per_poly(2) * vertex_per_face(3) * uv(2) + + static const int16 cube_texcoords[3][6 * 2 * 3 * 2] = { + { + 32, 32, 0, 32, 0, 0, + 32, 32, 0, 0, 32, 0, + + 0, 32, 0, 0, 32, 0, + 0, 32, 32, 0, 32, 32, + + 32, 32, 0, 32, 0, 0, + 32, 32, 0, 0, 32, 0, + + 32, 0, 32, 32, 0, 32, + 32, 0, 0, 32, 0, 0, + + 0, 0, 32, 0, 32, 32, + 0, 0, 32, 32, 0, 32, + + 0, 32, 0, 0, 32, 0, + 0, 32, 32, 0, 32, 32 + }, { + 32, 32, 0, 32, 0, 0, + 32, 32, 0, 0, 32, 0, + + 32, 0, 32, 32, 0, 32, + 32, 0, 0, 32, 0, 0, + + 32, 0, 32, 32, 0, 32, + 32, 0, 0, 32, 0, 0, + + 0, 32, 0, 0, 32, 0, + 0, 32, 32, 0, 32, 32, + + 32, 0, 32, 32, 0, 32, + 32, 0, 0, 32, 0, 0, + + 32, 0, 32, 32, 0, 32, + 32, 0, 0, 32, 0, 0 + }, { + 30, 30, 2, 30, 2, 2, + 30, 30, 2, 2, 30, 2, + + 2, 30, 2, 2, 30, 2, + 2, 30, 30, 2, 30, 30, + + 30, 30, 2, 30, 2, 2, + 30, 30, 2, 2, 30, 2, + + 30, 2, 30, 30, 2, 30, + 30, 2, 2, 30, 2, 2, + + 2, 2, 30, 2, 30, 30, + 2, 2, 30, 30, 2, 30, + + 2, 30, 2, 2, 30, 2, + 2, 30, 30, 2, 30, 30 + } + }; + + _cursCurPCMap = num; + int16 k = 0; + int mode = mapMode[num]; + int16 x = (num & 7) * 32; + int16 y = (num & 0x18) * 4; + for (int i = 0; i < 6 * 2; i++) { + for (int j = 0; j < 3; j++) { + _cube._faces[i]->_uv[j * 2 ] = x + cube_texcoords[mode][k++]; + _cube._faces[i]->_uv[j * 2 + 1] = y + cube_texcoords[mode][k++]; + } + } +} + +void EdenGame::Eden_dep_and_rot() { + int16 curs = _currCursor; + if (_normalCursor && (_globals->_drawFlags & DrawFlags::drDrawFlag20)) + curs = 10; + selectMap(curs); + _cursorNewTick = g_system->getMillis(); + if (_cursorNewTick - _cursorOldTick < 1) + return; + + _cursorOldTick = _cursorNewTick; + switch (_currCursor) { + case 0: + _rotationAngleZ = (_rotationAngleZ + 2) % 360; + _rotationAngleX = (_rotationAngleX + 2) % 360; + restoreZDEP(); + break; + case 1: + _rotationAngleZ = 0; + _rotationAngleX -= 2; + if (_rotationAngleX < 0) + _rotationAngleX += 360; + restoreZDEP(); + break; + case 2: + _rotationAngleZ = (_rotationAngleZ + 2) % 360; + _rotationAngleX = 0; + restoreZDEP(); + break; + case 3: + _rotationAngleZ -= 2; + if (_rotationAngleZ < 0) + _rotationAngleZ += 360; + _rotationAngleX = 0; + restoreZDEP(); + break; + case 4: + _rotationAngleZ = 0; + _rotationAngleX = (_rotationAngleX + 2) % 360; + restoreZDEP(); + break; + case 5: + _rotationAngleZ = 0; + _rotationAngleX = 0; + _translationZ += flt_2DF84; + if ((_translationZ < -3600.0 + flt_2DF80) || _translationZ > flt_2DF80) + flt_2DF84 = -flt_2DF84; + break; + case 6: + _rotationAngleZ = 0; + _rotationAngleX = 0; + _translationZ = flt_2DF80; + break; + case 7: + _rotationAngleZ -= 2; + if (_rotationAngleZ < 0) + _rotationAngleZ += 360; + _rotationAngleX = 0; + restoreZDEP(); + break; + case 8: + _rotationAngleZ = 0; + _rotationAngleX = 0; + _translationZ = flt_2DF80; + break; + case 9: + _rotationAngleZ = 0; + _rotationAngleX = 0; + _translationZ = flt_2DF80; + break; + } +} + +void EdenGame::restoreZDEP() { + flt_2DF84 = 200.0; + if (_translationZ < flt_2DF80) + _translationZ += flt_2DF84; + if (_translationZ > flt_2DF80) + _translationZ -= flt_2DF84; +} + +// Original name: affiche_polygone_mapping +void EdenGame::displayPolygoneMapping(Cube *cubep, CubeFace *face) { + uint16 *indices = face->_indices; + int idx = indices[0]; + int16 projX0 = cubep->_projection[idx].x; + int16 projY0 = cubep->_projection[idx].y; + + idx = indices[1]; + int16 projX1 = cubep->_projection[idx].x; + int16 projY1 = cubep->_projection[idx].y; + + idx = indices[2]; + int16 projX2 = cubep->_projection[idx].x; + int16 projY2 = cubep->_projection[idx].y; + + if ((projY1 - projY0) * (projX2 - projX0) - (projY2 - projY0) * (projX1 - projX0) > 0) + return; + + int16 *uv = face->_uv; + int16 ymin = 200; // min y + int16 ymax = 0; // max y + idx = indices[0]; + int16 r20 = cubep->_projection[idx].x; + int16 r30 = cubep->_projection[idx].y; + int16 r19 = *uv++; + int16 r18 = *uv++; + indices++; + for (int i = 0; i < face->tri - 1; i++, indices++) { + idx = indices[0]; + int16 r26 = cubep->_projection[idx].x; + int16 r31 = cubep->_projection[idx].y; + uint16 r25 = *uv++; //TODO: unsigned + int16 r24 = *uv++; //TODO: unsigned + ymin = MIN(r30, ymin); + ymax = MAX(r30, ymax); + ymin = MIN(r31, ymin); + ymax = MAX(r31, ymax); + drawMappingLine(r20, r30, r26, r31, r19, r18, r25, r24, _lines); + r20 = r26; + r30 = r31; + r19 = r25; + r18 = r24; + } + idx = face->_indices[0]; + int16 r26 = cubep->_projection[idx].x; + int16 r31 = cubep->_projection[idx].y; + uv = face->_uv; + uint16 r25 = *uv++; + int16 r24 = *uv; + ymin = MIN(r30, ymin); + ymax = MAX(r30, ymax); + ymin = MIN(r31, ymin); + ymax = MAX(r31, ymax); + drawMappingLine(r20, r30, r26, r31, r19, r18, r25, r24, _lines); + displayMappingLine(ymin, ymax, _mainView->_bufferPtr, face->_texturePtr); +} + +// Original name: trace_ligne_mapping +void EdenGame::drawMappingLine(int16 r3, int16 r4, int16 r5, int16 r6, int16 r7, int16 r8, int16 r9, int16 r10, int16 *linesp) { + int16 r26 = r6 - r4; + if (r26 <= 0) { + if (r26 == 0) { + linesp += r4 * 8; + if (r5 - r3 > 0) { + linesp[0] = r3; + linesp[1] = r5; + linesp[4] = r7; + linesp[5] = r9; + linesp[6] = r8; + linesp[7] = r10; + } else { + linesp[0] = r5; + linesp[1] = r3; + linesp[4] = r9; + linesp[5] = r7; + linesp[6] = r10; + linesp[7] = r8; + } + return; + } + int16 t = r3; + r3 = r5; + r5 = t; + t = r7; + r7 = r9; + r9 = t; + t = r8; + r8 = r10; + r10 = t; + linesp += r6 * 8; + r26 = -r26; + } else + linesp += r4 * 8 + 1; //TODO wha??? + + int r30 = r3 << 16; + int r29 = r7 << 16; + int r28 = r8 << 16; + + int r25 = ((r5 - r3) << 16) / r26; + int r24 = ((r9 - r7) << 16) / r26; + int r23 = ((r10 - r8) << 16) / r26; + + for (int i = 0; i < r26; i++) { + linesp[0] = r30 >> 16; + linesp[4] = r29 >> 16; + linesp[6] = r28 >> 16; + + r30 += r25; + r29 += r24; + r28 += r23; + linesp += 8; + } +} + +// Original name: affiche_ligne_mapping +void EdenGame::displayMappingLine(int16 r3, int16 r4, byte *target, byte *texture) { + int16 height = r4 - r3; + byte *trg_line = _mainView->_bufferPtr + r3 * 640; //TODO: target?? + int16 *line = &_lines[r3 * 8]; + // debug("curs: beg draw %d - %d", r3, r4); + for (int r22 = height; r22; r22--, line += 8, trg_line += 640) { + int16 r29 = line[0]; + int16 r28 = line[1]; + int16 len = r28 - r29; + if (len < 0) + break; + if (len == 0) + continue; + + // debug("curs: lin draw %d", r4 - height); + uint16 r31 = line[4] << 8; + uint16 r30 = line[6] << 8; + + int16 r21 = line[5] - line[4]; + int16 r20 = line[7] - line[6]; + + int16 r26 = (r21 << 8) / len; + int16 r25 = (r20 << 8) / len; + byte *trg = trg_line + r29; +#if 1 + while (r29++ < r28) { + *trg++ = texture[(r30 & 0xFF00) | (r31 >> 8)]; + r31 += r26; + r30 += r25; + } +#endif + } +} + +// PC cursor +CubeCursor _cursorsPC[9] = { + { { 0, 0, 0, 0, 0, 0 }, 3, 2 }, + { { 1, 1, 0, 1, 1, 0 }, 2, -2 }, + { { 2, 2, 2, 2, 2, 2 }, 1, 2 }, + { { 3, 3, 3, 3, 3, 3 }, 1, -2 }, + { { 4, 4, 4, 4, 4, 4 }, 2, 2 }, + { { 5, 5, 5, 5, 5, 5 }, 4, 0 }, + { { 6, 6, 6, 6, 6, 6 }, 1, 2 }, + { { 7, 7, 7, 7, 7, 7 }, 1, -2 }, +// { { 0, 8, 0, 0, 8, 8 }, 2, 2 }, + { { 0, 8, 0, 0, 8, 8 }, 2, 2 } +}; + +XYZ _cubePC[6][3] = { + { { -15, -15, -15 }, { -15, 15, -15 }, { 15, 15, -15 } }, + { { -15, -15, 15 }, { -15, 15, 15 }, { -15, 15, -15 } }, + { { -15, -15, 15 }, { -15, -15, -15 }, { 15, -15, -15 } }, + { { 15, -15, 15 }, { 15, 15, 15 }, { -15, 15, 15 } }, + { { 15, -15, -15 }, { 15, 15, -15 }, { 15, 15, 15 } }, + { { 15, 15, 15 }, { 15, 15, -15 }, { -15, 15, -15 } } +}; + +signed short cosineTable[] = { + // = cos(n) << 7; n += 10; + 128, 126, 120, 111, 98, 82, 64, 44, 22, 0, -22, -44, -64, -82, -98, -111, -120, -126, + -128, -126, -120, -111, -98, -82, -64, -44, -22, 0, 22, 44, 64, 82, 98, 111, 120, 126, + 128, 126, 120, 111, 98, 82, 64, 44, 22, 0 +}; + +void EdenGame::makeTables() { + for (int i = -15; i < 15; i++) { + int v = (i * 11) / 15 + 11; + tab1[i + 15] = v; + tab2[i + 15] = v * 22; + } + + for (int i = 0; i < 36; i++) { + for (int j = -35; j < 36; j++) + tab3[i][j + 35] = (cosineTable[i] * j) >> 7; + } +} + +void EdenGame::getSinCosTables(unsigned short angle, signed char **cos_table, signed char **sin_table) { + angle /= 2; + *cos_table = tab3[angle] + 35; + + angle += 9; + if (angle >= 36) + angle -= 36; + + *sin_table = tab3[angle] + 35; +} + + +void EdenGame::rotatePoint(XYZ *point, XYZ *rpoint) { + // see http://www.cprogramming.com/tutorial/3d/rotation.html + XYZ xrot; + + xrot.x = point->x; + xrot.y = _cosX[point->y] + _sinX[point->z]; + xrot.z = _sinX[-point->y] + _cosX[point->z]; + + rpoint->x = _cosY[xrot.x] + _sinY[-xrot.z]; + rpoint->y = xrot.y; + rpoint->z = _sinY[xrot.x] + _cosY[xrot.z]; + + rpoint->z += _zoomZ; +} + +void EdenGame::mapPoint(XYZ *point, short *x, short *y) { + *y = ((12800 / point->z) * point->y) >> 7; + *x = ((12800 / point->z) * point->x) >> 7; +} + +short EdenGame::calcFaceArea(XYZ *face) { + XYZ rpoint; + short x[3], y[3]; + + for (int i = 0; i < 3; i++) { + rotatePoint(&face[i], &rpoint); + mapPoint(&rpoint, &x[i], &y[i]); + } + + short area = (y[1] - y[0]) * (x[2] - x[0]) - (y[2] - y[0]) * (x[1] - x[0]); + + return area; +} + +void EdenGame::paintPixel(XYZ *point, unsigned char pixel) { + short x, y; + mapPoint(point, &x, &y); + _cursorCenter[y * 40 + x] = pixel; +} + +void EdenGame::paintFace0(XYZ *point) { + XYZ rpoint; + for (int y = -15; y < 15; y++) { + for (int x = -15; x < 15; x++) { + point->x = x; + point->y = y; + rotatePoint(point, &rpoint); + paintPixel(&rpoint, _face[0][tab1[x + 15] + tab2[y + 15]]); + } + } +} + +void EdenGame::paintFace1(XYZ *point) { + XYZ rpoint; + for (int y = -15; y < 15; y++) { + for (int x = -15; x < 15; x++) { + point->y = y; + point->z = -x; + rotatePoint(point, &rpoint); + paintPixel(&rpoint, _face[1][tab1[x + 15] + tab2[y + 15]]); + } + } +} + +void EdenGame::paintFace2(XYZ *point) { + XYZ rpoint; + for (int y = -15; y < 15; y++) { + for (int x = -15; x < 15; x++) { + point->x = x; + point->z = -y; + rotatePoint(point, &rpoint); + paintPixel(&rpoint, _face[2][tab1[x + 15] + tab2[y + 15]]); + } + } +} + +void EdenGame::paintFace3(XYZ *point) { + XYZ rpoint; + for (int y = -15; y < 15; y++) { + for (int x = -15; x < 15; x++) { + point->x = -x; + point->y = -y; + rotatePoint(point, &rpoint); + paintPixel(&rpoint, _face[3][tab1[x + 15] + tab2[y + 15]]); + } + } +} + +void EdenGame::paintFace4(XYZ *point) { + XYZ rpoint; + for (int y = -15; y < 15; y++) { + for (int x = -15; x < 15; x++) { + point->y = y; + point->z = x; + rotatePoint(point, &rpoint); + paintPixel(&rpoint, _face[4][tab1[x + 15] + tab2[y + 15]]); + } + } +} + +void EdenGame::paintFace5(XYZ *point) { + XYZ rpoint; + for (int y = -15; y < 15; y++) { + for (int x = -15; x < 15; x++) { + point->x = x; + point->z = y; + rotatePoint(point, &rpoint); + paintPixel(&rpoint, _face[5][tab1[x + 15] + tab2[y + 15]]); + } + } +} + +void EdenGame::paintFaces() { + XYZ point; + if (!(_faceSkip & 1)) { + point.z = -15; + paintFace0(&point); + } + if (!(_faceSkip & 2)) { + point.x = -15; + paintFace1(&point); + } + if (!(_faceSkip & 4)) { + point.y = -15; + paintFace2(&point); + } + if (!(_faceSkip & 8)) { + point.z = 15; + paintFace3(&point); + } + if (!(_faceSkip & 16)) { + point.x = 15; + paintFace4(&point); + } + if (!(_faceSkip & 32)) { + point.y = 15; + paintFace5(&point); + } +} + +void EdenGame::renderCube() { + for (uint16 i = 0; i < sizeof(_cursor); i++) + _cursor[i] = 0; + _cursorCenter = &_cursor[40 * 20 + 20]; + + getSinCosTables(_angleX, &_cosX, &_sinX); + getSinCosTables(_angleY, &_cosY, &_sinY); + getSinCosTables(_angleZ, &_cosZ, &_sinZ); + + for (int i = 0; i < 6; i++) { + int area = calcFaceArea(_cubePC[i]); + if (area <= 0) { + _face[i] = _newface[i]; // set new texture for invisible area, + _faceSkip |= 1 << i; // but don't draw it just yet + } else + _faceSkip &= ~(1 << i); + } + + paintFaces(); + + const int xshift = -5; // TODO: temporary fix to decrease left margin + unsigned char *cur = _cursor; + unsigned char *scr = _mainView->_bufferPtr + _cursorPosX + _scrollPos + xshift + _cursorPosY * _mainView->_pitch; + + for (int y = 0; y < 40; y++) { + for (int x = 0; x < 40; x++) { + if (x + _cursorPosX + _scrollPos + xshift < _mainView->_pitch && y + _cursorPosY < _mainView->_height) + if (*cur) + *scr = *cur; + scr++; + cur++; + } + scr += _mainView->_pitch - 40; + } +} + + +void EdenGame::incAngleX(int step) { + _angleX += step; + if (_angleX == 70 + 2) + _angleX = 0; + if (_angleX == 0 - 2) + _angleX = 70; +} + +void EdenGame::decAngleX() { + if (_angleX != 0) + _angleX -= (_angleX > 4) ? 4 : 2; +} + +void EdenGame::incAngleY(int step) { + _angleY += step; + if (_angleY == 70 + 2) + _angleY = 0; + if (_angleY == 0 - 2) + _angleY = 70; +} + +void EdenGame::decAngleY() { + if (_angleY != 0) + _angleY -= (_angleY > 4) ? 4 : 2; +} + +void EdenGame::incZoom() { + if (_zoomZ == 170) + _zoomZStep = 40; + else if (_zoomZ == 570) + _zoomZStep = -40; + _zoomZ += _zoomZStep; +} + +void EdenGame::decZoom() { + if (_zoomZ != 170) { + if (_zoomZ < 170) + _zoomZ = 170; + else + _zoomZ -= 40; + } +} + +void EdenGame::initCubePC() { + _zoomZ = 170; + _zoomZStep = 40; + _angleX = _angleY = _angleZ = 0; + _pcCursor = &_cursorsPC[0]; + _cursCurPCMap = -1; + makeTables(); +} + +void EdenGame::selectPCMap(int16 num) { + if (num != _cursCurPCMap) { + _pcCursor = &_cursorsPC[num]; + unsigned char *bank = _mainBankBuf + READ_LE_UINT16(_mainBankBuf); + for (int i = 0; i < 6; i++) { + _newface[i] = 4 + (unsigned char*)getElem(bank, _pcCursor->_sides[i]); + if (_cursCurPCMap == -1) + _face[i] = _newface[i]; + } + _cursCurPCMap = num; + } +} + +void EdenGame::enginePC() { + int16 curs = _currCursor; + if (_normalCursor && (_globals->_drawFlags & DrawFlags::drDrawFlag20)) + curs = 9; + selectPCMap(curs); + _cursorNewTick = g_system->getMillis(); + if (_cursorNewTick - _cursorOldTick < 1) + return; + _cursorOldTick = _cursorNewTick; + int step = _pcCursor->_speed; + switch (_pcCursor->_kind) { + case 0: + break; + case 1: // rot up-down + decAngleY(); + decZoom(); + incAngleX(step); + break; + case 2: // rot left-right + decAngleX(); + decZoom(); + incAngleY(step); + break; + case 3: // rotate random + decZoom(); + incAngleX(step); + incAngleY(step); + break; + case 4: // zoom in-out + _face[0] = _newface[0]; + decAngleY(); + decAngleX(); + incZoom(); + break; + } + renderCube(); +} + +////// macgame.c +//void MyDlgHook() { } +//void PrepareReply() { } +int16 EdenGame::OpenDialog(void *arg1, void *arg2) { + //TODO + return 0; +} + +//void SaveDialog() { } +//void LostEdenMac_SavePrefs() { } +//void LostEdenMac_LoadPrefs() { } + +void EdenGame::LostEdenMac_InitPrefs() { + _globals->_prefLanguage = 1; + _globals->_prefMusicVol[0] = 192; + _globals->_prefMusicVol[1] = 192; + _globals->_prefVoiceVol[0] = 255; + _globals->_prefVoiceVol[1] = 255; + _globals->_prefSoundVolume[0] = 32; + _globals->_prefSoundVolume[1] = 32; +} + +//void MacGame_DoAbout() { } +//void MacGame_DoAdjustMenus() { } +//void LostEdenMac_DoPreferences() { } +//void MacGame_DoSave() { } +//void MacGame_DoMenuCommand() { } +//void MacGame_DoOpen() { } +//void MacGame_DoSaveAs() { } + +} // namespace Cryo diff --git a/engines/cryo/eden.h b/engines/cryo/eden.h new file mode 100644 index 0000000000..b6d8f25485 --- /dev/null +++ b/engines/cryo/eden.h @@ -0,0 +1,744 @@ +/* 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. + * + */ + +#ifndef CRYO_EDEN_H +#define CRYO_EDEN_H + +#include "common/file.h" + +#include "cryo/sound.h" +#include "cryo/defs.h" + +enum Direction { + kCryoNorth = 0, + kCryoEast = 1, + kCryoSouth = 2, + kCryoWest = 3 +}; + +namespace Cryo { + +class CryoEngine; + +class EdenGame { +private: + CryoEngine *_vm; + +public: + EdenGame(CryoEngine *vm); + + void run(); + object_t *getObjectPtr(int16 id); + void showObjects(); + +private: + void removeConsole(); + void scroll(); + void resetScroll(); + void scrollFrescoes(); + void displayFrescoes(); + void gametofresques(); + void doFrescoes(); + void actionEndFrescoes(); + void scrollMirror(); + void scrollPanel(); + void displayFollower(Follower *follower, int16 x, int16 y); + void characterInMirror(); + void gameToMirror(byte arg1); + void flipMode(); + void quitMirror(); + void clictimbre(); + void actionClickValleyPlan(); + void gotoPlace(Goto *go); + void deplaval(uint16 roomNum); + void move(Direction dir); + void move2(Direction dir); + void actionDinoBlow(); + void actionPlateMonk(); + void actionGraaFrescoe(); + void actionLascFrescoe(); + void actionPushStone(); + void actionMummyHead(); + void actionSkelettonHead(); + void actionSkelettonMoorkong(); + void actionChoose(); + void handleDinaDialog(); + void handleKingDialog(); + void actionKingDialog1(); + void actionKingDialog2(); + void actionKingDialog3(); + void actionGetKnife(); + void actionGetPrism(); + void actionGetMushroom(); + void actionGetBadMushroom(); + void actionGetGold(); + void actionGetFullNest(); + void actionGetEmptyNest(); + void actionGetHorn(); + void actionGetSunStone(); + void actionGetEgg(); + void actionGetTablet(); + void actionLookLake(); + void actionGotoHall(); + void actionLabyrinthTurnAround(); + void actionGotoFullNest(); + void actionGotoVal(); + void actionVisit(); + void actionFinal(); + void actionMoveNorth(); + void actionMoveEast(); + void actionMoveSouth(); + void actionMoveWest(); + void display(); + void afficher128(); + void saveFriezes(); + void saveTopFrieze(int16 x); + void saveBottomFrieze(); + void restoreFriezes(); + void restoreTopFrieze(); + void restoreBottomFrieze(); + void useMainBank(); + void useCharacterBank(); + void useBank(int16 bank); + void sundcurs(int16 x, int16 y); + void rundcurs(); + void noclipax(int16 index, int16 x, int16 y); + void noclipax_avecnoir(int16 index, int16 x, int16 y); + void getglow(int16 x, int16 y, int16 w, int16 h); + void unglow(); + void glow(int16 index); + void readPalette(byte *ptr); + void spriteOnSubtitle(int16 index, int16 x, int16 y); + void hideBars(); + void showBars(); + void saveMouthBackground(); + void restoreMouthBackground(); + void drawBlackBars(); + void drawTopScreen(); + void displayValleyMap(); + void displayMapMark(int16 index, int16 location); + void displayAdamMapMark(int16 location); + void restoreAdamMapMark(); + void saveAdamMapMark(int16 x, int16 y); + bool istrice(int16 roomNum); + bool istyran(int16 roomNum); + void istyranval(Area *area); + char getDirection(perso_t *perso); + bool canMoveThere(char loc, perso_t *perso); + void scramble1(uint8 elem[4]); + void scramble2(uint8 elem[4]); + void scrambleDirections(); + bool naitredino(char persoType); + void newCitadel(char area, int16 level, Room *room); + void evolveCitadel(int16 level); + void destroyCitadelRoom(int16 roomNum); + void narratorBuildCitadel(); + void citadelFalls(char level); + void buildCitadel(); + void moveDino(perso_t *perso); + void moveAllDino(); + void newValley(); + char whereIsCita(); + bool isCita(int16 loc); + void placeVava(Area *area); + void vivredino(); + void vivreval(int16 areaNum); + void handleDay(); + void addTime(int16 t); + void animCharacter(); + void getanimrnd(); + void addanim(); + void removeMouthSprite(); + void AnimEndCharacter(); + void setCharacterSprite(byte *spr); + void displayImage(); + void displayCharacter1(); + void displayCharacter(); + void ef_perso(); + void loadCharacter(perso_t *perso); + void loadCurrCharacter(); + void fin_perso(); + void no_perso(); + void closeCharacterScreen(); + void displayBackgroundFollower(); + void displayNoFollower(int16 bank); + void displayCharacterBackground1(); + void displayCharacterBackground(); + void setCharacterIcon(); + void showCharacter(); + void displayCharacterPanel(); + void getDataSync(); + int16 readFrameNumber(); + void waitEndSpeak(); + void my_bulle(); + void my_pr_bulle(); + void drawSubtitleChar(byte c, byte color, int16 width); + void displaySubtitles(); + void saveUnderSubtitles(int16 y); + void restoreUnderSubtitles(); + void displayHNMSubtitle(); + void patchSentence(); + void vavapers(); + void citadelle(); + void selectZone(); + void showEvents1(); + void showEvents(); + void parle_mfin(); + void parlemoi_normal(); + void parle_moi(); + void initCharacterPointers(perso_t *perso); + void perso1(perso_t *perso); + void perso_normal(perso_t *perso); + void handleCharacterDialog(int16 pers); + void actionKing(); + void actionDina(); + void actionThoo(); + void actionMonk(); + void actionTormentor(); + void actionMessenger(); + void actionMango(); + void actionEve(); + void actionAzia(); + void actionMammi(); + void actionGuards(); + void actionBamboo(); + void actionKabuka(); + void actionFisher(); + void actionDino(); + void actionTyran(); + void actionMorkus(); + void comment(); + void actionAdam(); + void setChoiceYes(); + void setChoiceNo(); + bool isAnswerYes(); + void specialMushroom(perso_t *perso); + void specialEmptyNest(perso_t *perso); + void specialNestWithEggs(perso_t *perso); + void specialApple(perso_t *perso); + void specialGold(perso_t *perso); + void specialPrism(perso_t *perso); + void specialTalisman(perso_t *perso); + void specialMask(perso_t *perso); + void specialBag(perso_t *perso); + void specialTrumpet(perso_t *perso); + void specialWeapons(perso_t *perso); + void specialInstrument(perso_t *perso); + void specialEgg(perso_t *perso); + void tyranDies(perso_t *perso); + void specialObjects(perso_t *perso, char objid); + void dialautoon(); + void dialautooff(); + void follow(); + void dialonfollow(); + void abortDialogue(); + void subHandleNarrator(); + void handleNarrator(); + void checkPhraseFile(); + byte *getPhrase(int16 id); + void actionGotoMap(); + void record(); + bool dial_scan(Dialog *dial); + bool dialoscansvmas(Dialog *dial); + bool dialogEvent(perso_t *perso); + void characterStayHere(); + void endDeath(int16 vid); + void chronoEvent(); + void setChrono(int16 t); + void preloadDialogs(int16 vid); + void displayEffect1(); + void displayEffect2(); + void displayEffect3(); + void displayEffect4(); + void clearScreen(); + void colimacon(int16 pattern[16]); + void fadeToBlack(int delay); + void fadeToBlackLowPalette(int delay); + void fadeFromBlackLowPalette(int delay); + void blackRect32(); + void setSrcRect(int16 sx, int16 sy, int16 ex, int16 ey); + void setDestRect(int16 sx, int16 sy, int16 ex, int16 ey); + void wait(int howlong); + void effetpix(); + void verifh(byte *ptr); + void openbigfile(); + void closebigfile(); + void loadRawFile(uint16 num, byte *buffer); + void loadIconFile(uint16 num, Icon *buffer); + void loadRoomFile(uint16 num, Room *buffer); + void loadHnm(uint16 num); + int loadSound(uint16 num); + void convertMacToPC(); + void loadpermfiles(); + bool ReadDataSyncVOC(unsigned int num); + bool ReadDataSync(uint16 num); + void loadpartoffile(uint16 num, void *buffer, int32 pos, int32 len); + void expandHSQ(byte *input, byte *output); + void addInfo(byte info); + void unlockInfo(); + void nextInfo(); + void removeInfo(byte info); + void updateInfoList(); + void initGlobals(); + void initRects(); + void closeRoom(); + void displaySingleRoom(Room *room); + void displayRoom(); + void displayPlace(); + void loadPlace(int16 num); + void specialoutside(); + void specialout(); + void specialin(); + void animpiece(); + void getdino(Room *room); + Room *getRoom(int16 loc); + void initPlace(int16 roomNum); + void maj2(); + void updateRoom1(int16 roomNum); + void updateRoom(uint16 roomNum); + void allocateBuffers(); + void freebuf(); + void openWindow(); + void EmergencyExit(); + void edmain(); + void intro(); + void enterGame(); + void signon(const char *s); + void FRDevents(); + Icon *scan_icon_list(int16 x, int16 y, int16 index); + void updateCursor(); + void mouse(); + void showMovie(char arg1); + void playHNM(int16 num); + void handleHNMSubtitles(); + void musique(); + void startmusique(byte num); + void musicspy(); + int loadmusicfile(int16 num); + void persovox(); + void endCharacterSpeech(); + void fademusicup(); + void fademusica0(int16 delay); + void countObjects(); + void winObject(int16 id); + void loseObject(int16 id); + void lostObject(); + bool isObjectHere(int16 id); + void objectmain(int16 id); + void getObject(int16 id); + void putObject(); + void newObject(int16 id, int16 arg2); + void giveobjectal(int16 id); + void giveObject(); + void actionTakeObject(); + void newMushroom(); + void newEmptyNest(); + void newNestWithEggs(); + void newGold(); + void gotoPanel(); + void noclicpanel(); + void generique(); + void cancel2(); + void testvoice(); + void load(); + void initafterload(); + void save(); + void desktopcolors(); + void panelrestart(); + void reallyquit(); + void confirmer(char mode, char yesId); + void confirmYes(); + void confirmNo(); + void restart(); + void edenQuit(); + void choseSubtitleOption(); + void changeVolume(); + void changervol(); + void newvol(byte *volptr, int16 delta); + void playtape(); + void rewindtape(); + void depcurstape(); + void affcurstape(); + void forwardtape(); + void stoptape(); + void cliccurstape(); + void paneltobuf(); + void cursbuftopanel(); + void langbuftopanel(); + void displayPanel(); + void displayLanguage(); + void displayVolCursor(int16 x, int16 vol1, int16 vol2); + void displayCursors(); + void selectCursor(int itemId); + void displayTopPanel(); + void displayResult(); + void restrictCursorArea(int16 xmin, int16 xmax, int16 ymin, int16 ymax); + void edenShudown(); + void habitants(perso_t *perso); + void suiveurs(perso_t *perso); + void evenements(perso_t *perso); + void followme(perso_t *perso); + void rangermammi(perso_t *perso, Room *room); + void perso_ici(int16 action); + void setCharacterHere(); + void faire_suivre(int16 roomNum); + void AddCharacterToParty(); + void addToParty(int16 index); + void removeCharacterFromParty(); + void removeFromParty(int16 index); + void handleEloiDeparture(); + bool checkEloiReturn(); + void handleEloiReturn(); + void incPhase(); + void phase113(); + void phase130(); + void phase161(); + void phase226(); + void phase257(); + void phase353(); + void phase369(); + void phase371(); + void phase385(); + void phase418(); + void phase433(); + void phase434(); + void phase513(); + void phase514(); + void phase529(); + void phase545(); + void phase561(); + void bigphase1(); + void bigphase(); + void phase16(); + void phase32(); + void phase48(); + void phase64(); + void phase80(); + void phase96(); + void phase112(); + void phase128(); + void phase144(); + void phase160(); + void phase176(); + void phase192(); + void phase208(); + void phase224(); + void phase240(); + void phase256(); + void phase272(); + void phase288(); + void phase304(); + void phase320(); + void phase336(); + void phase352(); + void phase368(); + void phase384(); + void phase400(); + void phase416(); + void phase432(); + void phase448(); + void phase464(); + void phase480(); + void phase496(); + void phase512(); + void phase528(); + void phase544(); + void phase560(); + void savegame(char *name); + void loadrestart(); + void loadgame(char *name); + void vavaoffsetout(); + void vavaoffsetin(); + void lieuoffsetout(); + void lieuoffsetin(); + void bandeoffsetout(); + void bandeoffsetin(); + char testCondition(int16 index); + uint16 operAdd(uint16 v1, uint16 v2); + uint16 operSub(uint16 v1, uint16 v2); + uint16 operLogicalAnd(uint16 v1, uint16 v2); + uint16 operLogicalOr(uint16 v1, uint16 v2); + uint16 operIsEqual(uint16 v1, uint16 v2); + uint16 operIsSmaller(uint16 v1, uint16 v2); + uint16 operIsGreater(uint16 v1, uint16 v2); + uint16 operIsDifferent(uint16 v1, uint16 v2); + uint16 operIsSmallerOrEqual(uint16 v1, uint16 v2); + uint16 operIsGreaterOrEqual(uint16 v1, uint16 v2); + uint16 operFalse(uint16 v1, uint16 v2); + uint16 operation(byte op, uint16 v1, uint16 v2); + uint16 fetchValue(); + uint8 getByteVar(uint16 offset); + uint16 getWordVar(uint16 offset); + void actionNop(); + void initSinCosTable(); + void makeMatriceFix(); + void projectionFix(Cube *cube, int n); + void initCubeMac(); + void engineMac(); + void displayObject(Cube *cube); + void loadMap(int file_id, byte *buffer); + void NEWcharge_objet_mob(Cube *cube, int fileNum, byte *texturePtr); + static int nextVal(char **ptr, char *error); + void selectMap(int16 num); + void Eden_dep_and_rot(); + void restoreZDEP(); + void displayPolygoneMapping(Cube *cube, CubeFace *face); + void drawMappingLine(int16 r3, int16 r4, int16 r5, int16 r6, int16 r7, int16 r8, int16 r9, int16 r10, int16 *lines); + void displayMappingLine(int16 r3, int16 r4, byte *target, byte *texture); + int16 OpenDialog(void *arg1, void *arg2); + void LostEdenMac_InitPrefs(); + + void initCubePC(); + void enginePC(); + void selectPCMap(int16 num); + + void makeTables(); + void getSinCosTables(unsigned short angle, signed char **cos_table, signed char **sin_table); + void rotatePoint(XYZ *point, XYZ *rpoint); + void mapPoint(XYZ *point, short *x, short *y); + short calcFaceArea(XYZ *face); + void paintPixel(XYZ *point, unsigned char pixel); + void paintFace0(XYZ *point); + void paintFace1(XYZ *point); + void paintFace2(XYZ *point); + void paintFace3(XYZ *point); + void paintFace4(XYZ *point); + void paintFace5(XYZ *point); + void paintFaces(); + void renderCube(); + + void incAngleX(int step); + void decAngleX(); + void incAngleY(int step); + void decAngleY(); + void incZoom(); + void decZoom(); + + CubeCursor *_pcCursor; + + int16 tab1[30]; + int16 tab2[30]; + int8 tab3[36][71]; + int16 _angleX, _angleY, _angleZ, _zoomZ, _zoomZStep; + + int8 *_cosX, *_sinX; + int8 *_cosY, *_sinY; + int8 *_cosZ, *_sinZ; + + uint8 *_face[6], *_newface[6]; + int16 _faceSkip; + + uint8 _cursor[40 * 40]; + uint8 *_cursorCenter; + + byte _ownObjects[128]; + +private: + int16 _scrollPos; + int16 _oldScrollPos; + bool _frescoTalk; + byte _oldPix[8]; + Common::Point _adamMapMarkPos; + byte _cursKeepBuf[2500]; + Common::Point _cursKeepPos; + bool _torchCursor; + int16 _curBankNum; + int16 _glowX; + int16 _glowY; + int16 _glowW; + int16 _glowH; + bool _paletteUpdateRequired; + bool _cursorSaved; + bool _showBlackBars; + bool _backgroundSaved; + byte *_bankData; + color_t _globalPalette[256]; //TODO palette_t + perso_t *_tyranPtr; + int _lastAnimFrameNumb; + int _curAnimFrameNumb; + int _lastAnimTicks; + prect_t *_curCharacterRect; + int16 _numAnimFrames; + int16 _maxPersoDesc; + int16 _numImgDesc; + bool _restartAnimation; + bool _animationActive; + byte _animationDelay; + byte _animationIndex; + byte _lastAnimationIndex; + + byte *dword_30724; + byte *dword_30728; //TODO: rename - something amim-related + byte *_mouthAnimations; + byte *_animationTable; + byte _imageDesc[512]; + byte *_characterBankData; + bool _savedUnderSubtitles; + int16 _numTextLines; + byte _sentenceBuffer[400]; + byte phraseIconsBuffer[10]; + byte _sentenceCoordsBuffer[22]; + byte *_textOutPtr; + byte *textout; + object_t *_curSpecialObject; + bool _lastDialogChoice; + bool parlemoiNormalFlag; + + bool _closeCharacterDialog; + int dword_30B04; + + char _lastPhrasesFile; + byte _dialogSkipFlags; + + color3_t newColor; + color_t oldPalette[256]; // TODO palette_t ? + color_t newPalette[256]; + Common::Rect rect_dst, rect_src; + byte *_voiceSamplesBuffer; //TODO: sound sample buffer + Common::File _bigfile; + byte _infoList[16]; + bool _needToFade; + byte *_mainBankBuf; + byte *_musicBuf; + byte *_gameLipsync; + byte *_gamePhrases; + byte *_gameDialogs; //TODO: rename to dialogs? + byte *_gameConditions; + byte *_placeRawBuf; //TODO: fixme + byte *_bankDataBuf; + Icon *_gameIcons; + Room *_gameRooms; + PakHeaderNode *_bigfileHeader; + byte *_glowBuffer; + byte *_mainViewBuf; + byte *_view2Buf; + byte *_gameFont; //TODO: rename to font? + byte *_subtitlesViewBuf; + byte *_underSubtitlesViewBuf; // CHECKME: Useless? + global_t *_globals; + uint16 _mouseCenterX; + uint16 _mouseCenterY; + bool _bufferAllocationErrorFl; + bool _quitFlag2; + bool _quitFlag3; + bool _gameStarted; + bool _soundAllocated; + + CSoundChannel *_musicChannel; + CSoundChannel *_voiceChannel; + CSoundChannel *_hnmSoundChannel; + Sound *_voiceSound; + + View *_view2; + View *_underSubtitlesView; + View *_subtitlesView; + View *_underBarsView; + View *_mainView; + View *_hnmView; + Common::Rect _underSubtitlesBackupRect; + Common::Rect _underSubtitlesScreenRect; + Common::Rect _underBottomBarBackupRect; + Common::Rect _underBottomBarScreenRect; + Common::Rect _underTopBarBackupRect; + Common::Rect _underTopBarScreenRect; + int _demoCurrentTicks; + int _demoStartTicks; + int _currentTime; + int16 _cirsorPanX; + int16 _inventoryScrollDelay; + int16 _cursorPosX; + int16 _cursorPosY; + int16 _currCursor; + Icon *_currSpot; + Icon *_curSpot2; + bool _keyboardHeld; + bool _mouseHeld; + bool _normalCursor; + byte *_hnmViewBuf; + bool _showVideoSubtitle; + bool _videoCanceledFlag; //TODO: hnm_canceled + bool _specialTextMode; + int _hnmFrameNum; + int _voiceSamplesSize; //TODO: perso vox sample data len + int16 _musicRightVol; + int16 _musicLeftVol; + + + bool _animateTalking; + bool _personTalking; + byte _musicFadeFlag; + + char _musicSequencePos; + bool _musicPlayingFlag; + + byte *_musicSamplesPtr; + byte *_musicPatternsPtr; //TODO: sndblock_t ? + byte *_musSequencePtr; + bool _musicEnabledFlag; + uint16 *_currentObjectLocation; + bool byte_31D64; + + bool _noPalette; + bool _gameLoaded; +#define MAX_TAPES 16 + tape_t _tapes[MAX_TAPES]; + byte _confirmMode; + byte *_curSliderValuePtr; + byte _lastMenuItemIdLo; + int16 _lastTapeRoomNum; + int16 _curSliderX; + int16 _curSliderY; + int16 _destinationRoom; + int16 word_31E7A; // CHECKME: Unused? + + int16 word_378CC; // TODO: set by CLComputer_Init to 0 + int16 word_378CE; // CHECKME: Unused + + int _invIconsCount; + int _invIconsBase; + int _roomIconsBase; + + //// cube.c + int16 _cosTable[361]; + int16 _sinTable[361]; + int _passMat31, _passMat21, _passMat11; + int _passMat32, _passMat22, _passMat12; + int _passMat33, _passMat23, _passMat13; + int16 _rotationAngleY; // CHECKME: USeless? + int16 _rotationAngleX, _rotationAngleZ; + float _translationY, _translationX; // CHECKME: Useless? + Cube _cube; + int16 _cursCurPCMap; + int16 _lines[200 * 8]; + byte _cubeTexture[0x4000]; + int _cubeFaces; + uint32 _cursorOldTick, _cursorNewTick; + byte *_codePtr; + + uint8 tab_2CB1E[8][4]; + + const unsigned int kMaxMusicSize; // largest .mus file size +}; + +} + +#endif diff --git a/engines/cryo/module.mk b/engines/cryo/module.mk new file mode 100644 index 0000000000..d0eae378b7 --- /dev/null +++ b/engines/cryo/module.mk @@ -0,0 +1,19 @@ +MODULE := engines/cryo + +MODULE_OBJS = \ + cryo.o \ + cryolib.o \ + debugger.o \ + detection.o \ + eden.o \ + sound.o \ + staticdata.o \ + video.o + +# This module can be built as a plugin +ifeq ($(ENABLE_CRYO), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/cryo/platdefs.h b/engines/cryo/platdefs.h new file mode 100644 index 0000000000..69f8e625ea --- /dev/null +++ b/engines/cryo/platdefs.h @@ -0,0 +1,43 @@ +/* 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. + * + */ + +#ifndef CRYO_PLATDEFS_H +#define CRYO_PLATDEFS_H + +namespace Cryo { + +#if 1 +const int _subtitlesXMargin = 16; //PC +const int _subtitlesXScrMargin = 16; +const int _spaceWidth = 6; +#define FAKE_DOS_VERSION +#else +const int _subtitlesXMargin = 16; //MAC +const int _subtitlesXScrMargin = 16; //MAC +const int _spaceWidth = 4; +#endif +const int _subtitlesXWidth = (320 - _subtitlesXMargin * 2); +const int _subtitlesXCenter = _subtitlesXWidth / 2; + +} // End of namespace Cryo + +#endif diff --git a/engines/cryo/sound.cpp b/engines/cryo/sound.cpp new file mode 100644 index 0000000000..68f067588f --- /dev/null +++ b/engines/cryo/sound.cpp @@ -0,0 +1,113 @@ +/* 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.
+ *
+ */
+
+#include "cryo/sound.h"
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+
+namespace Cryo {
+
+CSoundChannel::CSoundChannel(Audio::Mixer *mixer, unsigned int sampleRate, bool stereo, bool is16bits) : _mixer(mixer), _sampleRate(sampleRate), _stereo(stereo) {
+ _bufferFlags = is16bits ? (Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_16BITS) : Audio::FLAG_UNSIGNED;
+ if (stereo)
+ _bufferFlags |= Audio::FLAG_STEREO;
+ _audioStream = nullptr;
+ _volumeLeft = _volumeRight = Audio::Mixer::kMaxChannelVolume;
+}
+
+CSoundChannel::~CSoundChannel() {
+ stop();
+ if (_audioStream)
+ delete _audioStream;
+}
+
+void CSoundChannel::queueBuffer(byte *buffer, unsigned int size, bool playNow, bool playQueue, bool buffering) {
+ if (playNow)
+ stop();
+
+ if (!buffer || !size)
+ return;
+
+ if (!_audioStream)
+ _audioStream = Audio::makeQueuingAudioStream(_sampleRate, _stereo);
+
+ if (buffering) {
+ byte *localBuffer = (byte*)malloc(size);
+ memcpy(localBuffer, buffer, size);
+ _audioStream->queueBuffer(localBuffer, size, DisposeAfterUse::YES, _bufferFlags);
+ } else
+ _audioStream->queueBuffer(buffer, size, DisposeAfterUse::NO, _bufferFlags);
+ if (playNow || playQueue)
+ play();
+}
+
+void CSoundChannel::play() {
+ if (!_audioStream)
+ return;
+ if (!_mixer->isSoundHandleActive(_soundHandle)) {
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ applyVolumeChange();
+ }
+}
+
+void CSoundChannel::stop() {
+ if (_mixer->isSoundHandleActive(_soundHandle))
+ _mixer->stopHandle(_soundHandle);
+
+ if (_audioStream) {
+ _audioStream->finish();
+ delete _audioStream;
+ _audioStream = nullptr;
+ }
+}
+
+unsigned int CSoundChannel::numQueued() {
+ return _audioStream ? _audioStream->numQueuedStreams() : 0;
+}
+
+unsigned int CSoundChannel::getVolume() {
+ return (_volumeRight + _volumeLeft) / 2;
+}
+
+void CSoundChannel::setVolume(unsigned int volumeLeft, unsigned int volumeRight) {
+ _volumeLeft = volumeLeft;
+ _volumeRight = volumeRight;
+ applyVolumeChange();
+}
+
+void CSoundChannel::setVolumeLeft(unsigned int volume) {
+ setVolume(volume, _volumeRight);
+}
+
+void CSoundChannel::setVolumeRight(unsigned int volume) {
+ setVolume(_volumeLeft, volume);
+}
+
+void CSoundChannel::applyVolumeChange() {
+ unsigned int volume = (_volumeRight + _volumeLeft) / 2;
+ int balance = (signed int)(_volumeRight - _volumeLeft) / 2;
+ _mixer->setChannelVolume(_soundHandle, volume);
+ _mixer->setChannelBalance(_soundHandle, balance);
+}
+
+}
diff --git a/engines/cryo/sound.h b/engines/cryo/sound.h new file mode 100644 index 0000000000..72232cc4f1 --- /dev/null +++ b/engines/cryo/sound.h @@ -0,0 +1,70 @@ +/* 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.
+ *
+ */
+
+#pragma once
+
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+
+#include "cryo/cryolib.h"
+
+namespace Cryo {
+
+class CryoEngine;
+
+class CSoundChannel {
+private:
+ Audio::Mixer *_mixer;
+ Audio::QueuingAudioStream *_audioStream;
+ Audio::SoundHandle _soundHandle;
+ unsigned int _sampleRate;
+ bool _stereo;
+ unsigned int _bufferFlags;
+
+ void applyVolumeChange();
+
+public:
+ CSoundChannel(Audio::Mixer *mixer, unsigned int sampleRate, bool stereo, bool is16bits = false);
+ ~CSoundChannel();
+
+ // Queue a new buffer, cancel any previously queued buffers if playNow is set
+ void queueBuffer(byte *buffer, unsigned int size, bool playNow = false, bool playQueue = true, bool buffering = true);
+
+ // Play any queued buffers
+ void play();
+
+ // Stop playing and purge play queue
+ void stop();
+
+ // How many buffers in queue (including currently playing one)
+ unsigned int numQueued();
+
+ // Volume control
+ int _volumeLeft, _volumeRight;
+ unsigned int getVolume();
+ void setVolume(unsigned int volumeLeft, unsigned int volumeRight);
+ void setVolumeLeft(unsigned int volume);
+ void setVolumeRight(unsigned int volume);
+};
+
+}
diff --git a/engines/cryo/staticdata.cpp b/engines/cryo/staticdata.cpp new file mode 100644 index 0000000000..1184791850 --- /dev/null +++ b/engines/cryo/staticdata.cpp @@ -0,0 +1,495 @@ +/* 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. + * + */ + +#include "cryo/defs.h" +#include "cryo/cryolib.h" + +namespace Cryo { + +Follower followerList[] = { +// char, X, sx, sy, ex, ey,bank, + { PersonId::pidGregor, 5, 211, 9, 320, 176, 228, 0, 0 }, + { PersonId::pidEloi, 4, 162, 47, 223, 176, 228, 112, 78 }, + { PersonId::pidDina, 3, 55, 0, 172, 176, 228, 90, 16 }, + { PersonId::pidChongOfChamaar, 4, 0, 5, 114, 176, 229, 0, 16 }, + { PersonId::pidKommalaOfKoto, 3, 0, 15, 102, 176, 229, 0, 16 }, + { PersonId::pidUlanOfUlele, 1, 0, 0, 129, 176, 230, 0, 16 }, + { PersonId::pidCabukaOfCantura, 2, 0, 0, 142, 176, 230, 0, 16 }, + { PersonId::pidFuggOfTamara, 0, 0, 17, 102, 176, 230, 0, 16 }, + { PersonId::pidJabber, 2, 0, 6, 134, 176, 228, 0, 16 }, + { PersonId::pidShazia, 1, 90, 17, 170, 176, 228, 50, 22 }, + { PersonId::pidThugg, 0, 489, 8, 640, 176, 228, 160, 24 }, + { PersonId::pidMungo, 5, 361, 0, 517, 176, 229, 0, 16 }, + { PersonId::pidMonk, 0, 419, 22, 569, 176, 229, 100, 30 }, + { PersonId::pidEve, 1, 300, 28, 428, 176, 229, 0, 38 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1 } +}; + + +/* + Labyrinth of Mo + + | | | | | | | | + +*/ + +byte kLabyrinthPath[] = { +// each nibble tells which direction to choose to exit the labyrinth + 0x11, 0x11, 0x11, 0x22, 0x33, 0x55, 0x25, 0x44, 0x25, 0x11, 0x11, 0x11, + 0x11, 0x35, 0x55, 0x45, 0x45, 0x44, 0x44, 0x34, 0x44, 0x34, 0x32, 0x52, + 0x33, 0x23, 0x24, 0x44, 0x24, 0x22, 0x54, 0x22, 0x54, 0x54, 0x44, 0x22, + 0x22, 0x42, 0x45, 0x22, 0x42, 0x45, 0x35, 0x11, 0x44, 0x34, 0x52, 0x11, + 0x44, 0x32, 0x55, 0x11, 0x11, 0x33, 0x11, 0x11, 0x53, 0x11, 0x11, 0x53, + 0x54, 0x24, 0x11, 0x22, 0x25, 0x33, 0x53, 0x54, 0x23, 0x44 +}; + +char kDinoSpeedForCitaLevel[16] = { 1, 2, 3, 4, 4, 5, 6, 7, 8, 9 }; + +char kTabletView[] = { //TODO: make as struct? + // opposite tablet id, video id + Objects::obUnused10, 83, + Objects::obUnused10, 84, + Objects::obTablet4, 85, + Objects::obTablet3, 86, + Objects::obTablet6, 87, + Objects::obTablet5, 85 +}; + +// special character backgrounds for specific rooms +char kPersoRoomBankTable[] = { + // first entry is default bank, then pairs of [roomNum, bankNum], terminated by -1 + 0, 3, 33, -1, + 21, 17, 35, -1, + 0, 2, 36, -1, + 22, 9, 38, 3, 39, -1, + 23, 8, 40, -1, + 0, 3, 41, 7, 42, -1, + 25, -1, + 27, 17, 45, -1, + 28, 26, 46, -1, + 29, 51, 48, -1, + 30, 53, 49, -1, + 0, 27, 50, -1, + 32, 17, 51, -1, + 52, 2, 52, -1, + -3, 3, -3, -1, + 31, -1, + 24, 6, 43, -1, + 47, -1, + 0, 2, 64, -1, + 54, 3, 54, -1, + 27, -1, + 26, 17, 45, -1 +}; + +// area transition descriptors +Goto gotos[] = { +// area, oldarea, vid, time, valleyVid + { 0, 1, 0, 2, 20 }, + { 0, 1, 162, 3, 168 }, + { 0, 2, 0, 2, 21 }, + { 0, 6, 0, 3, 108 }, + { 0, 9, 151, 3, 0 }, + { 0, 7, 106, 2, 101 }, + { 0, 10, 79, 3, 102 }, + { 0, 12, 0, 3, 0 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 1, 3, 58, 2, 104 }, + { 1, 4, 100, 4, 104 }, + { 1, 5, 107, 6, 104 }, + { 1, 6, 155, 8, 104 }, + { 1, 7, 165, 6, 104 }, + { 1, 8, 169, 6, 104 }, + { 1, 10, 111, 2, 104 }, + { 1, 11, 164, 4, 104 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 1, 3, 161, 3, 102 }, + { 1, 4, 163, 6, 102 }, + { 1, 5, 157, 9, 102 }, + { 1, 9, 160, 9, 102 }, + { 1, 10, 79, 3, 102 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 1, 3, 0, 3, 153 }, // 24 + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 3, 1, 154, 2, 103 }, + { 3, 4, 100, 2, 103 }, + { 3, 5, 107, 4, 103 }, + { 3, 6, 155, 6, 103 }, + { 3, 7, 165, 8, 103 }, + { 3, 8, 169, 6, 103 }, + { 3, 10, 111, 4, 103 }, + { 3, 11, 164, 6, 103 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 3, 1, 162, 3, 22 }, + { 3, 4, 163, 6, 22 }, + { 3, 5, 157, 9, 22 }, + { 3, 9, 160, 9, 22 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 3, 1, 0, 3, 166 }, // 40 + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 4, 1, 154, 4, 51 }, + { 4, 3, 58, 2, 51 }, + { 4, 5, 107, 2, 51 }, + { 4, 6, 155, 4, 51 }, + { 4, 7, 165, 6, 51 }, + { 4, 8, 169, 8, 51 }, + { 4, 10, 111, 6, 51 }, + { 4, 11, 164, 8, 51 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 4, 1, 162, 3, 109 }, // 51 + { 4, 3, 161, 6, 109 }, + { 4, 5, 157, 9, 109 }, + { 4, 9, 160, 9, 109 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 5, 1, 154, 6, 33 }, + { 5, 3, 58, 4, 33 }, + { 5, 4, 100, 2, 33 }, + { 5, 6, 155, 2, 33 }, + { 5, 7, 165, 4, 33 }, + { 5, 8, 169, 8, 33 }, + { 5, 10, 111, 8, 33 }, + { 5, 11, 164, 8, 33 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 5, 1, 162, 3, 99 }, // 65 + { 5, 3, 161, 6, 99 }, + { 5, 4, 163, 9, 99 }, + { 5, 9, 160, 9, 99 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 9, 1, 162, 3, 167 }, // 70 + { 9, 3, 161, 6, 167 }, + { 9, 4, 163, 9, 167 }, + { 9, 5, 157, 9, 167 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 6, 1, 154, 8, 105 }, // 75 + { 6, 3, 58, 6, 105 }, + { 6, 4, 100, 4, 105 }, + { 6, 5, 107, 2, 105 }, + { 6, 7, 165, 2, 105 }, + { 6, 8, 169, 10, 105 }, + { 6, 10, 111, 6, 105 }, + { 6, 11, 164, 8, 105 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 7, 1, 154, 4, 158 }, // 84 + { 7, 3, 58, 6, 158 }, + { 7, 4, 100, 6, 158 }, + { 7, 5, 107, 4, 158 }, + { 7, 6, 155, 2, 158 }, + { 7, 8, 169, 8, 158 }, + { 7, 10, 111, 4, 158 }, + { 7, 11, 164, 6, 158 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 8, 1, 154, 2, 159 }, // 93 + { 8, 3, 58, 4, 159 }, + { 8, 4, 100, 6, 159 }, + { 8, 5, 107, 8, 159 }, + { 8, 6, 155, 10, 159 }, + { 8, 7, 165, 8, 159 }, + { 8, 10, 111, 6, 159 }, + { 8, 11, 164, 4, 159 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 10, 1, 154, 2, 77 }, // 102 + { 10, 3, 58, 4, 77 }, + { 10, 4, 100, 6, 77 }, + { 10, 5, 107, 8, 77 }, + { 10, 6, 155, 6, 77 }, + { 10, 7, 165, 4, 77 }, + { 10, 8, 169, 6, 77 }, + { 10, 11, 164, 4, 77 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 11, 1, 154, 2, 80 }, // 111 + { 11, 3, 58, 4, 80 }, + { 11, 4, 100, 6, 80 }, + { 11, 5, 107, 8, 80 }, + { 11, 6, 155, 8, 80 }, + { 11, 7, 165, 6, 80 }, + { 11, 8, 169, 2, 80 }, + { 11, 10, 111, 4, 80 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 12, 1, 154, 8, 56 }, // 120 + { 12, 3, 58, 4, 56 }, + { 12, 4, 100, 4, 56 }, + { 12, 5, 107, 6, 56 }, + { 12, 6, 155, 8, 56 }, + { 12, 7, 165, 10, 56 }, + { 12, 8, 169, 4, 56 }, + { 12, 10, 111, 10, 56 }, + { 12, 11, 164, 6, 56 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, +}; + +object_t _objects[] = { + //id,fl,loc,masklow,maskhi,ct + { 1, 0, 3, 1, 0, 0}, // Eve's Way Stone + { 2, 0, 3, 2, 0, 0}, // Thau's Seashell + { 3, 0, 3, 4, 0, 0}, // Talisman of bravery + { 4, 0, 3, 8, 0, 0}, // An old tooth. Very old! Whoever lost it most certainly has no further use for it! + { 5, 0, 0, 0x10, 0, 0}, // Prism + { 6, 0, 3, 0, 0, 0}, // Flute + { 7, 0, 3, 0x4000, 0, 0}, // Apple + { 8, 0, 4, 0x1000, 0, 0}, // Egg of Destiny + { 9, 0, 3, 0x800, 0, 0}, // Root + { 10, 0, 3, 0, 0, 0}, // ??? + { 11, 0, 6, 0, 0, 0}, // Mushroom + { 12, 0, 13, 0, 0, 0}, // Poisonous Mushroom + { 13, 0, 2, 0x400, 0, 0}, // Graa's Knife + { 14, 0, 22, 0, 0, 0}, // Empty Nest + { 15, 0, 26, 0, 0, 0}, // Full Nest + { 16, 0, 33, 0x20, 0, 0}, // Gold + { 17, 0, 3, 0, 0, 0}, // Sign of Shadow Mistress (moon stone) + { 18, 0, 3, 0, 0, 0}, // Sign of Mother of all (bag of soil) + { 19, 0, 40, 0, 0, 0}, // Sign of the life-giving (sun star) + { 20, 0, 20, 0x200, 0, 0}, // King's Horn + { 21, 0, 3, 0, 0, 0}, // Golden Sword of Mashaar + // Masks + { 22, 0, 3, 0x40, 0, 0}, // Mask of Death + { 23, 0, 3, 0x80, 0, 0}, // Mask of Bonding + { 24, 0, 3, 0x100, 0, 0}, // Mask of Birth + // Objects of power + { 25, 0, 3, 0, 1, 0}, // Eye in the Storm + { 26, 0, 3, 0, 2, 0}, // Sky Hammer + { 27, 0, 3, 0, 4, 0}, // Fire in the Clouds + { 28, 0, 3, 0, 8, 0}, // Within and Without + { 29, 0, 3, 0, 0x10, 0}, // Eye in the Cyclone + { 30, 0, 3, 0, 0x20, 0}, // River that Winds + // Musical instruments + { 31, 0, 3, 0, 0x40, 0}, // Trumpet + { 32, 0, 3, 0, 0x80, 0}, // -- unused (but still has a dialog line) + { 33, 0, 3, 0, 0x100, 0}, // Drum + { 34, 0, 3, 0, 0x200, 0}, // -- unused (but still has a dialog line) + { 35, 0, 3, 0, 0x400, 0}, // -- unused (but still has a dialog line) + { 36, 0, 3, 0, 0x800, 0}, // Ring + // Tablets + { 37, 0, 3, 0, 0, 0}, // Tablet #1 (Mo) + { 38, 0, 42, 0x2000, 0, 0}, // Tablet #2 (Morkus' Lair) + { 39, 0, 3, 0, 0, 0}, // Tablet #3 (White Arch?) + { 40, 0, 3, 0, 0, 0}, // Tablet #4 + { 41, 0, 3, 0, 0, 0}, // Tablet #5 + { 42, 0, 3, 0x8000, 0, 0} // Tablet #6 (Castra) +}; + +uint16 kObjectLocations[100] = { + 0x112, 0xFFFF, + 0x202, 0xFFFF, + 0x120, 0xFFFF, + 0x340, 0x44B, 0x548, 0x640, 0x717, 0x830, 0xFFFF, + 0x340, 0x44B, 0x548, 0x640, 0x717, 0x830, 0xFFFF, + 0, 0xFFFF, + 0x344, 0x53A, 0x831, 0xFFFF, + 0x331, 0x420, 0x54B, 0x637, 0x716, 0x840, 0xFFFF, + 0x834A, 0x8430, 0x8531, 0x644, 0x745, 0x838, 0xFFFF, + 0x510, 0xFFFF, + 0xC04, 0xFFFF, + 0xFFFF +}; + +perso_t kPersons[] = { + // room, aid, party mask, id, flags, X,bank,X, X,sprId,sprX,speed, X + { 0x103, 230, PersonMask::pmGregor, PersonId::pidGregor , 0, 0, 1, 0, 0, 0, 0, 0, 0 }, + { 0x116, 231, PersonMask::pmDina , PersonId::pidDina , 0, 4, 2, 0, 0, 3, 9, 0, 0 }, + { 0x202, 232, PersonMask::pmTau , PersonId::pidTau , 0, 8, 3, 0, 0, 0, 0, 0, 0 }, + { 0x109, 233, PersonMask::pmMonk , PersonId::pidMonk , 0, 12, 4, 0, 0, 6, 52, 0, 0 }, + { 0x108, 234, PersonMask::pmJabber, PersonId::pidJabber , 0, 18, 5, 0, 0, 2, 0, 0, 0 }, + { 0x103, 235, PersonMask::pmEloi , PersonId::pidEloi , 0, 22, 6, 0, 0, 4, 20, 0, 0 }, + { 0x301, 236, PersonMask::pmMungo , PersonId::pidMungo , 0, 28, 8, 0, 0, 11, 45, 0, 0 }, + { 0x628, 237, PersonMask::pmEve , PersonId::pidEve , 0, 30, 10, 0, 0, 7, 35, 0, 0 }, + { 0x81A, 238, PersonMask::pmShazia, PersonId::pidShazia , 0, 34, 11, 0, 0, 1, 11, 0, 0 }, + { 0x330, 239, PersonMask::pmLeader, PersonId::pidChongOfChamaar , 0, 38, 13, 0, 0, 10, 0, 0, 0 }, + { 0x41B, 239, PersonMask::pmLeader, PersonId::pidUlanOfUlele , 0, 46, 15, 0, 0, 13, 0, 0, 0 }, + { 0x53B, 239, PersonMask::pmLeader, PersonId::pidKommalaOfKoto , 0, 42, 14, 0, 0, 9, 0, 0, 0 }, + { 0x711, 239, PersonMask::pmLeader, PersonId::pidCabukaOfCantura , 0, 50, 16, 0, 0, 14, 0, 0, 0 }, + { 0xA02, 239, PersonMask::pmLeader, PersonId::pidMarindaOfEmbalmers, 0, 54, 17, 0, 0, 0, 0, 0, 0 }, + { 0x628, 239, PersonMask::pmLeader, PersonId::pidFuggOfTamara , 0, 62, 18, 0, 0, 12, 0, 0, 0 }, + { 0x801, 239, PersonMask::pmLeader, PersonId::pidChongOfChamaar , 0, 38, 13, 0, 0, 10, 0, 0, 0 }, + { 0x41B, 10, PersonMask::pmQuest , PersonId::pidUlanOfUlele , PersonFlags::pfType2 , 46, 15, 0, 0, 13, 0, 0, 0 }, + { 0x711, 11, PersonMask::pmQuest , PersonId::pidCabukaOfCantura , PersonFlags::pfType2 , 50, 16, 0, 0, 14, 0, 0, 0 }, + { 0x106, 240, PersonMask::pmThugg , PersonId::pidThugg , 0, 64, 7, 0, 0, 0, 61, 0, 0 }, + { 0, 13, 0, PersonId::pidNarrator , 0, 68, 12, 0, 0, 0, 0, 0, 0 }, + { 0x902, 241, PersonMask::pmQuest , PersonId::pidNarrim , 0, 70, 19, 0, 0, 0, 0, 0, 0 }, + { 0xC03, 244, PersonMask::pmMorkus, PersonId::pidMorkus , 0, 74, 20, 0, 0, 0, 0, 0, 0 }, + // dinos in each valley + { 0x332, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pfType8 , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x329, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pfType8 , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x33B, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftTriceraptor , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x317, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftVelociraptor, 0, 0, 0, 0, 0, 0, 1, 0 }, + { 0x320, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pfType12 , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x349, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftMosasaurus , 0, 0, 0, 0, 0, 0, 0, 0 }, + + { 0x429, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pfType8 , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x43B, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftTriceraptor , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x422, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftVelociraptor, 0, 0, 0, 0, 0, 0, 1, 0 }, + { 0x432, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftMosasaurus , 0, 0, 0, 0, 0, 0, 0, 0 }, + + { 0x522, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pfType8 , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x534, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftTriceraptor , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x515, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pftVelociraptor , 0, 0, 0, 0, 0, 0, 1, 0 }, + { 0x533, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftMosasaurus , 0, 0, 0, 0, 0, 0, 0, 0 }, + + { 0x622, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pfType8 , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x630, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftTriceraptor , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x643, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftVelociraptor, 0, 0, 0, 0, 0, 0, 1, 0 }, + { 0x63A, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftMosasaurus , 0, 0, 0, 0, 0, 0, 0, 0 }, + + { 0x737, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pfType8 , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x739, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftTriceraptor , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x74A, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftVelociraptor, 0, 0, 0, 0, 0, 0, 1, 0 }, + { 0x726, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftMosasaurus , 0, 0, 0, 0, 0, 0, 0, 0 }, + + { 0x842, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pfType8 , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x822, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftTriceraptor , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x828, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pftVelociraptor , 0, 0, 0, 0, 0, 0, 1, 0 }, + { 0x84B, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pf80 | PersonFlags::pftMosasaurus , 0, 0, 0, 0, 0, 0, 0, 0 }, + + { 0xB03, 242, PersonMask::pmDino , PersonId::pidDinosaur , PersonFlags::pfType8 , 58, 252, 0, 0, 0, 0, 0, 0 }, + // enemy dinos + { 0x311, 243, PersonMask::pmEnemy , PersonId::pidEnemy , PersonFlags::pf80 | PersonFlags::pftTyrann , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x410, 243, PersonMask::pmEnemy , PersonId::pidEnemy , PersonFlags::pf80 | PersonFlags::pftTyrann , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x51B, 243, PersonMask::pmEnemy , PersonId::pidEnemy , PersonFlags::pf80 | PersonFlags::pftTyrann , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x618, 243, PersonMask::pmEnemy , PersonId::pidEnemy , PersonFlags::pf80 | PersonFlags::pftTyrann , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x71B, 243, PersonMask::pmEnemy , PersonId::pidEnemy , PersonFlags::pf80 | PersonFlags::pftTyrann , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0x81B, 243, PersonMask::pmEnemy , PersonId::pidEnemy , PersonFlags::pf80 | PersonFlags::pftTyrann , 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0xFFFF, 0xFFFF, 0xFFFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFFFF, 0xFFFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0x628, 237, PersonMask::pmEve , PersonId::pidEve , 0, 80, 9, 0, 0, 8, 35, 0, 0 }, + { 0x628, 237, PersonMask::pmEve , PersonId::pidEve , 0, 78, 10, 0, 0, 7, 35, 0, 0 } +}; + +Citadel _citadelList[] = { + { 1, { 163, 182, 0, 0, 124, 147, 193, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 48, { 285, 286, 0, 0, 287, 288, 284, 0 }, { 114, 115, 0, 0, 116, 117, 113, 0 } }, + { 63, { 290, 291, 0, 0, 292, 293, 289, 0 }, { 119, 120, 0, 0, 121, 122, 118, 0 } }, + { 95, { 295, 296, 0, 0, 297, 298, 294, 0 }, { 124, 125, 0, 0, 126, 127, 123, 0 } }, + { 127, { 300, 301, 0, 0, 302, 303, 299, 0 }, { 129, 130, 0, 0, 131, 132, 128, 0 } }, + { 159, { 305, 306, 0, 0, 307, 308, 304, 0 }, { 134, 135, 0, 0, 136, 137, 133, 0 } }, + { 255, { 310, 311, 0, 0, 312, 313, 309, 0 }, { 139, 140, 0, 0, 141, 142, 138, 0 } } +}; + +prect_t _characterRects[] = { //TODO: just an array of int16s? + { 93, 69, 223, 176}, + { 102, 86, 162, 126}, + { 88, 103, 168, 163}, + { 116, 66, 192, 176}, + { 129, 92, 202, 153}, + { 60, 95, 160, 176}, + { 155, 97, 230, 145}, + { 100, 77, 156, 145}, + { 110, 78, 170, 156}, + { 84, 76, 166, 162}, + { 57, 77, 125, 114}, + { 93, 69, 223, 175}, + { 93, 69, 223, 176}, + { 93, 69, 223, 176}, + { 154, 54, 245, 138}, + { 200, 50, 261, 116}, + { 70, 84, 162, 176}, + { 125, 101, 222, 172}, + { 188, 83, 251, 158} +}; + +byte _characterArray[][5] = { //TODO: struc? + { 8, 15, 23, 25, 0xFF}, + { 0, 9, 0xFF }, + { 0, 9, 0xFF }, + { 0, 9, 0xFF }, + { 0, 13, 0xFF }, + { 16, 21, 0xFF }, + { 11, 20, 0xFF }, + { 0, 12, 0xFF }, + { 0, 9, 0xFF }, + { 0, 9, 0xFF }, + { 5, 13, 0xFF }, + { 0xFF }, + { 0, 8, 0xFF }, + { 0xFF }, + { 0, 7, 0xFF }, + { 0, 8, 0xFF }, + { 8, 12, 0xFF }, + { 0, 5, 0xFF }, + { 0, 4, 0xFF }, + { 0xFF } +}; + +Area kAreasTable[] = { + { Areas::arMo , AreaType::atCitadel, 0, 0, 0, 1, 0, 0}, + { Areas::arTausCave , AreaType::atCave , 0, 112, 0, 2, 0, 0}, + { Areas::arChamaar , AreaType::atValley , 0, 133, 0, 3, 0, 0}, + { Areas::arUluru , AreaType::atValley , 0, 187, 0, 4, 0, 0}, + { Areas::arKoto , AreaType::atValley , AreaFlags::HasVelociraptors, 236, 0, 5, 0, 0}, + { Areas::arTamara , AreaType::atValley , 0, 288, 0, 6, 0, 0}, + { Areas::arCantura , AreaType::atValley , 0, 334, 0, 7, 0, 0}, + { Areas::arShandovra , AreaType::atValley , 0, 371, 0, 8, 0, 0}, + { Areas::arNarimsCave , AreaType::atCave , 0, 115, 0, 9, 0, 0}, + { Areas::arEmbalmersCave, AreaType::atCave , 0, 118, 0, 10, 0, 0}, + { Areas::arWhiteArch , AreaType::atCave , 0, 122, 0, 11, 0, 0}, + { Areas::arMoorkusLair , AreaType::atCave , 0, 127, 0, 12, 0, 0} +}; + +int16 tab_2CEF0[64] = { + 25, 257, 0, 0, 37, 258, 38, 259, 0, 0, 24, 260, 0, 0, 0, 0, + 0, 0, 53, 265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39, 261, 0, 0, 40, 262, 62, 263, 0, 0, 63, 264, 0, 0, 0, 0, + 18, 275, 0, 0, 35, 254, 36, 255, 19, 318, 23, 256, 0, 0, 0, 0 +}; + +int16 tab_2CF70[64] = { + 65, 266, 0, 0, 66, 267, 67, 268, 0, 0, 68, 269, 0, 0, 0, 0, + 0, 0, 73, 274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 69, 270, 0, 0, 70, 271, 71, 272, 0, 0, 72, 273, 0, 0, 0, 0, + 18, 275, 0, 0, 35, 254, 36, 255, 19, 318, 23, 256, 0, 0, 0, 0, +}; + +int16 kActionCursors[299] = { + 3, 1, 2, 4, 5, 5, 5, 0, 5, 5, + 5, 5, 5, 3, 2, 5, 5, 5, 3, 2, + 4, 5, 7, 7, 4, 5, 5, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, + 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 0, 5, 6, + 6, 1, 6, 6, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 0, 0, 6, 6, + 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +float _translationZ = -3400; +float flt_2DF80 = -3400; +float flt_2DF84 = 200; + +} // End of namespace Cryo diff --git a/engines/cryo/video.cpp b/engines/cryo/video.cpp new file mode 100644 index 0000000000..fe242425e5 --- /dev/null +++ b/engines/cryo/video.cpp @@ -0,0 +1,617 @@ +/* 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. + * + */ + +#include "cryo/cryo.h" +#include "cryo/video.h" + +namespace Cryo { +HnmPlayer::HnmPlayer(CryoEngine *vm) : _vm(vm) { + _soundStarted = false; + _pendingSounds = 0; + _timeDrift = 0.0; + _nextFrameTime = 0.0; + _expectedFrameTime = 0.0; + _rate = 0.0; + _useSoundSync = false; + _useSound = true; + _soundChannel = nullptr; + _prevRight = _prevLeft = 0; + _useAdpcm = false; + _customChunkHandler = nullptr; + _preserveColor0 = false; + _safePalette = false; + + for (int i = 0; i < 256; i++) + decompTable[i] = 0; +} + +// Original name: CLHNM_New +void HnmPlayer::resetInternals() { + _frameNum = 0; + _file = nullptr; + _tmpBuffer[0] = nullptr; + _tmpBuffer[1] = nullptr; + _finalBuffer = nullptr; + _readBuffer = nullptr; + for (int i = 0; i < 256; i++) { + _palette[i].a = 0; + _palette[i].r = 0; + _palette[i].g = 0; + _palette[i].b = 0; + } +} + +// Original name: CLHNM_SetFile +void HnmPlayer::setFile(Common::File *file) { + _file = file; +} + +// Original name: CLHNM_SetupTimer +void HnmPlayer::setupTimer(float rate) { + _rate = 100.0 / rate; +} + +// Original name: CLHNM_ResetInternalTimer +void HnmPlayer::resetInternalTimer() { + _timeDrift = 0.0; + _nextFrameTime = _expectedFrameTime = _vm->_timerTicks; +} + +// Original name: CLHNM_Reset +void HnmPlayer::reset() { + _frameNum = 0; + _soundStarted = false; + _pendingSounds = 0; + resetInternalTimer(); +} + +// Original name: CLHNM_Init +void HnmPlayer::init() { + _customChunkHandler = nullptr; + _preserveColor0 = false; + _useSound = true; +} + +// Original name: CLHNM_SetForceZero2Black +void HnmPlayer::setForceZero2Black(bool forceblack) { + _preserveColor0 = forceblack; +} + +// Original name: CLHNM_WaitLoop +void HnmPlayer::waitLoop() { + _expectedFrameTime += _rate; + _nextFrameTime = _expectedFrameTime - _timeDrift; + if (_useSoundSync && _vm->_timerTicks > 1000.0 + _nextFrameTime) + _useSound = false; + while (_vm->_timerTicks < _nextFrameTime) ; // waste time + _timeDrift = _vm->_timerTicks - _nextFrameTime; +} + +// Original name: CLHNM_WantsSound +void HnmPlayer::wantsSound(bool sound) { + _useSound = sound; +} + +// Original name: CLHNM_SetupSound +void HnmPlayer::setupSound(unsigned int rate, bool stereo, bool is16bits) { + _soundChannel = new CSoundChannel(_vm->_mixer, rate, stereo, is16bits); +} + +// Original name: CLHNM_CloseSound +void HnmPlayer::closeSound() { + if (_soundChannel) { + _soundChannel->stop(); + delete(_soundChannel); + _soundChannel = nullptr; + } +} + +// Original name: CLHNM_LoadDecompTable +void HnmPlayer::loadDecompTable(int16 *buffer) { + for (int16 i = 0; i < 256; i++) { + int16 e = *buffer++; + decompTable[i] = LE16(e); + } +} + +// Original name: CLHNM_DecompADPCM +void HnmPlayer::decompADPCM(byte *buffer, int16 *output, int size) { + int16 l = _prevLeft; + int16 r = _prevRight; + size &= ~1; + while (size--) { + *output++ = l += decompTable[*buffer++]; + *output++ = r += decompTable[*buffer++]; + if (l > 512 || r > 512) + error("decompADPCM - Unexpected values"); + } + _prevLeft = l; + _prevRight = r; +} + +// Original name: CLHNM_ReadHeader +void HnmPlayer::readHeader() { + _header._signature = _file->readUint32BE(); + _file->skip(4); + _header._width = _file->readUint16LE(); + _header._height = _file->readUint16LE(); + _file->skip(4); + _header._numbFrame = _file->readSint32LE(); + _file->skip(8); + _header._bufferSize = _file->readSint32LE(); + _file->skip(32); + + _header._bufferSize += 4096; //TODO: checkme +} + +// Original name: CLHNM_GetVersion +int16 HnmPlayer::getVersion() { + if (_header._signature == MKTAG('H','N','M','4')) + return 4; + return -1; +} + +// Original name: CLHNM_AllocMemory +void HnmPlayer::allocMemory() { +// TODO: rework this code + _tmpBuffer[0] = (byte *)malloc(_header._bufferSize + 2); + + if (!_tmpBuffer[0]) + return; + + _tmpBuffer[1] = (byte *)malloc(_header._bufferSize + 2); + + if (!_tmpBuffer[1]) { + free(_tmpBuffer[0]); + _tmpBuffer[0] = nullptr; + return; + } + + _readBuffer = (byte *)malloc(_header._bufferSize + 2); + if (!_readBuffer) { + free(_tmpBuffer[0]); + _tmpBuffer[0] = nullptr; + free(_tmpBuffer[1]); + _tmpBuffer[1] = nullptr; + } +} + +// Original name: CLHNM_DeallocMemory +void HnmPlayer::deallocMemory() { + free(_tmpBuffer[0]); + free(_tmpBuffer[1]); + free(_readBuffer); + + _tmpBuffer[0] = nullptr; + _tmpBuffer[1] = nullptr; + _readBuffer = nullptr; +} + +// Original name: CLHNM_SetFinalBuffer +void HnmPlayer::setFinalBuffer(byte *buffer) { + _finalBuffer = buffer; +} + +// Original name: CLHNM_GetFrameNum +int HnmPlayer::getFrameNum() { + return _frameNum; +} + +// Original name: CLHNM_TryRead +void HnmPlayer::tryRead(int size) { + _file->read(_readBuffer, size); +} + +// Original name: CLHNM_LoadFrame +bool HnmPlayer::loadFrame() { + tryRead(4); + int chunk = *(int *)_readBuffer; + chunk = LE32(chunk); + chunk &= 0xFFFFFF; // upper bit - keyframe mark? + if (!chunk) + return false; + + if (chunk - 4 > _header._bufferSize) + error("loadFrame - Chunk size"); + + tryRead(chunk - 4); + _dataPtr = _readBuffer; + return true; +} + +// Original name CLHNM_DecompLempelZiv +void HnmPlayer::decompLempelZiv(byte *buffer, byte *output) { + byte *inp = buffer; + byte *out = output; + + unsigned int queue = 0; + int qpos = -1; + + //TODO: fix for BE +#define GetBit() ( 1 & ( (qpos >= 0) ? (queue >> qpos--) : (queue = *(unsigned int*)((inp += 4) - 4)) >> ((qpos = 30) + 1) ) ) + + for (;;) { + if (GetBit()) { + *out++ = *inp++; + } else { + int l, o; + if (GetBit()) { + l = *inp & 7; + o = *(uint16 *)inp >> 3; + inp += 2; + o -= 8192; + if (!l) + l = *inp++; + if (!l) + break; + } else { + l = GetBit() * 2; + l += GetBit(); + o = *(inp++) - 256; + } + l += 2; + while (l--) { + *out = *(out + o); + out++; + } + } + } + +#undef GetBit + + return; +} + +// Original name: CLHNM_Desentrelace320 +void HnmPlayer::desentrelace320(byte *frame_buffer, byte *final_buffer, uint16 height) { + unsigned int *input = (unsigned int *)frame_buffer; + unsigned int *line0 = (unsigned int *)final_buffer; + unsigned int *line1 = (unsigned int *)(final_buffer + 320); + int count = (height) / 2; + while (count--) { + int16 i; + for (i = 0; i < 320 / 4; i++) { + unsigned int p0 = *input++; + unsigned int p4 = *input++; +#if 0 + *line0++ = ((p4 & 0xFF00) >> 8) | ((p4 & 0xFF000000) >> 16) | ((p0 & 0xFF00) << 8) | (p0 & 0xFF000000); + // *line0++ = (p0 & 0xFF000000) | ((p0 & 0xFF00) << 8) | ((p4 & 0xFF000000) >> 16) | ((p4 & 0xFF00) >> 8); + *line1++ = ((p0 & 0xFF0000) << 8) | ((p0 & 0xFF) << 16) | ((p4 & 0xFF0000) >> 8) | (p4 & 0xFF); +#else + *line0++ = (p0 & 0xFF) | ((p0 & 0xFF0000) >> 8) | ((p4 & 0xFF) << 16) | ((p4 & 0xFF0000) << 8); + *line1++ = ((p0 & 0xFF00) >> 8) | ((p0 & 0xFF000000) >> 16) | ((p4 & 0xFF00) << 8) | (p4 & 0xFF000000); +#endif + } + line0 += 320 / 4; + line1 += 320 / 4; + } +} + +// Original name: CLHNM_Desentrelace +void HnmPlayer::desentrelace() { + switch (_header._width) { + case 320: + desentrelace320(_newFrameBuffer, _finalBuffer, _header._height); + break; + // case 480: + // CLHNM_Desentrelace480(_newFrameBuffer, finalBuffer, _header._height); + // break; + default: + error("desentrelace - Unexpected width"); + } +} + +// Original name: CLHNM_DecompUBA +void HnmPlayer::decompUBA(byte *output, byte *curr_buffer, byte *prev_buffer, byte *input, int width, char flags) { + // return; + byte *out_start = output; + byte count; + unsigned int code; + uint16 offs; + byte mode; + byte swap; + + if ((flags & 1) == 0) { + //HNM4 classic + int twolinesabove = -(width * 2); + for (;;) { + code = READ_LE_UINT32(input) & 0xFFFFFF; //input++; + count = code & 0x1F; + if (count) { + input += 3; + offs = code >> 9; + // + mode = (code >> 5) & 0xF; + swap = mode >> 3; + byte *ref = ((mode & 1) ? prev_buffer : curr_buffer) + (output - out_start) + (offs * 2) - 32768; + int shft1, shft2; + if (mode & 2) { + // ref += twolinesabove; + shft1 = twolinesabove + 1; + shft2 = 0; + //swap ^= 1; + } else { + shft1 = 0; + shft2 = 1; + } + while (count--) { + byte b0 = ref[shft1]; + byte b1 = ref[shft2]; + output[swap] = b0; + output[swap ^ 1] = b1; + output += 2; + ref += (mode & 4) ? -2 : 2; + } + } else { + input++; + mode = code & 0xFF; // bits 0..4 are zero + switch (mode) { + case 0: + *(output++) = *(input++); + *(output++) = *(input++); + break; + case 0x20: + output += 2 * *(input++); + break; + case 0x40: + output += 2 * (code >> 8); + input += 2; + break; + case 0x60: { + count = *(input++); + byte color = *(input++); + while (count--) { + *(output++) = color; + *(output++) = color; + } + break; + } + default: + return; + } + } + } + } else { + assert(0); + //HNM4 hires + for (;;) { + code = READ_LE_UINT32(input) & 0xFFFFFF; + input++; + count = code & 0x3F; + if (count) { + mode = (code >> 5) & 0xF; + offs = code >> 9; + // + } else { + mode = code & 0xFF; // bits 0..5 are zero + switch (mode) { + case 0x00: + output += *input++; + break; + case 0x40: + *output++ = *input++; + *(output++ + width) = *input++; + break; + case 0x80: + output += width; + break; + default: + return; + } + } + } + } +} + +// Original name: CLHNM_NextElement +bool HnmPlayer::nextElement() { + if (_frameNum == 0) { + resetInternalTimer(); + _prevLeft = _prevRight = 0; + } + if (_frameNum == _header._numbFrame) + return false; + + if (!loadFrame()) + return false; + + for (;;) { + int sz = READ_LE_UINT32(_dataPtr) & 0xFFFFFF; + _dataPtr += 4; + int16 id = READ_LE_UINT16(_dataPtr); + _dataPtr += 2; + char h6 = *_dataPtr; + _dataPtr += 1; + char h7 = *_dataPtr; + _dataPtr += 1; + switch (id) { + case MKTAG16('L', 'P'): + changePalette(); + _dataPtr += sz - 8; + break; + case MKTAG16('Z', 'I'): + _frameNum++; + selectBuffers(); + decompLempelZiv(_dataPtr + 4, _newFrameBuffer); +#if 0 + switch (_header._width) { + case 320: + CLBlitter_RawCopy320ASM(_newFrameBuffer, _oldFrameBuffer, _header._height); + break; + case 480: + CLBlitter_RawCopy480ASM(_newFrameBuffer, _oldFrameBuffer, _header._height); + break; + case 640: + CLBlitter_RawCopy640ASM(_newFrameBuffer, _oldFrameBuffer, _header._height); + break; + default: + memcpy(_oldFrameBuffer, _newFrameBuffer, _header._width * _header._height); + } +#else + memcpy(_oldFrameBuffer, _newFrameBuffer, _header._bufferSize); //TODO strange buffer size here +#endif + if (!(h6 & 1)) + desentrelace(); + else { + // if(_header._width == 640) + // CLBlitter_RawCopy640(_newFrameBuffer, finalBuffer, _header._height); + // else + memcpy(_finalBuffer, _newFrameBuffer, _header._height); //TODO: wrong size? + } + + if (!_soundStarted) { + _soundChannel->play(); + _soundStarted = true; + } + + return true; + case MKTAG16('U', 'I'): + _frameNum++; + selectBuffers(); + decompUBA(_newFrameBuffer, _newFrameBuffer, _oldFrameBuffer, _dataPtr, _header._width, h6); + if (!(h6 & 1)) + desentrelace(); + else { + // if(_header._width == 640) + // CLBlitter_RawCopy640(_newFrameBuffer, _finalBuffer, _header._height); + // else + memcpy(_finalBuffer, _newFrameBuffer, _header._width * _header._height); + } + return true; + + case MKTAG16('d', 's'): + case MKTAG16('D', 'S'): + if (_useSound) { + if (!h6) { + int sound_size = sz - 8; + if (!_useAdpcm) { + _soundChannel->queueBuffer(_dataPtr, sound_size - 2, false, _soundStarted); + } else { +#if 0 + // Not used in Lost Eden + int16 *sound_buffer = (int16 *)_soundGroup->getNextBuffer(); + if (!_pendingSounds) { + const int kDecompTableSize = 256 * sizeof(int16); + loadDecompTable((int16 *)_dataPtr); + decompADPCM(_dataPtr + kDecompTableSize, sound_buffer, sound_size - kDecompTableSize); + _soundGroup->assignDatas(sound_buffer, (sound_size - kDecompTableSize) * 2, false); + } else { + decompADPCM(_dataPtr, sound_buffer, sound_size); + _soundGroup->assignDatas(sound_buffer, sound_size * 2, false); + } + _pendingSounds++; + if (_soundStarted) + _soundGroup->playNextSample(_soundChannel); +#endif + } + } else + error("nextElement - unexpected flag"); + } + _dataPtr += sz - 8; + break; + default: + if (_customChunkHandler) + _customChunkHandler(_dataPtr, sz - 8, id, h6, h7); + _dataPtr += sz - 8; + } + } + return true; +} + +// Original name: CLHNM_GetSoundChannel +CSoundChannel *HnmPlayer::getSoundChannel() { + return _soundChannel; +} + +// Original name: CLHNM_ChangePalette +void HnmPlayer::changePalette() { + CLPalette_GetLastPalette(_palette); + byte *pal = _dataPtr; + if (*(uint16 *)pal == 0xFFFF) + return; + + int16 mincolor = 255; + int16 maxcolor = 0; + do { + uint16 fst = *pal++; + uint16 cnt = *pal++; + if (cnt == 0) + cnt = 256; + debug("hnm: setting palette, fst = %d, cnt = %d, last = %d", fst, cnt, fst + cnt - 1); + assert(fst + cnt <= 256); + if (mincolor > fst) + mincolor = fst; + if (maxcolor < fst + cnt) + maxcolor = fst + cnt; + color_t *color = _palette + fst; + if (_safePalette) { + while (cnt--) { + byte r = *pal++; + byte g = *pal++; + byte b = *pal++; + int16 rr = r << 10; + int16 gg = g << 10; + int16 bb = b << 10; + if (color->r != rr || color->g != gg || color->b != bb) + CLBlitter_OneBlackFlash(); + color->r = rr; + color->g = gg; + color->b = bb; + color++; + } + } else { + while (cnt--) { + byte r = *pal++; + byte g = *pal++; + byte b = *pal++; + color->r = r << 10; + color->g = g << 10; + color->b = b << 10; + color++; + } + } + + } while (*(uint16 *)pal != 0xFFFF); +#if 0 + if (preserve_color0) { + _palette[0].r = 0; + _palette[0].g = 0; + _palette[0].b = 0; + } +#endif + // CLBlitter_Send2ScreenNextCopy(_palette, mincolor, maxcolor - mincolor); + CLBlitter_Send2ScreenNextCopy(_palette, 0, 256); +} + +// Original name: CLHNM_SelectBuffers +void HnmPlayer::selectBuffers() { + if (_frameNum % 2) { + _newFrameBuffer = _tmpBuffer[1]; + _oldFrameBuffer = _tmpBuffer[0]; + } else { + _newFrameBuffer = _tmpBuffer[0]; + _oldFrameBuffer = _tmpBuffer[1]; + } +} + +} // namespace Cryo + diff --git a/engines/cryo/video.h b/engines/cryo/video.h new file mode 100644 index 0000000000..83eddfb9b1 --- /dev/null +++ b/engines/cryo/video.h @@ -0,0 +1,106 @@ +/* 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. + * + */ + +#ifndef CRYO_VIDEO_H +#define CRYO_VIDEO_H + +#include "cryo/sound.h" + +namespace Cryo { + +class CryoEngine; + +class HnmPlayer { +public: + Common::File *_file; + HNMHeader _header; + +private: + CryoEngine *_vm; + + void resetInternalTimer(); + void wantsSound(bool sound); + void decompADPCM(byte *buffer, int16 *output, int size); + void loadDecompTable(int16 *buffer); + bool loadFrame(); + void tryRead(int size); + void changePalette(); + void selectBuffers(); + void decompLempelZiv(byte *buffer, byte *output); + void desentrelace320(byte *frame_buffer, byte *final_buffer, uint16 height); + void desentrelace(); + void decompUBA(byte *output, byte *curr_buffer, byte *prev_buffer, byte *input, int width, char flags); + void setupSoundADPCM(int16 numSounds, int16 length, int16 sampleSize, float rate, int16 mode); + void init(); + + bool _soundStarted; + int16 _pendingSounds; + float _timeDrift; + float _nextFrameTime; + float _expectedFrameTime; + float _rate; + bool _useSoundSync; + bool _useSound; + int16 _prevRight; + int16 _prevLeft; + bool _useAdpcm; + bool _preserveColor0; + int16 decompTable[256]; + bool _safePalette; + int _frameNum; + byte *_tmpBuffer[2]; + byte *_finalBuffer; + byte *_newFrameBuffer; + byte *_oldFrameBuffer; + byte *_readBuffer; + byte *_dataPtr; + color_t _palette[256]; + int _totalRead; + + void (*_customChunkHandler)(byte *buffer, int size, int16 id, char h6, char h7); + + CSoundChannel *_soundChannel; + +public: + HnmPlayer(CryoEngine *vm); + + void allocMemory(); + void closeSound(); + void deallocMemory(); + int getFrameNum(); + CSoundChannel *getSoundChannel(); + int16 getVersion(); + bool nextElement(); + void reset(); + void readHeader(); + void resetInternals(); + void setFile(Common::File *file); + void setFinalBuffer(byte *buffer); + void setForceZero2Black(bool forceblack); + void setupSound(unsigned int rate, bool stereo, bool is16bits); + void setupTimer(float rate); + void waitLoop(); +}; + +} // End of namespace Cryo + +#endif diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp index 4522eaeeb6..453ca08a07 100644 --- a/engines/director/cast.cpp +++ b/engines/director/cast.cpp @@ -180,8 +180,9 @@ ButtonCast::ButtonCast(Common::ReadStreamEndian &stream, uint16 version) : TextC stream.readByte(); stream.readByte(); - initialRect = Score::readRect(stream); - boundingRect = Score::readRect(stream); + //This has already been populated in the super TextCast constructor + //initialRect = Score::readRect(stream); + //boundingRect = Score::readRect(stream); buttonType = static_cast<ButtonType>(stream.readUint16BE()); } diff --git a/engines/director/director.cpp b/engines/director/director.cpp index 9417538f54..d9bf8cd0cc 100644 --- a/engines/director/director.cpp +++ b/engines/director/director.cpp @@ -76,6 +76,8 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam _movies = nullptr; + _nextMovieFrameI = -1; + _wm = nullptr; const Common::FSNode gameDataDir(ConfMan.get("path")); @@ -134,10 +136,14 @@ Common::Error DirectorEngine::run() { //_mainArchive = new RIFFArchive(); //_mainArchive->openFile("bookshelf_example.mmm"); - if (getPlatform() == Common::kPlatformWindows) + if (getPlatform() == Common::kPlatformWindows) { _sharedCastFile = "SHARDCST.MMM"; - else - _sharedCastFile = "Shared Cast"; + } else { + if (getVersion() < 3) + _sharedCastFile = "Shared Cast"; + else + _sharedCastFile = "Shared.dir"; + } loadSharedCastsFrom(_sharedCastFile); @@ -146,8 +152,43 @@ Common::Error DirectorEngine::run() { _currentScore = new Score(this, _mainArchive); debug(0, "Score name %s", _currentScore->getMacName().c_str()); - _currentScore->loadArchive(); - _currentScore->startLoop(); + bool loop = true; + + while (loop) { + loop = false; + + _currentScore->loadArchive(); + + // If we came in a loop, then skip as requested + if (!_nextMovieFrameS.empty()) + _currentScore->setStartToLabel(_nextMovieFrameS); + + if (_nextMovieFrameI != -1) + _currentScore->setCurrentFrame(_nextMovieFrameI); + + _currentScore->startLoop(); + + // If a loop was requested, do it + if (!_nextMovie.empty()) { + _lingo->restartLingo(); + + delete _currentScore; + + Archive *mov = openMainArchive(_nextMovie); + + if (!mov) { + warning("nextMovie: No score is loaded"); + + return Common::kNoError; + } + + _currentScore = new Score(this, mov); + debug(0, "Score name %s", _currentScore->getMacName().c_str()); + + _nextMovie.clear(); + loop = true; + } + } return Common::kNoError; } @@ -192,32 +233,4 @@ Common::HashMap<Common::String, Score *> *DirectorEngine::scanMovies(const Commo return nameMap; } -void DirectorEngine::setPalette(byte *palette, uint16 count) { - _currentPalette = palette; - _currentPaletteLength = count; -} - -void DirectorEngine::testFonts() { - Common::String fontName("Helvetica"); - - Common::MacResManager *fontFile = new Common::MacResManager(); - if (!fontFile->open(fontName)) - error("Could not open %s as a resource fork", fontName.c_str()); - - Common::MacResIDArray fonds = fontFile->getResIDArray(MKTAG('F','O','N','D')); - if (fonds.size() > 0) { - for (Common::Array<uint16>::iterator iterator = fonds.begin(); iterator != fonds.end(); ++iterator) { - Common::SeekableReadStream *stream = fontFile->getResource(MKTAG('F', 'O', 'N', 'D'), *iterator); - Common::String name = fontFile->getResName(MKTAG('F', 'O', 'N', 'D'), *iterator); - - debug("Font: %s", name.c_str()); - - Graphics::MacFontFamily font; - font.load(*stream); - } - } - - delete fontFile; -} - } // End of namespace Director diff --git a/engines/director/director.h b/engines/director/director.h index 9277abf2e2..001393bc97 100644 --- a/engines/director/director.h +++ b/engines/director/director.h @@ -60,6 +60,7 @@ enum { kDebugText = 1 << 4 }; +extern byte defaultPalette[768]; class DirectorEngine : public ::Engine { public: @@ -97,7 +98,6 @@ public: Common::HashMap<int, Cast *> *getSharedCasts() const { return _sharedCasts; } Common::HashMap<Common::String, Score *> *_movies; - Score *_currentScore; Common::RandomSource _rnd; Graphics::MacWindowManager *_wm; @@ -109,6 +109,10 @@ public: int _machineType; bool _playbackPaused; + Common::String _nextMovie; + Common::String _nextMovieFrameS; + int _nextMovieFrameI; + protected: virtual Common::Error run(); @@ -137,6 +141,8 @@ private: uint16 _currentPaletteLength; Lingo *_lingo; + Score *_currentScore; + Graphics::MacPatterns _director3Patterns; Graphics::MacPatterns _director3QuickDrawPatterns; diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp index 8992806ea8..f6a16e6cef 100644 --- a/engines/director/frame.cpp +++ b/engines/director/frame.cpp @@ -380,7 +380,7 @@ void Frame::prepareFrame(Score *score) { renderSprites(*score->_trailSurface, true); if (_transType != 0) - //T ODO Handle changing area case + // TODO Handle changing area case playTransition(score); if (_sound1 != 0 || _sound2 != 0) { @@ -391,8 +391,7 @@ void Frame::prepareFrame(Score *score) { } void Frame::playSoundChannel() { - debug(0, "Sound1 %d", _sound1); - debug(0, "Sound2 %d", _sound2); + debug(0, "STUB: playSoundChannel(), Sound1 %d Sound2 %d", _sound1, _sound2); } void Frame::playTransition(Score *score) { @@ -561,7 +560,7 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { break; } } else { - if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) { + if (!_vm->getCurrentScore()->_casts.contains(_sprites[i]->_castId)) { if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) { warning("Cast id %d not found", _sprites[i]->_castId); continue; @@ -570,13 +569,13 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId); } } else { - cast = _vm->_currentScore->_casts[_sprites[i]->_castId]; + cast = _vm->getCurrentScore()->_casts[_sprites[i]->_castId]; } castType = cast->type; } - //this needs precedence to be hit first... D3 does something really tricky with cast IDs for shapes. - //I don't like this implementation 100% as the 'cast' above might not actually hit a member and be null? + // this needs precedence to be hit first... D3 does something really tricky with cast IDs for shapes. + // I don't like this implementation 100% as the 'cast' above might not actually hit a member and be null? if (castType == kCastShape) { renderShape(surface, i); } else if (castType == kCastText) { @@ -599,7 +598,7 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { assert(_sprites[i]->_cast); BitmapCast *bitmapCast = static_cast<BitmapCast *>(_sprites[i]->_cast); - //TODO: might want a quicker way to determine if cast is from Shared Cast. + // TODO: might want a quicker way to determine if cast is from Shared Cast. if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(_sprites[i]->_castId + 1024)) { debugC(2, kDebugImages, "Shared cast sprite BMP: id: %d", _sprites[i]->_castId + 1024); bitmapCast = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(_sprites[i]->_castId)); @@ -642,10 +641,10 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) { if (_vm->getVersion() <= 3 && _sprites[spriteId]->_spriteType == 0x0c) { tmpSurface.fillRect(Common::Rect(shapeRect.width(), shapeRect.height()), 255); tmpSurface.frameRect(Common::Rect(shapeRect.width(), shapeRect.height()), 0); - //TODO: don't override, work out how to display correctly. + // TODO: don't override, work out how to display correctly. _sprites[spriteId]->_ink = kInkTypeTransparent; } else { - //No minus one on the pattern here! MacPlotData will do that for us! + // No minus one on the pattern here! MacPlotData will do that for us! Graphics::MacPlotData pd(&tmpSurface, &_vm->getPatterns(), _sprites[spriteId]->_castId, 1, _sprites[spriteId]->_backColor); Common::Rect fillRect(shapeRect.width(), shapeRect.height()); Graphics::drawFilledRect(fillRect, _sprites[spriteId]->_foreColor, Graphics::macDrawPixel, &pd); @@ -661,18 +660,23 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) { } void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId) { - renderText(surface, spriteId, _vm->getMainArchive()->getResource(MKTAG('S', 'T', 'X', 'T'), textId), true); - uint16 castId = _sprites[spriteId]->_castId; - ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[castId]); + ButtonCast *button = static_cast<ButtonCast *>(_vm->getCurrentScore()->_casts[castId]); uint32 rectLeft = button->initialRect.left; uint32 rectTop = button->initialRect.top; int x = _sprites[spriteId]->_startPoint.x + rectLeft; int y = _sprites[spriteId]->_startPoint.y + rectTop; - int height = _sprites[spriteId]->_height; - int width = _sprites[spriteId]->_width; + int height = button->initialRect.height(); // _sprites[spriteId]->_height; + int width = button->initialRect.width() + 3; // _sprites[spriteId]->_width; + + Common::Rect textRect(0, 0, width, height); + // pass the rect of the button into the label. + renderText(surface, spriteId, _vm->getMainArchive()->getResource(MKTAG('S', 'T', 'X', 'T'), textId), &textRect); + + // TODO: review all cases to confirm if we should use text height. + // height = textRect.height(); Common::Rect _rect; @@ -684,7 +688,7 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uin addDrawRect(spriteId, _rect); break; case kTypeButton: { - _rect = Common::Rect(x, y, x + width - 1, y + height + 5); + _rect = Common::Rect(x, y, x + width, y + height + 3); Graphics::MacPlotData pd(&surface, &_vm->getMacWindowManager()->getPatterns(), Graphics::MacGUIConstants::kPatternSolid, 1); Graphics::drawRoundRect(_rect, 4, 0, false, Graphics::macDrawPixel, &pd); addDrawRect(spriteId, _rect); @@ -699,14 +703,14 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uin Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { uint16 imgId = spriteId + 1024; - if (_vm->getVersion() >= 4 && _vm->_currentScore->_casts[spriteId]->children.size() > 0) - imgId = _vm->_currentScore->_casts[spriteId]->children[0].index; + if (_vm->getVersion() >= 4 && _vm->getCurrentScore()->_casts[spriteId]->children.size() > 0) + imgId = _vm->getCurrentScore()->_casts[spriteId]->children[0].index; Image::ImageDecoder *img = NULL; - if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) { + if (_vm->getCurrentScore()->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) { img = new DIBDecoder(); - img->loadStream(*_vm->_currentScore->getArchive()->getResource(MKTAG('D', 'I', 'B', ' '), imgId)); + img->loadStream(*_vm->getCurrentScore()->getArchive()->getResource(MKTAG('D', 'I', 'B', ' '), imgId)); return img; } @@ -722,11 +726,11 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) { debugC(2, kDebugImages, "Shared cast BMP: id: %d", imgId); pic = _vm->getSharedBMP()->getVal(imgId); - pic->seek(0); //TODO: this actually gets re-read every loop... we need to rewind it! + pic->seek(0); // TODO: this actually gets re-read every loop... we need to rewind it! bc = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(spriteId)); - } else if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) { - pic = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId); - bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]); + } else if (_vm->getCurrentScore()->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) { + pic = _vm->getCurrentScore()->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId); + bc = static_cast<BitmapCast *>(_vm->getCurrentScore()->_casts[spriteId]); } if (pic != NULL && bc != NULL) { @@ -737,7 +741,7 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2); img = new BITDDecoder(w, h); } else if (_vm->getVersion() < 6) { - bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]); + bc = static_cast<BitmapCast *>(_vm->getCurrentScore()->_casts[spriteId]); int w = bc->initialRect.width(), h = bc->initialRect.height(); debugC(2, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d", @@ -794,21 +798,21 @@ void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 castId) { Common::SeekableSubReadStreamEndian *textStream = NULL; - if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S', 'T', 'X', 'T'), castId)) { - textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S', 'T', 'X', 'T'), castId); + if (_vm->getCurrentScore()->_movieArchive->hasResource(MKTAG('S', 'T', 'X', 'T'), castId)) { + textStream = _vm->getCurrentScore()->_movieArchive->getResource(MKTAG('S', 'T', 'X', 'T'), castId); } else if (_vm->getSharedSTXT() != nullptr) { textStream = _vm->getSharedSTXT()->getVal(spriteId + 1024); } - renderText(surface, spriteId, textStream, false); + renderText(surface, spriteId, textStream, NULL); } -void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Common::SeekableSubReadStreamEndian *textStream, bool isButtonLabel) { +void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Common::SeekableSubReadStreamEndian *textStream, Common::Rect *textSize) { if (textStream == NULL) return; uint16 castId = _sprites[spriteId]->_castId; - TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castId]); + TextCast *textCast = static_cast<TextCast *>(_vm->getCurrentScore()->_casts[castId]); uint32 unk1 = textStream->readUint32(); uint32 strLen = textStream->readUint32(); @@ -886,6 +890,8 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo uint16 boxShadow = (uint16)textCast->boxShadow; uint16 borderSize = (uint16)textCast->borderSize; + if (textSize != NULL) + borderSize = 0; uint16 padding = (uint16)textCast->gutterSize; uint16 textShadow = (uint16)textCast->textShadow; @@ -894,20 +900,16 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo int x = _sprites[spriteId]->_startPoint.x; // +rectLeft; int y = _sprites[spriteId]->_startPoint.y; // +rectTop; - int height = _sprites[spriteId]->_height; - if (_vm->getVersion() >= 4 && !isButtonLabel) height = textCast->initialRect.bottom; - height += textShadow; - int width = _sprites[spriteId]->_width; - if (_vm->getVersion() >= 4 && !isButtonLabel) + if (_vm->getVersion() >= 4 && textSize != NULL) width = textCast->initialRect.right; - if (_vm->_currentScore->_fontMap.contains(textCast->fontId)) { - // We need to make sure that teh Shared Cast fonts have been loaded in? - //might need a mapping table here of our own. - //textCast->fontId = _vm->_wm->_fontMan->getFontIdByName(_vm->_currentScore->_fontMap[textCast->fontId]); + if (_vm->getCurrentScore()->_fontMap.contains(textCast->fontId)) { + // We need to make sure that the Shared Cast fonts have been loaded in? + // might need a mapping table here of our own. + // textCast->fontId = _vm->_wm->_fontMan->getFontIdByName(_vm->getCurrentScore()->_fontMap[textCast->fontId]); } Graphics::MacFont macFont = Graphics::MacFont(textCast->fontId, textCast->fontSize, textCast->textSlant); @@ -922,16 +924,28 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo else alignment++; + if (_vm->getVersion() >= 4) { + if (textSize == NULL) + width = textCast->initialRect.right; + else { + width = textSize->width(); + } + } + Graphics::MacText mt(ftext, _vm->_wm, font, 0x00, 0xff, width, (Graphics::TextAlign)alignment); mt.setInterLinear(1); mt.render(); const Graphics::ManagedSurface *textSurface = mt.getSurface(); height = textSurface->h; + if (textSize != NULL) { + // TODO: this offset could be due to incorrect fonts loaded! + textSize->bottom = height + mt.getLineCount(); + } uint16 textX = 0, textY = 0; - if (!isButtonLabel) { + if (textSize == NULL) { if (borderSize > 0) { if (_vm->getVersion() <= 3) height++; @@ -956,6 +970,9 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo if (textShadow > 0) textX--; } else { + x++; + if (width % 2 != 0) + x++; y += 2; } @@ -973,11 +990,11 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo Graphics::ManagedSurface textWithFeatures(width + (borderSize * 2) + boxShadow + textShadow, height + borderSize + boxShadow + textShadow); textWithFeatures.fillRect(Common::Rect(textWithFeatures.w, textWithFeatures.h), 0xff); - if (!isButtonLabel && boxShadow > 0) { + if (textSize == NULL && boxShadow > 0) { textWithFeatures.fillRect(Common::Rect(boxShadow, boxShadow, textWithFeatures.w + boxShadow, textWithFeatures.h), 0); } - if (!isButtonLabel && borderSize != kSizeNone) { + if (textSize == NULL && borderSize != kSizeNone) { for (int bb = 0; bb < borderSize; bb++) { Common::Rect borderRect(bb, bb, textWithFeatures.w - bb - boxShadow - textShadow, textWithFeatures.h - bb - boxShadow - textShadow); textWithFeatures.fillRect(borderRect, 0xff); diff --git a/engines/director/frame.h b/engines/director/frame.h index f822a83fdb..3799c2043c 100644 --- a/engines/director/frame.h +++ b/engines/director/frame.h @@ -125,7 +125,7 @@ private: void playSoundChannel(); void renderSprites(Graphics::ManagedSurface &surface, bool renderTrail); void renderText(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 castId); - void renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Common::SeekableSubReadStreamEndian *textStream, bool isButtonLabel); + void renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Common::SeekableSubReadStreamEndian *textStream, Common::Rect *textSize); void renderShape(Graphics::ManagedSurface &surface, uint16 spriteId); void renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId); void readPaletteInfo(Common::SeekableSubReadStreamEndian &stream); diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp index f980edee5c..76ff41788c 100644 --- a/engines/director/graphics.cpp +++ b/engines/director/graphics.cpp @@ -19,10 +19,72 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "common/events.h" +#include "common/macresman.h" +#include "common/system.h" +#include "engines/util.h" + +#include "graphics/palette.h" +#include "graphics/fonts/macfont.h" +#include "graphics/macgui/macfontmanager.h" +#include "graphics/macgui/macwindowmanager.h" + #include "director/director.h" namespace Director { +// Referred as extern +byte defaultPalette[768] = { + 0, 0, 0, 17, 17, 17, 34, 34, 34, 68, 68, 68, 85, 85, 85, 119, + 119, 119, 136, 136, 136, 170, 170, 170, 187, 187, 187, 221, 221, 221, 238, 238, + 238, 0, 0, 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, + 0, 0, 136, 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, + 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136, + 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 17, 0, 0, + 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136, 0, 0, 170, + 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 0, 0, 0, 51, 0, 0, + 102, 0, 0, 153, 0, 0, 204, 0, 0, 255, 0, 51, 0, 0, 51, 51, + 0, 51, 102, 0, 51, 153, 0, 51, 204, 0, 51, 255, 0, 102, 0, 0, + 102, 51, 0, 102, 102, 0, 102, 153, 0, 102, 204, 0, 102, 255, 0, 153, + 0, 0, 153, 51, 0, 153, 102, 0, 153, 153, 0, 153, 204, 0, 153, 255, + 0, 204, 0, 0, 204, 51, 0, 204, 102, 0, 204, 153, 0, 204, 204, 0, + 204, 255, 0, 255, 0, 0, 255, 51, 0, 255, 102, 0, 255, 153, 0, 255, + 204, 0, 255, 255, 51, 0, 0, 51, 0, 51, 51, 0, 102, 51, 0, 153, + 51, 0, 204, 51, 0, 255, 51, 51, 0, 51, 51, 51, 51, 51, 102, 51, + 51, 153, 51, 51, 204, 51, 51, 255, 51, 102, 0, 51, 102, 51, 51, 102, + 102, 51, 102, 153, 51, 102, 204, 51, 102, 255, 51, 153, 0, 51, 153, 51, + 51, 153, 102, 51, 153, 153, 51, 153, 204, 51, 153, 255, 51, 204, 0, 51, + 204, 51, 51, 204, 102, 51, 204, 153, 51, 204, 204, 51, 204, 255, 51, 255, + 0, 51, 255, 51, 51, 255, 102, 51, 255, 153, 51, 255, 204, 51, 255, 255, + 102, 0, 0, 102, 0, 51, 102, 0, 102, 102, 0, 153, 102, 0, 204, 102, + 0, 255, 102, 51, 0, 102, 51, 51, 102, 51, 102, 102, 51, 153, 102, 51, + 204, 102, 51, 255, 102, 102, 0, 102, 102, 51, 102, 102, 102, 102, 102, 153, + 102, 102, 204, 102, 102, 255, 102, 153, 0, 102, 153, 51, 102, 153, 102, 102, + 153, 153, 102, 153, 204, 102, 153, 255, 102, 204, 0, 102, 204, 51, 102, 204, + 102, 102, 204, 153, 102, 204, 204, 102, 204, 255, 102, 255, 0, 102, 255, 51, + 102, 255, 102, 102, 255, 153, 102, 255, 204, 102, 255, 255, 153, 0, 0, 153, + 0, 51, 153, 0, 102, 153, 0, 153, 153, 0, 204, 153, 0, 255, 153, 51, + 0, 153, 51, 51, 153, 51, 102, 153, 51, 153, 153, 51, 204, 153, 51, 255, + 153, 102, 0, 153, 102, 51, 153, 102, 102, 153, 102, 153, 153, 102, 204, 153, + 102, 255, 153, 153, 0, 153, 153, 51, 153, 153, 102, 153, 153, 153, 153, 153, + 204, 153, 153, 255, 153, 204, 0, 153, 204, 51, 153, 204, 102, 153, 204, 153, + 153, 204, 204, 153, 204, 255, 153, 255, 0, 153, 255, 51, 153, 255, 102, 153, + 255, 153, 153, 255, 204, 153, 255, 255, 204, 0, 0, 204, 0, 51, 204, 0, + 102, 204, 0, 153, 204, 0, 204, 204, 0, 255, 204, 51, 0, 204, 51, 51, + 204, 51, 102, 204, 51, 153, 204, 51, 204, 204, 51, 255, 204, 102, 0, 204, + 102, 51, 204, 102, 102, 204, 102, 153, 204, 102, 204, 204, 102, 255, 204, 153, + 0, 204, 153, 51, 204, 153, 102, 204, 153, 153, 204, 153, 204, 204, 153, 255, + 204, 204, 0, 204, 204, 51, 204, 204, 102, 204, 204, 153, 204, 204, 204, 204, + 204, 255, 204, 255, 0, 204, 255, 51, 204, 255, 102, 204, 255, 153, 204, 255, + 204, 204, 255, 255, 255, 0, 0, 255, 0, 51, 255, 0, 102, 255, 0, 153, + 255, 0, 204, 255, 0, 255, 255, 51, 0, 255, 51, 51, 255, 51, 102, 255, + 51, 153, 255, 51, 204, 255, 51, 255, 255, 102, 0, 255, 102, 51, 255, 102, + 102, 255, 102, 153, 255, 102, 204, 255, 102, 255, 255, 153, 0, 255, 153, 51, + 255, 153, 102, 255, 153, 153, 255, 153, 204, 255, 153, 255, 255, 204, 0, 255, + 204, 51, 255, 204, 102, 255, 204, 153, 255, 204, 204, 255, 204, 255, 255, 255, + 0, 255, 255, 51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255 }; + + static byte director3Patterns[][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0x77, 0xFF }, { 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF }, @@ -152,4 +214,90 @@ Graphics::MacPatterns &DirectorEngine::getPatterns() { return _director3QuickDrawPatterns; } +void DirectorEngine::setPalette(byte *palette, uint16 count) { + _currentPalette = palette; + _currentPaletteLength = count; +} + +void DirectorEngine::testFontScaling() { + int x = 10; + int y = 10; + int w = 640; + int h = 480; + + initGraphics(w, h, true); + _system->getPaletteManager()->setPalette(defaultPalette, 0, 256); + + Graphics::ManagedSurface surface; + + surface.create(w, h); + surface.clear(255); + + Graphics::MacFont origFont(Graphics::kMacFontNewYork, 18); + + const Graphics::MacFONTFont *font1 = (const Graphics::MacFONTFont *)_wm->_fontMan->getFont(origFont); + + Graphics::MacFONTFont::testBlit(font1, &surface, 0, x, y + 200, 500); + + Graphics::MacFont bigFont(Graphics::kMacFontNewYork, 15); + + font1 = (const Graphics::MacFONTFont *)_wm->_fontMan->getFont(bigFont); + + Graphics::MacFONTFont::testBlit(font1, &surface, 0, x, y + 50 + 200, 500); + + const char *text = "d"; + + for (int i = 9; i <= 20; i++) { + Graphics::MacFont macFont(Graphics::kMacFontNewYork, i); + + const Graphics::Font *font = _wm->_fontMan->getFont(macFont); + + int width = font->getStringWidth(text); + + Common::Rect bbox = font->getBoundingBox(text, x, y, w); + surface.frameRect(bbox, 15); + + font->drawString(&surface, text, x, y, width, 0); + + x += width + 1; + } + + g_system->copyRectToScreen(surface.getPixels(), surface.pitch, 0, 0, w, h); + + Common::Event event; + + while (true) { + if (g_system->getEventManager()->pollEvent(event)) + if (event.type == Common::EVENT_QUIT) + break; + + g_system->updateScreen(); + g_system->delayMillis(10); + } +} + +void DirectorEngine::testFonts() { + Common::String fontName("Helvetica"); + + Common::MacResManager *fontFile = new Common::MacResManager(); + if (!fontFile->open(fontName)) + error("Could not open %s as a resource fork", fontName.c_str()); + + Common::MacResIDArray fonds = fontFile->getResIDArray(MKTAG('F','O','N','D')); + if (fonds.size() > 0) { + for (Common::Array<uint16>::iterator iterator = fonds.begin(); iterator != fonds.end(); ++iterator) { + Common::SeekableReadStream *stream = fontFile->getResource(MKTAG('F', 'O', 'N', 'D'), *iterator); + Common::String name = fontFile->getResName(MKTAG('F', 'O', 'N', 'D'), *iterator); + + debug("Font: %s", name.c_str()); + + Graphics::MacFontFamily font; + font.load(*stream); + } + } + + delete fontFile; +} + + } diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp index a7a0d8b879..98a4399e4e 100644 --- a/engines/director/lingo/lingo-builtins.cpp +++ b/engines/director/lingo/lingo-builtins.cpp @@ -27,141 +27,171 @@ namespace Director { static struct BuiltinProto { const char *name; void (*func)(int); - int minArgs; + int minArgs; // -1 -- arglist int maxArgs; bool parens; } builtins[] = { // Math - { "abs", Lingo::b_abs, 1, 1, true }, // D2 - { "atan", Lingo::b_atan, 1, 1, true }, // D4 - { "cos", Lingo::b_cos, 1, 1, true }, // D4 - { "exp", Lingo::b_exp, 1, 1, true }, // D4 - { "float", Lingo::b_float, 1, 1, true }, // D4 - { "integer", Lingo::b_integer, 1, 1, true }, - { "log", Lingo::b_log, 1, 1, true }, // D4 - { "pi", Lingo::b_pi, 0, 0, true }, // D4 - { "power", Lingo::b_power, 2, 2, true }, // D4 - { "random", Lingo::b_random, 1, 1, true }, // D2 - { "sin", Lingo::b_sin, 1, 1, true }, - { "sqrt", Lingo::b_sqrt, 1, 1, true }, // D2 - { "tan", Lingo::b_tan, 1, 1, true }, // D4 + { "abs", Lingo::b_abs, 1, 1, true }, // D2 function + { "atan", Lingo::b_atan, 1, 1, true }, // D4 f + { "cos", Lingo::b_cos, 1, 1, true }, // D4 f + { "exp", Lingo::b_exp, 1, 1, true }, // D4 f + { "float", Lingo::b_float, 1, 1, true }, // D4 f + { "integer", Lingo::b_integer, 1, 1, true }, // D3 f + { "log", Lingo::b_log, 1, 1, true }, // D4 f + { "pi", Lingo::b_pi, 0, 0, true }, // D4 f + { "power", Lingo::b_power, 2, 2, true }, // D4 f + { "random", Lingo::b_random, 1, 1, true }, // D2 f + { "sin", Lingo::b_sin, 1, 1, true }, // D4 f + { "sqrt", Lingo::b_sqrt, 1, 1, true }, // D2 f + { "tan", Lingo::b_tan, 1, 1, true }, // D4 f // String - { "chars", Lingo::b_chars, 3, 3, true }, // D2 - { "charToNum", Lingo::b_charToNum, 1, 1, true }, // D2 - { "delete", Lingo::b_delete, 1, 1, true }, // D3 - { "hilite", Lingo::b_hilite, 1, 1, true }, // D3 - { "length", Lingo::b_length, 1, 1, true }, // D2 - { "numToChar", Lingo::b_numToChar, 1, 1, true }, // D2 - { "offset", Lingo::b_offset, 2, 2, true }, // D2 - { "string", Lingo::b_string, 1, 1, true }, // D2 - { "value", Lingo::b_value, 1, 1, true }, // D2 + { "chars", Lingo::b_chars, 3, 3, true }, // D2 f + { "charToNum", Lingo::b_charToNum, 1, 1, true }, // D2 f + { "delete", Lingo::b_delete, 1, 1, true }, // D3 c + { "hilite", Lingo::b_hilite, 1, 1, true }, // D3 c + { "length", Lingo::b_length, 1, 1, true }, // D2 f + { "numToChar", Lingo::b_numToChar, 1, 1, true }, // D2 f + { "offset", Lingo::b_offset, 2, 3, true }, // D2 f + { "string", Lingo::b_string, 1, 1, true }, // D2 f + { "value", Lingo::b_value, 1, 1, true }, // D2 f // Lists - { "add", Lingo::b_add, 2, 2, false }, // D4 - { "addAt", Lingo::b_addAt, 3, 3, false }, // D4 - { "addProp", Lingo::b_addProp, 3, 3, false }, // D4 - { "append", Lingo::b_append, 2, 2, false }, // D4 - { "count", Lingo::b_count, 1, 1, true }, // D4 - { "deleteAt", Lingo::b_deleteAt, 2, 2, false }, // D4 - { "deleteProp", Lingo::b_deleteProp, 2, 2, false }, // D4 - { "findPos", Lingo::b_findPos, 2, 2, true }, // D4 - { "findPosNear", Lingo::b_findPosNear, 2, 2, true }, // D4 - { "getaProp", Lingo::b_getaProp, 2, 2, true }, // D4 - { "getAt", Lingo::b_getAt, 2, 2, true }, // D4 - { "getLast", Lingo::b_getLast, 1, 1, true }, // D4 - { "getOne", Lingo::b_getOne, 2, 2, true }, // D4 - { "getPos", Lingo::b_getPos, 2, 2, true }, // D4 - { "getProp", Lingo::b_getProp, 2, 2, true }, // D4 - { "getPropAt", Lingo::b_getPropAt, 2, 2, true }, // D4 - { "list", Lingo::b_list, -1, 0, true }, // D4 - { "listP", Lingo::b_listP, 1, 1, true }, // D4 - { "max", Lingo::b_max, 1, 1, true }, // D4 - { "min", Lingo::b_min, 1, 1, true }, // D4 - { "setaProp", Lingo::b_setaProp, 3, 3, false }, // D4 - { "setAt", Lingo::b_setAt, 3, 3, false }, // D4 - { "setProp", Lingo::b_setProp, 3, 3, false }, // D4 - { "sort", Lingo::b_sort, 1, 1, false }, // D4 + { "add", Lingo::b_add, 2, 2, false }, // D4 command + { "addAt", Lingo::b_addAt, 3, 3, false }, // D4 c + { "addProp", Lingo::b_addProp, 3, 3, false }, // D4 c + { "append", Lingo::b_append, 2, 2, false }, // D4 c + { "count", Lingo::b_count, 1, 1, true }, // D4 f + { "deleteAt", Lingo::b_deleteAt, 2, 2, false }, // D4 c + { "deleteProp", Lingo::b_deleteProp, 2, 2, false }, // D4 c + { "findPos", Lingo::b_findPos, 2, 2, true }, // D4 f + { "findPosNear", Lingo::b_findPosNear, 2, 2, true }, // D4 f + { "getaProp", Lingo::b_getaProp, 2, 2, true }, // D4 f + { "getAt", Lingo::b_getAt, 2, 2, true }, // D4 f + { "getLast", Lingo::b_getLast, 1, 1, true }, // D4 f + { "getOne", Lingo::b_getOne, 2, 2, true }, // D4 f + { "getPos", Lingo::b_getPos, 2, 2, true }, // D4 f + { "getProp", Lingo::b_getProp, 2, 2, true }, // D4 f + { "getPropAt", Lingo::b_getPropAt, 2, 2, true }, // D4 f + { "list", Lingo::b_list, -1, 0, true }, // D4 f + { "listP", Lingo::b_listP, 1, 1, true }, // D4 f + { "max", Lingo::b_max, 1, 1, true }, // D4 f + { "min", Lingo::b_min, 1, 1, true }, // D4 f + { "setaProp", Lingo::b_setaProp, 3, 3, false }, // D4 c + { "setAt", Lingo::b_setAt, 3, 3, false }, // D4 c + { "setProp", Lingo::b_setProp, 3, 3, false }, // D4 c + { "sort", Lingo::b_sort, 1, 1, false }, // D4 c // Files - { "closeDA", Lingo::b_closeDA, 0, 0, false }, // D2 - { "closeResFile", Lingo::b_closeResFile, 0, 1, false }, // D2 - { "closeXlib", Lingo::b_closeXlib, 0, 1, false }, // D2 - // open // D2 - { "openDA", Lingo::b_openDA, 1, 1, false }, // D2 - { "openResFile", Lingo::b_openResFile, 1, 1, false }, // D2 - { "openXlib", Lingo::b_openXlib, 1, 1, false }, // D2 - { "setCallBack", Lingo::b_setCallBack, 2, 2, false }, // D3 - { "showResFile", Lingo::b_showResFile, 0, 1, false }, // D2 - { "showXlib", Lingo::b_showXlib, 0, 1, false }, // D2 - { "xFactoryList", Lingo::b_xFactoryList, 1, 1, true }, // D3 + { "closeDA", Lingo::b_closeDA, 0, 0, false }, // D2 c + { "closeResFile", Lingo::b_closeResFile, 0, 1, false }, // D2 c + { "closeXlib", Lingo::b_closeXlib, 0, 1, false }, // D2 c + { "getNthFileNameInFolder",Lingo::b_getNthFileNameInFolder,2,2,true },//D4 f + // open // D2 c + { "openDA", Lingo::b_openDA, 1, 1, false }, // D2 c + { "openResFile", Lingo::b_openResFile, 1, 1, false }, // D2 c + { "openXlib", Lingo::b_openXlib, 1, 1, false }, // D2 c + { "saveMovie", Lingo::b_saveMovie, 1, 1, false }, // D4 c + { "setCallBack", Lingo::b_setCallBack, 2, 2, false }, // D3 c + { "showResFile", Lingo::b_showResFile, 0, 1, false }, // D2 c + { "showXlib", Lingo::b_showXlib, 0, 1, false }, // D2 c + { "xFactoryList", Lingo::b_xFactoryList, 1, 1, true }, // D3 f // Control - { "abort", Lingo::b_abort, 0, 0, false }, // D4 - { "continue", Lingo::b_continue, 0, 0, false }, // D2 - { "dontPassEvent", Lingo::b_dontPassEvent, 0, 0, false }, // D2 - { "delay", Lingo::b_delay, 1, 1, false }, // D2 - { "do", Lingo::b_do, 1, 1, false }, // D2 - { "nothing", Lingo::b_nothing, 0, 0, false }, // D2 - { "pause", Lingo::b_pause, 0, 0, false }, // D2 - // play // D2 + { "abort", Lingo::b_abort, 0, 0, false }, // D4 c + { "continue", Lingo::b_continue, 0, 0, false }, // D2 c + { "dontPassEvent", Lingo::b_dontPassEvent, 0, 0, false }, // D2 c + { "delay", Lingo::b_delay, 1, 1, false }, // D2 c + { "do", Lingo::b_do, 1, 1, false }, // D2 c + { "halt", Lingo::b_halt, 0, 0, false }, // D4 c + { "nothing", Lingo::b_nothing, 0, 0, false }, // D2 c + { "pass", Lingo::b_pass, 0, 0, false }, // D4 c + { "pause", Lingo::b_pause, 0, 0, false }, // D2 c + // play // D2 c { "playAccel", Lingo::b_playAccel, -1,0, false }, // D2 // play done // D2 - { "preLoad", Lingo::b_preLoad, -1,0, false }, // D3 - { "preLoadCast", Lingo::b_preLoadCast, -1,0, false }, // D3 - { "quit", Lingo::b_quit, 0, 0, false }, // D2 - { "restart", Lingo::b_restart, 0, 0, false }, // D2 - { "shutDown", Lingo::b_shutDown, 0, 0, false }, // D2 - { "startTimer", Lingo::b_startTimer, 0, 0, false }, // D2 + { "preLoad", Lingo::b_preLoad, -1,0, false }, // D3 c + { "preLoadCast", Lingo::b_preLoadCast, -1,0, false }, // D3 c + { "quit", Lingo::b_quit, 0, 0, false }, // D2 c + { "restart", Lingo::b_restart, 0, 0, false }, // D2 c + { "shutDown", Lingo::b_shutDown, 0, 0, false }, // D2 c + { "startTimer", Lingo::b_startTimer, 0, 0, false }, // D2 c // when keyDown // D2 // when mouseDown // D2 // when mouseUp // D2 // when timeOut // D2 // Types { "floatP", Lingo::b_floatP, 1, 1, true }, // D3 - { "ilk", Lingo::b_ilk, 1, 2, false }, // D4 - { "integerp", Lingo::b_integerp, 1, 1, true }, // D2 - { "objectp", Lingo::b_objectp, 1, 1, true }, // D2 - { "stringp", Lingo::b_stringp, 1, 1, true }, // D2 - { "symbolp", Lingo::b_symbolp, 1, 1, true }, // D2 + { "ilk", Lingo::b_ilk, 1, 2, false }, // D4 f + { "integerp", Lingo::b_integerp, 1, 1, true }, // D2 f + { "objectp", Lingo::b_objectp, 1, 1, true }, // D2 f + { "pictureP", Lingo::b_pictureP, 1, 1, true }, // D4 f + { "stringp", Lingo::b_stringp, 1, 1, true }, // D2 f + { "symbolp", Lingo::b_symbolp, 1, 1, true }, // D2 f + { "voidP", Lingo::b_voidP, 1, 1, true }, // D4 f // Misc - { "alert", Lingo::b_alert, 1, 1, false }, // D2 - { "cursor", Lingo::b_cursor, 1, 1, false }, // D2 - { "framesToHMS", Lingo::b_framesToHMS, 4, 4, false }, // D3 - { "HMStoFrames", Lingo::b_HMStoFrames, 4, 4, false }, // D3 - { "printFrom", Lingo::b_printFrom, -1,0, false }, // D2 + { "alert", Lingo::b_alert, 1, 1, false }, // D2 c + { "birth", Lingo::b_birth, -1,0, false }, // D4 f + { "clearGlobals", Lingo::b_clearGlobals, 0, 0, false }, // D4 c + { "cursor", Lingo::b_cursor, 1, 1, false }, // D2 c + { "framesToHMS", Lingo::b_framesToHMS, 4, 4, false }, // D3 f + { "HMStoFrames", Lingo::b_HMStoFrames, 4, 4, false }, // D3 f + { "param", Lingo::b_param, 1, 1, true }, // D4 f + { "printFrom", Lingo::b_printFrom, -1,0, false }, // D2 c // put // D2 // set // D2 - { "showGlobals", Lingo::b_showGlobals, 0, 0, false }, // D2 - { "showLocals", Lingo::b_showLocals, 0, 0, false }, // D2 + { "showGlobals", Lingo::b_showGlobals, 0, 0, false }, // D2 c + { "showLocals", Lingo::b_showLocals, 0, 0, false }, // D2 c // Score - { "constrainH", Lingo::b_constrainH, 2, 2, true }, // D2 - { "constrainV", Lingo::b_constrainV, 2, 2, true }, // D2 - { "duplicate-cast", Lingo::b_duplicateCast, 1, 2, false }, // D4 + { "constrainH", Lingo::b_constrainH, 2, 2, true }, // D2 f + { "constrainV", Lingo::b_constrainV, 2, 2, true }, // D2 f + { "copyToClipBoard",Lingo::b_copyToClipBoard,1,1, false }, // D4 c + { "duplicate", Lingo::b_duplicate, 1, 2, false }, // D4 c { "editableText", Lingo::b_editableText, 0, 0, false }, // D2 - { "erase-cast", Lingo::b_eraseCast, 1, 2, false }, // D4 + { "erase", Lingo::b_erase, 1, 1, false }, // D4 c + { "findEmpty", Lingo::b_findEmpty, 1, 1, true }, // D4 f // go // D2 - { "installMenu", Lingo::b_installMenu, 1, 1, false }, // D2 - { "label", Lingo::b_label, 1, 1, true }, // D2 - { "marker", Lingo::b_marker, 1, 1, true }, // D2 + { "importFileInto", Lingo::b_importFileInto,2, 2, false }, // D4 c + { "installMenu", Lingo::b_installMenu, 1, 1, false }, // D2 c + { "label", Lingo::b_label, 1, 1, true }, // D2 f + { "marker", Lingo::b_marker, 1, 1, true }, // D2 f + { "move", Lingo::b_move, 1, 2, false }, // D4 c { "moveableSprite", Lingo::b_moveableSprite,0, 0, false }, // D2 - { "puppetPalette", Lingo::b_puppetPalette, -1,0, false }, // D2 - { "puppetSound", Lingo::b_puppetSound, -1,0, false }, // D2 - { "puppetSprite", Lingo::b_puppetSprite, -1,0, false }, // D2 - { "puppetTempo", Lingo::b_puppetTempo, 1, 1, false }, // D2 - { "puppetTransition",Lingo::b_puppetTransition,-1,0, false },// D2 - { "rollOver", Lingo::b_rollOver, 1, 1, true }, // D2 - { "spriteBox", Lingo::b_spriteBox, -1,0, false }, // D2 - { "updateStage", Lingo::b_updateStage, 0, 0, false }, // D2 - { "zoomBox", Lingo::b_zoomBox, -1,0, false }, // D2 + { "pasteClipBoardInto",Lingo::b_pasteClipBoardInto,1, 1, false }, // D4 c + { "puppetPalette", Lingo::b_puppetPalette, -1,0, false }, // D2 c + { "puppetSound", Lingo::b_puppetSound, -1,0, false }, // D2 c + { "puppetSprite", Lingo::b_puppetSprite, -1,0, false }, // D2 c + { "puppetTempo", Lingo::b_puppetTempo, 1, 1, false }, // D2 c + { "puppetTransition",Lingo::b_puppetTransition,-1,0, false },// D2 c + { "ramNeeded", Lingo::b_ramNeeded, 2, 2, true }, // D4 f + { "rollOver", Lingo::b_rollOver, 1, 1, true }, // D2 f + { "spriteBox", Lingo::b_spriteBox, -1,0, false }, // D2 c + { "unLoad", Lingo::b_unLoad, 0, 2, false }, // D4 c + { "unLoadCast", Lingo::b_unLoadCast, 0, 2, false }, // D4 c + { "updateStage", Lingo::b_updateStage, 0, 0, false }, // D2 c + { "zoomBox", Lingo::b_zoomBox, -1,0, false }, // D2 c // Point - { "point", Lingo::b_point, 2, 2, true }, + { "point", Lingo::b_point, 2, 2, true }, // D4 f + { "inside", Lingo::b_inside, 2, 2, true }, // D4 f + { "intersect", Lingo::b_intersect, 2, 2, false }, // D4 f + { "map", Lingo::b_map, 3, 3, true }, // D4 f + { "rect", Lingo::b_rect, 4, 4, true }, // D4 f + { "union", Lingo::b_union, 2, 2, true }, // D4 f // Sound { "beep", Lingo::b_beep, 0, 1, false }, // D2 - { "mci", Lingo::b_mci, 1, 1, false }, + { "mci", Lingo::b_mci, 1, 1, false }, // D4 c { "mciwait", Lingo::b_mciwait, 1, 1, false }, - { "sound-fadeIn", Lingo::b_soundFadeIn, 1, 2, false }, // D3 - { "sound-fadeOut", Lingo::b_soundFadeOut, 1, 2, false }, // D3 - { "sound-playFile", Lingo::b_soundPlayFile, 2, 2, false }, // D3 - { "sound-stop", Lingo::b_soundStop, 1, 1, false }, // D3 - { "soundBusy", Lingo::b_soundBusy, 1, 1, true }, // D3 + { "sound-close", Lingo::b_soundClose, 1, 1, false }, // D4 c + { "sound-fadeIn", Lingo::b_soundFadeIn, 1, 2, false }, // D3 c + { "sound-fadeOut", Lingo::b_soundFadeOut, 1, 2, false }, // D3 c + { "sound-playFile", Lingo::b_soundPlayFile, 2, 2, false }, // D3 c + { "sound-stop", Lingo::b_soundStop, 1, 1, false }, // D3 c + { "soundBusy", Lingo::b_soundBusy, 1, 1, true }, // D3 f + // Window + { "close", Lingo::b_close, 1, 1, false }, // D4 c + { "forget", Lingo::b_forget, 1, 1, false }, // D4 c + { "inflate", Lingo::b_inflate, 3, 3, true }, // D4 f + { "moveToBack", Lingo::b_moveToBack, 1, 1, false }, // D4 c + { "moveToFront", Lingo::b_moveToFront, 1, 1, false }, // D4 c // Constants + { "ancestor", Lingo::b_ancestor, 0, 0, false }, // D4 { "backspace", Lingo::b_backspace, 0, 0, false }, // D2 { "empty", Lingo::b_empty, 0, 0, false }, // D2 { "enter", Lingo::b_enter, 0, 0, false }, // D2 @@ -172,26 +202,121 @@ static struct BuiltinProto { { "true", Lingo::b_true, 0, 0, false }, // D2 { "version", Lingo::b_version, 0, 0, false }, // D3 // References - { "field", Lingo::b_field, 1, 1, false }, // D3 + { "cast", Lingo::b_cast, 1, 1, false }, // D4 f + { "field", Lingo::b_field, 1, 1, false }, // D3 f { "me", Lingo::b_me, -1,0, false }, // D3 - + { "script", Lingo::b_script, 1, 1, false }, // D4 f + { "window", Lingo::b_window, 1, 1, false }, // D4 f { 0, 0, 0, 0, false } }; static const char *twoWordBuiltins[] = { - "duplicate", - "erase", + //"duplicate", + //"erase", "sound", 0 }; +static const char *builtinFunctions[] = { + "abs", + "atan", + "backspace", + "birth", + "cast", + "chars", + "charToNum", + "constrainH", + "constrainV", + "cos", + "count", + "empty", + "enter", + "exp", + "false", + "field", + "findEmpty", + "findPos", + "findPosNear", + "float", + "framesToHMS", + "getaProp", + "getAt", + "getLast", + "getNthFileNameInFolder", + "getOne", + "getPos", + "getProp", + "getPropAt", + "HMStoFrames", + "ilk", + "inflate", + "inside", + "integer", + "integerp", + "intersect", + "label", + "length", + "list", + "listP", + "log", + "map", + "marker", + "max", + "min", + "numToChar", + "objectp", + "offset", + "param", + "pi", + "pictureP", + "point", + "power", + "ramNeeded", + "random", + "rect", + "rollOver", + "quote", + "return", + "script", + "sin", + "sqrt", + "soundBusy", + "string", + "stringp", + "symbolp", + "tab", + "tan", + "true", + "value", + "version", + "voidP", + "window", + "xFactoryList", + 0 +}; + + +static const char *predefinedMethods[] = { + "mAtFrame", // D3 + "mDescribe", // D3 + "mDispose", // D3 + "mGet", // D3 + "mInstanceRespondsTo", // D3 + "mMessageList", // D3 + "mName", // D3 + "mNew", // D3 + "mPerform", // D3 + "mPut", // D3 + "mRespondsTo", // D3 + 0 +}; + void Lingo::initBuiltIns() { for (BuiltinProto *blt = builtins; blt->name; blt++) { Symbol *sym = new Symbol; - sym->name = (char *)calloc(strlen(blt->name) + 1, 1); - Common::strlcpy(sym->name, blt->name, strlen(blt->name)); + sym->name = blt->name; sym->type = BLTIN; sym->nargs = blt->minArgs; sym->maxArgs = blt->maxArgs; @@ -203,8 +328,22 @@ void Lingo::initBuiltIns() { _functions[(void *)sym->u.s] = new FuncDesc(blt->name, ""); } + for (const char **b = builtinFunctions; *b; b++) { + if (!_builtins.contains(*b)) + error("Incorrectly setup builtinFunctions[]: %s", *b); + + _builtins[*b]->type = FBLTIN; + } + for (const char **b = twoWordBuiltins; *b; b++) _twoWordBuiltins[*b] = true; + + // Set predefined methods + for (const char **b = predefinedMethods; *b; b++) { + Symbol *s = g_lingo->lookupVar(*b, true, true); + s->type = SYMBOL; + s->u.s = new Common::String(*b); + } } void Lingo::printSTUBWithArglist(const char *funcname, int nargs) { @@ -438,6 +577,10 @@ void Lingo::b_numToChar(int nargs) { } void Lingo::b_offset(int nargs) { + if (nargs == 3) { + b_offsetRect(nargs); + return; + } Datum target = g_lingo->pop(); Datum source = g_lingo->pop(); @@ -613,6 +756,14 @@ void Lingo::b_closeXlib(int nargs) { delete d.u.s; } +void Lingo::b_getNthFileNameInFolder(int nargs) { + g_lingo->printSTUBWithArglist("b_getNthFileNameInFolder", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + void Lingo::b_openDA(int nargs) { Datum d = g_lingo->pop(); @@ -643,6 +794,12 @@ void Lingo::b_openXlib(int nargs) { delete d.u.s; } +void Lingo::b_saveMovie(int nargs) { + g_lingo->printSTUBWithArglist("b_saveMovie", nargs); + + g_lingo->dropStack(nargs); +} + void Lingo::b_setCallBack(int nargs) { warning("STUB: b_setCallBack"); } @@ -708,6 +865,18 @@ void Lingo::b_do(int nargs) { warning("STUB: b_do(%s)", d.u.s->c_str()); } +void Lingo::b_halt(int nargs) { + b_quit(nargs); + + warning("Movie halted"); +} + +void Lingo::b_pass(int nargs) { + g_lingo->printSTUBWithArglist("b_pass", nargs); + + g_lingo->dropStack(nargs); +} + void Lingo::b_pause(int nargs) { g_director->_playbackPaused = true; @@ -748,6 +917,12 @@ void Lingo::b_HMStoFrames(int nargs) { g_lingo->push(Datum(0)); } +void Lingo::b_param(int nargs) { + g_lingo->printSTUBWithArglist("b_param", nargs); + + g_lingo->dropStack(nargs); +} + void Lingo::b_printFrom(int nargs) { g_lingo->printSTUBWithArglist("b_printFrom", nargs); @@ -755,26 +930,20 @@ void Lingo::b_printFrom(int nargs) { } void Lingo::b_quit(int nargs) { - if (g_director->_currentScore) - g_director->_currentScore->_stopPlay = true; + if (g_director->getCurrentScore()) + g_director->getCurrentScore()->_stopPlay = true; g_lingo->pushVoid(); } void Lingo::b_restart(int nargs) { - if (g_director->_currentScore) - g_director->_currentScore->_stopPlay = true; - - g_lingo->pushVoid(); + b_quit(nargs); warning("Computer restarts"); } void Lingo::b_shutDown(int nargs) { - if (g_director->_currentScore) - g_director->_currentScore->_stopPlay = true; - - g_lingo->pushVoid(); + b_quit(nargs); warning("Computer shuts down"); } @@ -817,6 +986,12 @@ void Lingo::b_objectp(int nargs) { g_lingo->push(d); } +void Lingo::b_pictureP(int nargs) { + g_lingo->pop(); + warning("STUB: b_pictureP"); + g_lingo->push(Datum(0)); +} + void Lingo::b_stringp(int nargs) { Datum d = g_lingo->pop(); int res = (d.type == STRING) ? 1 : 0; @@ -833,6 +1008,14 @@ void Lingo::b_symbolp(int nargs) { g_lingo->push(d); } +void Lingo::b_voidP(int nargs) { + Datum d = g_lingo->pop(); + int res = (d.type == VOID) ? 1 : 0; + d.toInt(); + d.u.i = res; + g_lingo->push(d); +} + /////////////////// // Misc @@ -847,6 +1030,20 @@ void Lingo::b_alert(int nargs) { delete d.u.s; } +void Lingo::b_birth(int nargs) { + g_lingo->printSTUBWithArglist("b_birth", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_clearGlobals(int nargs) { + g_lingo->printSTUBWithArglist("b_clearGlobals", nargs); + + g_lingo->dropStack(nargs); +} + void Lingo::b_cursor(int nargs) { Datum d = g_lingo->pop(); d.toInt(); @@ -888,8 +1085,14 @@ void Lingo::b_constrainV(int nargs) { g_lingo->push(Datum(0)); } -void Lingo::b_duplicateCast(int nargs) { - g_lingo->printSTUBWithArglist("b_duplicateCast", nargs); +void Lingo::b_copyToClipBoard(int nargs) { + g_lingo->printSTUBWithArglist("b_copyToClipBoard", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_duplicate(int nargs) { + g_lingo->printSTUBWithArglist("b_duplicate", nargs); g_lingo->dropStack(nargs); } @@ -898,8 +1101,22 @@ void Lingo::b_editableText(int nargs) { warning("STUB: b_editableText"); } -void Lingo::b_eraseCast(int nargs) { - g_lingo->printSTUBWithArglist("b_eraseCast", nargs); +void Lingo::b_erase(int nargs) { + g_lingo->printSTUBWithArglist("b_erase", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_findEmpty(int nargs) { + g_lingo->printSTUBWithArglist("b_findEmpty", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_importFileInto(int nargs) { + g_lingo->printSTUBWithArglist("b_importFileInto", nargs); g_lingo->dropStack(nargs); } @@ -924,11 +1141,23 @@ void Lingo::b_marker(int nargs) { g_lingo->push(marker); } +void Lingo::b_move(int nargs) { + g_lingo->printSTUBWithArglist("b_move", nargs); + + g_lingo->dropStack(nargs); +} + void Lingo::b_moveableSprite(int nargs) { Datum d = g_lingo->pop(); warning("STUB: b_moveableSprite(%d)", d.u.i); } +void Lingo::b_pasteClipBoardInto(int nargs) { + g_lingo->printSTUBWithArglist("b_pasteClipBoardInto", nargs); + + g_lingo->dropStack(nargs); +} + void Lingo::b_puppetPalette(int nargs) { g_lingo->convertVOIDtoString(0, nargs); @@ -962,9 +1191,16 @@ void Lingo::b_puppetTransition(int nargs) { g_lingo->dropStack(nargs); } +void Lingo::b_ramNeeded(int nargs) { + Datum d = g_lingo->pop(); + warning("STUB: b_ramNeeded(%d)", d.u.i); + + g_lingo->push(Datum(0)); +} + void Lingo::b_rollOver(int nargs) { Datum d = g_lingo->pop(); - warning("STUB: b_puppetTempo(%d)", d.u.i); + warning("STUB: b_rollOver(%d)", d.u.i); g_lingo->push(Datum(0)); } @@ -975,6 +1211,18 @@ void Lingo::b_spriteBox(int nargs) { g_lingo->dropStack(nargs); } +void Lingo::b_unLoad(int nargs) { + g_lingo->printSTUBWithArglist("b_unLoad", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_unLoadCast(int nargs) { + g_lingo->printSTUBWithArglist("b_unLoadCast", nargs); + + g_lingo->dropStack(nargs); +} + void Lingo::b_zoomBox(int nargs) { g_lingo->printSTUBWithArglist("b_zoomBox", nargs); @@ -986,6 +1234,35 @@ void Lingo::b_updateStage(int nargs) { } +/////////////////// +// Window +/////////////////// + +void Lingo::b_close(int nargs) { + g_lingo->printSTUBWithArglist("b_close", nargs); + g_lingo->dropStack(nargs); +} + +void Lingo::b_forget(int nargs) { + g_lingo->printSTUBWithArglist("b_forget", nargs); + g_lingo->dropStack(nargs); +} + +void Lingo::b_inflate(int nargs) { + g_lingo->printSTUBWithArglist("b_inflate", nargs); + g_lingo->dropStack(nargs); +} + +void Lingo::b_moveToBack(int nargs) { + g_lingo->printSTUBWithArglist("b_moveToBack", nargs); + g_lingo->dropStack(nargs); +} + +void Lingo::b_moveToFront(int nargs) { + g_lingo->printSTUBWithArglist("b_moveToFront", nargs); + g_lingo->dropStack(nargs); +} + /////////////////// // Point @@ -1007,6 +1284,55 @@ void Lingo::b_point(int nargs) { g_lingo->push(d); } +void Lingo::b_rect(int nargs) { + g_lingo->printSTUBWithArglist("b_rect", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + + +void Lingo::b_intersect(int nargs) { + g_lingo->printSTUBWithArglist("b_intersect", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_inside(int nargs) { + g_lingo->printSTUBWithArglist("b_inside", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_map(int nargs) { + g_lingo->printSTUBWithArglist("b_map", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_offsetRect(int nargs) { + g_lingo->printSTUBWithArglist("b_offsetRect", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_union(int nargs) { + g_lingo->printSTUBWithArglist("b_union", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + /////////////////// // Sound @@ -1038,6 +1364,12 @@ void Lingo::b_soundBusy(int nargs) { g_lingo->dropStack(nargs); } +void Lingo::b_soundClose(int nargs) { + g_lingo->printSTUBWithArglist("b_soundClose", nargs); + + g_lingo->dropStack(nargs); +} + void Lingo::b_soundFadeIn(int nargs) { g_lingo->printSTUBWithArglist("b_soundFadeIn", nargs); @@ -1065,6 +1397,11 @@ void Lingo::b_soundStop(int nargs) { /////////////////// // Constants /////////////////// +void Lingo::b_ancestor(int nargs) { + warning("STUB: b_ancestor"); + g_lingo->push(Datum(0)); +} + void Lingo::b_backspace(int nargs) { g_lingo->push(Datum(new Common::String("\b"))); } @@ -1108,20 +1445,6 @@ void Lingo::b_factory(int nargs) { // This is intentionally empty } -// TODO: -// List of predefined methods in D3 -// mAtFrame -// mDescribe -// mDispose -// mGet -// mInstanceRespondsTo -// mMessageList -// mName -// mNew -// mPerform -// mPut -// mRespondsTo - void Lingo::factoryCall(Common::String &name, int nargs) { Common::String s("factoryCall: "); @@ -1154,6 +1477,10 @@ void Lingo::factoryCall(Common::String &name, int nargs) { /////////////////// // References /////////////////// +void Lingo::b_cast(int nargs) { + warning("STUB: b_cast"); +} + void Lingo::b_field(int nargs) { warning("STUB: b_field"); } @@ -1164,5 +1491,15 @@ void Lingo::b_me(int nargs) { g_lingo->dropStack(nargs); } +void Lingo::b_script(int nargs) { + warning("STUB: b_script"); +} + +void Lingo::b_window(int nargs) { + g_lingo->printSTUBWithArglist("b_window", nargs); + g_lingo->dropStack(nargs); + g_lingo->push(Datum(0)); +} + } // End of namespace Director diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp index 1b45359ac5..b79e51dcde 100644 --- a/engines/director/lingo/lingo-code.cpp +++ b/engines/director/lingo/lingo-code.cpp @@ -104,6 +104,7 @@ static struct FuncDescr { { Lingo::c_repeatwithcode,"c_repeatwithcode","ooooos" }, { Lingo::c_exitRepeat, "c_exitRepeat", "" }, { Lingo::c_ifcode, "c_ifcode", "oooi" }, + { Lingo::c_tellcode, "c_tellcode", "o" }, { Lingo::c_whencode, "c_whencode", "os" }, { Lingo::c_goto, "c_goto", "" }, { Lingo::c_gotoloop, "c_gotoloop", "" }, @@ -114,6 +115,7 @@ static struct FuncDescr { { Lingo::c_call, "c_call", "si" }, { Lingo::c_procret, "c_procret", "" }, { Lingo::c_global, "c_global", "s" }, + { Lingo::c_property, "c_property", "s" }, { Lingo::c_instance, "c_instance", "s" }, { Lingo::c_open, "c_open", "" }, { 0, 0, 0 } @@ -169,8 +171,8 @@ void Lingo::c_printtop(void) { if (!d.u.sym) { warning("Inconsistent stack: var, val: %d", d.u.i); } else { - if (d.u.sym->name) - warning("var: %s", d.u.sym->name); + if (!d.u.sym->name.empty()) + warning("var: %s", d.u.sym->name.c_str()); else warning("Nameless var. val: %d", d.u.sym->u.i); } @@ -304,7 +306,7 @@ void Lingo::c_assign() { if (d1.u.sym->type != INT && d1.u.sym->type != VOID && d1.u.sym->type != FLOAT && d1.u.sym->type != STRING) { - warning("assignment to non-variable '%s'", d1.u.sym->name); + warning("assignment to non-variable '%s'", d1.u.sym->name.c_str()); return; } @@ -339,14 +341,14 @@ void Lingo::c_assign() { } bool Lingo::verify(Symbol *s) { - if (s->type != INT && s->type != VOID && s->type != FLOAT && s->type != STRING && s->type != POINT) { - warning("attempt to evaluate non-variable '%s'", s->name); + if (s->type != INT && s->type != VOID && s->type != FLOAT && s->type != STRING && s->type != POINT && s->type != SYMBOL) { + warning("attempt to evaluate non-variable '%s'", s->name.c_str()); return false; } if (s->type == VOID) - warning("Variable used before assigning a value '%s'", s->name); + warning("Variable used before assigning a value '%s'", s->name.c_str()); return true; } @@ -885,8 +887,6 @@ void Lingo::c_repeatwithcode(void) { if (!g_lingo->_returning) g_lingo->_pc = end; /* next stmt */ - - delete counter; } void Lingo::c_exitRepeat(void) { @@ -946,6 +946,11 @@ void Lingo::c_whencode() { g_lingo->_pc = end; } +void Lingo::c_tellcode() { + warning("STUB: c_tellcode"); +} + + //************************ // Built-in functions //************************ @@ -1030,7 +1035,7 @@ void Lingo::call(Common::String name, int nargs) { warning("Call to undefined handler '%s'. Dropping %d stack items", name.c_str(), nargs); dropArgs = true; } else { - if (sym->type == BLTIN && sym->nargs != -1 && sym->nargs != nargs && sym->maxArgs != nargs) { + if ((sym->type == BLTIN || sym->type == FBLTIN) && sym->nargs != -1 && sym->nargs != nargs && sym->maxArgs != nargs) { if (sym->nargs == sym->maxArgs) warning("Incorrect number of arguments to handler '%s', expecting %d. Dropping %d stack items", name.c_str(), sym->nargs, nargs); else @@ -1057,7 +1062,7 @@ void Lingo::call(Common::String name, int nargs) { g_lingo->pop(); } - if (sym->type == BLTIN) { + if (sym->type == BLTIN || sym->type == FBLTIN) { if (sym->u.bltin == b_factory) g_lingo->factoryCall(name, nargs); else @@ -1130,8 +1135,14 @@ void Lingo::c_global() { s->global = true; g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str()); +} + +void Lingo::c_property() { + Common::String name((char *)&(*g_lingo->_currentScript)[g_lingo->_pc]); + + g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str()); - delete s; + warning("STUB: c_property()"); } void Lingo::c_instance() { diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp index 32d0bbbc11..95501677b7 100644 --- a/engines/director/lingo/lingo-codegen.cpp +++ b/engines/director/lingo/lingo-codegen.cpp @@ -142,7 +142,7 @@ Common::String Lingo::decodeInstruction(uint pc, uint *newPc) { } Symbol *Lingo::lookupVar(const char *name, bool create, bool putInGlobalList) { - Symbol *sym; + Symbol *sym = nullptr; // Looking for the cast member constants if (_vm->getVersion() < 4) { // TODO: There could be a flag 'Allow Outdated Lingo' in Movie Info in D4 @@ -165,17 +165,21 @@ Symbol *Lingo::lookupVar(const char *name, bool create, bool putInGlobalList) { } } - if (!_localvars->contains(name)) { // Create variable if it was not defined + if (!_localvars || !_localvars->contains(name)) { // Create variable if it was not defined + // Check if it is a global symbol + if (_globalvars.contains(name) && _globalvars[name]->type == SYMBOL) + return _globalvars[name]; + if (!create) return NULL; sym = new Symbol; - sym->name = (char *)calloc(strlen(name) + 1, 1); - Common::strlcpy(sym->name, name, strlen(name) + 1); + sym->name = name; sym->type = VOID; sym->u.i = 0; - (*_localvars)[name] = sym; + if (_localvars) + (*_localvars)[name] = sym; if (putInGlobalList) { sym->global = true; @@ -197,9 +201,7 @@ void Lingo::cleanLocalVars() { for (SymbolHash::const_iterator h = _localvars->begin(); h != _localvars->end(); ++h) { if (!h->_value->global) { - Symbol *sym = h->_value; - free(sym->name); - delete sym; + delete h->_value; } } @@ -218,11 +220,14 @@ void Lingo::define(Common::String &name, int start, int nargs, Common::String *p if (sym == NULL) { // Create variable if it was not defined sym = new Symbol; - sym->name = (char *)calloc(name.size() + 1, 1); - Common::strlcpy(sym->name, name.c_str(), name.size() + 1); + sym->name = name; sym->type = HANDLER; - _handlers[ENTITY_INDEX(_eventHandlerTypeIds[name.c_str()], _currentEntityId)] = sym; + if (!_eventHandlerTypeIds.contains(name)) { + _builtins[name] = sym; + } else { + _handlers[ENTITY_INDEX(_eventHandlerTypeIds[name.c_str()], _currentEntityId)] = sym; + } } else { //we don't want to be here. The getHandler call should have used the EntityId and the result //should have been unique! @@ -388,8 +393,7 @@ void Lingo::codeFactory(Common::String &name) { Symbol *sym = new Symbol; - sym->name = (char *)calloc(name.size() + 1, 1); - Common::strlcpy(sym->name, name.c_str(), name.size()); + sym->name = name; sym->type = BLTIN; sym->nargs = -1; sym->maxArgs = 0; diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp index ef19293d92..a6dc3f0c5e 100644 --- a/engines/director/lingo/lingo-funcs.cpp +++ b/engines/director/lingo/lingo-funcs.cpp @@ -171,6 +171,9 @@ void Lingo::func_mciwait(Common::String &s) { void Lingo::func_goto(Datum &frame, Datum &movie) { g_director->_playbackPaused = false; + if (!_vm->getCurrentScore()) + return; + if (movie.type != VOID) { movie.toString(); @@ -181,19 +184,24 @@ void Lingo::func_goto(Datum &frame, Datum &movie) { return; } - restartLingo(); + _vm->_nextMovie = *movie.u.s; + _vm->getCurrentScore()->_stopPlay = true; - delete _vm->_currentScore; + _vm->_nextMovieFrameS.clear(); + _vm->_nextMovieFrameI = -1; - Archive *mov = _vm->openMainArchive(*movie.u.s); + if (frame.type == VOID) + return; - _vm->_currentScore = new Score(_vm, mov); - debug(0, "Score name %s", _vm->_currentScore->getMacName().c_str()); - _vm->_currentScore->loadArchive(); - } + if (frame.type == STRING) { + _vm->_nextMovieFrameS = *frame.u.s; + return; + } + + frame.toInt(); + + _vm->_nextMovieFrameI = frame.u.i; - if (!_vm->_currentScore) { - warning("func_goto: No score is loaded"); return; } @@ -201,34 +209,36 @@ void Lingo::func_goto(Datum &frame, Datum &movie) { return; if (frame.type == STRING) { - _vm->_currentScore->setStartToLabel(*frame.u.s); + if (_vm->getCurrentScore()) + _vm->getCurrentScore()->setStartToLabel(*frame.u.s); return; } frame.toInt(); - _vm->_currentScore->setCurrentFrame(frame.u.i); + if (_vm->getCurrentScore()) + _vm->getCurrentScore()->setCurrentFrame(frame.u.i); } void Lingo::func_gotoloop() { - if (!_vm->_currentScore) + if (!_vm->getCurrentScore()) return; - _vm->_currentScore->gotoLoop(); + _vm->getCurrentScore()->gotoLoop(); } void Lingo::func_gotonext() { - if (!_vm->_currentScore) + if (!_vm->getCurrentScore()) return; - _vm->_currentScore->gotoNext(); + _vm->getCurrentScore()->gotoNext(); } void Lingo::func_gotoprevious() { - if (!_vm->_currentScore) + if (!_vm->getCurrentScore()) return; - _vm->_currentScore->gotoPrevious(); + _vm->getCurrentScore()->gotoPrevious(); } void Lingo::func_cursor(int c) { @@ -268,6 +278,9 @@ void Lingo::func_beep(int repeats) { } int Lingo::func_marker(int m) { + if (!_vm->getCurrentScore()) + return 0; + int labelNumber = _vm->getCurrentScore()->getCurrentLabelNumber(); if (m != 0) { if (m < 0) { diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp index 3e01ed0680..f32f171c07 100644 --- a/engines/director/lingo/lingo-gr.cpp +++ b/engines/director/lingo/lingo-gr.cpp @@ -84,66 +84,72 @@ BLTINONEARG = 273, BLTINARGLIST = 274, TWOWORDBUILTIN = 275, - ID = 276, - STRING = 277, - HANDLER = 278, - SYMBOL = 279, - ENDCLAUSE = 280, - tPLAYACCEL = 281, - tDOWN = 282, - tELSE = 283, - tNLELSIF = 284, - tEXIT = 285, - tFRAME = 286, - tGLOBAL = 287, - tGO = 288, - tIF = 289, - tINTO = 290, - tLOOP = 291, - tMACRO = 292, - tMOVIE = 293, - tNEXT = 294, - tOF = 295, - tPREVIOUS = 296, - tPUT = 297, - tREPEAT = 298, - tSET = 299, - tTHEN = 300, - tTO = 301, - tWHEN = 302, - tWITH = 303, - tWHILE = 304, - tNLELSE = 305, - tFACTORY = 306, - tMETHOD = 307, - tOPEN = 308, - tPLAY = 309, - tDONE = 310, - tINSTANCE = 311, - tGE = 312, - tLE = 313, - tGT = 314, - tLT = 315, - tEQ = 316, - tNEQ = 317, - tAND = 318, - tOR = 319, - tNOT = 320, - tMOD = 321, - tAFTER = 322, - tBEFORE = 323, - tCONCAT = 324, - tCONTAINS = 325, - tSTARTS = 326, - tCHAR = 327, - tITEM = 328, - tLINE = 329, - tWORD = 330, - tSPRITE = 331, - tINTERSECTS = 332, - tWITHIN = 333, - tON = 334, - tME = 335 + FBLTIN = 276, + FBLTINNOARGS = 277, + FBLTINONEARG = 278, + FBLTINARGLIST = 279, + ID = 280, + STRING = 281, + HANDLER = 282, + SYMBOL = 283, + ENDCLAUSE = 284, + tPLAYACCEL = 285, + tDOWN = 286, + tELSE = 287, + tNLELSIF = 288, + tEXIT = 289, + tFRAME = 290, + tGLOBAL = 291, + tGO = 292, + tIF = 293, + tINTO = 294, + tLOOP = 295, + tMACRO = 296, + tMOVIE = 297, + tNEXT = 298, + tOF = 299, + tPREVIOUS = 300, + tPUT = 301, + tREPEAT = 302, + tSET = 303, + tTHEN = 304, + tTO = 305, + tWHEN = 306, + tWITH = 307, + tWHILE = 308, + tNLELSE = 309, + tFACTORY = 310, + tMETHOD = 311, + tOPEN = 312, + tPLAY = 313, + tDONE = 314, + tINSTANCE = 315, + tGE = 316, + tLE = 317, + tGT = 318, + tLT = 319, + tEQ = 320, + tNEQ = 321, + tAND = 322, + tOR = 323, + tNOT = 324, + tMOD = 325, + tAFTER = 326, + tBEFORE = 327, + tCONCAT = 328, + tCONTAINS = 329, + tSTARTS = 330, + tCHAR = 331, + tITEM = 332, + tLINE = 333, + tWORD = 334, + tSPRITE = 335, + tINTERSECTS = 336, + tWITHIN = 337, + tTELL = 338, + tPROPERTY = 339, + tON = 340, + tME = 341 }; #endif /* Tokens. */ @@ -165,66 +171,72 @@ #define BLTINONEARG 273 #define BLTINARGLIST 274 #define TWOWORDBUILTIN 275 -#define ID 276 -#define STRING 277 -#define HANDLER 278 -#define SYMBOL 279 -#define ENDCLAUSE 280 -#define tPLAYACCEL 281 -#define tDOWN 282 -#define tELSE 283 -#define tNLELSIF 284 -#define tEXIT 285 -#define tFRAME 286 -#define tGLOBAL 287 -#define tGO 288 -#define tIF 289 -#define tINTO 290 -#define tLOOP 291 -#define tMACRO 292 -#define tMOVIE 293 -#define tNEXT 294 -#define tOF 295 -#define tPREVIOUS 296 -#define tPUT 297 -#define tREPEAT 298 -#define tSET 299 -#define tTHEN 300 -#define tTO 301 -#define tWHEN 302 -#define tWITH 303 -#define tWHILE 304 -#define tNLELSE 305 -#define tFACTORY 306 -#define tMETHOD 307 -#define tOPEN 308 -#define tPLAY 309 -#define tDONE 310 -#define tINSTANCE 311 -#define tGE 312 -#define tLE 313 -#define tGT 314 -#define tLT 315 -#define tEQ 316 -#define tNEQ 317 -#define tAND 318 -#define tOR 319 -#define tNOT 320 -#define tMOD 321 -#define tAFTER 322 -#define tBEFORE 323 -#define tCONCAT 324 -#define tCONTAINS 325 -#define tSTARTS 326 -#define tCHAR 327 -#define tITEM 328 -#define tLINE 329 -#define tWORD 330 -#define tSPRITE 331 -#define tINTERSECTS 332 -#define tWITHIN 333 -#define tON 334 -#define tME 335 +#define FBLTIN 276 +#define FBLTINNOARGS 277 +#define FBLTINONEARG 278 +#define FBLTINARGLIST 279 +#define ID 280 +#define STRING 281 +#define HANDLER 282 +#define SYMBOL 283 +#define ENDCLAUSE 284 +#define tPLAYACCEL 285 +#define tDOWN 286 +#define tELSE 287 +#define tNLELSIF 288 +#define tEXIT 289 +#define tFRAME 290 +#define tGLOBAL 291 +#define tGO 292 +#define tIF 293 +#define tINTO 294 +#define tLOOP 295 +#define tMACRO 296 +#define tMOVIE 297 +#define tNEXT 298 +#define tOF 299 +#define tPREVIOUS 300 +#define tPUT 301 +#define tREPEAT 302 +#define tSET 303 +#define tTHEN 304 +#define tTO 305 +#define tWHEN 306 +#define tWITH 307 +#define tWHILE 308 +#define tNLELSE 309 +#define tFACTORY 310 +#define tMETHOD 311 +#define tOPEN 312 +#define tPLAY 313 +#define tDONE 314 +#define tINSTANCE 315 +#define tGE 316 +#define tLE 317 +#define tGT 318 +#define tLT 319 +#define tEQ 320 +#define tNEQ 321 +#define tAND 322 +#define tOR 323 +#define tNOT 324 +#define tMOD 325 +#define tAFTER 326 +#define tBEFORE 327 +#define tCONCAT 328 +#define tCONTAINS 329 +#define tSTARTS 330 +#define tCHAR 331 +#define tITEM 332 +#define tLINE 333 +#define tWORD 334 +#define tSPRITE 335 +#define tINTERSECTS 336 +#define tWITHIN 337 +#define tTELL 338 +#define tPROPERTY 339 +#define tON 340 +#define tME 341 @@ -292,7 +304,7 @@ typedef union YYSTYPE Common::Array<double> *arr; } /* Line 193 of yacc.c. */ -#line 296 "engines/director/lingo/lingo-gr.cpp" +#line 308 "engines/director/lingo/lingo-gr.cpp" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -305,7 +317,7 @@ typedef union YYSTYPE /* Line 216 of yacc.c. */ -#line 309 "engines/director/lingo/lingo-gr.cpp" +#line 321 "engines/director/lingo/lingo-gr.cpp" #ifdef short # undef short @@ -518,22 +530,22 @@ union yyalloc #endif /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 113 +#define YYFINAL 123 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 1633 +#define YYLAST 1818 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 96 +#define YYNTOKENS 102 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 41 +#define YYNNTS 43 /* YYNRULES -- Number of rules. */ -#define YYNRULES 151 +#define YYNRULES 161 /* YYNRULES -- Number of states. */ -#define YYNSTATES 333 +#define YYNSTATES 355 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 335 +#define YYMAXUTOK 341 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -542,15 +554,15 @@ union yyalloc static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 88, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 94, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 87, 82, 2, - 89, 90, 85, 83, 95, 84, 2, 86, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 93, 88, 2, + 95, 96, 91, 89, 101, 90, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 92, 81, 91, 2, 2, 2, 2, 2, 2, 2, + 98, 87, 97, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 93, 2, 94, 2, 2, 2, 2, 2, 2, + 2, 99, 2, 100, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -574,7 +586,8 @@ static const yytype_uint8 yytranslate[] = 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80 + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86 }; #if YYDEBUG @@ -584,105 +597,110 @@ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 7, 9, 12, 14, 15, 17, 19, 21, 26, 31, 36, 41, 46, 52, 57, 62, 68, - 70, 72, 74, 76, 84, 95, 107, 111, 119, 130, - 141, 148, 159, 170, 171, 175, 178, 180, 183, 185, - 192, 194, 201, 203, 207, 211, 214, 218, 220, 222, - 223, 224, 225, 228, 231, 235, 237, 239, 241, 243, - 245, 250, 252, 254, 257, 259, 263, 267, 271, 275, - 279, 283, 287, 291, 295, 299, 303, 307, 310, 314, - 318, 322, 326, 329, 332, 336, 340, 345, 350, 355, - 362, 367, 374, 379, 386, 391, 398, 401, 403, 405, - 408, 410, 413, 416, 419, 422, 424, 429, 432, 437, - 444, 449, 452, 456, 458, 462, 464, 468, 471, 474, - 477, 480, 484, 487, 490, 492, 496, 499, 502, 505, - 509, 512, 513, 517, 518, 527, 530, 531, 540, 541, - 542, 553, 554, 556, 560, 565, 566, 569, 570, 572, - 576, 578 + 70, 72, 74, 76, 84, 95, 107, 111, 118, 123, + 131, 142, 153, 160, 171, 182, 183, 187, 190, 192, + 195, 197, 204, 206, 213, 215, 219, 223, 226, 230, + 232, 234, 235, 236, 237, 240, 243, 247, 249, 251, + 253, 255, 257, 259, 262, 265, 270, 275, 277, 279, + 282, 284, 288, 292, 296, 300, 304, 308, 312, 316, + 320, 324, 328, 332, 335, 339, 343, 347, 351, 354, + 357, 361, 365, 370, 375, 380, 387, 392, 399, 404, + 411, 416, 423, 426, 428, 430, 433, 435, 438, 441, + 444, 446, 449, 452, 454, 457, 462, 467, 474, 479, + 482, 486, 488, 492, 494, 498, 500, 504, 507, 510, + 513, 516, 520, 523, 526, 528, 532, 535, 538, 541, + 545, 548, 549, 553, 554, 563, 566, 567, 576, 577, + 578, 589, 590, 592, 596, 601, 602, 605, 606, 608, + 612, 614 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { - 97, 0, -1, 97, 98, 99, -1, 99, -1, 1, - 98, -1, 88, -1, -1, 127, -1, 134, -1, 102, - -1, 42, 118, 35, 21, -1, 42, 118, 67, 118, - -1, 42, 118, 68, 118, -1, 44, 21, 81, 118, - -1, 44, 12, 81, 118, -1, 44, 13, 118, 81, - 118, -1, 44, 21, 46, 118, -1, 44, 12, 46, - 118, -1, 44, 13, 118, 46, 118, -1, 118, -1, - 119, -1, 101, -1, 103, -1, 110, 89, 109, 90, - 116, 115, 25, -1, 111, 81, 118, 115, 46, 118, - 115, 116, 115, 25, -1, 111, 81, 118, 115, 27, - 46, 118, 115, 116, 115, 25, -1, 117, 118, 115, - -1, 112, 109, 45, 98, 116, 115, 25, -1, 112, - 109, 45, 98, 116, 115, 50, 116, 115, 25, -1, - 112, 109, 45, 98, 116, 115, 114, 105, 115, 25, - -1, 112, 109, 45, 114, 101, 115, -1, 112, 109, - 45, 114, 101, 115, 50, 114, 101, 115, -1, 112, - 109, 45, 114, 101, 115, 106, 115, 104, 115, -1, - -1, 50, 114, 101, -1, 105, 108, -1, 108, -1, - 106, 107, -1, 107, -1, 113, 109, 45, 114, 102, - 115, -1, 106, -1, 113, 109, 45, 114, 116, 115, - -1, 118, -1, 118, 81, 118, -1, 89, 109, 90, - -1, 43, 49, -1, 43, 48, 21, -1, 34, -1, - 29, -1, -1, -1, -1, 116, 98, -1, 116, 102, - -1, 47, 21, 45, -1, 11, -1, 14, -1, 24, - -1, 22, -1, 16, -1, 21, 89, 135, 90, -1, - 21, -1, 12, -1, 13, 118, -1, 100, -1, 118, - 83, 118, -1, 118, 84, 118, -1, 118, 85, 118, - -1, 118, 86, 118, -1, 118, 66, 118, -1, 118, - 91, 118, -1, 118, 92, 118, -1, 118, 62, 118, - -1, 118, 57, 118, -1, 118, 58, 118, -1, 118, - 63, 118, -1, 118, 64, 118, -1, 65, 118, -1, - 118, 82, 118, -1, 118, 69, 118, -1, 118, 70, - 118, -1, 118, 71, 118, -1, 83, 118, -1, 84, - 118, -1, 89, 118, 90, -1, 93, 135, 94, -1, - 76, 118, 77, 118, -1, 76, 118, 78, 118, -1, - 72, 118, 40, 118, -1, 72, 118, 46, 118, 40, - 118, -1, 73, 118, 40, 118, -1, 73, 118, 46, - 118, 40, 118, -1, 74, 118, 40, 118, -1, 74, - 118, 46, 118, 40, 118, -1, 75, 118, 40, 118, - -1, 75, 118, 46, 118, 40, 118, -1, 42, 118, - -1, 122, -1, 125, -1, 30, 43, -1, 30, -1, - 32, 120, -1, 56, 121, -1, 18, 118, -1, 17, - 118, -1, 17, -1, 19, 89, 135, 90, -1, 19, - 135, -1, 80, 89, 21, 90, -1, 80, 89, 21, - 95, 135, 90, -1, 53, 118, 48, 118, -1, 53, - 118, -1, 20, 21, 135, -1, 21, -1, 120, 95, - 21, -1, 21, -1, 121, 95, 21, -1, 33, 36, - -1, 33, 39, -1, 33, 41, -1, 33, 123, -1, - 33, 123, 124, -1, 33, 124, -1, 31, 118, -1, - 118, -1, 40, 38, 118, -1, 38, 118, -1, 54, - 55, -1, 54, 123, -1, 54, 123, 124, -1, 54, - 124, -1, -1, 26, 126, 135, -1, -1, 37, 21, - 128, 114, 132, 98, 133, 116, -1, 51, 21, -1, - -1, 52, 21, 129, 114, 132, 98, 133, 116, -1, - -1, -1, 79, 21, 130, 114, 131, 132, 98, 133, - 116, 25, -1, -1, 21, -1, 132, 95, 21, -1, - 132, 98, 95, 21, -1, -1, 21, 136, -1, -1, - 118, -1, 135, 95, 118, -1, 118, -1, 135, 95, - 118, -1 + 103, 0, -1, 103, 104, 105, -1, 105, -1, 1, + 104, -1, 94, -1, -1, 135, -1, 142, -1, 108, + -1, 46, 125, 39, 25, -1, 46, 125, 71, 125, + -1, 46, 125, 72, 125, -1, 48, 25, 87, 125, + -1, 48, 12, 87, 125, -1, 48, 13, 125, 87, + 125, -1, 48, 25, 50, 125, -1, 48, 12, 50, + 125, -1, 48, 13, 125, 50, 125, -1, 125, -1, + 126, -1, 107, -1, 109, -1, 116, 95, 115, 96, + 122, 121, 29, -1, 117, 87, 125, 121, 50, 125, + 121, 122, 121, 29, -1, 117, 87, 125, 121, 31, + 50, 125, 121, 122, 121, 29, -1, 123, 107, 121, + -1, 124, 125, 104, 122, 121, 29, -1, 124, 125, + 50, 125, -1, 118, 115, 49, 104, 122, 121, 29, + -1, 118, 115, 49, 104, 122, 121, 54, 122, 121, + 29, -1, 118, 115, 49, 104, 122, 121, 120, 111, + 121, 29, -1, 118, 115, 49, 120, 107, 121, -1, + 118, 115, 49, 120, 107, 121, 54, 120, 107, 121, + -1, 118, 115, 49, 120, 107, 121, 112, 121, 110, + 121, -1, -1, 54, 120, 107, -1, 111, 114, -1, + 114, -1, 112, 113, -1, 113, -1, 119, 115, 49, + 120, 108, 121, -1, 112, -1, 119, 115, 49, 120, + 122, 121, -1, 125, -1, 125, 87, 125, -1, 95, + 115, 96, -1, 47, 53, -1, 47, 52, 25, -1, + 38, -1, 33, -1, -1, -1, -1, 122, 104, -1, + 122, 108, -1, 51, 25, 49, -1, 83, -1, 11, + -1, 14, -1, 28, -1, 26, -1, 22, -1, 23, + 125, -1, 24, 144, -1, 24, 95, 144, 96, -1, + 25, 95, 143, 96, -1, 25, -1, 12, -1, 13, + 125, -1, 106, -1, 125, 89, 125, -1, 125, 90, + 125, -1, 125, 91, 125, -1, 125, 92, 125, -1, + 125, 70, 125, -1, 125, 97, 125, -1, 125, 98, + 125, -1, 125, 66, 125, -1, 125, 61, 125, -1, + 125, 62, 125, -1, 125, 67, 125, -1, 125, 68, + 125, -1, 69, 125, -1, 125, 88, 125, -1, 125, + 73, 125, -1, 125, 74, 125, -1, 125, 75, 125, + -1, 89, 125, -1, 90, 125, -1, 95, 125, 96, + -1, 99, 143, 100, -1, 80, 125, 81, 125, -1, + 80, 125, 82, 125, -1, 76, 125, 44, 125, -1, + 76, 125, 50, 125, 44, 125, -1, 77, 125, 44, + 125, -1, 77, 125, 50, 125, 44, 125, -1, 78, + 125, 44, 125, -1, 78, 125, 50, 125, 44, 125, + -1, 79, 125, 44, 125, -1, 79, 125, 50, 125, + 44, 125, -1, 46, 125, -1, 130, -1, 133, -1, + 34, 47, -1, 34, -1, 36, 127, -1, 84, 128, + -1, 60, 129, -1, 16, -1, 18, 125, -1, 17, + 125, -1, 17, -1, 19, 144, -1, 19, 95, 144, + 96, -1, 86, 95, 25, 96, -1, 86, 95, 25, + 101, 143, 96, -1, 57, 125, 52, 125, -1, 57, + 125, -1, 20, 25, 143, -1, 25, -1, 127, 101, + 25, -1, 25, -1, 128, 101, 25, -1, 25, -1, + 129, 101, 25, -1, 37, 40, -1, 37, 43, -1, + 37, 45, -1, 37, 131, -1, 37, 131, 132, -1, + 37, 132, -1, 35, 125, -1, 125, -1, 44, 42, + 125, -1, 42, 125, -1, 58, 59, -1, 58, 131, + -1, 58, 131, 132, -1, 58, 132, -1, -1, 30, + 134, 143, -1, -1, 41, 25, 136, 120, 140, 104, + 141, 122, -1, 55, 25, -1, -1, 56, 25, 137, + 120, 140, 104, 141, 122, -1, -1, -1, 85, 25, + 138, 120, 139, 140, 104, 141, 122, 29, -1, -1, + 25, -1, 140, 101, 25, -1, 140, 104, 101, 25, + -1, -1, 25, 144, -1, -1, 125, -1, 143, 101, + 125, -1, 125, -1, 144, 101, 125, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 117, 117, 118, 119, 122, 127, 128, 129, 130, - 133, 139, 140, 141, 147, 155, 163, 169, 177, 187, - 188, 191, 192, 197, 210, 228, 242, 250, 260, 272, - 284, 294, 304, 316, 317, 320, 321, 324, 325, 328, - 336, 337, 345, 346, 347, 350, 353, 360, 367, 375, - 378, 381, 382, 383, 386, 392, 393, 396, 399, 402, - 405, 408, 412, 419, 425, 426, 427, 428, 429, 430, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, + 0, 118, 118, 119, 120, 123, 128, 129, 130, 131, + 134, 140, 141, 142, 148, 156, 164, 170, 178, 188, + 189, 192, 193, 198, 211, 229, 243, 249, 252, 257, + 267, 279, 291, 301, 311, 323, 324, 327, 328, 331, + 332, 335, 343, 344, 352, 353, 354, 357, 360, 367, + 374, 382, 385, 388, 389, 390, 393, 399, 403, 404, + 407, 410, 413, 416, 419, 420, 421, 424, 428, 435, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, - 451, 452, 453, 454, 455, 456, 459, 460, 461, 462, - 463, 465, 466, 467, 470, 473, 476, 477, 478, 479, - 480, 481, 482, 485, 486, 489, 490, 501, 502, 503, - 504, 507, 510, 515, 516, 519, 520, 523, 524, 527, - 530, 533, 533, 563, 563, 569, 572, 572, 577, 578, - 577, 588, 589, 590, 591, 594, 598, 606, 607, 608, - 611, 612 + 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 475, 476, 477, 478, 479, 481, 482, 483, + 484, 487, 490, 493, 497, 498, 499, 500, 501, 502, + 503, 506, 507, 510, 511, 514, 515, 526, 527, 528, + 529, 532, 535, 540, 541, 544, 545, 548, 549, 552, + 555, 558, 558, 588, 588, 594, 597, 597, 602, 603, + 602, 613, 614, 615, 616, 619, 623, 631, 632, 633, + 636, 637 }; #endif @@ -694,7 +712,8 @@ static const char *const yytname[] = "$end", "error", "$undefined", "UNARY", "CASTREF", "VOID", "VAR", "POINT", "RECT", "ARRAY", "OBJECT", "INT", "THEENTITY", "THEENTITYWITHID", "FLOAT", "BLTIN", "BLTINNOARGS", "BLTINNOARGSORONE", - "BLTINONEARG", "BLTINARGLIST", "TWOWORDBUILTIN", "ID", "STRING", + "BLTINONEARG", "BLTINARGLIST", "TWOWORDBUILTIN", "FBLTIN", + "FBLTINNOARGS", "FBLTINONEARG", "FBLTINARGLIST", "ID", "STRING", "HANDLER", "SYMBOL", "ENDCLAUSE", "tPLAYACCEL", "tDOWN", "tELSE", "tNLELSIF", "tEXIT", "tFRAME", "tGLOBAL", "tGO", "tIF", "tINTO", "tLOOP", "tMACRO", "tMOVIE", "tNEXT", "tOF", "tPREVIOUS", "tPUT", "tREPEAT", @@ -702,16 +721,16 @@ static const char *const yytname[] = "tFACTORY", "tMETHOD", "tOPEN", "tPLAY", "tDONE", "tINSTANCE", "tGE", "tLE", "tGT", "tLT", "tEQ", "tNEQ", "tAND", "tOR", "tNOT", "tMOD", "tAFTER", "tBEFORE", "tCONCAT", "tCONTAINS", "tSTARTS", "tCHAR", "tITEM", - "tLINE", "tWORD", "tSPRITE", "tINTERSECTS", "tWITHIN", "tON", "tME", - "'='", "'&'", "'+'", "'-'", "'*'", "'/'", "'%'", "'\\n'", "'('", "')'", - "'>'", "'<'", "'['", "']'", "','", "$accept", "program", "nl", - "programline", "asgn", "stmtoneliner", "stmt", "ifstmt", - "elsestmtoneliner", "elseifstmt", "elseifstmtoneliner", + "tLINE", "tWORD", "tSPRITE", "tINTERSECTS", "tWITHIN", "tTELL", + "tPROPERTY", "tON", "tME", "'='", "'&'", "'+'", "'-'", "'*'", "'/'", + "'%'", "'\\n'", "'('", "')'", "'>'", "'<'", "'['", "']'", "','", + "$accept", "program", "nl", "programline", "asgn", "stmtoneliner", + "stmt", "ifstmt", "elsestmtoneliner", "elseifstmt", "elseifstmtoneliner", "elseifstmtoneliner1", "elseifstmt1", "cond", "repeatwhile", - "repeatwith", "if", "elseif", "begin", "end", "stmtlist", "when", "expr", - "func", "globallist", "instancelist", "gotofunc", "gotoframe", - "gotomovie", "playfunc", "@1", "defn", "@2", "@3", "@4", "@5", "argdef", - "argstore", "macro", "arglist", "nonemptyarglist", 0 + "repeatwith", "if", "elseif", "begin", "end", "stmtlist", "when", "tell", + "expr", "proc", "globallist", "propertylist", "instancelist", "gotofunc", + "gotoframe", "gotomovie", "playfunc", "@1", "defn", "@2", "@3", "@4", + "@5", "argdef", "argstore", "macro", "arglist", "nonemptyarglist", 0 }; #endif @@ -728,30 +747,32 @@ static const yytype_uint16 yytoknum[] = 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 61, 38, 43, 45, 42, 47, 37, 10, 40, - 41, 62, 60, 91, 93, 44 + 335, 336, 337, 338, 339, 340, 341, 61, 38, 43, + 45, 42, 47, 37, 10, 40, 41, 62, 60, 91, + 93, 44 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 96, 97, 97, 97, 98, 99, 99, 99, 99, - 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, - 101, 102, 102, 102, 102, 102, 102, 103, 103, 103, - 103, 103, 103, 104, 104, 105, 105, 106, 106, 107, - 108, 108, 109, 109, 109, 110, 111, 112, 113, 114, - 115, 116, 116, 116, 117, 118, 118, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 120, 120, 121, 121, 122, 122, 122, - 122, 122, 122, 123, 123, 124, 124, 125, 125, 125, - 125, 126, 125, 128, 127, 127, 129, 127, 130, 131, - 127, 132, 132, 132, 132, 133, 134, 135, 135, 135, - 136, 136 + 0, 102, 103, 103, 103, 104, 105, 105, 105, 105, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, + 107, 108, 108, 108, 108, 108, 108, 108, 108, 109, + 109, 109, 109, 109, 109, 110, 110, 111, 111, 112, + 112, 113, 114, 114, 115, 115, 115, 116, 117, 118, + 119, 120, 121, 122, 122, 122, 123, 124, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 127, 127, 128, 128, 129, 129, 130, 130, 130, + 130, 130, 130, 131, 131, 132, 132, 133, 133, 133, + 133, 134, 133, 136, 135, 135, 137, 135, 138, 139, + 135, 140, 140, 140, 140, 141, 142, 143, 143, 143, + 144, 144 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -759,16 +780,17 @@ static const yytype_uint8 yyr2[] = { 0, 2, 3, 1, 2, 1, 0, 1, 1, 1, 4, 4, 4, 4, 4, 5, 4, 4, 5, 1, - 1, 1, 1, 7, 10, 11, 3, 7, 10, 10, - 6, 10, 10, 0, 3, 2, 1, 2, 1, 6, - 1, 6, 1, 3, 3, 2, 3, 1, 1, 0, - 0, 0, 2, 2, 3, 1, 1, 1, 1, 1, - 4, 1, 1, 2, 1, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, - 3, 3, 2, 2, 3, 3, 4, 4, 4, 6, - 4, 6, 4, 6, 4, 6, 2, 1, 1, 2, - 1, 2, 2, 2, 2, 1, 4, 2, 4, 6, - 4, 2, 3, 1, 3, 1, 3, 2, 2, 2, + 1, 1, 1, 7, 10, 11, 3, 6, 4, 7, + 10, 10, 6, 10, 10, 0, 3, 2, 1, 2, + 1, 6, 1, 6, 1, 3, 3, 2, 3, 1, + 1, 0, 0, 0, 2, 2, 3, 1, 1, 1, + 1, 1, 1, 2, 2, 4, 4, 1, 1, 2, + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 2, 3, 3, 3, 3, 2, 2, + 3, 3, 4, 4, 4, 6, 4, 6, 4, 6, + 4, 6, 2, 1, 1, 2, 1, 2, 2, 2, + 1, 2, 2, 1, 2, 4, 4, 6, 4, 2, + 3, 1, 3, 1, 3, 1, 3, 2, 2, 2, 2, 3, 2, 2, 1, 3, 2, 2, 2, 3, 2, 0, 3, 0, 8, 2, 0, 8, 0, 0, 10, 0, 1, 3, 4, 0, 2, 0, 1, 3, @@ -780,442 +802,482 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 0, 55, 62, 0, 56, 59, 105, 0, 147, - 0, 61, 58, 57, 131, 100, 0, 0, 47, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 147, 0, 3, 64, 21, 9, 22, 0, 0, 0, - 0, 19, 20, 97, 98, 7, 8, 5, 4, 61, - 0, 63, 104, 103, 147, 148, 107, 147, 147, 150, - 0, 146, 147, 99, 113, 101, 0, 117, 0, 118, - 0, 119, 124, 120, 122, 133, 96, 0, 45, 0, - 0, 0, 0, 135, 136, 111, 127, 128, 130, 115, - 102, 77, 0, 0, 0, 0, 0, 138, 0, 82, - 83, 0, 0, 1, 6, 0, 0, 0, 0, 42, - 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 147, 0, 148, - 0, 0, 112, 0, 0, 132, 0, 123, 126, 0, - 121, 49, 0, 0, 0, 46, 0, 0, 0, 0, - 0, 54, 49, 0, 129, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 49, 0, 84, 85, - 2, 0, 50, 0, 0, 49, 0, 26, 73, 74, - 72, 75, 76, 69, 79, 80, 81, 78, 65, 66, - 67, 68, 70, 71, 106, 149, 60, 151, 114, 125, - 141, 10, 11, 12, 17, 14, 0, 0, 16, 13, - 141, 110, 116, 88, 0, 90, 0, 92, 0, 94, - 0, 86, 87, 139, 108, 147, 51, 0, 44, 51, - 0, 43, 142, 0, 18, 15, 0, 0, 0, 0, - 0, 141, 0, 50, 0, 0, 50, 50, 0, 145, - 145, 89, 91, 93, 95, 0, 109, 52, 53, 0, - 0, 50, 49, 30, 143, 0, 51, 51, 145, 23, - 50, 51, 27, 51, 0, 48, 49, 50, 38, 0, - 144, 134, 137, 51, 51, 50, 50, 50, 40, 36, - 0, 0, 37, 33, 0, 0, 50, 0, 0, 35, - 0, 0, 50, 49, 50, 49, 140, 0, 24, 28, - 29, 49, 31, 0, 32, 0, 25, 51, 34, 50, - 50, 39, 41 + 0, 0, 58, 68, 0, 59, 110, 113, 0, 0, + 0, 62, 0, 0, 67, 61, 60, 141, 106, 0, + 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, + 0, 0, 0, 0, 0, 157, 0, 3, 70, 21, + 9, 22, 0, 0, 0, 0, 0, 19, 20, 103, + 104, 7, 8, 5, 4, 67, 0, 69, 112, 111, + 0, 160, 114, 157, 63, 0, 64, 157, 156, 157, + 105, 121, 107, 0, 127, 0, 128, 0, 129, 134, + 130, 132, 143, 102, 0, 47, 0, 0, 0, 0, + 145, 146, 119, 137, 138, 140, 125, 109, 83, 0, + 0, 0, 0, 0, 123, 108, 148, 0, 88, 89, + 0, 158, 0, 1, 6, 0, 0, 0, 0, 44, + 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 157, 0, + 160, 0, 0, 120, 0, 158, 0, 142, 0, 133, + 136, 0, 131, 51, 0, 0, 0, 48, 0, 0, + 0, 0, 0, 56, 51, 0, 139, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, + 0, 90, 91, 0, 2, 0, 52, 0, 0, 51, + 0, 26, 0, 53, 79, 80, 78, 81, 82, 75, + 85, 86, 87, 84, 71, 72, 73, 74, 76, 77, + 115, 161, 65, 66, 122, 135, 151, 10, 11, 12, + 17, 14, 0, 0, 16, 13, 151, 118, 126, 94, + 0, 96, 0, 98, 0, 100, 0, 92, 93, 124, + 149, 116, 157, 159, 53, 0, 46, 53, 0, 45, + 28, 52, 152, 0, 18, 15, 0, 0, 0, 0, + 0, 151, 0, 52, 0, 0, 52, 52, 54, 55, + 0, 0, 155, 155, 95, 97, 99, 101, 0, 117, + 0, 0, 52, 51, 32, 27, 153, 0, 53, 53, + 155, 23, 52, 53, 29, 53, 0, 50, 51, 52, + 40, 0, 154, 144, 147, 53, 53, 52, 52, 52, + 42, 38, 0, 0, 39, 35, 0, 0, 52, 0, + 0, 37, 0, 0, 52, 51, 52, 51, 150, 0, + 24, 30, 31, 51, 33, 0, 34, 0, 25, 53, + 36, 52, 52, 41, 43 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 41, 267, 42, 43, 44, 268, 46, 314, 297, - 298, 288, 299, 118, 47, 48, 49, 289, 210, 187, - 253, 50, 51, 52, 75, 100, 53, 83, 84, 54, - 72, 55, 151, 162, 176, 251, 243, 276, 56, 143, - 71 + -1, 46, 278, 47, 48, 49, 279, 51, 336, 319, + 320, 310, 321, 128, 52, 53, 54, 311, 226, 201, + 261, 55, 56, 57, 58, 82, 115, 107, 59, 90, + 91, 60, 79, 61, 163, 174, 189, 271, 263, 298, + 62, 156, 72 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -240 +#define YYPACT_NINF -272 static const yytype_int16 yypact[] = { - 286, -64, -240, -240, 961, -240, -240, 961, 961, 1027, - 35, 369, -240, -240, -240, 53, 67, 860, -240, 77, - 961, -26, 45, 80, 81, 82, 961, 926, 83, 961, - 961, 961, 961, 961, 961, 84, 18, 961, 961, 961, - 961, 2, -240, -240, -240, -240, -240, 19, 25, 1052, - 961, 1541, -240, -240, -240, -240, -240, -240, -240, 22, - 961, 1541, 1541, 1541, 961, 1541, 20, 961, 961, 1345, - 24, -240, 961, -240, -240, 26, 961, -240, 961, -240, - 74, -240, 1541, 36, -240, -240, 142, 92, -240, -39, - 961, -32, 75, -240, -240, 1314, -240, 36, -240, -240, - 46, -66, 338, 1091, 1123, 1155, 1417, -240, 119, -66, - -66, 1479, -9, -240, 454, 1052, 961, 1052, 99, 1510, - 1541, 961, 961, 961, 961, 961, 961, 961, 961, 961, - 961, 961, 961, 961, 961, 961, 961, 961, 142, 1479, - -12, 961, 20, -8, 961, 20, 125, 1541, 1541, 961, - -240, -240, 126, 961, 961, -240, 961, 961, 763, 961, - 961, -240, -240, 961, -240, 128, 961, 961, 961, 961, - 961, 961, 961, 961, 961, 961, -240, -1, -240, -240, - -240, 61, 1541, 62, 1448, -64, 961, -240, 823, 823, - 823, -66, -66, -66, 1541, 823, 823, 1021, 129, 129, - -66, -66, 1541, 1541, -240, 1541, -240, 1381, -240, 1541, - 135, -240, 1541, 1541, 1541, 1541, 961, 961, 1541, 1541, - 135, 1541, -240, 1541, 1187, 1541, 1219, 1541, 1251, 1541, - 1283, 1541, 1541, -240, -240, 961, -240, 17, -240, -240, - 786, 1541, -240, -24, 1541, 1541, -24, 961, 961, 961, - 961, 135, 5, 620, 113, 961, 620, -240, 141, 68, - 68, 1541, 1541, 1541, 1541, -24, -240, -240, -240, 140, - 961, 1541, -5, -13, -240, 145, -240, -240, 68, -240, - 1541, -240, -240, -240, 150, -240, -240, 150, -240, 1052, - -240, 620, 620, -240, -240, 620, 620, 150, 150, -240, - 1052, 786, -240, 131, 138, 537, 620, 159, 160, -240, - 161, 146, -240, -240, -240, -240, -240, 165, -240, -240, - -240, -240, -240, 786, -240, 703, -240, 703, -240, -240, - 620, -240, -240 + 339, -52, -272, -272, 962, -272, -272, 962, 962, 1000, + 37, -272, 962, 1059, 1097, -272, -272, -272, 34, 66, + 864, -272, 72, 962, 41, 57, 77, 81, 90, 962, + 903, 97, 962, 962, 962, 962, 962, 962, -272, 98, + 100, -41, 962, 962, 962, 962, 2, -272, -272, -272, + -272, -272, 36, -21, 1156, 784, 962, 1720, -272, -272, + -272, -272, -272, -272, -272, 59, 962, 1720, 1720, 1720, + 962, 1720, 31, 962, 1720, 962, 31, 962, 31, 962, + -272, -272, 51, 962, -272, 962, -272, 113, -272, 1720, + 43, -272, -272, 1191, 131, -272, -47, 962, -39, 108, + -272, -272, 1555, -272, 43, -272, -272, 58, -48, 1224, + 1257, 1290, 1323, 1588, -272, 60, -272, 133, -48, -48, + 1654, 1720, 29, -272, 428, 1156, 962, 1156, 111, 1687, + -272, 1488, 962, 962, 962, 962, 962, 962, 962, 962, + 962, 962, 962, 962, 962, 962, 962, 962, 962, 1191, + 1654, -73, 962, 62, -69, 1654, 7, 62, 139, 1720, + 1720, 962, -272, -272, 140, 962, 962, -272, 962, 962, + 1522, 962, 962, -272, -272, 962, -272, 143, 962, 962, + 962, 962, 962, 962, 962, 962, 962, 962, 146, -272, + 8, -272, -272, 962, -272, 78, 1720, 79, 1621, -52, + 962, -272, 962, -272, 22, 22, 22, -48, -48, -48, + 1720, 22, 22, 147, 238, 238, -48, -48, 1720, 1720, + -272, 1720, -272, -272, -272, 1720, 164, -272, 1720, 1720, + 1720, 1720, 962, 962, 1720, 1720, 164, 1720, -272, 1720, + 1356, 1720, 1389, 1720, 1422, 1720, 1455, 1720, 1720, -272, + -272, -272, 962, 1720, -272, -9, -272, -272, 784, 1720, + 1720, 606, -272, -22, 1720, 1720, -22, 962, 962, 962, + 962, 164, 20, 606, 141, 962, 606, -272, -272, -272, + 161, 168, 94, 94, 1720, 1720, 1720, 1720, -22, -272, + 167, 962, 1720, -3, 6, -272, -272, 172, -272, -272, + 94, -272, 1720, -272, -272, -272, 165, -272, -272, 165, + -272, 1156, -272, 606, 606, -272, -272, 606, 606, 165, + 165, -272, 1156, 784, -272, 145, 151, 517, 606, 175, + 176, -272, 177, 159, -272, -272, -272, -272, -272, 180, + -272, -272, -272, -272, -272, 784, -272, 695, -272, 695, + -272, -272, 606, -272, -272 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -240, -240, 12, 87, -240, -239, 0, -240, -240, -240, - -79, -228, -101, -111, -240, -240, -240, -237, -133, -34, - -184, -240, 1, -240, -240, -240, -240, 175, -16, -240, - -240, -240, -240, -240, -240, -240, -205, -224, -240, 8, - -240 + -272, -272, 19, 86, -272, -51, 0, -272, -272, -272, + -83, -221, -107, -109, -272, -272, -272, -242, -116, -18, + -198, -272, -272, 1, -272, -272, -272, -272, -272, 186, + -29, -272, -272, -272, -272, -272, -272, -272, -219, -271, + -272, -26, -7 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -150 +#define YYTABLE_NINF -7 static const yytype_int16 yytable[] = { - 45, 257, 113, 127, 181, 61, 183, 156, 62, 63, - 65, 98, 69, 58, 159, 246, 285, 66, 82, 70, - 282, 86, 87, 88, 57, 135, 136, 95, 82, 220, - 101, 102, 103, 104, 105, 106, 277, 286, 109, 110, - 111, 65, 157, 233, 254, 283, 265, 300, 112, 160, - 119, 120, 240, 114, 293, 256, 67, 89, 90, 302, - 300, 138, 312, 255, 57, 139, 91, 150, 65, 139, - 302, 258, 140, 65, 78, 142, 80, 147, 204, 148, - 145, 164, 206, 141, 328, 179, 141, 141, 74, 234, - 57, 158, 291, 292, 235, 266, 73, 295, 85, 296, - 141, 92, 93, 94, 99, 107, 116, 108, 115, 305, - 306, 137, 149, 155, 45, 141, 119, 182, 184, 144, - 161, 146, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 65, 284, - 177, 165, 205, 330, 185, 207, 208, 211, 237, 222, - 209, 236, 238, 301, 212, 213, 242, 214, 215, 270, - 218, 219, 274, 275, 221, 279, 290, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 152, 304, 285, - 323, 313, 325, 315, 318, 319, 320, 241, 327, 311, - 326, 321, 124, 125, 287, 126, 309, 239, 127, 121, - 122, 180, 97, 0, 123, 124, 125, 0, 126, 153, - 154, 127, 128, 129, 133, 134, 0, 244, 245, 269, - 135, 136, 272, 273, 130, 131, 132, 133, 134, 0, - 0, 0, 0, 135, 136, 0, 65, 281, 0, 0, - 0, 0, 0, 252, 0, 0, 294, 0, 261, 262, - 263, 264, 0, 303, 0, 259, 271, 0, 260, 0, - 0, 307, 308, 310, 0, 0, 0, 0, 0, 0, - 0, 280, 317, 0, 0, 0, 0, 278, 322, 0, - 324, 0, 0, 0, 0, 0, -6, 1, 0, 0, - 119, 0, 0, 0, 0, 331, 332, 2, 3, 4, - 5, 119, 6, 7, 8, 9, 10, 11, 12, 0, - 13, 0, 14, 0, 0, 0, 15, 0, 16, 17, - 18, 0, 0, 19, 0, 329, 0, 329, 20, 21, - 22, 0, 0, 23, 0, 0, 0, 24, 25, 26, - 27, 0, 28, 0, 0, 0, 0, 0, 0, 0, - 0, 29, 0, 0, 0, 0, 0, 0, 30, 31, - 32, 33, 34, 0, 0, 35, 36, 0, 0, 37, - 38, 0, 0, 0, -6, 39, 0, 0, 166, 40, - 2, 3, 4, 5, 167, 6, 0, 0, 0, 0, - 59, 12, 0, 13, 0, 121, 122, 0, 0, 0, - 123, 124, 125, 0, 126, 0, 0, 127, 128, 129, - 0, 60, 0, 22, 0, 0, 0, 0, 0, 0, - 130, 131, 132, 133, 134, 0, 0, 0, 0, 135, - 136, 0, 0, 0, 29, 0, 0, 0, 0, 0, - 0, 30, 31, 32, 33, 34, 0, 0, 0, 0, - 0, 0, 37, 38, 0, 0, 0, 0, 68, 0, - 0, 0, 40, 0, -147, 2, 3, 4, 5, 0, - 6, 7, 8, 9, 10, 11, 12, 0, 13, 0, - 14, 0, 0, 0, 15, 0, 16, 17, 18, 0, - 0, 19, 0, 0, 0, 0, 20, 21, 22, 0, - 0, 23, 0, 0, 0, 24, 25, 26, 27, 0, - 28, 0, 0, 0, 0, 0, 0, 0, 0, 29, - 0, 0, 0, 0, 0, 0, 30, 31, 32, 33, - 34, 0, 0, 35, 36, 0, 0, 37, 38, 0, - 0, 0, 0, 39, 0, 0, 0, 40, 2, 3, - 4, 5, 0, 6, 7, 8, 9, 10, 59, 12, - 0, 13, 316, 14, 0, 0, 0, 15, 0, 16, - 17, 18, 0, 0, 0, 0, 0, 0, 0, 20, - 21, 22, 0, 0, 23, 0, 0, 0, 0, 0, - 26, 27, 0, 28, 0, 0, 0, 0, 0, 0, - 0, 0, 29, 0, 0, 0, 0, 0, 0, 30, - 31, 32, 33, 34, 0, 0, 0, 36, 0, 0, - 37, 38, 0, 0, 0, 57, 39, 0, 0, 0, - 40, 2, 3, 4, 5, 0, 6, 7, 8, 9, - 10, 59, 12, 0, 13, 0, 14, 0, 0, 0, - 15, 0, 16, 17, 18, 0, 0, 0, 0, 0, - 0, 0, 20, 21, 22, 0, 0, 23, 0, 0, - 0, 0, 0, 26, 27, 0, 28, 0, 0, 0, - 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, - 0, 0, 30, 31, 32, 33, 34, 0, 0, 0, - 36, 0, 0, 37, 38, 0, 0, 0, 57, 39, - 0, 0, 0, 40, 2, 3, 4, 5, 0, 6, - 7, 8, 9, 10, 59, 12, 0, 13, 0, 14, - 0, 0, 0, 15, 0, 16, 17, 18, 0, 0, - 0, 0, 0, 0, 0, 20, 21, 22, 0, 0, - 23, 0, 0, 0, 0, 0, 26, 27, 0, 28, - 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, - 0, 0, 0, 0, 0, 30, 31, 32, 33, 34, - 0, 0, 0, 36, 0, 0, 37, 38, 0, 0, - 0, 0, 39, 0, 0, 0, 40, 2, 3, 4, - 5, 0, 6, 7, 8, 9, 10, 59, 12, 216, - 13, 0, 14, 0, 0, 0, 15, 0, 16, 17, - 121, 122, 0, 0, 0, 123, 124, 125, 20, 126, - 22, 0, 127, 128, 129, 0, 0, 0, 0, 26, - 27, 0, 28, 0, 217, 130, 131, 132, 133, 134, - 0, 29, 0, 0, 135, 136, 0, 0, 30, 31, - 32, 33, 34, 0, 0, 0, 36, 0, 0, 37, - 38, 2, 3, 4, 5, 39, 6, 0, 0, 40, - 0, 59, 12, 0, 13, 0, 124, 125, 0, 126, - 0, 76, 127, 0, 0, 0, 77, 0, 78, 79, - 80, 81, 60, 0, 22, 130, 131, 132, 133, 134, - 0, 0, 0, 0, 135, 136, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, - 0, 0, 30, 31, 32, 33, 34, 2, 3, 4, - 5, 0, 6, 37, 38, 0, 0, 59, 12, 39, - 13, 0, 0, 40, 0, 0, 0, 76, 0, 0, - 0, 0, 0, 0, 78, 0, 80, 0, 60, 0, - 22, 0, 2, 3, 4, 5, 0, 6, 0, 0, - 0, 96, 59, 12, 0, 13, 0, 0, 0, 0, - 0, 29, 0, 0, 0, 0, 0, 0, 30, 31, - 32, 33, 34, 60, 0, 22, 0, 0, 0, 37, - 38, 0, 0, 0, 0, 39, 0, 0, 0, 40, - 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, - 0, 0, 0, 30, 31, 32, 33, 34, 2, 3, - 4, 5, 0, 6, 37, 38, 0, 0, 59, 12, - 39, 13, 0, 0, 40, 0, 0, 0, 0, 0, - 0, 0, 0, 2, 3, 4, 5, 0, 6, 60, - 0, 22, 0, 59, 12, 0, 13, 0, 0, 0, - 0, 0, 0, 0, 124, 125, 0, 126, 0, 0, - 127, 0, 29, 0, 60, 0, 22, 0, 0, 30, - 31, 32, 33, 34, 131, 132, 133, 134, 0, 0, - 37, 38, 135, 136, 0, 0, 64, 29, 0, 0, - 40, 0, 0, 0, 30, 31, 32, 33, 34, 0, - 0, 168, 0, 0, 0, 37, 38, 169, 0, 0, - 0, 117, 0, 0, 0, 40, 0, 0, 121, 122, - 0, 0, 0, 123, 124, 125, 0, 126, 0, 0, - 127, 128, 129, 170, 0, 0, 0, 0, 0, 171, - 0, 0, 0, 130, 131, 132, 133, 134, 0, 0, - 121, 122, 135, 136, 0, 123, 124, 125, 0, 126, - 0, 0, 127, 128, 129, 172, 0, 0, 0, 0, - 0, 173, 0, 0, 0, 130, 131, 132, 133, 134, - 0, 0, 121, 122, 135, 136, 0, 123, 124, 125, - 0, 126, 0, 0, 127, 128, 129, 247, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 130, 131, 132, - 133, 134, 0, 0, 121, 122, 135, 136, 0, 123, - 124, 125, 0, 126, 0, 0, 127, 128, 129, 248, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, - 131, 132, 133, 134, 0, 0, 121, 122, 135, 136, - 0, 123, 124, 125, 0, 126, 0, 0, 127, 128, - 129, 249, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 130, 131, 132, 133, 134, 0, 0, 121, 122, - 135, 136, 0, 123, 124, 125, 0, 126, 0, 0, - 127, 128, 129, 250, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 130, 131, 132, 133, 134, 0, 0, - 121, 122, 135, 136, 0, 123, 124, 125, 0, 126, - 0, 0, 127, 128, 129, 0, 0, 0, 0, 0, - 0, 0, 163, 0, 0, 130, 131, 132, 133, 134, - 0, 121, 122, 0, 135, 136, 123, 124, 125, 0, - 126, 0, 0, 127, 128, 129, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 130, 131, 132, 133, - 134, 0, 121, 122, 0, 135, 136, 123, 124, 125, - 0, 126, 0, 0, 127, 128, 129, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 130, 131, 132, - 133, 134, 0, 0, 0, 0, 135, 136, 121, 122, - -148, 0, 0, 123, 124, 125, 0, 126, 0, 0, - 127, 128, 129, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 130, 131, 132, 133, 134, 0, 0, - 0, 0, 135, 136, 121, 122, -149, 0, 0, 123, - 124, 125, 0, 126, 0, 0, 127, 128, 129, 0, - 0, 0, 0, 0, 174, 175, 0, 0, 0, 130, - 131, 132, 133, 134, 0, 121, 122, 0, 135, 136, - 123, 124, 125, 0, 126, 0, 0, 127, 128, 129, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, - 130, 131, 132, 133, 134, 0, 121, 122, 178, 135, - 136, 123, 124, 125, 0, 126, 0, 0, 127, 128, - 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 130, 131, 132, 133, 134, 0, 121, 122, 178, - 135, 136, 123, 124, 125, 0, 126, 0, 0, 127, - 128, 129, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 186, 130, 131, 132, 133, 134, 0, 121, 122, - 0, 135, 136, 123, 124, 125, 0, 126, 0, 0, - 127, 128, 129, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 130, 131, 132, 133, 134, 0, 0, - 0, 0, 135, 136 + 50, 105, 123, 168, 130, 67, 76, 78, 68, 69, + 71, 171, 299, 74, 71, 71, 195, 266, 197, 122, + 64, 89, 274, 220, 93, 138, 304, 222, 152, 315, + 102, 89, 152, 108, 109, 110, 111, 112, 113, 307, + 169, 275, 63, 118, 119, 120, 121, 153, 172, 146, + 147, 305, 288, 157, 117, 129, 273, 131, 236, 276, + 308, 162, 73, 151, 322, 124, 126, 149, 154, 96, + 97, 150, 63, 250, 121, 176, 150, 322, 155, 281, + 121, 80, 98, 258, 159, 85, 160, 87, 324, 135, + 136, 81, 137, 94, 95, 138, 63, 92, 170, 324, + 313, 314, 99, 223, 251, 317, 100, 318, 193, 252, + 141, 142, 143, 144, 145, 101, 289, 327, 328, 146, + 147, 193, 106, 114, 50, 116, 129, 196, 198, 192, + 193, 125, 152, 204, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 121, + 203, 352, 158, 221, 148, 161, 167, 173, 190, 177, + 199, 188, 225, 193, 224, 227, 228, 229, 238, 230, + 231, 249, 234, 235, 254, 256, 237, 306, 255, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 262, + 295, 291, 323, 296, 253, 297, 301, 312, 307, 335, + 337, 259, 326, 260, 340, 341, 342, 277, 343, 348, + 194, 309, 331, 333, 135, 136, 104, 137, 257, 345, + 138, 347, 0, 0, 0, 0, 272, 349, 0, 0, + 0, 0, 0, 264, 265, 0, 142, 143, 144, 145, + 0, 0, 0, 280, 146, 147, 0, 0, 0, 0, + 0, 0, 0, 121, 0, 290, 0, 0, 293, 294, + 0, 0, 0, 0, 0, 0, 0, 0, 284, 285, + 286, 287, 334, 0, 303, 0, 292, 0, 0, 0, + 0, 0, 282, 0, 316, 283, 0, 0, 0, 0, + 0, 325, 302, 0, 350, 0, 0, 0, 0, 329, + 330, 332, 0, 0, 0, 135, 136, 300, 137, 0, + 339, 138, 129, 0, 0, 0, 344, 0, 346, 0, + 0, 0, 0, 129, 0, 0, 0, 0, 0, 144, + 145, 0, 0, 353, 354, 146, 147, 0, 0, -6, + 1, 0, 0, 0, 0, 0, 0, 351, 0, 351, + 2, 3, 4, 5, 0, 6, 7, 8, 9, 10, + 0, 11, 12, 13, 14, 15, 0, 16, 0, 17, + 0, 0, 0, 18, 0, 19, 20, 21, 0, 0, + 22, 0, 0, 0, 0, 23, 24, 25, 0, 0, + 26, 0, 0, 0, 27, 28, 29, 30, 0, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 33, 34, 35, 36, 37, + 0, 0, 38, 39, 40, 41, 0, 0, 42, 43, + 0, 0, 0, -6, 44, 0, 0, 0, 45, 2, + 3, 4, 5, 0, 6, 7, 8, 9, 10, 0, + 11, 12, 13, 14, 15, 0, 16, 0, 17, 0, + 0, 0, 18, 0, 19, 20, 21, 0, 0, 22, + 0, 0, 0, 0, 23, 24, 25, 0, 0, 26, + 0, 0, 0, 27, 28, 29, 30, 0, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, + 0, 0, 0, 0, 33, 34, 35, 36, 37, 0, + 0, 38, 39, 40, 41, 0, 0, 42, 43, 0, + 0, 0, 0, 44, 0, 0, 0, 45, 2, 3, + 4, 5, 0, 6, 7, 8, 9, 10, 0, 11, + 12, 13, 65, 15, 0, 16, 338, 17, 0, 0, + 0, 18, 0, 19, 20, 21, 0, 0, 0, 0, + 0, 0, 0, 23, 24, 25, 0, 0, 26, 0, + 0, 0, 0, 0, 29, 30, 0, 31, 0, 0, + 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, + 0, 0, 0, 33, 34, 35, 36, 37, 0, 0, + 38, 39, 0, 41, 0, 0, 42, 43, 0, 0, + 0, 63, 44, 0, 0, 0, 45, 2, 3, 4, + 5, 0, 6, 7, 8, 9, 10, 0, 11, 12, + 13, 65, 15, 0, 16, 0, 17, 0, 0, 0, + 18, 0, 19, 20, 21, 0, 0, 0, 0, 0, + 0, 0, 23, 24, 25, 0, 0, 26, 0, 0, + 0, 0, 0, 29, 30, 0, 31, 0, 0, 0, + 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, + 0, 0, 33, 34, 35, 36, 37, 0, 0, 38, + 39, 0, 41, 0, 0, 42, 43, 0, 0, 0, + 63, 44, 0, 0, 0, 45, 2, 3, 4, 5, + 0, 6, 7, 8, 9, 10, 0, 11, 12, 13, + 65, 15, 0, 16, 0, 17, 0, 0, 0, 18, + 0, 19, 20, 21, 0, 0, 0, 0, 0, 0, + 0, 23, 24, 25, 0, 0, 26, 0, 0, 0, + 0, 0, 29, 30, 0, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, + 0, 33, 34, 35, 36, 37, 0, 0, 38, 39, + 0, 41, 0, 0, 42, 43, 0, 0, 0, 0, + 44, 0, 0, 0, 45, 2, 3, 4, 5, 0, + 6, 7, 8, 9, 10, 0, 11, 12, 13, 65, + 15, 0, 16, 0, 17, 0, 0, 0, 18, 0, + 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, + 23, 0, 25, 0, 0, 0, 0, 0, 0, 0, + 0, 29, 30, 0, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, + 33, 34, 35, 36, 37, 0, 0, 0, 39, 0, + 41, 0, 0, 42, 43, 2, 3, 4, 5, 44, + 0, 0, 0, 45, 0, 0, 11, 12, 13, 65, + 15, 0, 16, 0, 0, 0, 0, 0, 0, 83, + 0, 0, 0, 0, 84, 0, 85, 86, 87, 88, + 66, 0, 25, 0, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 11, 12, 13, 65, 15, + 0, 16, 0, 32, 0, 0, 0, 0, 83, 0, + 33, 34, 35, 36, 37, 85, 0, 87, 0, 66, + 0, 25, 0, 42, 43, 0, 0, 0, 0, 44, + 0, 0, 103, 45, 0, 0, 0, 0, 0, 0, + 0, 0, 32, 2, 3, 4, 5, 0, 0, 33, + 34, 35, 36, 37, 11, 12, 13, 65, 15, 0, + 16, 0, 42, 43, 0, 0, 0, 0, 44, 0, + 0, 0, 45, 0, 0, 0, 0, 0, 66, 0, + 25, 2, 3, 4, 5, 0, 0, 0, 0, 0, + 0, 0, 11, 12, 13, 65, 15, 0, 16, 0, + 0, 32, 0, 0, 0, 0, 0, 0, 33, 34, + 35, 36, 37, 0, 0, 0, 66, 0, 25, 0, + 0, 42, 43, 0, 0, 0, 0, 44, 0, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 0, 32, + 2, 3, 4, 5, 0, 0, 33, 34, 35, 36, + 37, 11, 12, 13, 65, 15, 0, 16, 0, 42, + 43, 0, 0, 0, 0, 70, 0, 0, 0, 45, + 0, 0, 0, 0, 0, 66, 0, 25, 2, 3, + 4, 5, 0, 0, 0, 0, 0, 0, 0, 11, + 12, 13, 65, 15, 0, 16, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 33, 34, 35, 36, 37, + 0, 0, 0, 66, 0, 25, 0, 0, 42, 43, + 0, 0, 0, 0, 75, 0, 0, 0, 45, 0, + 0, 0, 0, 0, 0, 0, 32, 2, 3, 4, + 5, 0, 0, 33, 34, 35, 36, 37, 11, 12, + 13, 65, 15, 0, 16, 0, 42, 43, 0, 0, + 0, 0, 77, 0, 0, 0, 45, 0, 0, 0, + 0, 0, 66, 0, 25, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, + 164, 0, 33, 34, 35, 36, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 42, 43, 0, 0, 0, + 0, 127, 132, 133, 0, 45, 0, 134, 135, 136, + 0, 137, 165, 166, 138, 139, 140, 0, 178, 0, + 0, 0, 0, 0, 179, 0, 0, 0, 0, 141, + 142, 143, 144, 145, 0, 132, 133, 0, 146, 147, + 134, 135, 136, 0, 137, 0, 0, 138, 139, 140, + 0, 180, 0, 0, 0, 0, 0, 181, 0, 0, + 0, 0, 141, 142, 143, 144, 145, 0, 132, 133, + 0, 146, 147, 134, 135, 136, 0, 137, 0, 0, + 138, 139, 140, 0, 182, 0, 0, 0, 0, 0, + 183, 0, 0, 0, 0, 141, 142, 143, 144, 145, + 0, 132, 133, 0, 146, 147, 134, 135, 136, 0, + 137, 0, 0, 138, 139, 140, 0, 184, 0, 0, + 0, 0, 0, 185, 0, 0, 0, 0, 141, 142, + 143, 144, 145, 0, 132, 133, 0, 146, 147, 134, + 135, 136, 0, 137, 0, 0, 138, 139, 140, 0, + 267, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 141, 142, 143, 144, 145, 0, 132, 133, 0, + 146, 147, 134, 135, 136, 0, 137, 0, 0, 138, + 139, 140, 0, 268, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 142, 143, 144, 145, 0, + 132, 133, 0, 146, 147, 134, 135, 136, 0, 137, + 0, 0, 138, 139, 140, 0, 269, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 141, 142, 143, + 144, 145, 0, 132, 133, 0, 146, 147, 134, 135, + 136, 0, 137, 0, 0, 138, 139, 140, 0, 270, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 141, 142, 143, 144, 145, 0, 132, 133, 0, 146, + 147, 134, 135, 136, 0, 137, 0, 0, 138, 139, + 140, 0, 0, 0, 0, 0, 0, 0, 202, 0, + 0, 0, 0, 141, 142, 143, 144, 145, 0, 132, + 133, 0, 146, 147, 134, 135, 136, 0, 137, 0, + 0, 138, 139, 140, 0, 0, 0, 0, 0, 0, + 0, 0, 232, 0, 0, 0, 141, 142, 143, 144, + 145, 0, 63, 132, 133, 146, 147, 0, 134, 135, + 136, 0, 137, 0, 0, 138, 139, 140, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 175, 0, 233, + 141, 142, 143, 144, 145, 0, 132, 133, 0, 146, + 147, 134, 135, 136, 0, 137, 0, 0, 138, 139, + 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 141, 142, 143, 144, 145, 0, 132, + 133, 0, 146, 147, 134, 135, 136, 0, 137, 0, + 0, 138, 139, 140, 0, 0, 0, 0, 0, 186, + 187, 0, 0, 0, 0, 0, 141, 142, 143, 144, + 145, 0, 132, 133, 0, 146, 147, 134, 135, 136, + 0, 137, 0, 0, 138, 139, 140, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 200, 141, + 142, 143, 144, 145, 0, 132, 133, 191, 146, 147, + 134, 135, 136, 0, 137, 0, 0, 138, 139, 140, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 141, 142, 143, 144, 145, 0, 132, 133, + 191, 146, 147, 134, 135, 136, 0, 137, 0, 0, + 138, 139, 140, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 200, 141, 142, 143, 144, 145, + 0, 132, 133, 0, 146, 147, 134, 135, 136, 0, + 137, 0, 0, 138, 139, 140, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 141, 142, + 143, 144, 145, 0, 0, 0, 0, 146, 147 }; static const yytype_int16 yycheck[] = { - 0, 240, 0, 69, 115, 4, 117, 46, 7, 8, - 9, 27, 11, 1, 46, 220, 29, 9, 17, 11, - 25, 20, 48, 49, 88, 91, 92, 26, 27, 162, - 29, 30, 31, 32, 33, 34, 260, 50, 37, 38, - 39, 40, 81, 176, 27, 50, 251, 284, 40, 81, - 49, 50, 185, 41, 278, 239, 21, 12, 13, 287, - 297, 60, 301, 46, 88, 64, 21, 83, 67, 68, - 298, 95, 64, 72, 38, 67, 40, 76, 90, 78, - 72, 97, 90, 95, 323, 94, 95, 95, 21, 90, - 88, 90, 276, 277, 95, 90, 43, 281, 21, 283, - 95, 21, 21, 21, 21, 21, 81, 89, 89, 293, - 294, 89, 38, 21, 114, 95, 115, 116, 117, 95, - 45, 95, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 272, - 21, 95, 141, 327, 45, 144, 21, 21, 182, 21, - 149, 90, 90, 286, 153, 154, 21, 156, 157, 46, - 159, 160, 21, 95, 163, 25, 21, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 35, 289, 29, - 313, 50, 315, 45, 25, 25, 25, 186, 321, 300, - 25, 45, 63, 64, 273, 66, 297, 185, 69, 57, - 58, 114, 27, -1, 62, 63, 64, -1, 66, 67, - 68, 69, 70, 71, 85, 86, -1, 216, 217, 253, - 91, 92, 256, 257, 82, 83, 84, 85, 86, -1, - -1, -1, -1, 91, 92, -1, 235, 271, -1, -1, - -1, -1, -1, 235, -1, -1, 280, -1, 247, 248, - 249, 250, -1, 287, -1, 243, 255, -1, 246, -1, - -1, 295, 296, 297, -1, -1, -1, -1, -1, -1, - -1, 270, 306, -1, -1, -1, -1, 265, 312, -1, - 314, -1, -1, -1, -1, -1, 0, 1, -1, -1, - 289, -1, -1, -1, -1, 329, 330, 11, 12, 13, - 14, 300, 16, 17, 18, 19, 20, 21, 22, -1, - 24, -1, 26, -1, -1, -1, 30, -1, 32, 33, - 34, -1, -1, 37, -1, 325, -1, 327, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, 52, 53, - 54, -1, 56, -1, -1, -1, -1, -1, -1, -1, - -1, 65, -1, -1, -1, -1, -1, -1, 72, 73, - 74, 75, 76, -1, -1, 79, 80, -1, -1, 83, - 84, -1, -1, -1, 88, 89, -1, -1, 40, 93, - 11, 12, 13, 14, 46, 16, -1, -1, -1, -1, - 21, 22, -1, 24, -1, 57, 58, -1, -1, -1, - 62, 63, 64, -1, 66, -1, -1, 69, 70, 71, - -1, 42, -1, 44, -1, -1, -1, -1, -1, -1, - 82, 83, 84, 85, 86, -1, -1, -1, -1, 91, - 92, -1, -1, -1, 65, -1, -1, -1, -1, -1, - -1, 72, 73, 74, 75, 76, -1, -1, -1, -1, - -1, -1, 83, 84, -1, -1, -1, -1, 89, -1, - -1, -1, 93, -1, 95, 11, 12, 13, 14, -1, - 16, 17, 18, 19, 20, 21, 22, -1, 24, -1, - 26, -1, -1, -1, 30, -1, 32, 33, 34, -1, - -1, 37, -1, -1, -1, -1, 42, 43, 44, -1, - -1, 47, -1, -1, -1, 51, 52, 53, 54, -1, - 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, - -1, -1, -1, -1, -1, -1, 72, 73, 74, 75, - 76, -1, -1, 79, 80, -1, -1, 83, 84, -1, - -1, -1, -1, 89, -1, -1, -1, 93, 11, 12, - 13, 14, -1, 16, 17, 18, 19, 20, 21, 22, - -1, 24, 25, 26, -1, -1, -1, 30, -1, 32, - 33, 34, -1, -1, -1, -1, -1, -1, -1, 42, - 43, 44, -1, -1, 47, -1, -1, -1, -1, -1, - 53, 54, -1, 56, -1, -1, -1, -1, -1, -1, - -1, -1, 65, -1, -1, -1, -1, -1, -1, 72, - 73, 74, 75, 76, -1, -1, -1, 80, -1, -1, - 83, 84, -1, -1, -1, 88, 89, -1, -1, -1, - 93, 11, 12, 13, 14, -1, 16, 17, 18, 19, - 20, 21, 22, -1, 24, -1, 26, -1, -1, -1, - 30, -1, 32, 33, 34, -1, -1, -1, -1, -1, - -1, -1, 42, 43, 44, -1, -1, 47, -1, -1, - -1, -1, -1, 53, 54, -1, 56, -1, -1, -1, - -1, -1, -1, -1, -1, 65, -1, -1, -1, -1, - -1, -1, 72, 73, 74, 75, 76, -1, -1, -1, - 80, -1, -1, 83, 84, -1, -1, -1, 88, 89, - -1, -1, -1, 93, 11, 12, 13, 14, -1, 16, - 17, 18, 19, 20, 21, 22, -1, 24, -1, 26, - -1, -1, -1, 30, -1, 32, 33, 34, -1, -1, - -1, -1, -1, -1, -1, 42, 43, 44, -1, -1, - 47, -1, -1, -1, -1, -1, 53, 54, -1, 56, - -1, -1, -1, -1, -1, -1, -1, -1, 65, -1, - -1, -1, -1, -1, -1, 72, 73, 74, 75, 76, - -1, -1, -1, 80, -1, -1, 83, 84, -1, -1, - -1, -1, 89, -1, -1, -1, 93, 11, 12, 13, - 14, -1, 16, 17, 18, 19, 20, 21, 22, 46, - 24, -1, 26, -1, -1, -1, 30, -1, 32, 33, - 57, 58, -1, -1, -1, 62, 63, 64, 42, 66, - 44, -1, 69, 70, 71, -1, -1, -1, -1, 53, - 54, -1, 56, -1, 81, 82, 83, 84, 85, 86, - -1, 65, -1, -1, 91, 92, -1, -1, 72, 73, - 74, 75, 76, -1, -1, -1, 80, -1, -1, 83, - 84, 11, 12, 13, 14, 89, 16, -1, -1, 93, - -1, 21, 22, -1, 24, -1, 63, 64, -1, 66, - -1, 31, 69, -1, -1, -1, 36, -1, 38, 39, - 40, 41, 42, -1, 44, 82, 83, 84, 85, 86, - -1, -1, -1, -1, 91, 92, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 65, -1, -1, -1, -1, - -1, -1, 72, 73, 74, 75, 76, 11, 12, 13, - 14, -1, 16, 83, 84, -1, -1, 21, 22, 89, - 24, -1, -1, 93, -1, -1, -1, 31, -1, -1, - -1, -1, -1, -1, 38, -1, 40, -1, 42, -1, - 44, -1, 11, 12, 13, 14, -1, 16, -1, -1, - -1, 55, 21, 22, -1, 24, -1, -1, -1, -1, - -1, 65, -1, -1, -1, -1, -1, -1, 72, 73, - 74, 75, 76, 42, -1, 44, -1, -1, -1, 83, - 84, -1, -1, -1, -1, 89, -1, -1, -1, 93, - -1, -1, -1, -1, -1, -1, 65, -1, -1, -1, - -1, -1, -1, 72, 73, 74, 75, 76, 11, 12, - 13, 14, -1, 16, 83, 84, -1, -1, 21, 22, - 89, 24, -1, -1, 93, -1, -1, -1, -1, -1, - -1, -1, -1, 11, 12, 13, 14, -1, 16, 42, - -1, 44, -1, 21, 22, -1, 24, -1, -1, -1, - -1, -1, -1, -1, 63, 64, -1, 66, -1, -1, - 69, -1, 65, -1, 42, -1, 44, -1, -1, 72, - 73, 74, 75, 76, 83, 84, 85, 86, -1, -1, - 83, 84, 91, 92, -1, -1, 89, 65, -1, -1, - 93, -1, -1, -1, 72, 73, 74, 75, 76, -1, - -1, 40, -1, -1, -1, 83, 84, 46, -1, -1, - -1, 89, -1, -1, -1, 93, -1, -1, 57, 58, - -1, -1, -1, 62, 63, 64, -1, 66, -1, -1, - 69, 70, 71, 40, -1, -1, -1, -1, -1, 46, - -1, -1, -1, 82, 83, 84, 85, 86, -1, -1, - 57, 58, 91, 92, -1, 62, 63, 64, -1, 66, - -1, -1, 69, 70, 71, 40, -1, -1, -1, -1, - -1, 46, -1, -1, -1, 82, 83, 84, 85, 86, - -1, -1, 57, 58, 91, 92, -1, 62, 63, 64, - -1, 66, -1, -1, 69, 70, 71, 40, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 82, 83, 84, - 85, 86, -1, -1, 57, 58, 91, 92, -1, 62, - 63, 64, -1, 66, -1, -1, 69, 70, 71, 40, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, - 83, 84, 85, 86, -1, -1, 57, 58, 91, 92, - -1, 62, 63, 64, -1, 66, -1, -1, 69, 70, - 71, 40, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 82, 83, 84, 85, 86, -1, -1, 57, 58, - 91, 92, -1, 62, 63, 64, -1, 66, -1, -1, - 69, 70, 71, 40, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 82, 83, 84, 85, 86, -1, -1, - 57, 58, 91, 92, -1, 62, 63, 64, -1, 66, - -1, -1, 69, 70, 71, -1, -1, -1, -1, -1, - -1, -1, 48, -1, -1, 82, 83, 84, 85, 86, - -1, 57, 58, -1, 91, 92, 62, 63, 64, -1, - 66, -1, -1, 69, 70, 71, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 82, 83, 84, 85, - 86, -1, 57, 58, -1, 91, 92, 62, 63, 64, - -1, 66, -1, -1, 69, 70, 71, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 82, 83, 84, - 85, 86, -1, -1, -1, -1, 91, 92, 57, 58, - 95, -1, -1, 62, 63, 64, -1, 66, -1, -1, - 69, 70, 71, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 82, 83, 84, 85, 86, -1, -1, - -1, -1, 91, 92, 57, 58, 95, -1, -1, 62, - 63, 64, -1, 66, -1, -1, 69, 70, 71, -1, - -1, -1, -1, -1, 77, 78, -1, -1, -1, 82, - 83, 84, 85, 86, -1, 57, 58, -1, 91, 92, - 62, 63, 64, -1, 66, -1, -1, 69, 70, 71, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, - 82, 83, 84, 85, 86, -1, 57, 58, 90, 91, - 92, 62, 63, 64, -1, 66, -1, -1, 69, 70, - 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 82, 83, 84, 85, 86, -1, 57, 58, 90, - 91, 92, 62, 63, 64, -1, 66, -1, -1, 69, - 70, 71, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 81, 82, 83, 84, 85, 86, -1, 57, 58, - -1, 91, 92, 62, 63, 64, -1, 66, -1, -1, - 69, 70, 71, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 82, 83, 84, 85, 86, -1, -1, - -1, -1, 91, 92 + 0, 30, 0, 50, 55, 4, 13, 14, 7, 8, + 9, 50, 283, 12, 13, 14, 125, 236, 127, 45, + 1, 20, 31, 96, 23, 73, 29, 96, 101, 300, + 29, 30, 101, 32, 33, 34, 35, 36, 37, 33, + 87, 50, 94, 42, 43, 44, 45, 73, 87, 97, + 98, 54, 271, 79, 95, 54, 254, 56, 174, 257, + 54, 90, 25, 70, 306, 46, 87, 66, 75, 12, + 13, 70, 94, 189, 73, 104, 75, 319, 77, 101, + 79, 47, 25, 199, 83, 42, 85, 44, 309, 67, + 68, 25, 70, 52, 53, 73, 94, 25, 97, 320, + 298, 299, 25, 96, 96, 303, 25, 305, 101, 101, + 88, 89, 90, 91, 92, 25, 96, 315, 316, 97, + 98, 101, 25, 25, 124, 25, 125, 126, 127, 100, + 101, 95, 101, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 131, 349, 101, 152, 95, 42, 25, 49, 25, 101, + 49, 101, 161, 101, 25, 25, 165, 166, 25, 168, + 169, 25, 171, 172, 96, 96, 175, 293, 196, 178, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 25, + 29, 50, 308, 25, 193, 101, 29, 25, 33, 54, + 49, 200, 311, 202, 29, 29, 29, 258, 49, 29, + 124, 294, 319, 322, 67, 68, 30, 70, 199, 335, + 73, 337, -1, -1, -1, -1, 252, 343, -1, -1, + -1, -1, -1, 232, 233, -1, 89, 90, 91, 92, + -1, -1, -1, 261, 97, 98, -1, -1, -1, -1, + -1, -1, -1, 252, -1, 273, -1, -1, 276, 277, + -1, -1, -1, -1, -1, -1, -1, -1, 267, 268, + 269, 270, 323, -1, 292, -1, 275, -1, -1, -1, + -1, -1, 263, -1, 302, 266, -1, -1, -1, -1, + -1, 309, 291, -1, 345, -1, -1, -1, -1, 317, + 318, 319, -1, -1, -1, 67, 68, 288, 70, -1, + 328, 73, 311, -1, -1, -1, 334, -1, 336, -1, + -1, -1, -1, 322, -1, -1, -1, -1, -1, 91, + 92, -1, -1, 351, 352, 97, 98, -1, -1, 0, + 1, -1, -1, -1, -1, -1, -1, 347, -1, 349, + 11, 12, 13, 14, -1, 16, 17, 18, 19, 20, + -1, 22, 23, 24, 25, 26, -1, 28, -1, 30, + -1, -1, -1, 34, -1, 36, 37, 38, -1, -1, + 41, -1, -1, -1, -1, 46, 47, 48, -1, -1, + 51, -1, -1, -1, 55, 56, 57, 58, -1, 60, + -1, -1, -1, -1, -1, -1, -1, -1, 69, -1, + -1, -1, -1, -1, -1, 76, 77, 78, 79, 80, + -1, -1, 83, 84, 85, 86, -1, -1, 89, 90, + -1, -1, -1, 94, 95, -1, -1, -1, 99, 11, + 12, 13, 14, -1, 16, 17, 18, 19, 20, -1, + 22, 23, 24, 25, 26, -1, 28, -1, 30, -1, + -1, -1, 34, -1, 36, 37, 38, -1, -1, 41, + -1, -1, -1, -1, 46, 47, 48, -1, -1, 51, + -1, -1, -1, 55, 56, 57, 58, -1, 60, -1, + -1, -1, -1, -1, -1, -1, -1, 69, -1, -1, + -1, -1, -1, -1, 76, 77, 78, 79, 80, -1, + -1, 83, 84, 85, 86, -1, -1, 89, 90, -1, + -1, -1, -1, 95, -1, -1, -1, 99, 11, 12, + 13, 14, -1, 16, 17, 18, 19, 20, -1, 22, + 23, 24, 25, 26, -1, 28, 29, 30, -1, -1, + -1, 34, -1, 36, 37, 38, -1, -1, -1, -1, + -1, -1, -1, 46, 47, 48, -1, -1, 51, -1, + -1, -1, -1, -1, 57, 58, -1, 60, -1, -1, + -1, -1, -1, -1, -1, -1, 69, -1, -1, -1, + -1, -1, -1, 76, 77, 78, 79, 80, -1, -1, + 83, 84, -1, 86, -1, -1, 89, 90, -1, -1, + -1, 94, 95, -1, -1, -1, 99, 11, 12, 13, + 14, -1, 16, 17, 18, 19, 20, -1, 22, 23, + 24, 25, 26, -1, 28, -1, 30, -1, -1, -1, + 34, -1, 36, 37, 38, -1, -1, -1, -1, -1, + -1, -1, 46, 47, 48, -1, -1, 51, -1, -1, + -1, -1, -1, 57, 58, -1, 60, -1, -1, -1, + -1, -1, -1, -1, -1, 69, -1, -1, -1, -1, + -1, -1, 76, 77, 78, 79, 80, -1, -1, 83, + 84, -1, 86, -1, -1, 89, 90, -1, -1, -1, + 94, 95, -1, -1, -1, 99, 11, 12, 13, 14, + -1, 16, 17, 18, 19, 20, -1, 22, 23, 24, + 25, 26, -1, 28, -1, 30, -1, -1, -1, 34, + -1, 36, 37, 38, -1, -1, -1, -1, -1, -1, + -1, 46, 47, 48, -1, -1, 51, -1, -1, -1, + -1, -1, 57, 58, -1, 60, -1, -1, -1, -1, + -1, -1, -1, -1, 69, -1, -1, -1, -1, -1, + -1, 76, 77, 78, 79, 80, -1, -1, 83, 84, + -1, 86, -1, -1, 89, 90, -1, -1, -1, -1, + 95, -1, -1, -1, 99, 11, 12, 13, 14, -1, + 16, 17, 18, 19, 20, -1, 22, 23, 24, 25, + 26, -1, 28, -1, 30, -1, -1, -1, 34, -1, + 36, 37, -1, -1, -1, -1, -1, -1, -1, -1, + 46, -1, 48, -1, -1, -1, -1, -1, -1, -1, + -1, 57, 58, -1, 60, -1, -1, -1, -1, -1, + -1, -1, -1, 69, -1, -1, -1, -1, -1, -1, + 76, 77, 78, 79, 80, -1, -1, -1, 84, -1, + 86, -1, -1, 89, 90, 11, 12, 13, 14, 95, + -1, -1, -1, 99, -1, -1, 22, 23, 24, 25, + 26, -1, 28, -1, -1, -1, -1, -1, -1, 35, + -1, -1, -1, -1, 40, -1, 42, 43, 44, 45, + 46, -1, 48, -1, 11, 12, 13, 14, -1, -1, + -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, + -1, 28, -1, 69, -1, -1, -1, -1, 35, -1, + 76, 77, 78, 79, 80, 42, -1, 44, -1, 46, + -1, 48, -1, 89, 90, -1, -1, -1, -1, 95, + -1, -1, 59, 99, -1, -1, -1, -1, -1, -1, + -1, -1, 69, 11, 12, 13, 14, -1, -1, 76, + 77, 78, 79, 80, 22, 23, 24, 25, 26, -1, + 28, -1, 89, 90, -1, -1, -1, -1, 95, -1, + -1, -1, 99, -1, -1, -1, -1, -1, 46, -1, + 48, 11, 12, 13, 14, -1, -1, -1, -1, -1, + -1, -1, 22, 23, 24, 25, 26, -1, 28, -1, + -1, 69, -1, -1, -1, -1, -1, -1, 76, 77, + 78, 79, 80, -1, -1, -1, 46, -1, 48, -1, + -1, 89, 90, -1, -1, -1, -1, 95, -1, -1, + -1, 99, -1, -1, -1, -1, -1, -1, -1, 69, + 11, 12, 13, 14, -1, -1, 76, 77, 78, 79, + 80, 22, 23, 24, 25, 26, -1, 28, -1, 89, + 90, -1, -1, -1, -1, 95, -1, -1, -1, 99, + -1, -1, -1, -1, -1, 46, -1, 48, 11, 12, + 13, 14, -1, -1, -1, -1, -1, -1, -1, 22, + 23, 24, 25, 26, -1, 28, -1, -1, 69, -1, + -1, -1, -1, -1, -1, 76, 77, 78, 79, 80, + -1, -1, -1, 46, -1, 48, -1, -1, 89, 90, + -1, -1, -1, -1, 95, -1, -1, -1, 99, -1, + -1, -1, -1, -1, -1, -1, 69, 11, 12, 13, + 14, -1, -1, 76, 77, 78, 79, 80, 22, 23, + 24, 25, 26, -1, 28, -1, 89, 90, -1, -1, + -1, -1, 95, -1, -1, -1, 99, -1, -1, -1, + -1, -1, 46, -1, 48, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 69, -1, -1, -1, -1, + 39, -1, 76, 77, 78, 79, 80, -1, -1, -1, + -1, -1, -1, -1, -1, 89, 90, -1, -1, -1, + -1, 95, 61, 62, -1, 99, -1, 66, 67, 68, + -1, 70, 71, 72, 73, 74, 75, -1, 44, -1, + -1, -1, -1, -1, 50, -1, -1, -1, -1, 88, + 89, 90, 91, 92, -1, 61, 62, -1, 97, 98, + 66, 67, 68, -1, 70, -1, -1, 73, 74, 75, + -1, 44, -1, -1, -1, -1, -1, 50, -1, -1, + -1, -1, 88, 89, 90, 91, 92, -1, 61, 62, + -1, 97, 98, 66, 67, 68, -1, 70, -1, -1, + 73, 74, 75, -1, 44, -1, -1, -1, -1, -1, + 50, -1, -1, -1, -1, 88, 89, 90, 91, 92, + -1, 61, 62, -1, 97, 98, 66, 67, 68, -1, + 70, -1, -1, 73, 74, 75, -1, 44, -1, -1, + -1, -1, -1, 50, -1, -1, -1, -1, 88, 89, + 90, 91, 92, -1, 61, 62, -1, 97, 98, 66, + 67, 68, -1, 70, -1, -1, 73, 74, 75, -1, + 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 88, 89, 90, 91, 92, -1, 61, 62, -1, + 97, 98, 66, 67, 68, -1, 70, -1, -1, 73, + 74, 75, -1, 44, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 88, 89, 90, 91, 92, -1, + 61, 62, -1, 97, 98, 66, 67, 68, -1, 70, + -1, -1, 73, 74, 75, -1, 44, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 88, 89, 90, + 91, 92, -1, 61, 62, -1, 97, 98, 66, 67, + 68, -1, 70, -1, -1, 73, 74, 75, -1, 44, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 88, 89, 90, 91, 92, -1, 61, 62, -1, 97, + 98, 66, 67, 68, -1, 70, -1, -1, 73, 74, + 75, -1, -1, -1, -1, -1, -1, -1, 50, -1, + -1, -1, -1, 88, 89, 90, 91, 92, -1, 61, + 62, -1, 97, 98, 66, 67, 68, -1, 70, -1, + -1, 73, 74, 75, -1, -1, -1, -1, -1, -1, + -1, -1, 50, -1, -1, -1, 88, 89, 90, 91, + 92, -1, 94, 61, 62, 97, 98, -1, 66, 67, + 68, -1, 70, -1, -1, 73, 74, 75, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 52, -1, 87, + 88, 89, 90, 91, 92, -1, 61, 62, -1, 97, + 98, 66, 67, 68, -1, 70, -1, -1, 73, 74, + 75, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 88, 89, 90, 91, 92, -1, 61, + 62, -1, 97, 98, 66, 67, 68, -1, 70, -1, + -1, 73, 74, 75, -1, -1, -1, -1, -1, 81, + 82, -1, -1, -1, -1, -1, 88, 89, 90, 91, + 92, -1, 61, 62, -1, 97, 98, 66, 67, 68, + -1, 70, -1, -1, 73, 74, 75, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 87, 88, + 89, 90, 91, 92, -1, 61, 62, 96, 97, 98, + 66, 67, 68, -1, 70, -1, -1, 73, 74, 75, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 88, 89, 90, 91, 92, -1, 61, 62, + 96, 97, 98, 66, 67, 68, -1, 70, -1, -1, + 73, 74, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 87, 88, 89, 90, 91, 92, + -1, 61, 62, -1, 97, 98, 66, 67, 68, -1, + 70, -1, -1, 73, 74, 75, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 88, 89, + 90, 91, 92, -1, -1, -1, -1, 97, 98 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -1223,39 +1285,41 @@ static const yytype_int16 yycheck[] = static const yytype_uint8 yystos[] = { 0, 1, 11, 12, 13, 14, 16, 17, 18, 19, - 20, 21, 22, 24, 26, 30, 32, 33, 34, 37, - 42, 43, 44, 47, 51, 52, 53, 54, 56, 65, - 72, 73, 74, 75, 76, 79, 80, 83, 84, 89, - 93, 97, 99, 100, 101, 102, 103, 110, 111, 112, - 117, 118, 119, 122, 125, 127, 134, 88, 98, 21, - 42, 118, 118, 118, 89, 118, 135, 21, 89, 118, - 135, 136, 126, 43, 21, 120, 31, 36, 38, 39, - 40, 41, 118, 123, 124, 21, 118, 48, 49, 12, - 13, 21, 21, 21, 21, 118, 55, 123, 124, 21, - 121, 118, 118, 118, 118, 118, 118, 21, 89, 118, - 118, 118, 135, 0, 98, 89, 81, 89, 109, 118, - 118, 57, 58, 62, 63, 64, 66, 69, 70, 71, - 82, 83, 84, 85, 86, 91, 92, 89, 118, 118, - 135, 95, 135, 135, 95, 135, 95, 118, 118, 38, - 124, 128, 35, 67, 68, 21, 46, 81, 118, 46, - 81, 45, 129, 48, 124, 95, 40, 46, 40, 46, - 40, 46, 40, 46, 77, 78, 130, 21, 90, 94, - 99, 109, 118, 109, 118, 45, 81, 115, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 118, 90, 118, 90, 118, 21, 118, - 114, 21, 118, 118, 118, 118, 46, 81, 118, 118, - 114, 118, 21, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 114, 90, 95, 90, 115, 90, 98, - 114, 118, 21, 132, 118, 118, 132, 40, 40, 40, - 40, 131, 135, 116, 27, 46, 116, 101, 95, 98, - 98, 118, 118, 118, 118, 132, 90, 98, 102, 115, - 46, 118, 115, 115, 21, 95, 133, 133, 98, 25, - 118, 115, 25, 50, 114, 29, 50, 106, 107, 113, - 21, 116, 116, 133, 115, 116, 116, 105, 106, 108, - 113, 114, 107, 115, 109, 116, 116, 115, 115, 108, - 115, 109, 101, 50, 104, 45, 25, 115, 25, 25, - 25, 45, 115, 114, 115, 114, 25, 114, 101, 102, - 116, 115, 115 + 20, 22, 23, 24, 25, 26, 28, 30, 34, 36, + 37, 38, 41, 46, 47, 48, 51, 55, 56, 57, + 58, 60, 69, 76, 77, 78, 79, 80, 83, 84, + 85, 86, 89, 90, 95, 99, 103, 105, 106, 107, + 108, 109, 116, 117, 118, 123, 124, 125, 126, 130, + 133, 135, 142, 94, 104, 25, 46, 125, 125, 125, + 95, 125, 144, 25, 125, 95, 144, 95, 144, 134, + 47, 25, 127, 35, 40, 42, 43, 44, 45, 125, + 131, 132, 25, 125, 52, 53, 12, 13, 25, 25, + 25, 25, 125, 59, 131, 132, 25, 129, 125, 125, + 125, 125, 125, 125, 25, 128, 25, 95, 125, 125, + 125, 125, 143, 0, 104, 95, 87, 95, 115, 125, + 107, 125, 61, 62, 66, 67, 68, 70, 73, 74, + 75, 88, 89, 90, 91, 92, 97, 98, 95, 125, + 125, 144, 101, 143, 144, 125, 143, 143, 101, 125, + 125, 42, 132, 136, 39, 71, 72, 25, 50, 87, + 125, 50, 87, 49, 137, 52, 132, 101, 44, 50, + 44, 50, 44, 50, 44, 50, 81, 82, 101, 138, + 25, 96, 100, 101, 105, 115, 125, 115, 125, 49, + 87, 121, 50, 104, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 96, 125, 96, 96, 25, 125, 120, 25, 125, 125, + 125, 125, 50, 87, 125, 125, 120, 125, 25, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 25, + 120, 96, 101, 125, 96, 121, 96, 104, 120, 125, + 125, 122, 25, 140, 125, 125, 140, 44, 44, 44, + 44, 139, 143, 122, 31, 50, 122, 107, 104, 108, + 121, 101, 104, 104, 125, 125, 125, 125, 140, 96, + 121, 50, 125, 121, 121, 29, 25, 101, 141, 141, + 104, 29, 125, 121, 29, 54, 120, 33, 54, 112, + 113, 119, 25, 122, 122, 141, 121, 122, 122, 111, + 112, 114, 119, 120, 113, 121, 115, 122, 122, 121, + 121, 114, 121, 115, 107, 54, 110, 49, 29, 121, + 29, 29, 29, 49, 121, 120, 121, 120, 29, 120, + 107, 108, 122, 121, 121 }; #define yyerrok (yyerrstatus = 0) @@ -2070,12 +2134,12 @@ yyreduce: switch (yyn) { case 4: -#line 119 "engines/director/lingo/lingo-gr.y" +#line 120 "engines/director/lingo/lingo-gr.y" { yyerrok; ;} break; case 5: -#line 122 "engines/director/lingo/lingo-gr.y" +#line 123 "engines/director/lingo/lingo-gr.y" { g_lingo->_linenumber++; g_lingo->_colnumber = 1; @@ -2083,7 +2147,7 @@ yyreduce: break; case 10: -#line 133 "engines/director/lingo/lingo-gr.y" +#line 134 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_varpush); g_lingo->codeString((yyvsp[(4) - (4)].s)->c_str()); @@ -2093,17 +2157,17 @@ yyreduce: break; case 11: -#line 139 "engines/director/lingo/lingo-gr.y" +#line 140 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code1(g_lingo->c_after); ;} break; case 12: -#line 140 "engines/director/lingo/lingo-gr.y" +#line 141 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code1(g_lingo->c_before); ;} break; case 13: -#line 141 "engines/director/lingo/lingo-gr.y" +#line 142 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_varpush); g_lingo->codeString((yyvsp[(2) - (4)].s)->c_str()); @@ -2113,7 +2177,7 @@ yyreduce: break; case 14: -#line 147 "engines/director/lingo/lingo-gr.y" +#line 148 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(0); // Put dummy id g_lingo->code1(g_lingo->c_theentityassign); @@ -2125,7 +2189,7 @@ yyreduce: break; case 15: -#line 155 "engines/director/lingo/lingo-gr.y" +#line 156 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_swap); g_lingo->code1(g_lingo->c_theentityassign); @@ -2137,7 +2201,7 @@ yyreduce: break; case 16: -#line 163 "engines/director/lingo/lingo-gr.y" +#line 164 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_varpush); g_lingo->codeString((yyvsp[(2) - (4)].s)->c_str()); @@ -2147,7 +2211,7 @@ yyreduce: break; case 17: -#line 169 "engines/director/lingo/lingo-gr.y" +#line 170 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(0); // Put dummy id g_lingo->code1(g_lingo->c_theentityassign); @@ -2159,7 +2223,7 @@ yyreduce: break; case 18: -#line 177 "engines/director/lingo/lingo-gr.y" +#line 178 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_swap); g_lingo->code1(g_lingo->c_theentityassign); @@ -2171,12 +2235,12 @@ yyreduce: break; case 19: -#line 187 "engines/director/lingo/lingo-gr.y" +#line 188 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_xpop); ;} break; case 23: -#line 197 "engines/director/lingo/lingo-gr.y" +#line 198 "engines/director/lingo/lingo-gr.y" { inst body = 0, end = 0; WRITE_UINT32(&body, (yyvsp[(5) - (7)].code)); @@ -2188,7 +2252,7 @@ yyreduce: break; case 24: -#line 210 "engines/director/lingo/lingo-gr.y" +#line 211 "engines/director/lingo/lingo-gr.y" { inst init = 0, finish = 0, body = 0, end = 0, inc = 0; WRITE_UINT32(&init, (yyvsp[(3) - (10)].code)); @@ -2206,7 +2270,7 @@ yyreduce: break; case 25: -#line 228 "engines/director/lingo/lingo-gr.y" +#line 229 "engines/director/lingo/lingo-gr.y" { inst init = 0, finish = 0, body = 0, end = 0, inc = 0; WRITE_UINT32(&init, (yyvsp[(3) - (11)].code)); @@ -2224,7 +2288,7 @@ yyreduce: break; case 26: -#line 242 "engines/director/lingo/lingo-gr.y" +#line 243 "engines/director/lingo/lingo-gr.y" { inst end = 0; WRITE_UINT32(&end, (yyvsp[(3) - (3)].code)); @@ -2234,7 +2298,21 @@ yyreduce: break; case 27: -#line 250 "engines/director/lingo/lingo-gr.y" +#line 249 "engines/director/lingo/lingo-gr.y" + { + warning("STUB: TELL is not implemented"); + checkEnd((yyvsp[(6) - (6)].s), "tell", true); ;} + break; + + case 28: +#line 252 "engines/director/lingo/lingo-gr.y" + { + warning("STUB: TELL is not implemented"); + ;} + break; + + case 29: +#line 257 "engines/director/lingo/lingo-gr.y" { inst then = 0, end = 0; WRITE_UINT32(&then, (yyvsp[(5) - (7)].code)); @@ -2247,8 +2325,8 @@ yyreduce: g_lingo->processIf(0, 0); ;} break; - case 28: -#line 260 "engines/director/lingo/lingo-gr.y" + case 30: +#line 267 "engines/director/lingo/lingo-gr.y" { inst then = 0, else1 = 0, end = 0; WRITE_UINT32(&then, (yyvsp[(5) - (10)].code)); @@ -2263,8 +2341,8 @@ yyreduce: g_lingo->processIf(0, 0); ;} break; - case 29: -#line 272 "engines/director/lingo/lingo-gr.y" + case 31: +#line 279 "engines/director/lingo/lingo-gr.y" { inst then = 0, else1 = 0, end = 0; WRITE_UINT32(&then, (yyvsp[(5) - (10)].code)); @@ -2279,8 +2357,8 @@ yyreduce: g_lingo->processIf(0, (yyvsp[(9) - (10)].code)); ;} break; - case 30: -#line 284 "engines/director/lingo/lingo-gr.y" + case 32: +#line 291 "engines/director/lingo/lingo-gr.y" { inst then = 0, else1 = 0, end = 0; WRITE_UINT32(&then, (yyvsp[(4) - (6)].code)); @@ -2293,8 +2371,8 @@ yyreduce: g_lingo->processIf(0, 0); ;} break; - case 31: -#line 294 "engines/director/lingo/lingo-gr.y" + case 33: +#line 301 "engines/director/lingo/lingo-gr.y" { inst then = 0, else1 = 0, end = 0; WRITE_UINT32(&then, (yyvsp[(4) - (10)].code)); @@ -2307,8 +2385,8 @@ yyreduce: g_lingo->processIf(0, 0); ;} break; - case 32: -#line 304 "engines/director/lingo/lingo-gr.y" + case 34: +#line 311 "engines/director/lingo/lingo-gr.y" { inst then = 0, else1 = 0, end = 0; WRITE_UINT32(&then, (yyvsp[(4) - (10)].code)); @@ -2321,18 +2399,18 @@ yyreduce: g_lingo->processIf(0, (yyvsp[(10) - (10)].code)); ;} break; - case 33: -#line 316 "engines/director/lingo/lingo-gr.y" + case 35: +#line 323 "engines/director/lingo/lingo-gr.y" { (yyval.code) = 0; ;} break; - case 34: -#line 317 "engines/director/lingo/lingo-gr.y" + case 36: +#line 324 "engines/director/lingo/lingo-gr.y" { (yyval.code) = (yyvsp[(2) - (3)].code); ;} break; - case 39: -#line 328 "engines/director/lingo/lingo-gr.y" + case 41: +#line 335 "engines/director/lingo/lingo-gr.y" { inst then = 0; WRITE_UINT32(&then, (yyvsp[(4) - (6)].code)); @@ -2341,8 +2419,8 @@ yyreduce: g_lingo->codeLabel((yyvsp[(1) - (6)].code)); ;} break; - case 41: -#line 337 "engines/director/lingo/lingo-gr.y" + case 43: +#line 344 "engines/director/lingo/lingo-gr.y" { inst then = 0; WRITE_UINT32(&then, (yyvsp[(5) - (6)].code)); @@ -2351,23 +2429,23 @@ yyreduce: g_lingo->codeLabel((yyvsp[(1) - (6)].code)); ;} break; - case 42: -#line 345 "engines/director/lingo/lingo-gr.y" + case 44: +#line 352 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(STOP); ;} break; - case 43: -#line 346 "engines/director/lingo/lingo-gr.y" + case 45: +#line 353 "engines/director/lingo/lingo-gr.y" { g_lingo->code2(g_lingo->c_eq, STOP); ;} break; - case 45: -#line 350 "engines/director/lingo/lingo-gr.y" + case 47: +#line 357 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code3(g_lingo->c_repeatwhilecode, STOP, STOP); ;} break; - case 46: -#line 353 "engines/director/lingo/lingo-gr.y" + case 48: +#line 360 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code3(g_lingo->c_repeatwithcode, STOP, STOP); g_lingo->code3(STOP, STOP, STOP); @@ -2375,8 +2453,8 @@ yyreduce: delete (yyvsp[(3) - (3)].s); ;} break; - case 47: -#line 360 "engines/director/lingo/lingo-gr.y" + case 49: +#line 367 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code1(g_lingo->c_ifcode); g_lingo->code3(STOP, STOP, STOP); @@ -2384,8 +2462,8 @@ yyreduce: g_lingo->codeLabel(0); ;} break; - case 48: -#line 367 "engines/director/lingo/lingo-gr.y" + case 50: +#line 374 "engines/director/lingo/lingo-gr.y" { inst skipEnd; WRITE_UINT32(&skipEnd, 1); // We have to skip end to avoid multiple executions @@ -2394,23 +2472,23 @@ yyreduce: g_lingo->code1(skipEnd); ;} break; - case 49: -#line 375 "engines/director/lingo/lingo-gr.y" + case 51: +#line 382 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->_currentScript->size(); ;} break; - case 50: -#line 378 "engines/director/lingo/lingo-gr.y" + case 52: +#line 385 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(STOP); (yyval.code) = g_lingo->_currentScript->size(); ;} break; - case 51: -#line 381 "engines/director/lingo/lingo-gr.y" + case 53: +#line 388 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->_currentScript->size(); ;} break; - case 54: -#line 386 "engines/director/lingo/lingo-gr.y" + case 56: +#line 393 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code1(g_lingo->c_whencode); g_lingo->code1(STOP); @@ -2418,56 +2496,80 @@ yyreduce: delete (yyvsp[(2) - (3)].s); ;} break; - case 55: -#line 392 "engines/director/lingo/lingo-gr.y" + case 57: +#line 399 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->code1(g_lingo->c_tellcode); + g_lingo->code1(STOP); ;} + break; + + case 58: +#line 403 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->codeConst((yyvsp[(1) - (1)].i)); ;} break; - case 56: -#line 393 "engines/director/lingo/lingo-gr.y" + case 59: +#line 404 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code1(g_lingo->c_fconstpush); g_lingo->codeFloat((yyvsp[(1) - (1)].f)); ;} break; - case 57: -#line 396 "engines/director/lingo/lingo-gr.y" + case 60: +#line 407 "engines/director/lingo/lingo-gr.y" { // D3 (yyval.code) = g_lingo->code1(g_lingo->c_symbolpush); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); ;} break; - case 58: -#line 399 "engines/director/lingo/lingo-gr.y" + case 61: +#line 410 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code1(g_lingo->c_stringpush); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); ;} break; - case 59: -#line 402 "engines/director/lingo/lingo-gr.y" + case 62: +#line 413 "engines/director/lingo/lingo-gr.y" { - (yyval.code) = g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (1)].s)]->u.func); + g_lingo->codeFunc((yyvsp[(1) - (1)].s), 0); delete (yyvsp[(1) - (1)].s); ;} break; - case 60: -#line 405 "engines/director/lingo/lingo-gr.y" + case 63: +#line 416 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeFunc((yyvsp[(1) - (2)].s), 1); + delete (yyvsp[(1) - (2)].s); ;} + break; + + case 64: +#line 419 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeFunc((yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].narg)); ;} + break; + + case 65: +#line 420 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg)); ;} + break; + + case 66: +#line 421 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg)); delete (yyvsp[(1) - (4)].s); ;} break; - case 61: -#line 408 "engines/director/lingo/lingo-gr.y" + case 67: +#line 424 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code1(g_lingo->c_eval); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;} break; - case 62: -#line 412 "engines/director/lingo/lingo-gr.y" + case 68: +#line 428 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->codeConst(0); // Put dummy id g_lingo->code1(g_lingo->c_theentitypush); @@ -2477,8 +2579,8 @@ yyreduce: g_lingo->code2(e, f); ;} break; - case 63: -#line 419 "engines/director/lingo/lingo-gr.y" + case 69: +#line 435 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code1(g_lingo->c_theentitypush); inst e = 0, f = 0; @@ -2487,334 +2589,352 @@ yyreduce: g_lingo->code2(e, f); ;} break; - case 65: -#line 426 "engines/director/lingo/lingo-gr.y" + case 71: +#line 442 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_add); ;} break; - case 66: -#line 427 "engines/director/lingo/lingo-gr.y" + case 72: +#line 443 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_sub); ;} break; - case 67: -#line 428 "engines/director/lingo/lingo-gr.y" + case 73: +#line 444 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_mul); ;} break; - case 68: -#line 429 "engines/director/lingo/lingo-gr.y" + case 74: +#line 445 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_div); ;} break; - case 69: -#line 430 "engines/director/lingo/lingo-gr.y" + case 75: +#line 446 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_mod); ;} break; - case 70: -#line 431 "engines/director/lingo/lingo-gr.y" + case 76: +#line 447 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_gt); ;} break; - case 71: -#line 432 "engines/director/lingo/lingo-gr.y" + case 77: +#line 448 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_lt); ;} break; - case 72: -#line 433 "engines/director/lingo/lingo-gr.y" + case 78: +#line 449 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_neq); ;} break; - case 73: -#line 434 "engines/director/lingo/lingo-gr.y" + case 79: +#line 450 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_ge); ;} break; - case 74: -#line 435 "engines/director/lingo/lingo-gr.y" + case 80: +#line 451 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_le); ;} break; - case 75: -#line 436 "engines/director/lingo/lingo-gr.y" + case 81: +#line 452 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_and); ;} break; - case 76: -#line 437 "engines/director/lingo/lingo-gr.y" + case 82: +#line 453 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_or); ;} break; - case 77: -#line 438 "engines/director/lingo/lingo-gr.y" + case 83: +#line 454 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_not); ;} break; - case 78: -#line 439 "engines/director/lingo/lingo-gr.y" + case 84: +#line 455 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_ampersand); ;} break; - case 79: -#line 440 "engines/director/lingo/lingo-gr.y" + case 85: +#line 456 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_concat); ;} break; - case 80: -#line 441 "engines/director/lingo/lingo-gr.y" + case 86: +#line 457 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_contains); ;} break; - case 81: -#line 442 "engines/director/lingo/lingo-gr.y" + case 87: +#line 458 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_starts); ;} break; - case 82: -#line 443 "engines/director/lingo/lingo-gr.y" + case 88: +#line 459 "engines/director/lingo/lingo-gr.y" { (yyval.code) = (yyvsp[(2) - (2)].code); ;} break; - case 83: -#line 444 "engines/director/lingo/lingo-gr.y" + case 89: +#line 460 "engines/director/lingo/lingo-gr.y" { (yyval.code) = (yyvsp[(2) - (2)].code); g_lingo->code1(g_lingo->c_negate); ;} break; - case 84: -#line 445 "engines/director/lingo/lingo-gr.y" + case 90: +#line 461 "engines/director/lingo/lingo-gr.y" { (yyval.code) = (yyvsp[(2) - (3)].code); ;} break; - case 85: -#line 446 "engines/director/lingo/lingo-gr.y" + case 91: +#line 462 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->codeArray((yyvsp[(2) - (3)].narg)); ;} break; - case 86: -#line 447 "engines/director/lingo/lingo-gr.y" + case 92: +#line 463 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_intersects); ;} break; - case 87: -#line 448 "engines/director/lingo/lingo-gr.y" + case 93: +#line 464 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_within); ;} break; - case 88: -#line 449 "engines/director/lingo/lingo-gr.y" + case 94: +#line 465 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_charOf); ;} break; - case 89: -#line 450 "engines/director/lingo/lingo-gr.y" + case 95: +#line 466 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_charToOf); ;} break; - case 90: -#line 451 "engines/director/lingo/lingo-gr.y" + case 96: +#line 467 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_itemOf); ;} break; - case 91: -#line 452 "engines/director/lingo/lingo-gr.y" + case 97: +#line 468 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_itemToOf); ;} break; - case 92: -#line 453 "engines/director/lingo/lingo-gr.y" + case 98: +#line 469 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_lineOf); ;} break; - case 93: -#line 454 "engines/director/lingo/lingo-gr.y" + case 99: +#line 470 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_lineToOf); ;} break; - case 94: -#line 455 "engines/director/lingo/lingo-gr.y" + case 100: +#line 471 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_wordOf); ;} break; - case 95: -#line 456 "engines/director/lingo/lingo-gr.y" + case 101: +#line 472 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_wordToOf); ;} break; - case 96: -#line 459 "engines/director/lingo/lingo-gr.y" + case 102: +#line 475 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_printtop); ;} break; - case 99: -#line 462 "engines/director/lingo/lingo-gr.y" + case 105: +#line 478 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_exitRepeat); ;} break; - case 100: -#line 463 "engines/director/lingo/lingo-gr.y" + case 106: +#line 479 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(0); // Push fake value on stack g_lingo->code1(g_lingo->c_procret); ;} break; - case 103: -#line 467 "engines/director/lingo/lingo-gr.y" + case 110: +#line 484 "engines/director/lingo/lingo-gr.y" { - g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (2)].s)]->u.func); + g_lingo->codeFunc((yyvsp[(1) - (1)].s), 0); + delete (yyvsp[(1) - (1)].s); ;} + break; + + case 111: +#line 487 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeFunc((yyvsp[(1) - (2)].s), 1); delete (yyvsp[(1) - (2)].s); ;} break; - case 104: -#line 470 "engines/director/lingo/lingo-gr.y" + case 112: +#line 490 "engines/director/lingo/lingo-gr.y" { - g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (2)].s)]->u.func); + g_lingo->codeFunc((yyvsp[(1) - (2)].s), 1); delete (yyvsp[(1) - (2)].s); ;} break; - case 105: -#line 473 "engines/director/lingo/lingo-gr.y" + case 113: +#line 493 "engines/director/lingo/lingo-gr.y" { - g_lingo->code2(g_lingo->c_voidpush, g_lingo->_builtins[*(yyvsp[(1) - (1)].s)]->u.func); + g_lingo->code1(g_lingo->c_voidpush); + g_lingo->codeFunc((yyvsp[(1) - (1)].s), 1); delete (yyvsp[(1) - (1)].s); ;} break; - case 106: -#line 476 "engines/director/lingo/lingo-gr.y" - { g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg)); ;} + case 114: +#line 497 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeFunc((yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].narg)); ;} break; - case 107: -#line 477 "engines/director/lingo/lingo-gr.y" - { g_lingo->codeFunc((yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].narg)); ;} + case 115: +#line 498 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg)); ;} break; - case 108: -#line 478 "engines/director/lingo/lingo-gr.y" + case 116: +#line 499 "engines/director/lingo/lingo-gr.y" { g_lingo->codeMe((yyvsp[(3) - (4)].s), 0); ;} break; - case 109: -#line 479 "engines/director/lingo/lingo-gr.y" + case 117: +#line 500 "engines/director/lingo/lingo-gr.y" { g_lingo->codeMe((yyvsp[(3) - (6)].s), (yyvsp[(5) - (6)].narg)); ;} break; - case 110: -#line 480 "engines/director/lingo/lingo-gr.y" + case 118: +#line 501 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_open); ;} break; - case 111: -#line 481 "engines/director/lingo/lingo-gr.y" + case 119: +#line 502 "engines/director/lingo/lingo-gr.y" { g_lingo->code2(g_lingo->c_voidpush, g_lingo->c_open); ;} break; - case 112: -#line 482 "engines/director/lingo/lingo-gr.y" + case 120: +#line 503 "engines/director/lingo/lingo-gr.y" { Common::String s(*(yyvsp[(1) - (3)].s)); s += '-'; s += *(yyvsp[(2) - (3)].s); g_lingo->codeFunc(&s, (yyvsp[(3) - (3)].narg)); ;} break; - case 113: -#line 485 "engines/director/lingo/lingo-gr.y" + case 121: +#line 506 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;} break; - case 114: -#line 486 "engines/director/lingo/lingo-gr.y" + case 122: +#line 507 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;} break; - case 115: -#line 489 "engines/director/lingo/lingo-gr.y" + case 123: +#line 510 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_property); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;} + break; + + case 124: +#line 511 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_property); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;} + break; + + case 125: +#line 514 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_instance); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;} break; - case 116: -#line 490 "engines/director/lingo/lingo-gr.y" + case 126: +#line 515 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_instance); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;} break; - case 117: -#line 501 "engines/director/lingo/lingo-gr.y" + case 127: +#line 526 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_gotoloop); ;} break; - case 118: -#line 502 "engines/director/lingo/lingo-gr.y" + case 128: +#line 527 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_gotonext); ;} break; - case 119: -#line 503 "engines/director/lingo/lingo-gr.y" + case 129: +#line 528 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_gotoprevious); ;} break; - case 120: -#line 504 "engines/director/lingo/lingo-gr.y" + case 130: +#line 529 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(1); g_lingo->code1(g_lingo->c_goto); ;} break; - case 121: -#line 507 "engines/director/lingo/lingo-gr.y" + case 131: +#line 532 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(3); g_lingo->code1(g_lingo->c_goto); ;} break; - case 122: -#line 510 "engines/director/lingo/lingo-gr.y" + case 132: +#line 535 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(2); g_lingo->code1(g_lingo->c_goto); ;} break; - case 127: -#line 523 "engines/director/lingo/lingo-gr.y" + case 137: +#line 548 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_playdone); ;} break; - case 128: -#line 524 "engines/director/lingo/lingo-gr.y" + case 138: +#line 549 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(1); g_lingo->code1(g_lingo->c_play); ;} break; - case 129: -#line 527 "engines/director/lingo/lingo-gr.y" + case 139: +#line 552 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(3); g_lingo->code1(g_lingo->c_play); ;} break; - case 130: -#line 530 "engines/director/lingo/lingo-gr.y" + case 140: +#line 555 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(2); g_lingo->code1(g_lingo->c_play); ;} break; - case 131: -#line 533 "engines/director/lingo/lingo-gr.y" + case 141: +#line 558 "engines/director/lingo/lingo-gr.y" { g_lingo->codeSetImmediate(true); ;} break; - case 132: -#line 533 "engines/director/lingo/lingo-gr.y" + case 142: +#line 558 "engines/director/lingo/lingo-gr.y" { g_lingo->codeSetImmediate(false); g_lingo->codeFunc((yyvsp[(1) - (3)].s), (yyvsp[(3) - (3)].narg)); ;} break; - case 133: -#line 563 "engines/director/lingo/lingo-gr.y" + case 143: +#line 588 "engines/director/lingo/lingo-gr.y" { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); ;} break; - case 134: -#line 564 "engines/director/lingo/lingo-gr.y" + case 144: +#line 589 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(0); // Push fake value on stack g_lingo->code1(g_lingo->c_procret); @@ -2822,38 +2942,38 @@ yyreduce: g_lingo->_indef = false; ;} break; - case 135: -#line 569 "engines/director/lingo/lingo-gr.y" + case 145: +#line 594 "engines/director/lingo/lingo-gr.y" { g_lingo->codeFactory(*(yyvsp[(2) - (2)].s)); ;} break; - case 136: -#line 572 "engines/director/lingo/lingo-gr.y" + case 146: +#line 597 "engines/director/lingo/lingo-gr.y" { g_lingo->_indef = true; ;} break; - case 137: -#line 573 "engines/director/lingo/lingo-gr.y" + case 147: +#line 598 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_procret); g_lingo->define(*(yyvsp[(2) - (8)].s), (yyvsp[(4) - (8)].code), (yyvsp[(5) - (8)].narg) + 1, &g_lingo->_currentFactory); g_lingo->_indef = false; ;} break; - case 138: -#line 577 "engines/director/lingo/lingo-gr.y" + case 148: +#line 602 "engines/director/lingo/lingo-gr.y" { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); ;} break; - case 139: -#line 578 "engines/director/lingo/lingo-gr.y" + case 149: +#line 603 "engines/director/lingo/lingo-gr.y" { g_lingo->_ignoreMe = true; ;} break; - case 140: -#line 578 "engines/director/lingo/lingo-gr.y" + case 150: +#line 603 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(0); // Push fake value on stack g_lingo->code1(g_lingo->c_procret); @@ -2865,33 +2985,33 @@ yyreduce: ;} break; - case 141: -#line 588 "engines/director/lingo/lingo-gr.y" + case 151: +#line 613 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = 0; ;} break; - case 142: -#line 589 "engines/director/lingo/lingo-gr.y" + case 152: +#line 614 "engines/director/lingo/lingo-gr.y" { g_lingo->codeArg((yyvsp[(1) - (1)].s)); (yyval.narg) = 1; ;} break; - case 143: -#line 590 "engines/director/lingo/lingo-gr.y" + case 153: +#line 615 "engines/director/lingo/lingo-gr.y" { g_lingo->codeArg((yyvsp[(3) - (3)].s)); (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;} break; - case 144: -#line 591 "engines/director/lingo/lingo-gr.y" + case 154: +#line 616 "engines/director/lingo/lingo-gr.y" { g_lingo->codeArg((yyvsp[(4) - (4)].s)); (yyval.narg) = (yyvsp[(1) - (4)].narg) + 1; ;} break; - case 145: -#line 594 "engines/director/lingo/lingo-gr.y" + case 155: +#line 619 "engines/director/lingo/lingo-gr.y" { g_lingo->codeArgStore(); ;} break; - case 146: -#line 598 "engines/director/lingo/lingo-gr.y" + case 156: +#line 623 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_call); g_lingo->codeString((yyvsp[(1) - (2)].s)->c_str()); @@ -2900,34 +3020,34 @@ yyreduce: g_lingo->code1(numpar); ;} break; - case 147: -#line 606 "engines/director/lingo/lingo-gr.y" + case 157: +#line 631 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = 0; ;} break; - case 148: -#line 607 "engines/director/lingo/lingo-gr.y" + case 158: +#line 632 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = 1; ;} break; - case 149: -#line 608 "engines/director/lingo/lingo-gr.y" + case 159: +#line 633 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;} break; - case 150: -#line 611 "engines/director/lingo/lingo-gr.y" + case 160: +#line 636 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = 1; ;} break; - case 151: -#line 612 "engines/director/lingo/lingo-gr.y" + case 161: +#line 637 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;} break; /* Line 1267 of yacc.c. */ -#line 2931 "engines/director/lingo/lingo-gr.cpp" +#line 3051 "engines/director/lingo/lingo-gr.cpp" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -3141,6 +3261,6 @@ yyreturn: } -#line 615 "engines/director/lingo/lingo-gr.y" +#line 640 "engines/director/lingo/lingo-gr.y" diff --git a/engines/director/lingo/lingo-gr.h b/engines/director/lingo/lingo-gr.h index 5f9a89477e..0bd75956d2 100644 --- a/engines/director/lingo/lingo-gr.h +++ b/engines/director/lingo/lingo-gr.h @@ -57,66 +57,72 @@ BLTINONEARG = 273, BLTINARGLIST = 274, TWOWORDBUILTIN = 275, - ID = 276, - STRING = 277, - HANDLER = 278, - SYMBOL = 279, - ENDCLAUSE = 280, - tPLAYACCEL = 281, - tDOWN = 282, - tELSE = 283, - tNLELSIF = 284, - tEXIT = 285, - tFRAME = 286, - tGLOBAL = 287, - tGO = 288, - tIF = 289, - tINTO = 290, - tLOOP = 291, - tMACRO = 292, - tMOVIE = 293, - tNEXT = 294, - tOF = 295, - tPREVIOUS = 296, - tPUT = 297, - tREPEAT = 298, - tSET = 299, - tTHEN = 300, - tTO = 301, - tWHEN = 302, - tWITH = 303, - tWHILE = 304, - tNLELSE = 305, - tFACTORY = 306, - tMETHOD = 307, - tOPEN = 308, - tPLAY = 309, - tDONE = 310, - tINSTANCE = 311, - tGE = 312, - tLE = 313, - tGT = 314, - tLT = 315, - tEQ = 316, - tNEQ = 317, - tAND = 318, - tOR = 319, - tNOT = 320, - tMOD = 321, - tAFTER = 322, - tBEFORE = 323, - tCONCAT = 324, - tCONTAINS = 325, - tSTARTS = 326, - tCHAR = 327, - tITEM = 328, - tLINE = 329, - tWORD = 330, - tSPRITE = 331, - tINTERSECTS = 332, - tWITHIN = 333, - tON = 334, - tME = 335 + FBLTIN = 276, + FBLTINNOARGS = 277, + FBLTINONEARG = 278, + FBLTINARGLIST = 279, + ID = 280, + STRING = 281, + HANDLER = 282, + SYMBOL = 283, + ENDCLAUSE = 284, + tPLAYACCEL = 285, + tDOWN = 286, + tELSE = 287, + tNLELSIF = 288, + tEXIT = 289, + tFRAME = 290, + tGLOBAL = 291, + tGO = 292, + tIF = 293, + tINTO = 294, + tLOOP = 295, + tMACRO = 296, + tMOVIE = 297, + tNEXT = 298, + tOF = 299, + tPREVIOUS = 300, + tPUT = 301, + tREPEAT = 302, + tSET = 303, + tTHEN = 304, + tTO = 305, + tWHEN = 306, + tWITH = 307, + tWHILE = 308, + tNLELSE = 309, + tFACTORY = 310, + tMETHOD = 311, + tOPEN = 312, + tPLAY = 313, + tDONE = 314, + tINSTANCE = 315, + tGE = 316, + tLE = 317, + tGT = 318, + tLT = 319, + tEQ = 320, + tNEQ = 321, + tAND = 322, + tOR = 323, + tNOT = 324, + tMOD = 325, + tAFTER = 326, + tBEFORE = 327, + tCONCAT = 328, + tCONTAINS = 329, + tSTARTS = 330, + tCHAR = 331, + tITEM = 332, + tLINE = 333, + tWORD = 334, + tSPRITE = 335, + tINTERSECTS = 336, + tWITHIN = 337, + tTELL = 338, + tPROPERTY = 339, + tON = 340, + tME = 341 }; #endif /* Tokens. */ @@ -138,66 +144,72 @@ #define BLTINONEARG 273 #define BLTINARGLIST 274 #define TWOWORDBUILTIN 275 -#define ID 276 -#define STRING 277 -#define HANDLER 278 -#define SYMBOL 279 -#define ENDCLAUSE 280 -#define tPLAYACCEL 281 -#define tDOWN 282 -#define tELSE 283 -#define tNLELSIF 284 -#define tEXIT 285 -#define tFRAME 286 -#define tGLOBAL 287 -#define tGO 288 -#define tIF 289 -#define tINTO 290 -#define tLOOP 291 -#define tMACRO 292 -#define tMOVIE 293 -#define tNEXT 294 -#define tOF 295 -#define tPREVIOUS 296 -#define tPUT 297 -#define tREPEAT 298 -#define tSET 299 -#define tTHEN 300 -#define tTO 301 -#define tWHEN 302 -#define tWITH 303 -#define tWHILE 304 -#define tNLELSE 305 -#define tFACTORY 306 -#define tMETHOD 307 -#define tOPEN 308 -#define tPLAY 309 -#define tDONE 310 -#define tINSTANCE 311 -#define tGE 312 -#define tLE 313 -#define tGT 314 -#define tLT 315 -#define tEQ 316 -#define tNEQ 317 -#define tAND 318 -#define tOR 319 -#define tNOT 320 -#define tMOD 321 -#define tAFTER 322 -#define tBEFORE 323 -#define tCONCAT 324 -#define tCONTAINS 325 -#define tSTARTS 326 -#define tCHAR 327 -#define tITEM 328 -#define tLINE 329 -#define tWORD 330 -#define tSPRITE 331 -#define tINTERSECTS 332 -#define tWITHIN 333 -#define tON 334 -#define tME 335 +#define FBLTIN 276 +#define FBLTINNOARGS 277 +#define FBLTINONEARG 278 +#define FBLTINARGLIST 279 +#define ID 280 +#define STRING 281 +#define HANDLER 282 +#define SYMBOL 283 +#define ENDCLAUSE 284 +#define tPLAYACCEL 285 +#define tDOWN 286 +#define tELSE 287 +#define tNLELSIF 288 +#define tEXIT 289 +#define tFRAME 290 +#define tGLOBAL 291 +#define tGO 292 +#define tIF 293 +#define tINTO 294 +#define tLOOP 295 +#define tMACRO 296 +#define tMOVIE 297 +#define tNEXT 298 +#define tOF 299 +#define tPREVIOUS 300 +#define tPUT 301 +#define tREPEAT 302 +#define tSET 303 +#define tTHEN 304 +#define tTO 305 +#define tWHEN 306 +#define tWITH 307 +#define tWHILE 308 +#define tNLELSE 309 +#define tFACTORY 310 +#define tMETHOD 311 +#define tOPEN 312 +#define tPLAY 313 +#define tDONE 314 +#define tINSTANCE 315 +#define tGE 316 +#define tLE 317 +#define tGT 318 +#define tLT 319 +#define tEQ 320 +#define tNEQ 321 +#define tAND 322 +#define tOR 323 +#define tNOT 324 +#define tMOD 325 +#define tAFTER 326 +#define tBEFORE 327 +#define tCONCAT 328 +#define tCONTAINS 329 +#define tSTARTS 330 +#define tCHAR 331 +#define tITEM 332 +#define tLINE 333 +#define tWORD 334 +#define tSPRITE 335 +#define tINTERSECTS 336 +#define tWITHIN 337 +#define tTELL 338 +#define tPROPERTY 339 +#define tON 340 +#define tME 341 @@ -215,7 +227,7 @@ typedef union YYSTYPE Common::Array<double> *arr; } /* Line 1529 of yacc.c. */ -#line 219 "engines/director/lingo/lingo-gr.hpp" +#line 231 "engines/director/lingo/lingo-gr.hpp" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y index 2f693603f1..1e3c721f08 100644 --- a/engines/director/lingo/lingo-gr.y +++ b/engines/director/lingo/lingo-gr.y @@ -92,6 +92,7 @@ void checkEnd(Common::String *token, const char *expect, bool required) { %token<e> THEENTITY THEENTITYWITHID %token<f> FLOAT %token<s> BLTIN BLTINNOARGS BLTINNOARGSORONE BLTINONEARG BLTINARGLIST TWOWORDBUILTIN +%token<s> FBLTIN FBLTINNOARGS FBLTINONEARG FBLTINARGLIST %token<s> ID STRING HANDLER SYMBOL %token<s> ENDCLAUSE tPLAYACCEL %token tDOWN tELSE tNLELSIF tEXIT tFRAME tGLOBAL tGO tIF tINTO tLOOP tMACRO @@ -99,10 +100,10 @@ void checkEnd(Common::String *token, const char *expect, bool required) { %token tWITH tWHILE tNLELSE tFACTORY tMETHOD tOPEN tPLAY tDONE tINSTANCE %token tGE tLE tGT tLT tEQ tNEQ tAND tOR tNOT tMOD %token tAFTER tBEFORE tCONCAT tCONTAINS tSTARTS tCHAR tITEM tLINE tWORD -%token tSPRITE tINTERSECTS tWITHIN +%token tSPRITE tINTERSECTS tWITHIN tTELL tPROPERTY %token tON tME -%type<code> asgn begin elseif elsestmtoneliner end expr if when repeatwhile repeatwith stmtlist +%type<code> asgn begin elseif elsestmtoneliner end expr if when repeatwhile repeatwith stmtlist tell %type<narg> argdef arglist nonemptyarglist %right '=' @@ -185,7 +186,7 @@ asgn: tPUT expr tINTO ID { ; stmtoneliner: expr { g_lingo->code1(g_lingo->c_xpop); } - | func + | proc ; stmt: stmtoneliner @@ -239,12 +240,18 @@ stmt: stmtoneliner (*g_lingo->_currentScript)[$1 + 5] = end; /* end, if cond fails */ checkEnd($11, "repeat", true); } - | when expr end { + | when stmtoneliner end { inst end = 0; WRITE_UINT32(&end, $3); g_lingo->code1(STOP); (*g_lingo->_currentScript)[$1 + 1] = end; } + | tell expr nl stmtlist end ENDCLAUSE { + warning("STUB: TELL is not implemented"); + checkEnd($6, "tell", true); } + | tell expr tTO expr { + warning("STUB: TELL is not implemented"); + } ; ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE { @@ -389,6 +396,10 @@ when: tWHEN ID tTHEN { g_lingo->codeString($2->c_str()); delete $2; } +tell: tTELL { + $$ = g_lingo->code1(g_lingo->c_tellcode); + g_lingo->code1(STOP); } + expr: INT { $$ = g_lingo->codeConst($1); } | FLOAT { $$ = g_lingo->code1(g_lingo->c_fconstpush); @@ -399,9 +410,14 @@ expr: INT { $$ = g_lingo->codeConst($1); } | STRING { $$ = g_lingo->code1(g_lingo->c_stringpush); g_lingo->codeString($1->c_str()); } - | BLTINNOARGS { - $$ = g_lingo->code1(g_lingo->_builtins[*$1]->u.func); + | FBLTINNOARGS { + g_lingo->codeFunc($1, 0); delete $1; } + | FBLTINONEARG expr { + g_lingo->codeFunc($1, 1); + delete $1; } + | FBLTINARGLIST nonemptyarglist { g_lingo->codeFunc($1, $2); } + | FBLTINARGLIST '(' nonemptyarglist ')' { g_lingo->codeFunc($1, $3); } | ID '(' arglist ')' { $$ = g_lingo->codeFunc($1, $3); delete $1; } @@ -456,25 +472,30 @@ expr: INT { $$ = g_lingo->codeConst($1); } | tWORD expr tTO expr tOF expr { g_lingo->code1(g_lingo->c_wordToOf); } ; -func: tPUT expr { g_lingo->code1(g_lingo->c_printtop); } +proc: tPUT expr { g_lingo->code1(g_lingo->c_printtop); } | gotofunc | playfunc | tEXIT tREPEAT { g_lingo->code1(g_lingo->c_exitRepeat); } | tEXIT { g_lingo->codeConst(0); // Push fake value on stack g_lingo->code1(g_lingo->c_procret); } | tGLOBAL globallist + | tPROPERTY propertylist | tINSTANCE instancelist + | BLTINNOARGS { + g_lingo->codeFunc($1, 0); + delete $1; } | BLTINONEARG expr { - g_lingo->code1(g_lingo->_builtins[*$1]->u.func); + g_lingo->codeFunc($1, 1); delete $1; } | BLTINNOARGSORONE expr { - g_lingo->code1(g_lingo->_builtins[*$1]->u.func); + g_lingo->codeFunc($1, 1); delete $1; } | BLTINNOARGSORONE { - g_lingo->code2(g_lingo->c_voidpush, g_lingo->_builtins[*$1]->u.func); + g_lingo->code1(g_lingo->c_voidpush); + g_lingo->codeFunc($1, 1); delete $1; } - | BLTINARGLIST '(' arglist ')' { g_lingo->codeFunc($1, $3); } - | BLTINARGLIST arglist { g_lingo->codeFunc($1, $2); } + | BLTINARGLIST nonemptyarglist { g_lingo->codeFunc($1, $2); } + | BLTINARGLIST '(' nonemptyarglist ')' { g_lingo->codeFunc($1, $3); } | tME '(' ID ')' { g_lingo->codeMe($3, 0); } | tME '(' ID ',' arglist ')' { g_lingo->codeMe($3, $5); } | tOPEN expr tWITH expr { g_lingo->code1(g_lingo->c_open); } @@ -482,8 +503,12 @@ func: tPUT expr { g_lingo->code1(g_lingo->c_printtop); } | TWOWORDBUILTIN ID arglist { Common::String s(*$1); s += '-'; s += *$2; g_lingo->codeFunc(&s, $3); } ; -globallist: ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($1->c_str()); delete $1; } - | globallist ',' ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($3->c_str()); delete $3; } +globallist: ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($1->c_str()); delete $1; } + | globallist ',' ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($3->c_str()); delete $3; } + ; + +propertylist: ID { g_lingo->code1(g_lingo->c_property); g_lingo->codeString($1->c_str()); delete $1; } + | propertylist ',' ID { g_lingo->code1(g_lingo->c_property); g_lingo->codeString($3->c_str()); delete $3; } ; instancelist: ID { g_lingo->code1(g_lingo->c_instance); g_lingo->codeString($1->c_str()); delete $1; } @@ -608,8 +633,8 @@ arglist: /* nothing */ { $$ = 0; } | arglist ',' expr { $$ = $1 + 1; } ; -nonemptyarglist: expr { $$ = 1; } - | arglist ',' expr { $$ = $1 + 1; } +nonemptyarglist: expr { $$ = 1; } + | nonemptyarglist ',' expr { $$ = $1 + 1; } ; %% diff --git a/engines/director/lingo/lingo-lex.cpp b/engines/director/lingo/lingo-lex.cpp index fb6c4a21e5..66199ecaa1 100644 --- a/engines/director/lingo/lingo-lex.cpp +++ b/engines/director/lingo/lingo-lex.cpp @@ -364,8 +364,8 @@ static void yy_fatal_error (yyconst char msg[] ); *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 69 -#define YY_END_OF_BUFFER 70 +#define YY_NUM_RULES 72 +#define YY_END_OF_BUFFER 73 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -373,36 +373,37 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[253] = +static yyconst flex_int16_t yy_accept[271] = { 0, - 0, 0, 70, 68, 3, 66, 66, 68, 68, 68, - 65, 65, 65, 64, 65, 65, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 2, 2, 3, 66, 0, 0, - 0, 0, 0, 67, 4, 61, 1, 63, 64, 60, - 58, 59, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 22, 12, 62, 62, 62, - 62, 62, 62, 62, 62, 62, 35, 36, 62, 38, - 62, 62, 62, 62, 62, 62, 62, 62, 51, 62, - 62, 62, 2, 2, 0, 4, 1, 63, 62, 6, - - 62, 62, 62, 62, 62, 62, 16, 62, 62, 62, - 62, 0, 62, 62, 62, 62, 62, 62, 62, 31, - 62, 62, 34, 62, 62, 62, 42, 62, 44, 62, - 62, 62, 62, 62, 62, 62, 0, 62, 62, 8, - 62, 10, 11, 15, 0, 16, 18, 62, 62, 62, - 0, 62, 62, 25, 26, 27, 28, 62, 62, 62, - 33, 37, 39, 62, 62, 62, 62, 0, 50, 55, - 62, 53, 57, 14, 5, 62, 62, 16, 16, 62, - 19, 62, 21, 62, 62, 29, 62, 32, 62, 62, - 62, 62, 62, 49, 49, 56, 62, 0, 7, 62, - - 16, 62, 20, 62, 62, 30, 62, 62, 43, 52, - 45, 0, 0, 49, 54, 0, 62, 17, 62, 62, - 62, 62, 0, 0, 0, 0, 49, 13, 9, 23, - 62, 62, 41, 0, 0, 0, 49, 62, 40, 0, - 0, 0, 0, 24, 48, 47, 48, 0, 0, 0, - 46, 0 + 0, 0, 73, 71, 3, 69, 69, 71, 71, 71, + 68, 68, 68, 67, 68, 68, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 2, 2, 3, 69, 0, 0, + 0, 0, 0, 70, 4, 64, 1, 66, 67, 63, + 61, 62, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 22, 12, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 35, 36, 65, 38, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 54, + 65, 65, 65, 2, 2, 0, 4, 1, 66, 65, + + 6, 65, 65, 65, 65, 65, 65, 16, 65, 65, + 65, 65, 0, 65, 65, 65, 65, 65, 65, 65, + 31, 65, 65, 34, 65, 65, 65, 65, 43, 65, + 45, 65, 65, 65, 65, 65, 65, 65, 65, 0, + 65, 65, 8, 65, 10, 11, 15, 0, 16, 18, + 65, 65, 65, 0, 65, 65, 25, 26, 27, 28, + 65, 65, 65, 33, 37, 39, 65, 65, 65, 65, + 65, 47, 0, 53, 58, 65, 56, 60, 14, 5, + 65, 65, 16, 16, 65, 19, 65, 21, 65, 65, + 29, 65, 32, 65, 65, 65, 65, 65, 65, 52, + + 52, 52, 59, 65, 0, 7, 65, 16, 65, 20, + 65, 65, 30, 65, 65, 65, 44, 55, 46, 0, + 0, 52, 52, 57, 0, 65, 17, 65, 65, 65, + 65, 65, 0, 0, 0, 0, 52, 52, 13, 9, + 23, 65, 65, 41, 42, 0, 0, 0, 52, 52, + 65, 40, 0, 0, 0, 0, 0, 24, 51, 50, + 51, 0, 0, 0, 0, 0, 0, 48, 49, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -448,73 +449,77 @@ static yyconst flex_int32_t yy_meta[65] = 5, 5, 5, 5 } ; -static yyconst flex_int16_t yy_base[264] = +static yyconst flex_int16_t yy_base[282] = { 0, - 0, 63, 160, 645, 67, 71, 75, 79, 140, 0, - 645, 133, 126, 54, 70, 94, 65, 67, 65, 61, + 0, 63, 159, 697, 67, 71, 75, 79, 147, 0, + 697, 133, 126, 54, 70, 94, 65, 67, 65, 61, 71, 87, 72, 0, 103, 81, 119, 109, 135, 118, - 82, 112, 146, 155, 194, 208, 212, 645, 216, 181, - 220, 121, 99, 645, 0, 645, 0, 88, 95, 645, - 645, 645, 0, 118, 96, 105, 142, 177, 197, 173, - 183, 183, 210, 215, 204, 88, 0, 202, 217, 211, - 213, 225, 211, 228, 208, 216, 0, 0, 228, 0, - 235, 232, 220, 225, 227, 235, 255, 255, 0, 260, - 248, 251, 291, 300, 253, 0, 0, 84, 267, 0, - - 260, 258, 263, 278, 280, 279, 314, 277, 282, 290, - 302, 321, 293, 300, 301, 311, 300, 301, 311, 0, - 312, 304, 0, 311, 303, 307, 0, 326, 0, 323, - 317, 364, 322, 332, 337, 345, 349, 343, 344, 0, - 354, 0, 0, 0, 189, 0, 0, 348, 358, 364, - 354, 365, 352, 0, 0, 0, 0, 357, 358, 368, - 0, 0, 374, 369, 380, 364, 368, 408, 0, 0, - 384, 390, 0, 237, 0, 397, 395, 0, 0, 391, - 0, 398, 645, 397, 394, 0, 401, 0, 410, 401, - 397, 412, 401, 434, 455, 0, 408, 465, 0, 409, - - 0, 407, 0, 432, 432, 0, 444, 432, 0, 0, - 0, 475, 444, 481, 0, 447, 438, 0, 452, 455, - 454, 448, 479, 476, 475, 476, 502, 645, 0, 0, - 473, 489, 0, 482, 519, 491, 525, 489, 0, 504, - 526, 518, 540, 0, 645, 544, 645, 546, 522, 550, - 551, 645, 600, 602, 605, 608, 614, 619, 624, 627, - 632, 634, 639 + 82, 112, 153, 155, 191, 208, 212, 697, 216, 179, + 224, 119, 99, 697, 0, 697, 0, 88, 95, 697, + 697, 697, 0, 113, 96, 105, 159, 169, 194, 172, + 188, 199, 215, 218, 201, 88, 0, 203, 218, 212, + 212, 224, 213, 226, 211, 216, 0, 0, 223, 0, + 235, 237, 219, 226, 238, 243, 262, 255, 259, 0, + 263, 251, 257, 290, 313, 262, 0, 0, 84, 277, + + 0, 271, 269, 268, 278, 278, 287, 184, 276, 277, + 291, 303, 327, 293, 309, 306, 301, 306, 307, 317, + 0, 317, 309, 0, 316, 308, 312, 319, 0, 330, + 0, 328, 323, 330, 377, 330, 333, 341, 350, 350, + 342, 344, 0, 368, 0, 0, 0, 386, 0, 0, + 357, 368, 375, 364, 380, 367, 0, 0, 0, 0, + 372, 373, 377, 0, 0, 387, 382, 387, 392, 377, + 378, 0, 414, 0, 0, 394, 395, 0, 423, 0, + 400, 406, 0, 0, 402, 0, 411, 697, 410, 408, + 0, 423, 0, 425, 417, 416, 415, 430, 419, 450, + + 465, 476, 0, 432, 478, 0, 435, 0, 447, 0, + 435, 463, 0, 470, 455, 457, 0, 0, 0, 492, + 475, 491, 519, 0, 476, 468, 0, 484, 487, 492, + 483, 478, 531, 502, 513, 514, 538, 545, 697, 0, + 0, 510, 526, 0, 0, 519, 554, 529, 560, 561, + 524, 0, 546, 570, 547, 581, 582, 0, 697, 586, + 697, 593, 552, 598, 567, 603, 604, 605, 613, 697, + 652, 654, 657, 660, 666, 671, 676, 679, 684, 686, + 691 } ; -static yyconst flex_int16_t yy_def[264] = +static yyconst flex_int16_t yy_def[282] = { 0, - 252, 1, 252, 252, 252, 252, 252, 252, 253, 254, - 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 252, 252, 252, 252, 252, 252, - 252, 252, 253, 252, 256, 252, 257, 252, 252, 252, - 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 252, 252, 252, 256, 257, 252, 255, 255, - - 255, 255, 255, 255, 255, 255, 258, 255, 255, 255, - 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 252, 255, 255, 255, - 255, 255, 255, 255, 259, 260, 255, 255, 255, 255, - 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 261, 255, 255, - 255, 255, 255, 252, 255, 255, 255, 262, 260, 255, - 255, 255, 252, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 261, 261, 255, 255, 252, 255, 255, - - 262, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 252, 252, 261, 255, 252, 255, 255, 255, 255, - 255, 255, 252, 252, 252, 252, 261, 252, 255, 255, - 255, 255, 255, 252, 252, 252, 261, 255, 255, 252, - 263, 252, 252, 255, 252, 263, 252, 252, 252, 252, - 263, 0, 252, 252, 252, 252, 252, 252, 252, 252, - 252, 252, 252 + 270, 1, 270, 270, 270, 270, 270, 270, 271, 272, + 270, 270, 270, 270, 270, 270, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 270, 270, 270, 270, 270, 270, + 270, 270, 271, 270, 274, 270, 275, 270, 270, 270, + 270, 270, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 270, 270, 270, 274, 275, 270, 273, + + 273, 273, 273, 273, 273, 273, 273, 276, 273, 273, + 273, 273, 270, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 270, + 273, 273, 273, 273, 273, 273, 273, 277, 278, 273, + 273, 273, 273, 270, 273, 273, 273, 273, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, + 273, 273, 279, 273, 273, 273, 273, 273, 270, 273, + 273, 273, 280, 278, 273, 273, 273, 270, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 279, + + 279, 279, 273, 273, 270, 273, 273, 280, 273, 273, + 273, 273, 273, 273, 273, 273, 273, 273, 273, 270, + 270, 279, 279, 273, 270, 273, 273, 273, 273, 273, + 273, 273, 270, 270, 270, 270, 279, 279, 270, 273, + 273, 273, 273, 273, 273, 270, 270, 270, 279, 279, + 273, 273, 270, 281, 270, 270, 270, 273, 270, 281, + 270, 270, 270, 270, 270, 270, 270, 281, 281, 0, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270 } ; -static yyconst flex_int16_t yy_nxt[710] = +static yyconst flex_int16_t yy_nxt[762] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 11, 13, 4, 14, 15, 11, 16, 17, 18, 19, 20, @@ -524,79 +529,85 @@ static yyconst flex_int16_t yy_nxt[710] = 26, 27, 28, 29, 30, 24, 31, 32, 33, 24, 24, 34, 24, 24, 35, 48, 49, 36, 37, 38, 38, 39, 40, 41, 41, 40, 40, 41, 41, 40, - 39, 38, 38, 39, 50, 51, 54, 56, 57, 112, - 59, 42, 112, 55, 58, 42, 98, 60, 65, 61, + 39, 38, 38, 39, 50, 51, 54, 56, 57, 113, + 59, 42, 113, 55, 58, 42, 99, 60, 65, 61, - 98, 66, 84, 63, 44, 70, 48, 49, 52, 62, - 71, 54, 56, 57, 59, 100, 42, 55, 58, 64, - 42, 60, 65, 61, 67, 66, 101, 84, 63, 75, + 99, 66, 84, 63, 44, 70, 48, 49, 52, 62, + 71, 54, 56, 57, 59, 101, 42, 55, 58, 64, + 42, 60, 65, 61, 67, 66, 102, 84, 63, 75, 70, 68, 85, 62, 71, 72, 47, 69, 76, 73, - 100, 46, 86, 64, 81, 44, 87, 95, 74, 67, - 82, 101, 99, 83, 75, 68, 77, 85, 102, 252, - 72, 69, 76, 78, 73, 79, 86, 80, 81, 88, - 87, 95, 74, 252, 82, 89, 99, 83, 90, 91, - 252, 77, 40, 102, 92, 40, 252, 78, 252, 79, - 145, 80, 252, 145, 88, 93, 38, 38, 94, 89, - - 252, 42, 107, 90, 91, 103, 106, 108, 92, 94, - 38, 38, 94, 37, 38, 38, 39, 39, 38, 38, - 39, 40, 41, 41, 40, 104, 42, 107, 109, 103, - 106, 110, 108, 111, 105, 113, 114, 115, 198, 116, - 42, 198, 117, 118, 252, 119, 122, 120, 124, 104, - 123, 125, 126, 109, 127, 128, 110, 111, 105, 113, - 114, 129, 115, 116, 121, 42, 117, 130, 118, 119, - 122, 131, 120, 124, 123, 132, 125, 126, 127, 128, - 133, 252, 135, 136, 134, 129, 137, 138, 121, 139, - 140, 130, 93, 38, 38, 94, 131, 141, 142, 144, - - 132, 94, 38, 38, 94, 133, 135, 136, 143, 134, - 137, 147, 138, 139, 140, 145, 148, 149, 145, 150, - 153, 141, 112, 142, 144, 112, 53, 152, 155, 154, - 157, 156, 143, 158, 159, 147, 160, 252, 161, 162, - 148, 149, 163, 164, 150, 153, 165, 166, 252, 167, - 170, 152, 155, 154, 157, 151, 156, 158, 171, 159, - 172, 160, 161, 162, 173, 168, 163, 164, 168, 174, - 177, 165, 166, 167, 170, 175, 176, 180, 181, 151, - 182, 184, 171, 183, 185, 172, 186, 187, 188, 173, - 189, 252, 169, 190, 174, 177, 191, 252, 192, 175, - - 176, 180, 193, 181, 196, 182, 184, 183, 185, 168, - 186, 187, 168, 188, 197, 189, 169, 199, 190, 200, - 206, 191, 192, 202, 203, 204, 193, 205, 207, 196, - 208, 209, 210, 252, 211, 212, 215, 217, 212, 197, - 252, 195, 199, 213, 200, 206, 218, 202, 203, 204, - 219, 205, 220, 207, 208, 209, 212, 210, 211, 212, - 215, 217, 221, 224, 213, 195, 198, 222, 228, 198, - 218, 229, 230, 231, 232, 219, 223, 220, 226, 223, - 223, 233, 212, 223, 252, 212, 214, 221, 224, 216, - 213, 222, 234, 228, 224, 229, 235, 230, 231, 232, - - 236, 252, 226, 212, 225, 233, 212, 238, 225, 226, - 214, 213, 252, 227, 216, 239, 240, 234, 242, 224, - 241, 235, 244, 241, 245, 236, 243, 241, 225, 243, - 241, 238, 225, 226, 213, 252, 237, 227, 247, 239, - 240, 248, 242, 250, 248, 252, 244, 248, 252, 245, - 248, 251, 251, 252, 251, 251, 252, 252, 252, 224, - 237, 252, 252, 247, 252, 252, 252, 252, 250, 249, - 252, 252, 252, 252, 226, 249, 252, 252, 252, 252, - 252, 252, 252, 252, 224, 252, 252, 252, 252, 252, - 252, 252, 252, 249, 252, 252, 252, 252, 226, 249, - - 43, 43, 252, 43, 43, 43, 45, 45, 53, 53, - 53, 96, 96, 96, 97, 97, 252, 97, 97, 97, - 146, 252, 146, 146, 146, 178, 252, 252, 178, 178, - 179, 179, 179, 194, 252, 252, 194, 201, 201, 201, - 246, 252, 252, 246, 3, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - - 252, 252, 252, 252, 252, 252, 252, 252, 252 + 101, 46, 86, 64, 81, 96, 87, 100, 74, 67, + 82, 102, 44, 83, 75, 68, 77, 85, 270, 270, + 72, 69, 76, 78, 73, 79, 86, 80, 81, 96, + 87, 100, 74, 88, 82, 103, 89, 83, 91, 92, + 40, 77, 90, 40, 93, 148, 270, 78, 148, 79, + 270, 80, 94, 38, 38, 95, 53, 104, 88, 42, + + 103, 89, 270, 91, 92, 107, 90, 108, 93, 95, + 38, 38, 95, 37, 38, 38, 39, 39, 38, 38, + 39, 104, 105, 109, 42, 40, 41, 41, 40, 107, + 112, 106, 108, 110, 111, 270, 114, 115, 116, 270, + 117, 118, 119, 125, 42, 121, 105, 120, 109, 123, + 124, 126, 270, 129, 112, 106, 130, 127, 110, 111, + 114, 115, 122, 116, 117, 118, 128, 119, 125, 42, + 121, 120, 131, 123, 124, 132, 126, 129, 133, 135, + 130, 134, 127, 136, 270, 138, 122, 137, 270, 139, + 128, 94, 38, 38, 95, 140, 131, 141, 145, 132, + + 142, 143, 144, 133, 135, 134, 146, 147, 136, 138, + 150, 151, 137, 139, 95, 38, 38, 95, 152, 140, + 153, 159, 141, 145, 142, 143, 144, 155, 113, 156, + 146, 113, 147, 158, 150, 151, 160, 270, 157, 161, + 162, 163, 152, 164, 165, 153, 159, 166, 167, 168, + 169, 155, 170, 270, 156, 171, 172, 158, 175, 176, + 160, 154, 157, 161, 177, 162, 163, 164, 165, 178, + 179, 166, 167, 168, 180, 169, 181, 170, 173, 171, + 172, 173, 175, 176, 182, 154, 185, 148, 186, 177, + 148, 187, 270, 188, 178, 179, 189, 193, 180, 190, + + 181, 191, 192, 194, 270, 174, 195, 196, 197, 182, + 185, 198, 199, 186, 203, 173, 187, 188, 173, 204, + 206, 189, 193, 190, 205, 191, 192, 205, 194, 174, + 207, 195, 196, 197, 209, 198, 199, 210, 211, 203, + 201, 212, 213, 214, 204, 206, 215, 202, 216, 217, + 218, 220, 219, 228, 220, 207, 270, 270, 209, 221, + 224, 210, 211, 226, 201, 212, 220, 213, 214, 220, + 215, 202, 216, 217, 221, 218, 219, 220, 228, 205, + 220, 222, 205, 229, 224, 221, 227, 226, 230, 270, + 231, 232, 220, 233, 234, 220, 233, 239, 270, 270, + + 221, 240, 225, 270, 241, 242, 222, 223, 229, 236, + 227, 234, 243, 230, 231, 232, 244, 245, 246, 234, + 220, 235, 239, 220, 237, 240, 236, 225, 221, 241, + 242, 223, 233, 236, 247, 233, 234, 243, 248, 220, + 244, 245, 220, 246, 251, 235, 220, 221, 237, 220, + 236, 238, 252, 253, 221, 254, 255, 258, 254, 247, + 235, 256, 257, 248, 256, 257, 259, 261, 251, 221, + 221, 254, 249, 266, 254, 238, 252, 253, 270, 250, + 255, 258, 262, 264, 235, 262, 264, 270, 267, 270, + 270, 259, 261, 270, 262, 270, 249, 262, 266, 264, + + 234, 234, 264, 250, 268, 269, 268, 268, 269, 268, + 263, 265, 270, 267, 269, 236, 236, 269, 270, 270, + 270, 270, 263, 270, 270, 234, 234, 265, 270, 270, + 270, 270, 270, 270, 263, 265, 270, 270, 270, 236, + 236, 270, 270, 270, 270, 270, 263, 270, 270, 270, + 270, 265, 43, 43, 270, 43, 43, 43, 45, 45, + 53, 53, 53, 97, 97, 97, 98, 98, 270, 98, + 98, 98, 149, 270, 149, 149, 149, 183, 270, 270, + 183, 183, 184, 184, 184, 200, 270, 270, 200, 208, + 208, 208, 260, 270, 270, 260, 3, 270, 270, 270, + + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270 } ; -static yyconst flex_int16_t yy_chk[710] = +static yyconst flex_int16_t yy_chk[762] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -607,75 +618,81 @@ static yyconst flex_int16_t yy_chk[710] = 1, 1, 1, 1, 2, 14, 14, 2, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 15, 15, 17, 18, 19, 66, - 20, 6, 66, 17, 19, 7, 98, 21, 23, 21, + 20, 6, 66, 17, 19, 7, 99, 21, 23, 21, 48, 23, 31, 22, 43, 26, 49, 49, 16, 21, 26, 17, 18, 19, 20, 55, 6, 17, 19, 22, 7, 21, 23, 21, 25, 23, 56, 31, 22, 28, 26, 25, 32, 21, 26, 27, 13, 25, 28, 27, - 55, 12, 32, 22, 30, 9, 32, 42, 27, 25, - 30, 56, 54, 30, 28, 25, 29, 32, 57, 3, - 27, 25, 28, 29, 27, 29, 32, 29, 30, 33, - 32, 42, 27, 0, 30, 33, 54, 30, 34, 34, - 0, 29, 40, 57, 34, 40, 0, 29, 0, 29, - 145, 29, 0, 145, 33, 35, 35, 35, 35, 33, - - 0, 40, 61, 34, 34, 58, 60, 62, 34, 36, + 55, 12, 32, 22, 30, 42, 32, 54, 27, 25, + 30, 56, 9, 30, 28, 25, 29, 32, 3, 0, + 27, 25, 28, 29, 27, 29, 32, 29, 30, 42, + 32, 54, 27, 33, 30, 57, 33, 30, 34, 34, + 40, 29, 33, 40, 34, 108, 0, 29, 108, 29, + 0, 29, 35, 35, 35, 35, 108, 58, 33, 40, + + 57, 33, 0, 34, 34, 60, 33, 61, 34, 36, 36, 36, 36, 37, 37, 37, 37, 39, 39, 39, - 39, 41, 41, 41, 41, 59, 40, 61, 63, 58, - 60, 64, 62, 65, 59, 68, 68, 69, 174, 70, - 41, 174, 71, 72, 0, 73, 75, 74, 79, 59, - 76, 81, 82, 63, 83, 84, 64, 65, 59, 68, - 68, 85, 69, 70, 74, 41, 71, 86, 72, 73, - 75, 87, 74, 79, 76, 88, 81, 82, 83, 84, - 90, 0, 91, 92, 90, 85, 95, 99, 74, 101, - 102, 86, 93, 93, 93, 93, 87, 103, 104, 106, - - 88, 94, 94, 94, 94, 90, 91, 92, 105, 90, - 95, 108, 99, 101, 102, 107, 109, 110, 107, 111, - 114, 103, 112, 104, 106, 112, 107, 113, 115, 114, - 117, 116, 105, 118, 119, 108, 121, 0, 122, 124, - 109, 110, 125, 126, 111, 114, 128, 130, 0, 131, - 133, 113, 115, 114, 117, 112, 116, 118, 134, 119, - 135, 121, 122, 124, 136, 132, 125, 126, 132, 137, - 141, 128, 130, 131, 133, 138, 139, 148, 149, 112, - 150, 152, 134, 151, 153, 135, 158, 159, 160, 136, - 163, 0, 132, 164, 137, 141, 165, 0, 166, 138, - - 139, 148, 167, 149, 171, 150, 152, 151, 153, 168, - 158, 159, 168, 160, 172, 163, 132, 176, 164, 177, - 187, 165, 166, 180, 182, 184, 167, 185, 189, 171, - 190, 191, 192, 0, 193, 194, 197, 200, 194, 172, - 0, 168, 176, 194, 177, 187, 202, 180, 182, 184, - 204, 185, 205, 189, 190, 191, 195, 192, 193, 195, - 197, 200, 207, 213, 195, 168, 198, 208, 216, 198, - 202, 217, 219, 220, 221, 204, 212, 205, 213, 212, - 223, 222, 214, 223, 0, 214, 195, 207, 213, 198, - 214, 208, 224, 216, 212, 217, 225, 219, 220, 221, - - 226, 0, 213, 227, 212, 222, 227, 231, 223, 212, - 195, 227, 0, 214, 198, 232, 234, 224, 236, 212, - 235, 225, 238, 235, 240, 226, 237, 241, 212, 237, - 241, 231, 223, 212, 237, 0, 227, 214, 242, 232, - 234, 243, 236, 249, 243, 246, 238, 248, 246, 240, - 248, 250, 251, 0, 250, 251, 0, 0, 0, 243, - 227, 0, 0, 242, 0, 0, 0, 0, 249, 243, - 0, 0, 0, 0, 243, 248, 0, 0, 0, 0, - 0, 0, 0, 0, 243, 0, 0, 0, 0, 0, - 0, 0, 0, 243, 0, 0, 0, 0, 243, 248, - - 253, 253, 0, 253, 253, 253, 254, 254, 255, 255, - 255, 256, 256, 256, 257, 257, 0, 257, 257, 257, - 258, 0, 258, 258, 258, 259, 0, 0, 259, 259, - 260, 260, 260, 261, 0, 0, 261, 262, 262, 262, - 263, 0, 0, 263, 252, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - - 252, 252, 252, 252, 252, 252, 252, 252, 252 + 39, 58, 59, 62, 40, 41, 41, 41, 41, 60, + 65, 59, 61, 63, 64, 0, 68, 68, 69, 0, + 70, 71, 72, 79, 41, 74, 59, 73, 62, 75, + 76, 81, 0, 83, 65, 59, 84, 82, 63, 64, + 68, 68, 74, 69, 70, 71, 82, 72, 79, 41, + 74, 73, 85, 75, 76, 86, 81, 83, 87, 89, + 84, 88, 82, 91, 0, 92, 74, 91, 0, 93, + 82, 94, 94, 94, 94, 96, 85, 100, 105, 86, + + 102, 103, 104, 87, 89, 88, 106, 107, 91, 92, + 109, 110, 91, 93, 95, 95, 95, 95, 111, 96, + 112, 117, 100, 105, 102, 103, 104, 114, 113, 115, + 106, 113, 107, 116, 109, 110, 118, 0, 115, 119, + 120, 122, 111, 123, 125, 112, 117, 126, 127, 128, + 130, 114, 132, 0, 115, 133, 134, 116, 136, 137, + 118, 113, 115, 119, 138, 120, 122, 123, 125, 139, + 140, 126, 127, 128, 141, 130, 142, 132, 135, 133, + 134, 135, 136, 137, 144, 113, 151, 148, 152, 138, + 148, 153, 0, 154, 139, 140, 155, 163, 141, 156, + + 142, 161, 162, 166, 0, 135, 167, 168, 169, 144, + 151, 170, 171, 152, 176, 173, 153, 154, 173, 177, + 181, 155, 163, 156, 179, 161, 162, 179, 166, 135, + 182, 167, 168, 169, 185, 170, 171, 187, 189, 176, + 173, 190, 192, 194, 177, 181, 195, 173, 196, 197, + 198, 200, 199, 211, 200, 182, 0, 0, 185, 200, + 204, 187, 189, 207, 173, 190, 201, 192, 194, 201, + 195, 173, 196, 197, 201, 198, 199, 202, 211, 205, + 202, 201, 205, 212, 204, 202, 209, 207, 214, 0, + 215, 216, 222, 220, 221, 222, 220, 225, 0, 0, + + 222, 226, 205, 0, 228, 229, 201, 202, 212, 221, + 209, 220, 230, 214, 215, 216, 231, 232, 234, 221, + 223, 220, 225, 223, 222, 226, 220, 205, 223, 228, + 229, 202, 233, 221, 235, 233, 220, 230, 236, 237, + 231, 232, 237, 234, 242, 220, 238, 237, 222, 238, + 220, 223, 243, 246, 238, 247, 248, 251, 247, 235, + 233, 249, 250, 236, 249, 250, 253, 255, 242, 249, + 250, 254, 237, 263, 254, 223, 243, 246, 0, 238, + 248, 251, 256, 257, 233, 256, 257, 260, 265, 0, + 260, 253, 255, 0, 262, 0, 237, 262, 263, 264, + + 256, 257, 264, 238, 266, 267, 268, 266, 267, 268, + 256, 257, 0, 265, 269, 256, 257, 269, 0, 0, + 0, 0, 262, 0, 0, 256, 257, 264, 0, 0, + 0, 0, 0, 0, 256, 257, 0, 0, 0, 256, + 257, 0, 0, 0, 0, 0, 262, 0, 0, 0, + 0, 264, 271, 271, 0, 271, 271, 271, 272, 272, + 273, 273, 273, 274, 274, 274, 275, 275, 0, 275, + 275, 275, 276, 0, 276, 276, 276, 277, 0, 0, + 277, 277, 278, 278, 278, 279, 0, 0, 279, 280, + 280, 280, 281, 0, 0, 281, 270, 270, 270, 270, + + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270 } ; static yy_state_type yy_last_accepting_state; @@ -760,7 +777,7 @@ static int checkImmediate(int token) { return token; } -#line 764 "engines/director/lingo/lingo-lex.cpp" +#line 781 "engines/director/lingo/lingo-lex.cpp" #define INITIAL 0 @@ -946,7 +963,7 @@ YY_DECL #line 82 "engines/director/lingo/lingo-lex.l" -#line 950 "engines/director/lingo/lingo-lex.cpp" +#line 967 "engines/director/lingo/lingo-lex.cpp" if ( !(yy_init) ) { @@ -1000,13 +1017,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 253 ) + if ( yy_current_state >= 271 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 645 ); + while ( yy_base[yy_current_state] != 697 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1250,41 +1267,72 @@ YY_RULE_SETUP case 42: YY_RULE_SETUP #line 137 "engines/director/lingo/lingo-lex.l" -{ count(); return tPUT; } +{ count(); return tPROPERTY; } // D4 YY_BREAK case 43: YY_RULE_SETUP #line 138 "engines/director/lingo/lingo-lex.l" -{ count(); return checkImmediate(tREPEAT); } +{ count(); return tPUT; } YY_BREAK case 44: YY_RULE_SETUP #line 139 "engines/director/lingo/lingo-lex.l" -{ count(); return tSET; } +{ count(); return checkImmediate(tREPEAT); } YY_BREAK case 45: YY_RULE_SETUP #line 140 "engines/director/lingo/lingo-lex.l" -{ count(); return tSTARTS; } +{ count(); return tSET; } YY_BREAK case 46: YY_RULE_SETUP #line 141 "engines/director/lingo/lingo-lex.l" +{ count(); return tSTARTS; } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 142 "engines/director/lingo/lingo-lex.l" +{ count(); return tTELL; } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 143 "engines/director/lingo/lingo-lex.l" +{ + count(); + + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the last: Read '%s'", yytext); + + yylval.e[0] = g_lingo->_theEntities["last"]->entity; + yylval.e[1] = 0; // No field + + return THEENTITYWITHID; + } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 154 "engines/director/lingo/lingo-lex.l" { count(); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the sqrt: Read '%s'", yytext); + yylval.e[0] = g_lingo->_theEntities["sqrt"]->entity; yylval.e[1] = 0; // No field return THEENTITYWITHID; } YY_BREAK -case 47: +case 50: YY_RULE_SETUP -#line 149 "engines/director/lingo/lingo-lex.l" +#line 165 "engines/director/lingo/lingo-lex.l" { count(); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the of: Read '%s'", yytext); + const char *ptr = &yytext[4]; // Skip 'the ' while (*ptr == ' ' || *ptr == '\t') ptr++; @@ -1323,12 +1371,15 @@ YY_RULE_SETUP warning("Unhandled the entity %s", ptr); } YY_BREAK -case 48: +case 51: YY_RULE_SETUP -#line 189 "engines/director/lingo/lingo-lex.l" +#line 208 "engines/director/lingo/lingo-lex.l" { count(); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the date: Read '%s'", yytext); + const char *ptr = &yytext[4]; // Skip 'the ' while (*ptr == ' ' || *ptr == '\t') ptr++; @@ -1358,12 +1409,15 @@ YY_RULE_SETUP return THEENTITY; } YY_BREAK -case 49: +case 52: YY_RULE_SETUP -#line 220 "engines/director/lingo/lingo-lex.l" +#line 242 "engines/director/lingo/lingo-lex.l" { count(); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the: Read '%s'", yytext); + const char *ptr = &yytext[4]; // Skip 'the ' while (*ptr == ' ' || *ptr == '\t') ptr++; @@ -1381,73 +1435,76 @@ YY_RULE_SETUP warning("Unhandled the entity %s", ptr); } YY_BREAK -case 50: +case 53: YY_RULE_SETUP -#line 239 "engines/director/lingo/lingo-lex.l" +#line 264 "engines/director/lingo/lingo-lex.l" { count(); return tTHEN; } YY_BREAK -case 51: +case 54: YY_RULE_SETUP -#line 240 "engines/director/lingo/lingo-lex.l" +#line 265 "engines/director/lingo/lingo-lex.l" { count(); return tTO; } YY_BREAK -case 52: +case 55: YY_RULE_SETUP -#line 241 "engines/director/lingo/lingo-lex.l" +#line 266 "engines/director/lingo/lingo-lex.l" { count(); return tSPRITE; } YY_BREAK -case 53: +case 56: YY_RULE_SETUP -#line 242 "engines/director/lingo/lingo-lex.l" +#line 267 "engines/director/lingo/lingo-lex.l" { count(); return tWITH; } YY_BREAK -case 54: +case 57: YY_RULE_SETUP -#line 243 "engines/director/lingo/lingo-lex.l" +#line 268 "engines/director/lingo/lingo-lex.l" { count(); return tWITHIN; } YY_BREAK -case 55: +case 58: YY_RULE_SETUP -#line 244 "engines/director/lingo/lingo-lex.l" +#line 269 "engines/director/lingo/lingo-lex.l" { count(); return tWHEN; } YY_BREAK -case 56: +case 59: YY_RULE_SETUP -#line 245 "engines/director/lingo/lingo-lex.l" +#line 270 "engines/director/lingo/lingo-lex.l" { count(); return tWHILE; } YY_BREAK -case 57: +case 60: YY_RULE_SETUP -#line 246 "engines/director/lingo/lingo-lex.l" +#line 271 "engines/director/lingo/lingo-lex.l" { count(); return tWORD; } YY_BREAK -case 58: +case 61: YY_RULE_SETUP -#line 248 "engines/director/lingo/lingo-lex.l" +#line 273 "engines/director/lingo/lingo-lex.l" { count(); return tNEQ; } YY_BREAK -case 59: +case 62: YY_RULE_SETUP -#line 249 "engines/director/lingo/lingo-lex.l" +#line 274 "engines/director/lingo/lingo-lex.l" { count(); return tGE; } YY_BREAK -case 60: +case 63: YY_RULE_SETUP -#line 250 "engines/director/lingo/lingo-lex.l" +#line 275 "engines/director/lingo/lingo-lex.l" { count(); return tLE; } YY_BREAK -case 61: +case 64: YY_RULE_SETUP -#line 251 "engines/director/lingo/lingo-lex.l" +#line 276 "engines/director/lingo/lingo-lex.l" { count(); return tCONCAT; } YY_BREAK -case 62: +case 65: YY_RULE_SETUP -#line 253 "engines/director/lingo/lingo-lex.l" +#line 278 "engines/director/lingo/lingo-lex.l" { count(); yylval.s = new Common::String(yytext); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: identifier: Read '%s'", yytext); + if (g_lingo->_ignoreMe && yylval.s->equalsIgnoreCase("me")) return ID; @@ -1461,21 +1518,22 @@ YY_RULE_SETUP } if (g_lingo->_builtins.contains(yytext)) { - if (g_lingo->_builtins[yytext]->type == BLTIN && g_lingo->_builtins[yytext]->parens == false) { + int type = g_lingo->_builtins[yytext]->type; + if ((type == BLTIN || type == FBLTIN) && g_lingo->_builtins[yytext]->parens == false) { if (g_lingo->_builtins[yytext]->nargs == 0) { if (g_lingo->_builtins[yytext]->maxArgs == 0) - return BLTINNOARGS; + return type == BLTIN ? BLTINNOARGS : FBLTINNOARGS; else if (g_lingo->_builtins[yytext]->maxArgs == 1) return BLTINNOARGSORONE; else - error("Incorrect setup for builtin: %s", yytext); + return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST; } else if (g_lingo->_builtins[yytext]->nargs == 1 && g_lingo->_builtins[yytext]->maxArgs == 1) { - return BLTINONEARG; + return type == BLTIN ? BLTINONEARG : FBLTINONEARG; } else if (g_lingo->_builtins[yytext]->nargs == -1) { - return BLTINARGLIST; + return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST; } else { - error("Incorrect setup for builtin: %s", yytext); + return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST; } } } @@ -1483,43 +1541,43 @@ YY_RULE_SETUP return ID; } YY_BREAK -case 63: +case 66: YY_RULE_SETUP -#line 291 "engines/director/lingo/lingo-lex.l" +#line 320 "engines/director/lingo/lingo-lex.l" { count(); yylval.f = atof(yytext); return FLOAT; } YY_BREAK -case 64: +case 67: YY_RULE_SETUP -#line 292 "engines/director/lingo/lingo-lex.l" +#line 321 "engines/director/lingo/lingo-lex.l" { count(); yylval.i = strtol(yytext, NULL, 10); return INT; } YY_BREAK -case 65: +case 68: YY_RULE_SETUP -#line 293 "engines/director/lingo/lingo-lex.l" +#line 322 "engines/director/lingo/lingo-lex.l" { count(); return *yytext; } YY_BREAK -case 66: -/* rule 66 can match eol */ +case 69: +/* rule 69 can match eol */ YY_RULE_SETUP -#line 294 "engines/director/lingo/lingo-lex.l" +#line 323 "engines/director/lingo/lingo-lex.l" { return '\n'; } YY_BREAK -case 67: +case 70: YY_RULE_SETUP -#line 295 "engines/director/lingo/lingo-lex.l" +#line 324 "engines/director/lingo/lingo-lex.l" { count(); yylval.s = new Common::String(&yytext[1]); yylval.s->deleteLastChar(); return STRING; } YY_BREAK -case 68: +case 71: YY_RULE_SETUP -#line 296 "engines/director/lingo/lingo-lex.l" +#line 325 "engines/director/lingo/lingo-lex.l" YY_BREAK -case 69: +case 72: YY_RULE_SETUP -#line 298 "engines/director/lingo/lingo-lex.l" +#line 327 "engines/director/lingo/lingo-lex.l" ECHO; YY_BREAK -#line 1523 "engines/director/lingo/lingo-lex.cpp" +#line 1581 "engines/director/lingo/lingo-lex.cpp" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1812,7 +1870,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 253 ) + if ( yy_current_state >= 271 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1840,11 +1898,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 253 ) + if ( yy_current_state >= 271 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 252); + yy_is_jam = (yy_current_state == 270); return yy_is_jam ? 0 : yy_current_state; } @@ -2482,7 +2540,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 298 "engines/director/lingo/lingo-lex.l" +#line 327 "engines/director/lingo/lingo-lex.l" diff --git a/engines/director/lingo/lingo-lex.l b/engines/director/lingo/lingo-lex.l index 00750c4523..93b57a079a 100644 --- a/engines/director/lingo/lingo-lex.l +++ b/engines/director/lingo/lingo-lex.l @@ -82,22 +82,22 @@ whitespace [\t ] %% --[^\r\n]* -^{whitespace}+ { count(); } -[\t]+ { count(); return ' '; } +^{whitespace}+ { count(); } +[\t]+ { count(); return ' '; } -[#]{identifier} { count(); yylval.s = new Common::String(yytext); return SYMBOL; } // D3 +[#]{identifier} { count(); yylval.s = new Common::String(yytext); return SYMBOL; } // D3 (?i:after) { count(); return tAFTER; } // D3 -(?i:and) { count(); return tAND; } +(?i:and) { count(); return tAND; } (?i:before) { count(); return tBEFORE; } // D3 -(?i:char) { count(); return tCHAR; } // D3 +(?i:char) { count(); return tCHAR; } // D3 (?i:contains) { count(); return tCONTAINS; } -(?i:done) { count(); return tDONE; } -(?i:down) { count(); return tDOWN; } -(?i:if) { count(); return tIF; } +(?i:done) { count(); return tDONE; } +(?i:down) { count(); return tDOWN; } +(?i:if) { count(); return tIF; } (?i:[\n\r]+[\t ]*else[\t ]+if) { countnl(); return tNLELSIF; } (?i:[\n\r]+[\t ]*else) { countnl(); return tNLELSE; } -(?i:else) { count(); return tELSE; } +(?i:else) { count(); return tELSE; } (?i:end)([\t ]*{identifier})? { count(); @@ -110,37 +110,53 @@ whitespace [\t ] return ENDCLAUSE; } (?i:factory) { count(); return tFACTORY; } -(?i:exit) { count(); return tEXIT; } +(?i:exit) { count(); return tEXIT; } (?i:frame) { count(); return tFRAME; } (?i:global) { count(); return tGLOBAL; } -(?i:go[\t ]+to) { count(); return tGO; } -(?i:go) { count(); return tGO; } +(?i:go[\t ]+to) { count(); return tGO; } +(?i:go) { count(); return tGO; } (?i:instance) { count(); return tINSTANCE; } -(?i:intersects) { count(); return tINTERSECTS; } -(?i:into) { count(); return tINTO; } -(?i:item) { count(); return tITEM; } -(?i:line) { count(); return tLINE; } -(?i:loop) { count(); return checkImmediate(tLOOP); } +(?i:intersects) { count(); return tINTERSECTS; } +(?i:into) { count(); return tINTO; } +(?i:item) { count(); return tITEM; } +(?i:line) { count(); return tLINE; } +(?i:loop) { count(); return checkImmediate(tLOOP); } (?i:macro) { count(); return tMACRO; } (?i:method) { count(); return tMETHOD; } -(?i:mod) { count(); return tMOD; } +(?i:mod) { count(); return tMOD; } (?i:movie) { count(); return tMOVIE; } -(?i:next) { count(); return tNEXT; } -(?i:not) { count(); return tNOT; } -(?i:of) { count(); return tOF; } -(?i:on) { count(); return tON; } // D3 -(?i:open) { count(); return tOPEN; } -(?i:or) { count(); return tOR; } -(?i:play) { count(); return tPLAY; } -(?i:playAccel) { count(); yylval.s = new Common::String(yytext); return tPLAYACCEL; } +(?i:next) { count(); return tNEXT; } +(?i:not) { count(); return tNOT; } +(?i:of) { count(); return tOF; } +(?i:on) { count(); return tON; } // D3 +(?i:open) { count(); return tOPEN; } +(?i:or) { count(); return tOR; } +(?i:play) { count(); return tPLAY; } +(?i:playAccel) { count(); yylval.s = new Common::String(yytext); return tPLAYACCEL; } (?i:previous) { count(); return tPREVIOUS; } -(?i:put) { count(); return tPUT; } +(?i:property) { count(); return tPROPERTY; } // D4 +(?i:put) { count(); return tPUT; } (?i:repeat) { count(); return checkImmediate(tREPEAT); } -(?i:set) { count(); return tSET; } +(?i:set) { count(); return tSET; } (?i:starts) { count(); return tSTARTS; } +(?i:tell) { count(); return tTELL; } +(?i:the[ \t]+last[\t ]+of[\t ]+) { + count(); + + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the last: Read '%s'", yytext); + + yylval.e[0] = g_lingo->_theEntities["last"]->entity; + yylval.e[1] = 0; // No field + + return THEENTITYWITHID; + } (?i:the[ \t]+sqrt[\t ]+of[\t ]+) { count(); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the sqrt: Read '%s'", yytext); + yylval.e[0] = g_lingo->_theEntities["sqrt"]->entity; yylval.e[1] = 0; // No field @@ -149,6 +165,9 @@ whitespace [\t ] (?i:the[ \t]+[[:alpha:]]+[\t ]+of[\t ]+[[:alpha:]]+) { count(); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the of: Read '%s'", yytext); + const char *ptr = &yytext[4]; // Skip 'the ' while (*ptr == ' ' || *ptr == '\t') ptr++; @@ -189,6 +208,9 @@ whitespace [\t ] (?i:the[ \t]+[[:alpha:]]+[ \t+](date|time)) { count(); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the date: Read '%s'", yytext); + const char *ptr = &yytext[4]; // Skip 'the ' while (*ptr == ' ' || *ptr == '\t') ptr++; @@ -220,6 +242,9 @@ whitespace [\t ] (?i:the[ \t]+[[:alpha:]]+) { count(); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: the: Read '%s'", yytext); + const char *ptr = &yytext[4]; // Skip 'the ' while (*ptr == ' ' || *ptr == '\t') ptr++; @@ -236,24 +261,27 @@ whitespace [\t ] warning("Unhandled the entity %s", ptr); } -(?i:then) { count(); return tTHEN; } -(?i:to) { count(); return tTO; } +(?i:then) { count(); return tTHEN; } +(?i:to) { count(); return tTO; } (?i:sprite) { count(); return tSPRITE; } -(?i:with) { count(); return tWITH; } +(?i:with) { count(); return tWITH; } (?i:within) { count(); return tWITHIN; } -(?i:when) { count(); return tWHEN; } +(?i:when) { count(); return tWHEN; } (?i:while) { count(); return tWHILE; } -(?i:word) { count(); return tWORD; } +(?i:word) { count(); return tWORD; } -[<][>] { count(); return tNEQ; } -[>][=] { count(); return tGE; } -[<][=] { count(); return tLE; } -[&][&] { count(); return tCONCAT; } +[<][>] { count(); return tNEQ; } +[>][=] { count(); return tGE; } +[<][=] { count(); return tLE; } +[&][&] { count(); return tCONCAT; } -{identifier} { +{identifier} { count(); yylval.s = new Common::String(yytext); + if (debugChannelSet(-1, kDebugLingoCompile)) + debug("LEXER: identifier: Read '%s'", yytext); + if (g_lingo->_ignoreMe && yylval.s->equalsIgnoreCase("me")) return ID; @@ -267,32 +295,33 @@ whitespace [\t ] } if (g_lingo->_builtins.contains(yytext)) { - if (g_lingo->_builtins[yytext]->type == BLTIN && g_lingo->_builtins[yytext]->parens == false) { + int type = g_lingo->_builtins[yytext]->type; + if ((type == BLTIN || type == FBLTIN) && g_lingo->_builtins[yytext]->parens == false) { if (g_lingo->_builtins[yytext]->nargs == 0) { if (g_lingo->_builtins[yytext]->maxArgs == 0) - return BLTINNOARGS; + return type == BLTIN ? BLTINNOARGS : FBLTINNOARGS; else if (g_lingo->_builtins[yytext]->maxArgs == 1) return BLTINNOARGSORONE; else - error("Incorrect setup for builtin: %s", yytext); + return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST; } else if (g_lingo->_builtins[yytext]->nargs == 1 && g_lingo->_builtins[yytext]->maxArgs == 1) { - return BLTINONEARG; + return type == BLTIN ? BLTINONEARG : FBLTINONEARG; } else if (g_lingo->_builtins[yytext]->nargs == -1) { - return BLTINARGLIST; + return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST; } else { - error("Incorrect setup for builtin: %s", yytext); + return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST; } } } return ID; } -{constfloat} { count(); yylval.f = atof(yytext); return FLOAT; } +{constfloat} { count(); yylval.f = atof(yytext); return FLOAT; } {constinteger} { count(); yylval.i = strtol(yytext, NULL, 10); return INT; } -{operator} { count(); return *yytext; } -{newline} { return '\n'; } -{conststring} { count(); yylval.s = new Common::String(&yytext[1]); yylval.s->deleteLastChar(); return STRING; } +{operator} { count(); return *yytext; } +{newline} { return '\n'; } +{conststring} { count(); yylval.s = new Common::String(&yytext[1]); yylval.s->deleteLastChar(); return STRING; } . %% diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp index 71211e3bff..8f874435f7 100644 --- a/engines/director/lingo/lingo-the.cpp +++ b/engines/director/lingo/lingo-the.cpp @@ -30,7 +30,7 @@ class Sprite; TheEntity entities[] = { { kTheActorList, "actorList", false }, // D4 property - { kTheBeepOn, "beepOn", false }, // D2 property + { kTheBeepOn, "beepOn", false }, // D2 p { kTheButtonStyle, "buttonStyle", false }, // D2 p { kTheCast, "cast", true }, // D3 { kTheCastMembers, "castmembers", false }, // D3 @@ -38,7 +38,8 @@ TheEntity entities[] = { { kTheChars, "chars", false }, // D3 { kTheCheckBoxAccess, "checkBoxAccess", false }, // D2 p { kTheCheckBoxType, "checkBoxType", false }, // D2 p - { kTheClickOn, "clickOn", false }, // D2 function + { kTheClickLoc, "clickLoc", false }, // D4 function + { kTheClickOn, "clickOn", false }, // D2 f { kTheColorDepth, "colorDepth", false }, // D2 p { kTheColorQD, "colorQD", false }, // D2 f { kTheCommandDown, "commandDown", false }, // D2 f @@ -50,24 +51,29 @@ TheEntity entities[] = { { kTheFixStageSize, "fixStageSize", false }, // D2 p { kTheFloatPrecision, "floatPrecision", false }, // D3 p { kTheFrame, "frame", false }, // D2 f + { kTheFrameLabel, "frameLabel", false }, // D4 p { kTheFrameScript, "frameScript", false }, // D4 p + { kTheFramePalette, "framePalette", false }, // D4 p { kTheFreeBlock, "freeBlock", false }, // D2 f { kTheFreeBytes, "freeBytes", false }, // D2 f { kTheFullColorPermit, "fullColorPermit", false }, // D2 p { kTheImageDirect, "imageDirect", false }, // D2 p { kTheItems, "items", false }, // D3 - { kTheItemDelimiter, "itemDelimiter", false }, + { kTheItemDelimiter, "itemDelimiter", false }, // D4 p { kTheKey, "key", false }, // D2 f { kTheKeyCode, "keyCode", false }, // D2 f { kTheKeyDownScript, "keyDownScript", false }, // D2 p + { kTheKeyUpScript, "keyUpScript", false }, // D4 p { kTheLabelList, "labelList", false }, // D3 f + { kTheLast, "last", false }, // D4 f { kTheLastClick, "lastClick", false }, // D2 f { kTheLastEvent, "lastEvent", false }, // D2 f - { kTheLastFrame, "lastFrame", false }, + { kTheLastFrame, "lastFrame", false }, // D4 p { kTheLastKey, "lastKey", false }, // D2 f { kTheLastRoll, "lastRoll", false }, // D2 f { kTheLines, "lines", false }, // D3 { kTheMachineType, "machineType", false }, // D2 f + { kTheMaxInteger, "maxInteger", false }, // D4 f { kTheMemorySize, "memorySize", false }, // D2 f { kTheMenu, "menu", true }, { kTheMenus, "menus", false }, @@ -85,16 +91,26 @@ TheEntity entities[] = { { kTheMouseV, "mouseV", false }, // D2 f { kTheMouseWord, "mouseWord", false }, // D3 f { kTheMovie, "movie", false }, // D2 f - { kTheMultiSound, "multiSound", false }, + { kTheMovieFileFreeSize,"movieFileFreeSize",false }, // D4 f + { kTheMovieFileSize, "movieFileSize", false }, // D4 f + { kTheMovieName, "movieName", false }, // D4 f + { kTheMoviePath, "moviePath", false }, // D4 f + { kTheMultiSound, "multiSound", false }, // D4 p { kTheOptionDown, "optionDown", false }, // D2 f + { kTheParamCount, "paramCount", false }, // D4 f { kThePathName, "pathName", false }, // D2 f { kThePauseState, "pauseState", false }, // D2 f { kThePerFrameHook, "perFrameHook", false }, // D2 p - { kThePreloadEventAbort,"preloadEventAbort",false }, + { kThePreloadEventAbort,"preloadEventAbort",false }, // D4 p + { kThePreLoadRAM, "preLoadRAM", false }, // D4 p + { kTheQuickTimePresent, "quickTimePresent", false }, // D4 f + { kTheRandomSeed, "randomSeed", false }, // D4 p { kTheResult, "result", false }, // D2 f { kTheRightMouseDown, "rightMouseDown", false }, { kTheRightMouseUp, "rightMouseUp", false }, - { kTheRomanLingo, "romanLingo", false }, + { kTheRomanLingo, "romanLingo", false }, // D4 p + { kTheSearchCurrentFolder,"searchCurrentFolder",false },// D4 f + { kTheSearchPath, "searchPath", false }, // D4 f { kTheSelection, "selection", false }, // D2 f { kTheSelEnd, "selEnd", false }, // D2 p { kTheSelStart, "selStart", false }, // D2 p @@ -103,7 +119,7 @@ TheEntity entities[] = { { kTheSoundLevel, "soundLevel", false }, // D2 p { kTheSprite, "sprite", true }, // D4 { kTheSqrt, "sqrt", false }, // D2 f - { kTheStage, "stage", false }, + { kTheStage, "stage", false }, // D4 p { kTheStageBottom, "stageBottom", false }, // D2 f { kTheStageColor, "stageColor", false }, // D3 p { kTheStageLeft, "stageLeft", false }, // D2 f @@ -120,19 +136,24 @@ TheEntity entities[] = { { kTheTimeoutScript, "timeoutScript", false }, // D2 p { kTheTime, "time", false }, // D3 f { kTheTimer, "timer", false }, // D2 p - { kTheWindow, "window", false }, + { kTheTrace, "trace", false }, // D4 p + { kTheTraceLoad, "traceLoad", false }, // D4 p + { kTheTraceLogFile, "traceLogFile", false }, // D4 p + { kTheUpdateMovieEnabled,"updateMovieEnabled",false }, // D4 p + { kTheWindow, "window", true }, // D4 + { kTheWindowList, "windowList", false }, // D4 p { kTheWords, "words", false }, // D3 { kTheNOEntity, NULL, false } }; TheEntityField fields[] = { { kTheSprite, "backColor", kTheBackColor }, // D2 p - { kTheSprite, "blend", kTheBlend }, + { kTheSprite, "blend", kTheBlend }, // D4 p { kTheSprite, "bottom", kTheBottom }, // D2 p { kTheSprite, "castNum", kTheCastNum }, // D2 p { kTheSprite, "constraint", kTheConstraint }, // D2 p { kTheSprite, "cursor", kTheCursor }, // D2 p - { kTheSprite, "editableText", kTheEditableText }, + { kTheSprite, "editableText", kTheEditableText }, // D4 p { kTheSprite, "foreColor", kTheForeColor }, // D2 p { kTheSprite, "height", kTheHeight }, // D2 p { kTheSprite, "immediate", kTheImmediate }, // D2 p @@ -141,58 +162,63 @@ TheEntityField fields[] = { { kTheSprite, "lineSize", kTheLineSize }, // D2 p { kTheSprite, "locH", kTheLocH }, // D2 p { kTheSprite, "locV", kTheLocV }, // D2 p - { kTheSprite, "moveable", kTheMoveable }, - { kTheSprite, "movieRate", kTheMovieRate }, - { kTheSprite, "movieTime", kTheMovieTime }, + { kTheSprite, "moveableSprite",kTheMoveableSprite },// D4 p + { kTheSprite, "movieRate", kTheMovieRate }, // D4 P + { kTheSprite, "movieTime", kTheMovieTime }, // D4 P { kTheSprite, "pattern", kThePattern }, // D2 p { kTheSprite, "puppet", kThePuppet }, // D2 p { kTheSprite, "right", kTheRight }, // D2 p - { kTheSprite, "scriptNum", kTheScriptNum }, - { kTheSprite, "startTime", kTheStartTime }, + { kTheSprite, "scoreColor", kTheScoreColor }, // D4 p + { kTheSprite, "scriptNum", kTheScriptNum }, // D4 p + { kTheSprite, "startTime", kTheStartTime }, // D4 p { kTheSprite, "stretch", kTheStrech }, // D2 p - { kTheSprite, "stopTime", kTheStopTime }, + { kTheSprite, "stopTime", kTheStopTime }, // D4 p { kTheSprite, "top", kTheTop }, // D2 p - { kTheSprite, "trails", kTheTrails }, + { kTheSprite, "trails", kTheTrails }, // D4 p { kTheSprite, "type", kTheType }, // D2 p - { kTheSprite, "visible", kTheVisible }, - { kTheSprite, "volume", kTheVolume }, + { kTheSprite, "visible", kTheVisible }, // D4 p + { kTheSprite, "volume", kTheVolume }, // D4 p { kTheSprite, "width", kTheWidth }, // D2 p // Common cast fields { kTheCast, "castType", kTheCastType }, // D4 p - { kTheCast, "filename", kTheFilename }, - { kTheCast, "height", kTheHeight }, - { kTheCast, "loaded", kTheLoaded }, - { kTheCast, "modified", kTheModified }, + { kTheCast, "filename", kTheFileName }, // D4 p + { kTheCast, "height", kTheHeight }, // D4 p + { kTheCast, "loaded", kTheLoaded }, // D4 p + { kTheCast, "modified", kTheModified }, // D4 p { kTheCast, "name", kTheName }, // D3 p { kTheCast, "number", kTheNumber }, // D3 p - { kTheCast, "rect", kTheRect }, - { kTheCast, "purgePriority",kThePurgePriority }, // 0 Never purge, 1 Purge Last, 2 Purge next, 2 Purge normal - { kTheCast, "scriptText", kTheScriptText }, - { kTheCast, "width", kTheWidth }, + { kTheCast, "rect", kTheRect }, // D4 p + { kTheCast, "purgePriority",kThePurgePriority },// D4 p // 0 Never purge, 1 Purge Last, 2 Purge next, 2 Purge normal + { kTheCast, "scriptText", kTheScriptText }, // D4 p + { kTheCast, "width", kTheWidth }, // D4 p // Shape fields - { kTheCast, "backColor", kTheBackColor }, - { kTheCast, "foreColor", kTheForeColor }, + { kTheCast, "backColor", kTheBackColor }, // D4 p + { kTheCast, "foreColor", kTheForeColor }, // D4 p // Digital video fields - { kTheCast, "controller", kTheController }, - { kTheCast, "directToStage",kTheDirectToStage }, - { kTheCast, "frameRate", kTheFrameRate }, - { kTheCast, "loop", kTheLoop }, - { kTheCast, "pausedAtStart",kThePausedAtStart }, - { kTheCast, "preload", kThePreload }, - { kTheCast, "sound", kTheSound }, // 0-1 off-on + { kTheCast, "center", kTheCenter }, // D4 p + { kTheCast, "controller", kTheController }, // D4 p + { kTheCast, "crop", kTheCrop }, // D4 p + { kTheCast, "directToStage",kTheDirectToStage },// D4 p + { kTheCast, "duration", kTheDuration }, // D4 p + { kTheCast, "frameRate", kTheFrameRate }, // D4 p + { kTheCast, "loop", kTheLoop }, // D4 p + { kTheCast, "pausedAtStart",kThePausedAtStart },// D4 p + { kTheCast, "preLoad", kThePreLoad }, // D4 p + { kTheCast, "sound", kTheSound }, // D4 p // 0-1 off-on + { kTheCast, "video", kTheVideo }, // D4 p // Bitmap fields { kTheCast, "depth", kTheDepth }, - { kTheCast, "regPoint", kTheRegPoint }, - { kTheCast, "palette", kThePalette }, + { kTheCast, "regPoint", kTheRegPoint }, // D4 p + { kTheCast, "palette", kThePalette }, // D4 p { kTheCast, "picture", kThePicture }, // D3 p // TextCast fields { kTheCast, "hilite", kTheHilite }, // D2 p - { kTheCast, "size", kTheSize }, + { kTheCast, "size", kTheSize }, // D4 p { kTheCast, "text", kTheText }, // D2 p // Field fields @@ -202,10 +228,15 @@ TheEntityField fields[] = { { kTheField, "textSize", kTheTextSize }, // D3 p { kTheField, "textStyle", kTheTextStyle }, // D3 p - { kTheWindow, "drawRect", kTheDrawRect }, - { kTheWindow, "filename", kTheFilename }, - { kTheWindow, "sourceRect", kTheSourceRect }, - { kTheWindow, "visible", kTheVisible }, + { kTheWindow, "drawRect", kTheDrawRect }, // D4 p + { kTheWindow, "fileName", kTheFileName }, // D4 p + { kTheWindow, "modal", kTheModal }, // D4 p + { kTheWindow, "rect", kTheRect }, // D4 p + { kTheWindow, "title", kTheTitle }, // D4 p + { kTheWindow, "titleVisible", kTheTitleVisible }, // D4 p + { kTheWindow, "sourceRect", kTheSourceRect }, // D4 p + { kTheWindow, "visible", kTheVisible }, // D4 p + { kTheWindow, "windowType", kTheWindowType }, // D4 p { kTheMenuItem, "checkmark", kTheCheckMark }, // D3 p { kTheMenuItem, "enabled", kTheEnabled }, // D3 p @@ -289,20 +320,20 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) { d.toInt(); // Enforce Integer - if (!_vm->_currentScore) { + if (!_vm->getCurrentScore()) { warning("The sprite %d field %d setting over non-active score", id, field); return; } - Sprite *sprite = _vm->_currentScore->getSpriteById(id); + Sprite *sprite = _vm->getCurrentScore()->getSpriteById(id); if (!sprite) return; switch (field) { case kTheCastNum: - if (_vm->_currentScore->_casts.contains(d.u.i)) { - sprite->_cast = _vm->_currentScore->_casts[d.u.i]; + if (_vm->getCurrentScore()->_casts.contains(d.u.i)) { + sprite->_cast = _vm->getCurrentScore()->_casts[d.u.i]; sprite->_castId = d.u.i; } break; @@ -327,7 +358,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) { case kTheConstraint: sprite->_constraint = d.u.i; break; - case kTheMoveable: + case kTheMoveableSprite: sprite->_moveable = d.u.i; break; case kTheBackColor: @@ -491,12 +522,12 @@ Datum Lingo::getTheSprite(Datum &id1, int field) { return d; } - if (!_vm->_currentScore) { + if (!_vm->getCurrentScore()) { warning("The sprite %d field %d setting over non-active score", id, field); return d; } - Sprite *sprite = _vm->_currentScore->getSpriteById(id); + Sprite *sprite = _vm->getCurrentScore()->getSpriteById(id); if (!sprite) return d; @@ -528,7 +559,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) { case kTheConstraint: d.u.i = sprite->_constraint; break; - case kTheMoveable: + case kTheMoveableSprite: d.u.i = sprite->_moveable; break; case kTheBackColor: @@ -602,14 +633,14 @@ Datum Lingo::getTheCast(Datum &id1, int field) { return d; } - if (!_vm->_currentScore) { + if (!_vm->getCurrentScore()) { warning("The cast %d field %d setting over non-active score", id, field); return d; } Cast *cast; CastInfo *castInfo; - if (!_vm->_currentScore->_casts.contains(id)) { + if (!_vm->getCurrentScore()->_casts.contains(id)) { if (field == kTheLoaded) { d.type = INT; d.u.i = 0; @@ -620,8 +651,8 @@ Datum Lingo::getTheCast(Datum &id1, int field) { warning("The cast %d found", id); } - cast = _vm->_currentScore->_casts[id]; - castInfo = _vm->_currentScore->_castsInfo[id]; + cast = _vm->getCurrentScore()->_casts[id]; + castInfo = _vm->getCurrentScore()->_castsInfo[id]; d.type = INT; @@ -629,7 +660,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) { case kTheCastType: d.u.i = cast->type; break; - case kTheFilename: + case kTheFileName: d.toString(); d.u.s = &castInfo->fileName; break; @@ -655,7 +686,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) { return d; } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]); + ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); d.u.i = shape->bgCol; } break; @@ -667,7 +698,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) { return d; } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]); + ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); d.u.i = shape->fgCol; } break; @@ -693,13 +724,13 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) { return; } - if (!_vm->_currentScore) { + if (!_vm->getCurrentScore()) { warning("The cast %d field %d setting over non-active score", id, field); return; } - Cast *cast = _vm->_currentScore->_casts[id]; - CastInfo *castInfo = _vm->_currentScore->_castsInfo[id]; + Cast *cast = _vm->getCurrentScore()->_casts[id]; + CastInfo *castInfo = _vm->getCurrentScore()->_castsInfo[id]; if (!cast) { warning("The cast %d found", id); @@ -711,7 +742,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) { cast->type = static_cast<CastType>(d.u.i); cast->modified = 1; break; - case kTheFilename: + case kTheFileName: castInfo->fileName = *d.u.s; break; case kTheName: @@ -733,7 +764,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) { if (cast->type != kCastShape) { warning("Field %d of cast %d not found", field, id); } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]); + ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); shape->bgCol = d.u.i; shape->modified = 1; } @@ -744,7 +775,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) { warning("Field %d of cast %d not found", field, id); return; } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]); + ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); shape->fgCol = d.u.i; shape->modified = 1; } diff --git a/engines/director/lingo/lingo-the.h b/engines/director/lingo/lingo-the.h index 8cec0ced13..173efe6bbe 100644 --- a/engines/director/lingo/lingo-the.h +++ b/engines/director/lingo/lingo-the.h @@ -36,6 +36,7 @@ enum TheEntityType { kTheChars, kTheCheckBoxAccess, kTheCheckBoxType, + kTheClickLoc, kTheClickOn, kTheColorDepth, kTheColorQD, @@ -48,6 +49,8 @@ enum TheEntityType { kTheFixStageSize, kTheFloatPrecision, kTheFrame, + kTheFrameLabel, + kTheFramePalette, kTheFrameScript, kTheFreeBlock, kTheFreeBytes, @@ -58,7 +61,9 @@ enum TheEntityType { kTheKey, kTheKeyCode, kTheKeyDownScript, + kTheKeyUpScript, kTheLabelList, + kTheLast, kTheLastClick, kTheLastEvent, kTheLastFrame, @@ -66,6 +71,7 @@ enum TheEntityType { kTheLastRoll, kTheLines, kTheMachineType, + kTheMaxInteger, kTheMemorySize, kTheMenu, kTheMenuItem, @@ -83,16 +89,26 @@ enum TheEntityType { kTheMouseV, kTheMouseWord, kTheMovie, + kTheMovieFileFreeSize, + kTheMovieFileSize, + kTheMovieName, + kTheMoviePath, kTheMultiSound, kTheOptionDown, + kTheParamCount, kThePathName, kThePauseState, kThePerFrameHook, kThePreloadEventAbort, + kThePreLoadRAM, + kTheQuickTimePresent, + kTheRandomSeed, kTheResult, kTheRightMouseDown, kTheRightMouseUp, kTheRomanLingo, + kTheSearchCurrentFolder, + kTheSearchPath, kTheSelection, kTheSelEnd, kTheSelStart, @@ -118,80 +134,94 @@ enum TheEntityType { kTheTimeoutPlay, kTheTimeoutScript, kTheTimer, + kTheTrace, + kTheTraceLoad, + kTheTraceLogFile, + kTheUpdateMovieEnabled, kTheWindow, + kTheWindowList, kTheWords }; enum TheFieldType { kTheNOField = 0, kTheAbbr = 1, + kTheBackColor, + kTheBlend, + kTheBottom, kTheCastNum, kTheCastType, + kTheCenter, kTheCheckMark, + kTheConstraint, kTheController, + kTheCrop, kTheCursor, kTheDepth, kTheDirectToStage, kTheDrawRect, - kTheLocH, - kTheLocV, - kTheBackColor, - kTheBlend, - kTheBottom, - kTheConstraint, + kTheDuration, kTheEditableText, kTheEnabled, + kTheFileName, kTheForeColor, kTheFrameRate, - kTheFilename, kTheHeight, kTheHilite, kTheImmediate, kTheInk, kTheLeft, kTheLineSize, + kTheLoaded, + kTheLocH, + kTheLocV, kTheLong, kTheLoop, - kTheLoaded, + kTheModal, kTheModified, - kTheMoveable, + kTheMoveableSprite, kTheMovieRate, kTheMovieTime, - kTheNumber, kTheName, + kTheNumber, kThePalette, kThePattern, kThePausedAtStart, kThePicture, - kThePreload, + kThePreLoad, kThePuppet, kThePurgePriority, kTheRect, kTheRegPoint, kTheRight, - kTheShort, - kTheStopTime, - kTheStretch, - kTheStartTime, + kTheScoreColor, kTheScript, kTheScriptNum, kTheScriptText, + kTheShort, kTheSize, - kTheStrech, kTheSound, kTheSourceRect, + kTheStartTime, + kTheStopTime, + kTheStrech, + kTheStretch, kTheText, kTheTextAlign, kTheTextFont, kTheTextheight, kTheTextSize, kTheTextStyle, + kTheTitle, + kTheTitleVisible, kTheTop, kTheTrails, kTheType, + kTheVideo, kTheVisible, kTheVolume, - kTheWidth + kTheWidth, + kTheWindowType }; struct TheEntity { diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp index 4a9b612649..79dfc1f2db 100644 --- a/engines/director/lingo/lingo.cpp +++ b/engines/director/lingo/lingo.cpp @@ -36,18 +36,19 @@ struct EventHandlerType { const char *name; } static const eventHandlerDescs[] = { { kEventPrepareMovie, "prepareMovie" }, - { kEventStartMovie, "startMovie" }, - { kEventStopMovie, "stopMovie" }, + { kEventStartMovie, "startMovie" }, // D3? + { kEventStepMovie, "stepMovie" }, // D3? + { kEventStopMovie, "stopMovie" }, // D3? { kEventNew, "newSprite" }, { kEventBeginSprite, "beginSprite" }, { kEventEndSprite, "endSprite" }, - { kEventEnterFrame, "enterFrame" }, + { kEventEnterFrame, "enterFrame" }, // D4 { kEventPrepareFrame, "prepareFrame" }, { kEventIdle, "idle" }, { kEventStepFrame, "stepFrame"}, - { kEventExitFrame, "exitFrame" }, + { kEventExitFrame, "exitFrame" }, // D4 { kEventActivateWindow, "activateWindow" }, { kEventDeactivateWindow, "deactivateWindow" }, @@ -57,10 +58,10 @@ struct EventHandlerType { { kEventCloseWindow, "closeWindow" }, { kEventStart, "start" }, - { kEventKeyUp, "keyUp" }, - { kEventKeyDown, "keyDown" }, // D2 as when - { kEventMouseUp, "mouseUp" }, // D2 as when - { kEventMouseDown, "mouseDown" }, // D2 as when + { kEventKeyUp, "keyUp" }, // D4 + { kEventKeyDown, "keyDown" }, // D2 w D4 (as when from D2) + { kEventMouseUp, "mouseUp" }, // D2 w D3? + { kEventMouseDown, "mouseDown" }, // D2 w D3? { kEventRightMouseDown, "rightMouseDown" }, { kEventRightMouseUp, "rightMouseUp" }, { kEventMouseEnter, "mouseEnter" }, @@ -74,7 +75,6 @@ struct EventHandlerType { }; Symbol::Symbol() { - name = NULL; type = VOID; u.s = NULL; nargs = 0; @@ -91,10 +91,6 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) { _eventHandlerTypes[t->handler] = t->name; } - initBuiltIns(); - initFuncs(); - initTheEntities(); - _currentScript = 0; _currentScriptType = kMovieScript; _currentEntityId = 0; @@ -119,6 +115,10 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) { _localvars = NULL; + initBuiltIns(); + initFuncs(); + initTheEntities(); + warning("Lingo Inited"); } @@ -387,6 +387,7 @@ Common::String *Datum::toString() { delete s; s = u.s; break; + case SYMBOL: case OBJECT: *s = Common::String::format("#%s", u.s->c_str()); break; @@ -394,7 +395,7 @@ Common::String *Datum::toString() { *s = "#void"; break; case VAR: - *s = Common::String::format("var: #%s", u.sym->name); + *s = Common::String::format("var: #%s", u.sym->name.c_str()); break; default: warning("Incorrect operation toString() for type: %s", type2str()); diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h index 0899bacdfa..550156c1c7 100644 --- a/engines/director/lingo/lingo.h +++ b/engines/director/lingo/lingo.h @@ -36,6 +36,7 @@ namespace Director { enum LEvent { kEventPrepareMovie, kEventStartMovie, + kEventStepMovie, kEventStopMovie, kEventNew, @@ -103,7 +104,7 @@ struct Pointer_Hash { typedef Common::HashMap<void *, FuncDesc *, Pointer_Hash, Pointer_EqualTo> FuncHash; struct Symbol { /* symbol table entry */ - char *name; + Common::String name; int type; union { int i; /* VAR */ @@ -173,6 +174,8 @@ public: Lingo(DirectorEngine *vm); ~Lingo(); + void restartLingo(); + void addCode(const char *code, ScriptType type, uint16 id); void executeScript(ScriptType type, uint16 id); void printStack(const char *s); @@ -284,6 +287,7 @@ public: static void c_repeatwithcode(); static void c_ifcode(); static void c_whencode(); + static void c_tellcode(); static void c_exitRepeat(); static void c_eq(); static void c_neq(); @@ -305,6 +309,7 @@ public: static void c_gotoprevious(); static void c_global(); static void c_instance(); + static void c_property(); static void c_play(); static void c_playdone(); @@ -368,13 +373,18 @@ public: static void b_ilk(int nargs); static void b_integerp(int nargs); static void b_objectp(int nargs); + static void b_pictureP(int nargs); static void b_stringp(int nargs); static void b_symbolp(int nargs); + static void b_voidP(int nargs); static void b_alert(int nargs); + static void b_birth(int nargs); + static void b_clearGlobals(int nargs); static void b_cursor(int nargs); static void b_framesToHMS(int nargs); static void b_HMStoFrames(int nargs); + static void b_param(int nargs); static void b_printFrom(int nargs); static void b_showGlobals(int nargs); static void b_showLocals(int nargs); @@ -382,20 +392,28 @@ public: static void b_constrainH(int nargs); static void b_constrainV(int nargs); - static void b_duplicateCast(int nargs); + static void b_copyToClipBoard(int nargs); + static void b_duplicate(int nargs); static void b_editableText(int nargs); - static void b_eraseCast(int nargs); + static void b_erase(int nargs); + static void b_findEmpty(int nargs); + static void b_importFileInto(int nargs); static void b_installMenu(int nargs); static void b_label(int nargs); static void b_marker(int nargs); + static void b_move(int nargs); static void b_moveableSprite(int nargs); + static void b_pasteClipBoardInto(int nargs); static void b_puppetPalette(int nargs); static void b_puppetSound(int nargs); static void b_puppetSprite(int nargs); static void b_puppetTempo(int nargs); static void b_puppetTransition(int nargs); + static void b_ramNeeded(int nargs); static void b_rollOver(int nargs); static void b_spriteBox(int nargs); + static void b_unLoad(int nargs); + static void b_unLoadCast(int nargs); static void b_updateStage(int nargs); static void b_zoomBox(int nargs); @@ -404,7 +422,9 @@ public: static void b_dontPassEvent(int nargs); static void b_delay(int nargs); static void b_do(int nargs); + static void b_halt(int nargs); static void b_nothing(int nargs); + static void b_pass(int nargs); static void b_pause(int nargs); static void b_playAccel(int nargs); static void b_preLoad(int nargs); @@ -417,25 +437,42 @@ public: static void b_closeDA(int nargs); static void b_closeResFile(int nargs); static void b_closeXlib(int nargs); + static void b_getNthFileNameInFolder(int nargs); static void b_openDA(int nargs); static void b_openResFile(int nargs); static void b_openXlib(int nargs); static void b_setCallBack(int nargs); + static void b_saveMovie(int nargs); static void b_showResFile(int nargs); static void b_showXlib(int nargs); static void b_xFactoryList(int nargs); static void b_point(int nargs); + static void b_inside(int nargs); + static void b_intersect(int nargs); + static void b_map(int nargs); + static void b_offsetRect(int nargs); + static void b_rect(int nargs); + static void b_union(int nargs); + + static void b_close(int nargs); + static void b_forget(int nargs); + static void b_inflate(int nargs); + static void b_moveToBack(int nargs); + static void b_moveToFront(int nargs); + static void b_window(int nargs); static void b_beep(int nargs); static void b_mci(int nargs); static void b_mciwait(int nargs); static void b_soundBusy(int nargs); + static void b_soundClose(int nargs); static void b_soundFadeIn(int nargs); static void b_soundFadeOut(int nargs); static void b_soundPlayFile(int nargs); static void b_soundStop(int nargs); + static void b_ancestor(int nargs); static void b_backspace(int nargs); static void b_empty(int nargs); static void b_enter(int nargs); @@ -449,8 +486,10 @@ public: static void b_factory(int nargs); void factoryCall(Common::String &name, int nargs); + static void b_cast(int nargs); static void b_field(int nargs); static void b_me(int nargs); + static void b_script(int nargs); void func_mci(Common::String &s); void func_mciwait(Common::String &s); @@ -510,8 +549,6 @@ private: void push(Datum d); Datum pop(void); - void restartLingo(); - Common::HashMap<uint32, const char *> _eventHandlerTypes; Common::HashMap<Common::String, uint32> _eventHandlerTypeIds; Common::HashMap<Common::String, Audio::AudioStream *> _audioAliases; diff --git a/engines/director/lingo/tests/builtin.lingo b/engines/director/lingo/tests/builtin.lingo index 351efdb12c..561ecd3659 100644 --- a/engines/director/lingo/tests/builtin.lingo +++ b/engines/director/lingo/tests/builtin.lingo @@ -22,3 +22,9 @@ puppetSprite 15, true puppetTempo 30 puppetTransition 1 puppetTransition 2,4,20 + +move cast 1, cast 3 +move cast 3 +put findEmpty(cast 10) +pasteClipBoardInto cast 2 +put the width of cast 3 diff --git a/engines/director/score.cpp b/engines/director/score.cpp index deff766f72..fbb89e41c6 100644 --- a/engines/director/score.cpp +++ b/engines/director/score.cpp @@ -27,7 +27,6 @@ #include "engines/util.h" #include "graphics/font.h" -#include "graphics/fonts/macfont.h" #include "graphics/palette.h" #include "graphics/macgui/macfontmanager.h" #include "graphics/macgui/macwindowmanager.h" @@ -42,113 +41,6 @@ namespace Director { -static byte defaultPalette[768] = { - 0, 0, 0, 17, 17, 17, 34, 34, 34, 68, 68, 68, 85, 85, 85, 119, - 119, 119, 136, 136, 136, 170, 170, 170, 187, 187, 187, 221, 221, 221, 238, 238, - 238, 0, 0, 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, - 0, 0, 136, 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, - 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136, - 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 17, 0, 0, - 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136, 0, 0, 170, - 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 0, 0, 0, 51, 0, 0, - 102, 0, 0, 153, 0, 0, 204, 0, 0, 255, 0, 51, 0, 0, 51, 51, - 0, 51, 102, 0, 51, 153, 0, 51, 204, 0, 51, 255, 0, 102, 0, 0, - 102, 51, 0, 102, 102, 0, 102, 153, 0, 102, 204, 0, 102, 255, 0, 153, - 0, 0, 153, 51, 0, 153, 102, 0, 153, 153, 0, 153, 204, 0, 153, 255, - 0, 204, 0, 0, 204, 51, 0, 204, 102, 0, 204, 153, 0, 204, 204, 0, - 204, 255, 0, 255, 0, 0, 255, 51, 0, 255, 102, 0, 255, 153, 0, 255, - 204, 0, 255, 255, 51, 0, 0, 51, 0, 51, 51, 0, 102, 51, 0, 153, - 51, 0, 204, 51, 0, 255, 51, 51, 0, 51, 51, 51, 51, 51, 102, 51, - 51, 153, 51, 51, 204, 51, 51, 255, 51, 102, 0, 51, 102, 51, 51, 102, - 102, 51, 102, 153, 51, 102, 204, 51, 102, 255, 51, 153, 0, 51, 153, 51, - 51, 153, 102, 51, 153, 153, 51, 153, 204, 51, 153, 255, 51, 204, 0, 51, - 204, 51, 51, 204, 102, 51, 204, 153, 51, 204, 204, 51, 204, 255, 51, 255, - 0, 51, 255, 51, 51, 255, 102, 51, 255, 153, 51, 255, 204, 51, 255, 255, - 102, 0, 0, 102, 0, 51, 102, 0, 102, 102, 0, 153, 102, 0, 204, 102, - 0, 255, 102, 51, 0, 102, 51, 51, 102, 51, 102, 102, 51, 153, 102, 51, - 204, 102, 51, 255, 102, 102, 0, 102, 102, 51, 102, 102, 102, 102, 102, 153, - 102, 102, 204, 102, 102, 255, 102, 153, 0, 102, 153, 51, 102, 153, 102, 102, - 153, 153, 102, 153, 204, 102, 153, 255, 102, 204, 0, 102, 204, 51, 102, 204, - 102, 102, 204, 153, 102, 204, 204, 102, 204, 255, 102, 255, 0, 102, 255, 51, - 102, 255, 102, 102, 255, 153, 102, 255, 204, 102, 255, 255, 153, 0, 0, 153, - 0, 51, 153, 0, 102, 153, 0, 153, 153, 0, 204, 153, 0, 255, 153, 51, - 0, 153, 51, 51, 153, 51, 102, 153, 51, 153, 153, 51, 204, 153, 51, 255, - 153, 102, 0, 153, 102, 51, 153, 102, 102, 153, 102, 153, 153, 102, 204, 153, - 102, 255, 153, 153, 0, 153, 153, 51, 153, 153, 102, 153, 153, 153, 153, 153, - 204, 153, 153, 255, 153, 204, 0, 153, 204, 51, 153, 204, 102, 153, 204, 153, - 153, 204, 204, 153, 204, 255, 153, 255, 0, 153, 255, 51, 153, 255, 102, 153, - 255, 153, 153, 255, 204, 153, 255, 255, 204, 0, 0, 204, 0, 51, 204, 0, - 102, 204, 0, 153, 204, 0, 204, 204, 0, 255, 204, 51, 0, 204, 51, 51, - 204, 51, 102, 204, 51, 153, 204, 51, 204, 204, 51, 255, 204, 102, 0, 204, - 102, 51, 204, 102, 102, 204, 102, 153, 204, 102, 204, 204, 102, 255, 204, 153, - 0, 204, 153, 51, 204, 153, 102, 204, 153, 153, 204, 153, 204, 204, 153, 255, - 204, 204, 0, 204, 204, 51, 204, 204, 102, 204, 204, 153, 204, 204, 204, 204, - 204, 255, 204, 255, 0, 204, 255, 51, 204, 255, 102, 204, 255, 153, 204, 255, - 204, 204, 255, 255, 255, 0, 0, 255, 0, 51, 255, 0, 102, 255, 0, 153, - 255, 0, 204, 255, 0, 255, 255, 51, 0, 255, 51, 51, 255, 51, 102, 255, - 51, 153, 255, 51, 204, 255, 51, 255, 255, 102, 0, 255, 102, 51, 255, 102, - 102, 255, 102, 153, 255, 102, 204, 255, 102, 255, 255, 153, 0, 255, 153, 51, - 255, 153, 102, 255, 153, 153, 255, 153, 204, 255, 153, 255, 255, 204, 0, 255, - 204, 51, 255, 204, 102, 255, 204, 153, 255, 204, 204, 255, 204, 255, 255, 255, - 0, 255, 255, 51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255 }; - -void DirectorEngine::testFontScaling() { - int x = 10; - int y = 10; - int w = 640; - int h = 480; - - initGraphics(w, h, true); - g_system->getPaletteManager()->setPalette(defaultPalette, 0, 256); - - Graphics::ManagedSurface surface; - - surface.create(w, h); - surface.clear(255); - - Graphics::MacFont origFont(Graphics::kMacFontNewYork, 18); - - const Graphics::MacFONTFont *font1 = (const Graphics::MacFONTFont *)_wm->_fontMan->getFont(origFont); - - Graphics::MacFONTFont::testBlit(font1, &surface, 0, x, y + 200, 500); - - Graphics::MacFont bigFont(Graphics::kMacFontNewYork, 15); - - font1 = (const Graphics::MacFONTFont *)_wm->_fontMan->getFont(bigFont); - - Graphics::MacFONTFont::testBlit(font1, &surface, 0, x, y + 50 + 200, 500); - - const char *text = "d"; - - for (int i = 9; i <= 20; i++) { - Graphics::MacFont macFont(Graphics::kMacFontNewYork, i); - - const Graphics::Font *font = _wm->_fontMan->getFont(macFont); - - int width = font->getStringWidth(text); - - Common::Rect bbox = font->getBoundingBox(text, x, y, w); - surface.frameRect(bbox, 15); - - font->drawString(&surface, text, x, y, width, 0); - - x += width + 1; - } - - g_system->copyRectToScreen(surface.getPixels(), surface.pitch, 0, 0, w, h); - - Common::Event event; - - while (true) { - if (g_system->getEventManager()->pollEvent(event)) - if (event.type == Common::EVENT_QUIT) - break; - - g_system->updateScreen(); - g_system->delayMillis(10); - } -} - Score::Score(DirectorEngine *vm, Archive *archive) { _vm = vm; _surface = new Graphics::ManagedSurface; @@ -474,35 +366,22 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id, switch (castType) { case kCastBitmap: - warning("CASt: Bitmap"); - Common::hexdump(data, size1 + 16); _casts[id] = new BitmapCast(castStream, _vm->getVersion()); _casts[id]->type = kCastBitmap; break; case kCastText: - warning("CASt: Text"); - Common::hexdump(data, size1 + 16); _casts[id] = new TextCast(castStream, _vm->getVersion()); _casts[id]->type = kCastText; break; case kCastShape: - warning("CASt: Shape"); - Common::hexdump(data, size1 + 16); - _casts[id] = new ShapeCast(castStream, _vm->getVersion()); _casts[id]->type = kCastShape; break; case kCastButton: - warning("CASt: Button"); - Common::hexdump(data, size1 + 16); - _casts[id] = new ButtonCast(castStream, _vm->getVersion()); _casts[id]->type = kCastButton; break; case kCastLingoScript: - warning("CASt: Script"); - Common::hexdump(data, size1 + 16); - _casts[id] = new ScriptCast(castStream, _vm->getVersion()); _casts[id]->type = kCastLingoScript; break; @@ -743,10 +622,15 @@ void Score::gotoLoop() { // If no marker are to the left of the playback head, the playback head continues to the right. Common::SortedArray<Label *>::iterator i; - for (i = _labels->begin(); i != _labels->end(); ++i) { - if ((*i)->name == _currentLabel) { - _currentFrame = (*i)->number; - return; + if (_labels == NULL) { + _currentFrame = 0; + return; + } else { + for (i = _labels->begin(); i != _labels->end(); ++i) { + if ((*i)->name == _currentLabel) { + _currentFrame = (*i)->number; + return; + } } } } diff --git a/engines/dreamweb/detection_tables.h b/engines/dreamweb/detection_tables.h index 0a59543c51..fdffb689f1 100644 --- a/engines/dreamweb/detection_tables.h +++ b/engines/dreamweb/detection_tables.h @@ -244,6 +244,24 @@ static const DreamWebGameDescription gameDescriptions[] = { }, }, + // Italian CD release + { + { + "dreamweb", + "CD", + { + {"dreamweb.exe", 0, "44d1708535cdb863b9cca372ad0b05dd", 65370}, + {"dreamweb.r00", 0, "66dcab08354232f423c590156335f819", 155448}, + {"dreamweb.r02", 0, "87a026e9f80ed4f94169381f871ee305", 199676}, + AD_LISTEND + }, + Common::IT_ITA, + Common::kPlatformDOS, + ADGF_CD, + GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE) + }, + }, + // Czech fan-made translation // From bug #7078 { diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index f1bb8d3e7f..ae8ab14d84 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1264,7 +1264,7 @@ bool Console::cmdMapInstrument(int argc, const char **argv) { char *instrumentName = new char[11]; Common::strlcpy(instrumentName, argv[1], 11); - for (uint16 i = 0; i < strlen(instrumentName); i++) + for (uint16 i = 0; i < Common::strnlen(instrumentName, 11); i++) if (instrumentName[i] == '_') instrumentName[i] = ' '; diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index f4bd437d3e..91cf189d0a 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -313,7 +313,7 @@ int fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { if (maxsize > 1) { memset(dest, 0, maxsize); f->_in->readLine(dest, maxsize); - readBytes = strlen(dest); // FIXME: sierra sci returned byte count and didn't react on NUL characters + readBytes = Common::strnlen(dest, maxsize); // FIXME: sierra sci returned byte count and didn't react on NUL characters // The returned string must not have an ending LF if (readBytes > 0) { if (dest[readBytes - 1] == 0x0A) diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 49ad4caedb..25483b6507 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -338,7 +338,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { score = Common::String::format("%u%03u", save.highScore, save.lowScore); } - const uint nameLength = strlen(save.name); + const uint nameLength = Common::strnlen(save.name, SCI_MAX_SAVENAME_LENGTH); const uint size = nameLength + /* \r\n */ 2 + score.size(); char *buffer = (char *)malloc(size); memcpy(buffer, save.name, nameLength); @@ -372,7 +372,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { fillSavegameDesc(g_sci->getSavegameName(saveNo), &save); const Common::String avatarId = Common::String::format("%02d", save.avatarId); - const uint nameLength = strlen(save.name); + const uint nameLength = Common::strnlen(save.name, SCI_MAX_SAVENAME_LENGTH); const uint size = nameLength + /* \r\n */ 2 + avatarId.size() + 1; char *buffer = (char *)malloc(size); memcpy(buffer, save.name, nameLength); diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 08e3115e48..07a1c47547 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -824,8 +824,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { int16 celNo; int16 priority; reg_t listSeeker; - Common::String *listStrings = NULL; - const char **listEntries = NULL; + Common::String *listStrings = nullptr; bool isAlias = false; rect = kControlCreateRect(x, y, @@ -922,11 +921,9 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { if (listCount) { // We create a pointer-list to the different strings, we also find out whats upper and cursor position listSeeker = textReference; - listEntries = (const char**)malloc(sizeof(char *) * listCount); listStrings = new Common::String[listCount]; for (i = 0; i < listCount; i++) { listStrings[i] = s->_segMan->getString(listSeeker); - listEntries[i] = listStrings[i].c_str(); if (listSeeker.getOffset() == upperOffset) upperPos = i; if (listSeeker.getOffset() == cursorOffset) @@ -936,8 +933,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { } debugC(kDebugLevelGraphics, "drawing list control %04x:%04x to %d,%d, diff %d", PRINT_REG(controlObject), x, y, SCI_MAX_SAVENAME_LENGTH); - g_sci->_gfxControls16->kernelDrawList(rect, controlObject, maxChars, listCount, listEntries, fontId, style, upperPos, cursorPos, isAlias, hilite); - free(listEntries); + g_sci->_gfxControls16->kernelDrawList(rect, controlObject, maxChars, listCount, listStrings, fontId, style, upperPos, cursorPos, isAlias, hilite); delete[] listStrings; return; diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index ae91ef088a..4c5f1228de 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -305,7 +305,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) { Common::String tempsource = g_sci->getKernel()->lookupText(reg, arguments[paramindex + 1]); - int slen = strlen(tempsource.c_str()); + int slen = tempsource.size(); int extralen = strLength - slen; assert((target - targetbuf) + extralen <= maxsize); if (extralen < 0) diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index 26ab9b47a5..5e07ead5d7 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -32,6 +32,7 @@ struct MessageRecord { MessageTuple tuple; MessageTuple refTuple; const char *string; + uint32 length; byte talker; }; @@ -77,7 +78,13 @@ public: record.tuple = tuple; record.refTuple = MessageTuple(); record.talker = 0; - record.string = (const char *)_data + READ_LE_UINT16(recordPtr + 2); + const uint16 stringOffset = READ_LE_UINT16(recordPtr + 2); + const uint32 maxSize = _size - stringOffset; + record.string = (const char *)_data + stringOffset; + record.length = Common::strnlen(record.string, maxSize); + if (record.length == maxSize) { + warning("Message %s appears truncated at %ld", tuple.toString().c_str(), recordPtr - _data); + } return true; } recordPtr += _recordSize; @@ -100,7 +107,13 @@ public: record.tuple = tuple; record.refTuple = MessageTuple(); record.talker = recordPtr[4]; - record.string = (const char *)_data + READ_LE_UINT16(recordPtr + 5); + const uint16 stringOffset = READ_LE_UINT16(recordPtr + 5); + const uint32 maxSize = _size - stringOffset; + record.string = (const char *)_data + stringOffset; + record.length = Common::strnlen(record.string, maxSize); + if (record.length == maxSize) { + warning("Message %s appears truncated at %ld", tuple.toString().c_str(), recordPtr - _data); + } return true; } recordPtr += _recordSize; @@ -123,7 +136,13 @@ public: record.tuple = tuple; record.refTuple = MessageTuple(recordPtr[7], recordPtr[8], recordPtr[9]); record.talker = recordPtr[4]; - record.string = (const char *)_data + READ_SCI11ENDIAN_UINT16(recordPtr + 5); + const uint16 stringOffset = READ_SCI11ENDIAN_UINT16(recordPtr + 5); + const uint32 maxSize = _size - stringOffset; + record.string = (const char *)_data + stringOffset; + record.length = Common::strnlen(record.string, maxSize); + if (record.length == maxSize) { + warning("Message %s appears truncated at %ld", tuple.toString().c_str(), recordPtr - _data); + } return true; } recordPtr += _recordSize; @@ -149,7 +168,13 @@ public: record.tuple = tuple; record.refTuple = MessageTuple(recordPtr[8], recordPtr[9], recordPtr[10]); record.talker = recordPtr[4]; - record.string = (const char *)_data + READ_BE_UINT16(recordPtr + 6); + const uint16 stringOffset = READ_BE_UINT16(recordPtr + 6); + const uint32 maxSize = _size - stringOffset; + record.string = (const char *)_data + stringOffset; + record.length = Common::strnlen(record.string, maxSize); + if (record.length == maxSize) { + warning("Message %s appears truncated at %ld", tuple.toString().c_str(), recordPtr - _data); + } return true; } recordPtr += _recordSize; @@ -161,7 +186,7 @@ public: #endif bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &record) { - Resource *res = g_sci->getResMan()->findResource(ResourceId(kResourceTypeMessage, stack.getModule()), 0); + Resource *res = g_sci->getResMan()->findResource(ResourceId(kResourceTypeMessage, stack.getModule()), false); if (!res) { warning("Failed to open message resource %d", stack.getModule()); @@ -238,6 +263,7 @@ bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &re // as the text shown in this screen is very short (one-liners). // Just output an empty string here instead of showing an error. record.string = ""; + record.length = 0; delete reader; return true; } @@ -285,7 +311,7 @@ int MessageState::nextMessage(reg_t buf) { return record.talker; } else { MessageTuple &t = _cursorStack.top(); - outputString(buf, Common::String::format("Msg %d: %d %d %d %d not found", _cursorStack.getModule(), t.noun, t.verb, t.cond, t.seq)); + outputString(buf, Common::String::format("Msg %d: %s not found", _cursorStack.getModule(), t.toString().c_str())); return 0; } } else { @@ -304,7 +330,7 @@ int MessageState::messageSize(int module, MessageTuple &t) { stack.init(module, t); if (getRecord(stack, true, record)) - return strlen(record.string) + 1; + return record.length + 1; else return 0; } diff --git a/engines/sci/engine/message.h b/engines/sci/engine/message.h index 5847e4767e..a4de19bc74 100644 --- a/engines/sci/engine/message.h +++ b/engines/sci/engine/message.h @@ -40,6 +40,11 @@ struct MessageTuple { MessageTuple(byte noun_ = 0, byte verb_ = 0, byte cond_ = 0, byte seq_ = 1) : noun(noun_), verb(verb_), cond(cond_), seq(seq_) { } + + Common::String toString() const { + return Common::String::format("noun %d, verb %d, cond %d, seq %d", + noun, verb, cond, seq); + } }; class CursorStack : public Common::Stack<MessageTuple> { diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 54b925a1b6..6002cbd8e4 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -598,8 +598,12 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { case SCI_OBJ_STRINGS: debugN("Strings\n"); while (script->data [seeker]) { - debugN("%04x: %s\n", seeker, script->data + seeker); - seeker += strlen((char *)script->data + seeker) + 1; + debugN("%04x: %s", seeker, script->data + seeker); + seeker += Common::strnlen((char *)script->data + seeker, script->size - seeker) + 1; + if (seeker > script->size) { + debugN("[TRUNCATED]"); + } + debugN("\n"); } seeker++; // the ending zero byte break; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 23d1942dd3..9ccd1098d3 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -786,7 +786,10 @@ size_t SegManager::strlen(reg_t str) { } if (str_r.isRaw) { - return ::strlen((const char *)str_r.raw); + // There is no guarantee that raw strings are zero-terminated; for + // example, Phant1 reads "\r\n" from a pointer of size 2 during the + // chase + return Common::strnlen((const char *)str_r.raw, str_r.maxSize); } else { int i = 0; while (getChar(str_r, i)) @@ -807,19 +810,23 @@ Common::String SegManager::getString(reg_t pointer) { return ret; } - if (src_r.isRaw) - ret = (char *)src_r.raw; - else { + if (src_r.isRaw) { + // There is no guarantee that raw strings are zero-terminated; for + // example, Phant1 reads "\r\n" from a pointer of size 2 during the + // chase + const uint size = Common::strnlen((const char *)src_r.raw, src_r.maxSize); + ret = Common::String((const char *)src_r.raw, size); + } else { uint i = 0; - for (;;) { - char c = getChar(src_r, i); + while (i < (uint)src_r.maxSize) { + const char c = getChar(src_r, i); if (!c) break; i++; ret += c; - }; + } } return ret; } diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 1ec13176e4..281837d921 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -528,7 +528,7 @@ public: */ void snug() { assert(_type == kArrayTypeString || _type == kArrayTypeByte); - resize(strlen((char *)_data) + 1, true); + resize(Common::strnlen((char *)_data, _size) + 1, true); } /** @@ -808,7 +808,7 @@ public: } if (flags & kArrayTrimRight) { - source = data + strlen((char *)data) - 1; + source = data + Common::strnlen((char *)data, _size) - 1; while (source > data && *source != showChar && *source <= kWhitespaceBoundary) { *source = '\0'; --source; @@ -844,7 +844,7 @@ public: } ++source; - memmove(target, source, strlen((char *)source) + 1); + memmove(target, source, Common::strnlen((char *)source, _size - 1) + 1); } } } diff --git a/engines/sci/graphics/controls16.cpp b/engines/sci/graphics/controls16.cpp index b4bd92699a..479044a3e2 100644 --- a/engines/sci/graphics/controls16.cpp +++ b/engines/sci/graphics/controls16.cpp @@ -52,14 +52,12 @@ GfxControls16::~GfxControls16() { const char controlListUpArrow[2] = { 0x18, 0 }; const char controlListDownArrow[2] = { 0x19, 0 }; -void GfxControls16::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { +void GfxControls16::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const Common::String *entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { Common::Rect workerRect = rect; GuiResourceId oldFontId = _text16->GetFontId(); int16 oldPenColor = _ports->_curPort->penClr; uint16 fontSize = 0; int16 i; - const char *listEntry; - int16 listEntryLen; int16 lastYpos; // draw basic window @@ -92,11 +90,10 @@ void GfxControls16::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars // Write actual text for (i = upperPos; i < count; i++) { _paint16->eraseRect(workerRect); - listEntry = entries[i]; + const Common::String &listEntry = entries[i]; if (listEntry[0]) { _ports->moveTo(workerRect.left, workerRect.top); - listEntryLen = strlen(listEntry); - _text16->Draw(listEntry, 0, MIN(maxChars, listEntryLen), oldFontId, oldPenColor); + _text16->Draw(listEntry.c_str(), 0, MIN<int16>(maxChars, listEntry.size()), oldFontId, oldPenColor); if ((!isAlias) && (i == cursorPos)) { _paint16->invertRect(workerRect); } @@ -370,7 +367,7 @@ void GfxControls16::kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId v } } -void GfxControls16::kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite) { +void GfxControls16::kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const Common::String *entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite) { if (!hilite) { drawListControl(rect, obj, maxChars, count, entries, fontId, upperPos, cursorPos, isAlias); rect.grow(1); diff --git a/engines/sci/graphics/controls16.h b/engines/sci/graphics/controls16.h index 39ffa243fb..09d5800ca0 100644 --- a/engines/sci/graphics/controls16.h +++ b/engines/sci/graphics/controls16.h @@ -59,13 +59,13 @@ public: void kernelDrawText(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, int16 alignment, int16 style, bool hilite); void kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite); void kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, int16 loopNo, int16 celNo, int16 priority, int16 style, bool hilite); - void kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite); + void kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const Common::String *entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite); void kernelTexteditChange(reg_t controlObject, reg_t eventObject); private: void texteditSetBlinkTime(); - void drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias); + void drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const Common::String *entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias); void texteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos); void texteditCursorErase(); int getPicNotValid(); diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp index b5dd9aee0b..903136c29d 100644 --- a/engines/sci/graphics/text16.cpp +++ b/engines/sci/graphics/text16.cpp @@ -200,7 +200,7 @@ int16 GfxText16::GetLongest(const char *&textPtr, int16 maxWidth, GuiResourceId if (!_font) return 0; - while (1) { + for (;;) { curChar = (*(const byte *)textPtr); if (_font->isDoubleByte(curChar)) { curChar |= (*(const byte *)(textPtr + 1)) << 8; @@ -300,7 +300,7 @@ int16 GfxText16::GetLongest(const char *&textPtr, int16 maxWidth, GuiResourceId punctuationTable = text16_shiftJIS_punctuation_SCI01; } - while (1) { + for (;;) { // Look up if character shouldn't be the first on a new line nonBreakingPos = 0; while (punctuationTable[nonBreakingPos]) { @@ -383,15 +383,15 @@ void GfxText16::Width(const char *text, int16 from, int16 len, GuiResourceId org return; } -void GfxText16::StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) { - Width(str, 0, (int16)strlen(str), orgFontId, textWidth, textHeight, true); +void GfxText16::StringWidth(const Common::String &str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) { + Width(str.c_str(), 0, str.size(), orgFontId, textWidth, textHeight, true); } -void GfxText16::ShowString(const char *str, GuiResourceId orgFontId, int16 orgPenColor) { - Show(str, 0, (int16)strlen(str), orgFontId, orgPenColor); +void GfxText16::ShowString(const Common::String &str, GuiResourceId orgFontId, int16 orgPenColor) { + Show(str.c_str(), 0, str.size(), orgFontId, orgPenColor); } -void GfxText16::DrawString(const char *str, GuiResourceId orgFontId, int16 orgPenColor) { - Draw(str, 0, (int16)strlen(str), orgFontId, orgPenColor); +void GfxText16::DrawString(const Common::String &str, GuiResourceId orgFontId, int16 orgPenColor) { + Draw(str.c_str(), 0, str.size(), orgFontId, orgPenColor); } int16 GfxText16::Size(Common::Rect &rect, const char *text, uint16 languageSplitter, GuiResourceId fontId, int16 maxWidth) { @@ -580,20 +580,21 @@ void GfxText16::Box(const char *text, uint16 languageSplitter, bool show, const } } -void GfxText16::DrawString(const char *text) { +void GfxText16::DrawString(const Common::String &text) { GuiResourceId previousFontId = GetFontId(); int16 previousPenColor = _ports->_curPort->penClr; - Draw(text, 0, strlen(text), previousFontId, previousPenColor); + Draw(text.c_str(), 0, text.size(), previousFontId, previousPenColor); SetFont(previousFontId); _ports->penColor(previousPenColor); } // we need to have a separate status drawing code // In KQ4 the IV char is actually 0xA, which would otherwise get considered as linebreak and not printed -void GfxText16::DrawStatus(const char *text) { +void GfxText16::DrawStatus(const Common::String &str) { uint16 curChar, charWidth; - uint16 textLen = strlen(text); + const byte *text = (const byte *)str.c_str(); + uint16 textLen = str.size(); Common::Rect rect; GetFont(); @@ -603,7 +604,7 @@ void GfxText16::DrawStatus(const char *text) { rect.top = _ports->_curPort->curTop; rect.bottom = rect.top + _ports->_curPort->fontHeight; while (textLen--) { - curChar = (*(const byte *)text++); + curChar = *text++; switch (curChar) { case 0: break; diff --git a/engines/sci/graphics/text16.h b/engines/sci/graphics/text16.h index eb39fb2513..cb3deb0c60 100644 --- a/engines/sci/graphics/text16.h +++ b/engines/sci/graphics/text16.h @@ -53,9 +53,9 @@ public: int16 GetLongest(const char *&text, int16 maxWidth, GuiResourceId orgFontId); void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont); - void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); - void ShowString(const char *str, GuiResourceId orgFontId, int16 orgPenColor); - void DrawString(const char *str, GuiResourceId orgFontId, int16 orgPenColor); + void StringWidth(const Common::String &str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); + void ShowString(const Common::String &str, GuiResourceId orgFontId, int16 orgPenColor); + void DrawString(const Common::String &str, GuiResourceId orgFontId, int16 orgPenColor); int16 Size(Common::Rect &rect, const char *text, uint16 textLanguage, GuiResourceId fontId, int16 maxWidth); void Draw(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor); void Show(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor); @@ -65,8 +65,8 @@ public: Box(text, 0, show, rect, alignment, fontId); } - void DrawString(const char *text); - void DrawStatus(const char *text); + void DrawString(const Common::String &str); + void DrawStatus(const Common::String &str); GfxFont *_font; diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp index a0f958167d..ea8722aefd 100644 --- a/engines/sci/parser/vocabulary.cpp +++ b/engines/sci/parser/vocabulary.cpp @@ -207,8 +207,12 @@ bool Vocabulary::loadSuffixes() { while ((seeker < resource->size - 1) && (resource->data[seeker + 1] != 0xff)) { suffix_t suffix; + int maxSize = resource->size - seeker; suffix.alt_suffix = (const char *)resource->data + seeker; - suffix.alt_suffix_length = strlen(suffix.alt_suffix); + suffix.alt_suffix_length = Common::strnlen(suffix.alt_suffix, maxSize); + if (suffix.alt_suffix_length == maxSize) { + error("Vocabulary alt appears truncated for suffix %d in resource %d at %u", _parserSuffixes.size(), resource->getNumber(), seeker); + } seeker += suffix.alt_suffix_length + 1; // Hit end of string suffix.result_class = (int16)READ_BE_UINT16(resource->data + seeker); @@ -217,8 +221,12 @@ bool Vocabulary::loadSuffixes() { // Beginning of next string - skip leading '*' seeker++; + maxSize = resource->size - seeker; suffix.word_suffix = (const char *)resource->data + seeker; - suffix.word_suffix_length = strlen(suffix.word_suffix); + suffix.word_suffix_length = Common::strnlen(suffix.word_suffix, maxSize); + if (suffix.word_suffix_length == maxSize) { + error("Vocabulary word appears truncated for suffix %d in resource %d at %u", _parserSuffixes.size(), resource->getNumber(), seeker); + } seeker += suffix.word_suffix_length + 1; suffix.class_mask = (int16)READ_BE_UINT16(resource->data + seeker); @@ -288,12 +296,20 @@ bool Vocabulary::loadAltInputs() { AltInput t; t._input = data; - uint32 l = strlen(data); + uint32 maxSize = data_end - data; + uint32 l = Common::strnlen(data, maxSize); + if (l == maxSize) { + error("Alt input from %d appears truncated at %ld", resource->getNumber(), (const byte *)data - resource->data); + } t._inputLength = l; data += l + 1; t._replacement = data; - l = strlen(data); + maxSize = data_end - data; + l = Common::strnlen(data, maxSize); + if (l == maxSize) { + error("Alt input replacement from %d appears truncated at %ld", resource->getNumber(), (const byte *)data - resource->data); + } data += l + 1; if (data < data_end && strncmp(data, t._input, t._inputLength) == 0) @@ -316,7 +332,7 @@ void Vocabulary::freeAltInputs() { _altInputs.clear(); } -bool Vocabulary::checkAltInput(Common::String& text, uint16& cursorPos) { +bool Vocabulary::checkAltInput(Common::String &text, uint16 &cursorPos) { if (_altInputs.empty()) return false; if (SELECTOR(parseLang) == -1) @@ -330,7 +346,7 @@ bool Vocabulary::checkAltInput(Common::String& text, uint16& cursorPos) { do { changed = false; - const char* t = text.c_str(); + const char *t = text.c_str(); uint32 tlen = text.size(); for (uint32 p = 0; p < tlen && !changed; ++p) { @@ -345,10 +361,11 @@ bool Vocabulary::checkAltInput(Common::String& text, uint16& cursorPos) { continue; if (strncmp(i->_input, t+p, i->_inputLength) == 0) { // replace + const uint32 maxSize = text.size() - cursorPos; if (cursorPos > p + i->_inputLength) { - cursorPos += strlen(i->_replacement) - i->_inputLength; + cursorPos += Common::strnlen(i->_replacement, maxSize) - i->_inputLength; } else if (cursorPos > p) { - cursorPos = p + strlen(i->_replacement); + cursorPos = p + Common::strnlen(i->_replacement, maxSize); } for (uint32 j = 0; j < i->_inputLength; ++j) diff --git a/engines/titanic/sound/audio_buffer.cpp b/engines/titanic/sound/audio_buffer.cpp index 67a3d67958..029e7f0d9c 100644 --- a/engines/titanic/sound/audio_buffer.cpp +++ b/engines/titanic/sound/audio_buffer.cpp @@ -24,7 +24,7 @@ namespace Titanic { -CAudioBuffer::CAudioBuffer(int bufferSize) : _flag(true), _field18(0) { +CAudioBuffer::CAudioBuffer(int bufferSize) : _flag(true), _disabled(false) { _buffer.resize(bufferSize); reset(); } @@ -35,48 +35,48 @@ CAudioBuffer::~CAudioBuffer() { void CAudioBuffer::reset() { _flag = true; - _fieldC = _field10 = _buffer.size() / 2; + _readBytesLeft = _writeBytesLeft = _buffer.size() / 2; } -byte *CAudioBuffer::getDataPtr1() { +byte *CAudioBuffer::getBegin() { return _flag ? &_buffer[_buffer.size() / 2] : &_buffer[0]; } -byte *CAudioBuffer::getDataPtr2() { +byte *CAudioBuffer::getEnd() { return _flag ? &_buffer[0] : &_buffer[_buffer.size() / 2]; } -byte *CAudioBuffer::getPtr1() { - byte *ptr = getDataPtr1(); - return ptr + (_buffer.size() / 2 - _fieldC); +int16 *CAudioBuffer::getReadPtr() { + byte *ptr = getBegin(); + return (int16 *)(ptr + (_buffer.size() / 2 - _readBytesLeft)); } -uint16 *CAudioBuffer::getPtr2() { - byte *ptr = getDataPtr2(); - return (uint16 *)(ptr + (_buffer.size() / 2 - _field10)); +int16 *CAudioBuffer::getWritePtr() { + byte *ptr = getEnd(); + return (int16 *)(ptr + (_buffer.size() / 2 - _writeBytesLeft)); } -void CAudioBuffer::setC(int val) { - _fieldC -= val; - if (_fieldC < 0) { - _fieldC = 0; - } else if (val && !_field10) { - update(); +void CAudioBuffer::advanceRead(int size) { + _readBytesLeft -= size; + if (_readBytesLeft < 0) { + _readBytesLeft = 0; + } else if (size && !_writeBytesLeft) { + reverse(); } } -void CAudioBuffer::set10(int val) { - _field10 -= val; - if (_field10 < 0) { - _field10 = 0; - } else if (val && !_field10) { - update(); +void CAudioBuffer::advanceWrite(int size) { + _writeBytesLeft -= size; + if (_writeBytesLeft < 0) { + _writeBytesLeft = 0; + } else if (size && !_readBytesLeft) { + reverse(); } } -void CAudioBuffer::update() { +void CAudioBuffer::reverse() { _flag = !_flag; - _fieldC = _field10 = _buffer.size() / 2; + _readBytesLeft = _writeBytesLeft = _buffer.size() / 2; } void CAudioBuffer::enterCriticalSection() { diff --git a/engines/titanic/sound/audio_buffer.h b/engines/titanic/sound/audio_buffer.h index b65f0bb8cc..54dd807250 100644 --- a/engines/titanic/sound/audio_buffer.h +++ b/engines/titanic/sound/audio_buffer.h @@ -31,26 +31,67 @@ namespace Titanic { class CAudioBuffer { private: Common::Mutex _mutex; +private: + /** + * Gets the beginning of stored audio data + */ + byte *getBegin(); + + /** + * Gets the end of the stored audio data + */ + byte *getEnd(); + + /** + * Reverses the audio buffer + */ + void reverse(); public: Common::Array<byte> _buffer; - int _fieldC; - int _field10; + int _readBytesLeft; + int _writeBytesLeft; bool _flag; - int _field18; + bool _disabled; public: CAudioBuffer(int bufferSize); ~CAudioBuffer(); + /** + * Resets the audio buffer + */ void reset(); - byte *getDataPtr1(); - byte *getDataPtr2(); - byte *getPtr1(); - uint16 *getPtr2(); - int getC() const { return _fieldC; } - int get10() const { return _field10; } - void setC(int val); - void set10(int val); - void update(); + + /** + * Gets a pointer to the start of previously written data + */ + int16 *getReadPtr(); + + /** + * Returns the number of bytes that can be read + */ + int getBytesToRead() const { return _readBytesLeft; } + + /** + * Advances the read index + */ + void advanceRead(int size); + + /** + * Gets a pointer to the remainder of the audio buffer that + * can be written to + */ + int16 *getWritePtr(); + + /** + * Returns how many bytes can be written before hitting the + * end of the audio buffer + */ + int getWriteBytesLeft() const { return _writeBytesLeft; } + + /** + * Advances the write pointer by the specified number of bytes + */ + void advanceWrite(int size); /** * Enters a critical section diff --git a/engines/titanic/sound/music_object.cpp b/engines/titanic/sound/music_object.cpp index 3e8d887412..d12b6eb403 100644 --- a/engines/titanic/sound/music_object.cpp +++ b/engines/titanic/sound/music_object.cpp @@ -21,45 +21,21 @@ */ #include "titanic/sound/music_object.h" +#include "titanic/titanic.h" #include "common/util.h" namespace Titanic { -static const char *const DATA[4] = { - "64,^|^|^|^|^|^|^|^|^|^|^|^|^|^|^|^|8,^^^^ 5:A///|64,/|/|/|/|/|/|/" - "|/|/|/|/|/|/|/|/|/|^|^|^|^|^|^|^|^|^|16, ^B//|64,/|/|/|/|^|16,^C/" - "/|64,/|/|/|/|", - "2:8,^^^^B//a|//g//B//|g///B//a|//g//A//|B//^C//b|//a//a//|BCb/b//" - "a|//g//A//|g/+f/D//c|//b//gA/|g/^^C//C|//C//a//|BCb////a|//g//g//" - "|g/g//B/a|/g//////|//^^B//a|//g//B//|g///B//a|//g//B//|g//^C//b|/" - "/a//a//|BCb/b//a|//g//B//|g/+f/D//c|//b//gA/|g/^^C//C|//C//a//|BC" - "b////a|//g//g//|g/g//B/a|/g//////|3:^^B//a//|g//A//g/|/^B//a//|g/" - "/A//B/|b^ 3:C//b//|a//g//+f/|+fG/G/GA/|B/a/g///|B///+f//G|G/G/+f/" - "G/|^^e//d//|c//b//gA|g/B//a//|g//g//g/|g//B/a/g|//////^^|^^Ga///G" - "|////////|////////|////////|", - "2:8,^^^^^^D/|/E//E//E|/d//^^d/|/E//E//E|/E//^^G/|/d//d//d|/^^^^^d" - "/|/E//E//E|/d/^^^E/|/E//d/+F/|bD^^^^G/|/e//e//e|^^^^^^d/|/E//E//E" - "|//d///d/|//b/////|^^^^^^D/|/E//E//E|/d//^^d/|/E//E//E|/E//^^G/|/" - "d//d//d|/^^^^^d/|/E//E//E|/d/^^^E/|/E//d/d/|d/^^^^G/|/e//e//e|^^^" - "^^^d/|/E//E//E|//d///d/|//b/////|3:D///c//b|//b//b//|D///c//b|//b" - "//g//|E///d//c|//b//a//|aB/B/BC/|D/c/b///|^^^D//DE|/E/E/d/d|//E/g" - "//g|//g//d//|^^^^g//E|//E//E//|d///d///|b///////|// 3:Db///C|///b" - "/// 5:A|64,/|/|/|/|/|/|/|/|", - "2:8,^^G//+f//|e//e//e/|//G//+f//|e//e//+F/|G/a//g//|+f//+f//+f/|/" - "/G//+F//|e//e//e/|//B//a//|g//e///d|//c//b//|a//a//a/|+f/G// 2:+F" - "//|e//e//C/|//b/g/+f/|//G/////|^^G//+f//|e//e//e/|//G//+f//|e//e/" - "/e/|//a//g//|+f//+f//+f/|//G//+F//|e//e//e/|//B//a//|g//e///d|/ " - "2:dC//b//|a//a//a/|+f/G//+F//|e//e//C/|//b/g/+f/|//G/////|d//d//d" - "/|/E//E//d|d//d//E/|/+F//G//b|a//a//a/|/D//D// 3:D|//g/g//D|/d/G/" - "///|^^b//b//|b//ba/B/|c//B//a/|/g//+f//+f|G//+F//e/|/c//C///|b/g/" - "+f///|G///////|G///////|C///////|////////|////////|" -}; - -/*------------------------------------------------------------------------*/ - CMusicObject::CMusicObject(int index) { - assert(index >= 0 && index <= 3); - CMusicParser parser(DATA[index]); + // Read in the list of parser strings + Common::SeekableReadStream *res = g_vm->_filesManager->getResource("MUSIC/PARSER"); + Common::StringArray parserStrings; + while (res->pos() < res->size()) + parserStrings.push_back(readStringFromStream(res)); + delete res; + + // Set up a new parser with the desired string + CMusicParser parser(parserStrings[index].c_str()); // Count how many encoded values there are CValuePair r; @@ -68,11 +44,13 @@ CMusicObject::CMusicObject(int index) { ++count; assert(count > 0); + // Read in the values to the array _data.resize(count); parser.reset(); for (int idx = 0; idx < count; ++idx) parser.parse(_data[idx]); + // Figure out the range of values in the array _minVal = 0x7FFFFFFF; int maxVal = -0x7FFFFFFF; @@ -170,13 +148,13 @@ bool CMusicParser::parse(CValuePair &r) { r._field0 = _field8; } else if (_currentChar >= 'a' && _currentChar <= 'g') { val1 -= val2; - if (val1 < 0) - val1 = 12; + if (val1 >= 0) + val1 -= 12; r._field0 = _field8 + val1; } else if (_currentChar >= 'A' && _currentChar <= 'G') { val1 -= val2; if (val1 <= 0) - val1 = 12; + val1 += 12; r._field0 = _field8 + val1; } else { flag = false; diff --git a/engines/titanic/sound/music_room.cpp b/engines/titanic/sound/music_room.cpp index 4ef3b1dfc7..c2e5b5e380 100644 --- a/engines/titanic/sound/music_room.cpp +++ b/engines/titanic/sound/music_room.cpp @@ -85,7 +85,8 @@ void CMusicRoom::setupMusic(int volume) { _musicHandler->setMuteControl(idx, instr._muteControl); } - _musicHandler->setVolume(volume); + // Set up the music handler + _musicHandler->setup(volume); } } diff --git a/engines/titanic/sound/music_room_handler.cpp b/engines/titanic/sound/music_room_handler.cpp index f25bee727a..01d074c388 100644 --- a/engines/titanic/sound/music_room_handler.cpp +++ b/engines/titanic/sound/music_room_handler.cpp @@ -35,10 +35,10 @@ CMusicRoomHandler::CMusicRoomHandler(CProjectItem *project, CSoundManager *sound _startTicks = _soundStartTicks = 0; Common::fill(&_musicWaves[0], &_musicWaves[4], (CMusicWave *)nullptr); for (int idx = 0; idx < 4; ++idx) - _array3[idx] = new CMusicObject(idx); - Common::fill(&_array4[0], &_array4[4], 0); + _musicObjs[idx] = new CMusicObject(idx); + Common::fill(&_startPos[0], &_startPos[4], 0); Common::fill(&_array5[0], &_array5[4], 0.0); - Common::fill(&_array6[0], &_array6[4], 0); + Common::fill(&_position[0], &_position[4], 0); _audioBuffer = new CAudioBuffer(176400); } @@ -46,7 +46,7 @@ CMusicRoomHandler::CMusicRoomHandler(CProjectItem *project, CSoundManager *sound CMusicRoomHandler::~CMusicRoomHandler() { stop(); for (int idx = 0; idx < 4; ++idx) - delete _array3[idx]; + delete _musicObjs[idx]; delete _audioBuffer; } @@ -69,11 +69,11 @@ CMusicWave *CMusicRoomHandler::createMusicWave(MusicInstrument instrument, int c return nullptr; } - _musicWaves[instrument]->setSize(count); + _musicWaves[instrument]->setFilesCount(count); return _musicWaves[instrument]; } -void CMusicRoomHandler::setVolume(int volume) { +void CMusicRoomHandler::setup(int volume) { _volume = volume; _audioBuffer->reset(); @@ -82,12 +82,12 @@ void CMusicRoomHandler::setVolume(int volume) { MusicRoomInstrument &ins2 = _array2[idx]; if (ins1._directionControl == ins2._directionControl) { - _array4[idx] = 0; + _startPos[idx] = 0; } else { - _array4[idx] = _array3[idx]->size(); + _startPos[idx] = _musicObjs[idx]->size() - 1; } - _array6[idx] = _array4[idx]; + _position[idx] = _startPos[idx]; _array5[idx] = 0.0; } @@ -95,8 +95,8 @@ void CMusicRoomHandler::setVolume(int volume) { _field118 = 1; update(); - _waveFile = _soundManager->loadMusic(_audioBuffer); - _audioBuffer->setC(_audioBuffer->getC()); + _waveFile = _soundManager->loadMusic(_audioBuffer, DisposeAfterUse::NO); + _audioBuffer->advanceRead(_audioBuffer->getBytesToRead()); update(); } @@ -149,7 +149,7 @@ void CMusicRoomHandler::setDirectionControl2(MusicInstrument instrument, bool va void CMusicRoomHandler::setPitchControl(MusicInstrument instrument, int value) { if (instrument >= BELLS && instrument <= BASS && value >= -2 && value <= 2) - _array1[instrument]._pitchControl = value; + _array1[instrument]._pitchControl = value * 3; } void CMusicRoomHandler::setSpeedControl(MusicInstrument instrument, int value) { @@ -203,30 +203,33 @@ bool CMusicRoomHandler::update() { void CMusicRoomHandler::updateAudio() { _audioBuffer->enterCriticalSection(); - int size = _audioBuffer->get10(); + int size = _audioBuffer->getWriteBytesLeft(); int count; - uint16 *ptr; + int16 *ptr; if (size > 0) { - uint16 *audioPtr = _audioBuffer->getPtr2(); - Common::fill(audioPtr, audioPtr + size, 0); + // Null out the destination write area + int16 *audioPtr = _audioBuffer->getWritePtr(); + Common::fill(audioPtr, audioPtr + size / sizeof(uint16), 0); - for (int waveIdx = 0; waveIdx < 4; ++waveIdx) { - CMusicWave *musicWave = _musicWaves[waveIdx]; + for (int instrIdx = 0; instrIdx < 4; ++instrIdx) { + CMusicWave *musicWave = _musicWaves[instrIdx]; + // Iterate through each of the four instruments and do an additive + // read that will merge their data onto the output buffer for (count = size, ptr = audioPtr; count > 0; ) { int amount = musicWave->read(ptr, count); if (amount > 0) { count -= amount; ptr += amount / sizeof(uint16); - } else if (!fn2(waveIdx)) { + } else if (!fn2(instrIdx)) { --_field108; break; } } } - _audioBuffer->set10(size); + _audioBuffer->advanceWrite(size); } _audioBuffer->leaveCriticalSection(); @@ -240,8 +243,8 @@ void CMusicRoomHandler::fn1() { CMusicWave *musicWave = _musicWaves[idx]; // Is this about checking playback position? - if (_array6[idx] < 0 || ins1._muteControl || _array6[idx] >= _array3[idx]->size()) { - _array6[idx] = -1; + if (_position[idx] < 0 || ins1._muteControl || _position[idx] >= _musicObjs[idx]->size()) { + _position[idx] = -1; continue; } @@ -249,18 +252,18 @@ void CMusicRoomHandler::fn1() { double val = (double)ticks * 0.001 - 0.6; if (val >= musicWave->_floatVal) { - _array5[idx] += fn3(idx, _array6[idx]); + _array5[idx] += fn3(idx, _position[idx]); - const CValuePair &vp = (*_array3[idx])[_array6[idx]]; + const CValuePair &vp = (*_musicObjs[idx])[_position[idx]]; if (vp._field0 != 0x7FFFFFFF) { - int amount = getPitch(idx, _array6[idx]); + int amount = getPitch(idx, _position[idx]); _musicWaves[idx]->start(amount); } if (ins1._directionControl == ins2._directionControl) { - _array6[idx]++; + _position[idx]++; } else { - _array6[idx]--; + _position[idx]--; } } } @@ -268,13 +271,13 @@ void CMusicRoomHandler::fn1() { } bool CMusicRoomHandler::fn2(int index) { - int &arrIndex = _array4[index]; + int &arrIndex = _startPos[index]; if (arrIndex < 0) { _musicWaves[index]->reset(); return false; } - const CMusicObject &mObj = *_array3[index]; + const CMusicObject &mObj = *_musicObjs[index]; if (arrIndex >= mObj.size()) { arrIndex = -1; _musicWaves[index]->reset(); @@ -287,7 +290,7 @@ bool CMusicRoomHandler::fn2(int index) { if (vp._field0 == 0x7FFFFFFF || _array1[index]._muteControl) _musicWaves[index]->setSize(size); else - _musicWaves[index]->processArray(getPitch(index, arrIndex), size); + _musicWaves[index]->chooseWaveFile(getPitch(index, arrIndex), size); if (_array1[index]._directionControl == _array2[index]._directionControl) { ++arrIndex; @@ -299,7 +302,7 @@ bool CMusicRoomHandler::fn2(int index) { } double CMusicRoomHandler::fn3(int index, int arrIndex) { - const CValuePair &vp = (*_array3[index])[arrIndex]; + const CValuePair &vp = (*_musicObjs[index])[arrIndex]; switch (_array1[index]._speedControl + _array2[index]._speedControl + 3) { case 0: @@ -320,7 +323,7 @@ double CMusicRoomHandler::fn3(int index, int arrIndex) { } int CMusicRoomHandler::getPitch(int index, int arrIndex) { - const CMusicObject &mObj = *_array3[index]; + const CMusicObject &mObj = *_musicObjs[index]; const CValuePair &vp = mObj[arrIndex]; int val = vp._field0; const MusicRoomInstrument &ins1 = _array1[index]; diff --git a/engines/titanic/sound/music_room_handler.h b/engines/titanic/sound/music_room_handler.h index 5f615ccd84..38c1748ab4 100644 --- a/engines/titanic/sound/music_room_handler.h +++ b/engines/titanic/sound/music_room_handler.h @@ -52,10 +52,10 @@ private: CMusicWave *_musicWaves[4]; MusicRoomInstrument _array1[4]; MusicRoomInstrument _array2[4]; - CMusicObject *_array3[4]; - int _array4[4]; + CMusicObject *_musicObjs[4]; + int _startPos[4]; + int _position[4]; double _array5[4]; - int _array6[4]; bool _active; CWaveFile *_waveFile; @@ -88,9 +88,9 @@ public: CMusicWave *createMusicWave(MusicInstrument instrument, int count); /** - * TODO: Verify - this starts the given music? + * Main setup for the music room handler */ - void setVolume(int volume); + void setup(int volume); /** * Flags whether the music handler is active diff --git a/engines/titanic/sound/music_wave.cpp b/engines/titanic/sound/music_wave.cpp index 821a4fd0f4..f6ea612537 100644 --- a/engines/titanic/sound/music_wave.cpp +++ b/engines/titanic/sound/music_wave.cpp @@ -50,10 +50,10 @@ void CMusicWave::deinit() { } CMusicWave::CMusicWave(CProjectItem *project, CSoundManager *soundManager, MusicWaveInstrument instrument) : - _soundManager(soundManager), _instrument(instrument) { + _project(project), _soundManager(soundManager), _instrument(instrument) { Common::fill(&_gameObjects[0], &_gameObjects[4], (CGameObject *)nullptr); _floatVal = 0.0; - _field34 = -1; + _waveIndex = -1; _readPos = 0; _readIncrement = 0; _size = 0; @@ -79,9 +79,9 @@ CMusicWave::CMusicWave(CProjectItem *project, CSoundManager *soundManager, Music break; case MV_SNAKE: - _gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Snake Hammer")); - _gameObjects[1] = static_cast<CGameObject *>(_project->findByName("Snake Glass")); - _gameObjects[2] = static_cast<CGameObject *>(_project->findByName("Snake Head")); + _gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Snake_Hammer")); + _gameObjects[1] = static_cast<CGameObject *>(_project->findByName("Snake_Glass")); + _gameObjects[2] = static_cast<CGameObject *>(_project->findByName("Snake_Head")); _floatVal = 0.17; break; } @@ -162,6 +162,7 @@ void CMusicWave::start(int val) { _gameObjects[0]->movieSetAudioTiming(true); _gameObjects[0]->playMovie(0, 512, MOVIE_STOP_PREVIOUS); _floatVal = 0.6; + break; case 62: _gameObjects[0]->playMovie(828, 1023, MOVIE_STOP_PREVIOUS); @@ -253,7 +254,7 @@ void CMusicWave::trigger() { } void CMusicWave::reset() { - _field34 = 0; + _waveIndex = 0; _readPos = 0; _readIncrement = 0; _size = 0; @@ -261,85 +262,91 @@ void CMusicWave::reset() { } void CMusicWave::setSize(uint total) { - _field34 = -1; + _waveIndex = -1; _readPos = 0; _readIncrement = 0; _size = total; _count = 0; } -int CMusicWave::read(uint16 *ptr, uint size) { +int CMusicWave::read(int16 *ptr, uint size) { if (!_size) return 0; if (size >= _size) size = _size; - if (_field34 != -1) { - const byte *data = _items[_field34]._waveFile->lock(0, 0); + if (_waveIndex != -1) { + // Lock the specified wave file for access + const int16 *data = _items[_waveIndex]._waveFile->lock(); assert(data); - const uint16 *src = (const uint16 *)data; + const int16 *src = data; - // Loop through copying over data - for (uint idx = 0; idx < size; idx += 2, _readPos += _readIncrement) { + // Loop through merging data from the wave file into the dest buffer + for (uint idx = 0; idx < (size / sizeof(int16)); ++idx, _readPos += _readIncrement) { uint srcPos = _readPos >> 8; if (srcPos >= _count) break; - uint16 val = READ_LE_UINT16(src + srcPos); - *ptr++ = val; + int16 val = READ_LE_UINT16(src + srcPos); + *ptr++ += val; } - _items[_field34]._waveFile->unlock(data); + // Unlock the wave file + _items[_waveIndex]._waveFile->unlock(data); } _size -= size; return size; } -void CMusicWave::processArray(int index, int size) { +void CMusicWave::chooseWaveFile(int index, int size) { if (!_array) setupArray(-36, 36); - int minVal = _items[0]._value - index; - int minIndex = 0; + int minDiff = ABS(_items[0]._value - index); + int waveIndex = 0; + for (uint idx = 1; idx < _items.size(); ++idx) { - int val = _items[idx]._value - index; - if (val < minVal) { - minVal = val; - minIndex = idx; + int diff = ABS(_items[idx]._value - index); + if (diff < minDiff) { + minDiff = diff; + waveIndex = idx; } } - int arrIndex = _arrayIndex - _items[minIndex]._value + index; + const CMusicWaveFile &wf = _items[waveIndex]; + int arrIndex = _arrayIndex - wf._value + index; + uint waveSize = wf._waveFile->size(); - _field34 = minIndex; + _waveIndex = waveIndex; _readPos = 0; _readIncrement = (int)(_array[arrIndex] * 256); _size = size; - _count = _items[minIndex]._waveFile->getSize() / 2; + _count = waveSize / 2; } void CMusicWave::setupArray(int minVal, int maxVal) { + // Delete any prior array and recreate it delete[] _array; - // TODO: Figure out if the weird shift can be represented as a simpler equation - uint32 arrSize = ((uint32)minVal << 29) - (uint32)minVal + maxVal; - _array = new double[arrSize / 8]; - _arrayIndex = maxVal; + int arrSize = maxVal - minVal + 1; + _array = new double[arrSize]; + _arrayIndex = ABS(minVal); + // Setup array contents _array[_arrayIndex] = 1.0; double val = 1.0594634; for (int idx = 1; idx <= maxVal; ++idx) { - val *= 1.0594634; _array[_arrayIndex + idx] = val; + val *= 1.0594634; } val = 0.94387404038686; for (int idx = -1; idx >= minVal; --idx) { - val *= 0.94387404038686; _array[_arrayIndex + idx] = val; + val *= 0.94387404038686; } } diff --git a/engines/titanic/sound/music_wave.h b/engines/titanic/sound/music_wave.h index d1ccb33f30..f3782574ec 100644 --- a/engines/titanic/sound/music_wave.h +++ b/engines/titanic/sound/music_wave.h @@ -54,7 +54,7 @@ private: MusicWaveInstrument _instrument; CProjectItem *_project; CGameObject *_gameObjects[4]; - int _field34; + int _waveIndex; int _readPos; int _readIncrement; uint _size; @@ -66,6 +66,11 @@ private: */ CWaveFile *createWaveFile(const CString &name); + /** + * Sets up an array used for figuring out the sequence in which to + * play the different wave files for each instrument to give the + * music based on the console's settings + */ void setupArray(int minVal, int maxVal); public: double _floatVal; @@ -112,11 +117,15 @@ public: void setSize(uint total); /** - * Reads sound data and passes it to the provided buffer + * If there is any wave file currently specified, reads it in + * and merges it into the supplied buffer */ - int read(uint16 *ptr, uint size); + int read(int16 *ptr, uint size); - void processArray(int index, int freq); + /** + * Figure out which wave file to use next + */ + void chooseWaveFile(int index, int freq); }; } // End of namespace Titanic diff --git a/engines/titanic/sound/qmixer.cpp b/engines/titanic/sound/qmixer.cpp index b3910f846a..9ff6834efc 100644 --- a/engines/titanic/sound/qmixer.cpp +++ b/engines/titanic/sound/qmixer.cpp @@ -204,9 +204,9 @@ void QMixer::qsWaveMixPump() { if (sound._started && !_mixer->isSoundHandleActive(sound._soundHandle)) { if (sound._loops == -1 || sound._loops-- > 0) { // Need to loop the sound again - sound._waveFile->_stream->rewind(); + sound._waveFile->audioStream()->rewind(); _mixer->playStream(sound._waveFile->_soundType, - &sound._soundHandle, sound._waveFile->_stream, + &sound._soundHandle, sound._waveFile->audioStream(), -1, channel.getRawVolume(), 0, DisposeAfterUse::NO); } else { // Sound is finished @@ -230,7 +230,7 @@ void QMixer::qsWaveMixPump() { // Calculate an effective volume based on distance of source _mixer->playStream(sound._waveFile->_soundType, - &sound._soundHandle, sound._waveFile->_stream, + &sound._soundHandle, sound._waveFile->audioStream(), -1, channel.getRawVolume(), 0, DisposeAfterUse::NO); sound._started = true; } diff --git a/engines/titanic/sound/sound_manager.cpp b/engines/titanic/sound/sound_manager.cpp index 7c995c29f7..09ba1ae4a7 100644 --- a/engines/titanic/sound/sound_manager.cpp +++ b/engines/titanic/sound/sound_manager.cpp @@ -155,11 +155,11 @@ CWaveFile *QSoundManager::loadMusic(const CString &name) { return waveFile; } -CWaveFile *QSoundManager::loadMusic(CAudioBuffer *buffer) { +CWaveFile *QSoundManager::loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) { CWaveFile *waveFile = new CWaveFile(); // Try to load the specified audio buffer - if (!waveFile->loadMusic(buffer)) { + if (!waveFile->loadMusic(buffer, disposeAfterUse)) { delete waveFile; return nullptr; } diff --git a/engines/titanic/sound/sound_manager.h b/engines/titanic/sound/sound_manager.h index 1d522a7edf..3c217324c2 100644 --- a/engines/titanic/sound/sound_manager.h +++ b/engines/titanic/sound/sound_manager.h @@ -76,7 +76,7 @@ public: * @param buffer Audio buffer * @returns Loaded wave file */ - virtual CWaveFile *loadMusic(CAudioBuffer *buffer) { return nullptr; } + virtual CWaveFile *loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) { return nullptr; } /** * Start playing a previously loaded wave file @@ -352,7 +352,7 @@ public: * @param buffer Audio buffer * @returns Loaded wave file */ - virtual CWaveFile *loadMusic(CAudioBuffer *buffer); + virtual CWaveFile *loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse); /** * Start playing a previously loaded sound resource diff --git a/engines/titanic/sound/wave_file.cpp b/engines/titanic/sound/wave_file.cpp index 78be580801..a4cd9d3e3f 100644 --- a/engines/titanic/sound/wave_file.cpp +++ b/engines/titanic/sound/wave_file.cpp @@ -20,6 +20,7 @@ * */ +#include "audio/decoders/raw.h" #include "audio/decoders/wave.h" #include "common/memstream.h" #include "titanic/sound/wave_file.h" @@ -28,46 +29,100 @@ namespace Titanic { -CWaveFile::CWaveFile() : _owner(nullptr), _stream(nullptr), - _soundType(Audio::Mixer::kPlainSoundType) { +/** + * This creates a ScummVM audio stream around a CAudioBuffer buffer, + * allowing for streaming audio output for the music room music + */ +class AudioBufferStream : public Audio::SeekableAudioStream { +private: + CAudioBuffer *_audioBuffer; +public: + AudioBufferStream(CAudioBuffer *audioBuffer) : _audioBuffer(audioBuffer) {} + + virtual int readBuffer(int16 *buffer, const int numSamples); + virtual bool isStereo() const { return false; } + virtual bool endOfData() const; + virtual int getRate() const { return 22050; } + virtual Audio::Timestamp getLength() const { return Audio::Timestamp(); } + virtual bool seek(const Audio::Timestamp &where) { return false; } +}; + +int AudioBufferStream::readBuffer(int16 *buffer, const int numSamples) { + _audioBuffer->enterCriticalSection(); + int samplesToRead = MIN((const int)numSamples, (const int)(_audioBuffer->getBytesToRead() / sizeof(uint16))); + + const int16 *src = _audioBuffer->getReadPtr(); + Common::copy(src, src + samplesToRead, buffer); + _audioBuffer->advanceRead(samplesToRead * 2); + + _audioBuffer->leaveCriticalSection(); + return samplesToRead; +} + +bool AudioBufferStream::endOfData() const { + return _audioBuffer->_disabled; +} + +/*------------------------------------------------------------------------*/ + +CWaveFile::CWaveFile() : _audioStream(nullptr), + _waveData(nullptr), _waveSize(0), _dataSize(0), _headerSize(0), + _rate(0), _flags(0), _wavType(0), _soundType(Audio::Mixer::kPlainSoundType) { + setup(); +} + +CWaveFile::CWaveFile(QSoundManager *owner) : _audioStream(nullptr), + _waveData(nullptr), _waveSize(0), _dataSize(0), _headerSize(0), + _rate(0), _flags(0), _wavType(0), _soundType(Audio::Mixer::kPlainSoundType) { + setup(); } -CWaveFile::CWaveFile(QSoundManager *owner) : _owner(owner), _stream(nullptr), - _soundType(Audio::Mixer::kPlainSoundType) { +void CWaveFile::setup() { + _loadMode = LOADMODE_SCUMMVM; + _dataSize = 0; + _audioBuffer = nullptr; + _disposeAudioBuffer = DisposeAfterUse::NO; + _channel = -1; } CWaveFile::~CWaveFile() { - if (_stream) { - _owner->soundFreed(_soundHandle); - delete _stream; + if (_audioStream) { + //_soundManager->soundFreed(_soundHandle); + delete _audioStream; } + + if (_disposeAudioBuffer == DisposeAfterUse::YES && _audioBuffer) + delete _audioBuffer; + + delete[] _waveData; } uint CWaveFile::getDurationTicks() const { - if (!_stream) + if (!_audioStream) return 0; // FIXME: The original uses acmStreamSize to calculate // a desired size. Since I have no idea how the system API // method works, for now I'm using a simple ratio of a // sample output to input value - uint dataSize = _size - 0x46; - double newSize = (double)dataSize * (1475712.0 / 199836.0); - return (uint)(newSize * 1000.0 / _stream->getRate()); + double newSize = (double)_dataSize * (1475712.0 / 199836.0); + return (uint)(newSize * 1000.0 / _audioStream->getRate()); } bool CWaveFile::loadSound(const CString &name) { - assert(!_stream); + assert(!_audioStream); StdCWadFile file; if (!file.open(name)) return false; Common::SeekableReadStream *stream = file.readStream(); - _size = stream->size(); - _stream = Audio::makeWAVStream(stream->readStream(_size), DisposeAfterUse::YES); - _soundType = Audio::Mixer::kSFXSoundType; + uint wavSize = stream->size(); + byte *data = new byte[wavSize]; + stream->read(data, wavSize); + load(data, wavSize); + _soundType = Audio::Mixer::kSFXSoundType; return true; } @@ -78,56 +133,91 @@ bool CWaveFile::loadSpeech(CDialogueFile *dialogueFile, int speechIndex) { byte *data = (byte *)malloc(res->_size); dialogueFile->read(res, data, res->_size); + load(data, res->_size); - _size = res->_size; - _stream = Audio::makeWAVStream(new Common::MemoryReadStream(data, _size, DisposeAfterUse::YES), - DisposeAfterUse::YES); _soundType = Audio::Mixer::kSpeechSoundType; - return true; } bool CWaveFile::loadMusic(const CString &name) { - assert(!_stream); + assert(!_audioStream); StdCWadFile file; if (!file.open(name)) return false; Common::SeekableReadStream *stream = file.readStream(); - _size = stream->size(); - _stream = Audio::makeWAVStream(stream->readStream(_size), DisposeAfterUse::YES); + uint wavSize = stream->size(); + byte *data = new byte[wavSize]; + stream->read(data, wavSize); + delete stream; + + load(data, wavSize); _soundType = Audio::Mixer::kMusicSoundType; + return true; +} +bool CWaveFile::loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) { + _audioBuffer = buffer; + _disposeAudioBuffer = disposeAfterUse; + _loadMode = LOADMODE_AUDIO_BUFFER; + + _audioStream = new AudioBufferStream(_audioBuffer); return true; } -bool CWaveFile::loadMusic(CAudioBuffer *buffer) { - assert(!_stream && buffer); - warning("TODO: CWaveFile::loadMusic"); - return false; +void CWaveFile::load(byte *data, uint dataSize) { + _waveData = data; + _waveSize = dataSize; + + // Parse the wave header + Common::MemoryReadStream wavStream(data, dataSize, DisposeAfterUse::NO); + Audio::loadWAVFromStream(wavStream, _dataSize, _rate, _flags, &_wavType); + _headerSize = wavStream.pos(); } -uint CWaveFile::getFrequency() const { - return _stream->getRate(); +Audio::SeekableAudioStream *CWaveFile::audioStream() { + if (!_audioStream) { + // No stream yet, so create one and give it control of the raw wave data + assert(_waveData); + _audioStream = Audio::makeWAVStream( + new Common::MemoryReadStream(_waveData, _waveSize, DisposeAfterUse::YES), + DisposeAfterUse::YES); + _waveData = nullptr; + } + + return _audioStream; } -void CWaveFile::reset() { - _stream->rewind(); + +uint CWaveFile::getFrequency() { + return audioStream()->getRate(); } -uint CWaveFile::getSize() const { - // TODO - return _stream->getLength().totalNumberOfFrames() * 2; +void CWaveFile::reset() { + audioStream()->rewind(); } -const byte *CWaveFile::lock(int val1, int val2) { - // TODO - return nullptr; +const int16 *CWaveFile::lock() { + enum { kWaveFormatPCM = 1 }; + + switch (_loadMode) { + case LOADMODE_SCUMMVM: + // Sanity checking that only raw 16-bit LE 22Khz waves can be locked + assert(_waveData && _rate == 22050); + assert(_flags == (Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_16BITS)); + assert(_wavType == kWaveFormatPCM); + + // Return a pointer to the data section of the wave file + return (const int16 *)(_waveData + _headerSize); + + default: + return nullptr; + } } -void CWaveFile::unlock(const byte *ptr) { - // TODO +void CWaveFile::unlock(const int16 *ptr) { + // No implementation needed in ScummVM } } // End of namespace Titanic z diff --git a/engines/titanic/sound/wave_file.h b/engines/titanic/sound/wave_file.h index 560188576b..6bd18989b9 100644 --- a/engines/titanic/sound/wave_file.h +++ b/engines/titanic/sound/wave_file.h @@ -31,16 +31,37 @@ namespace Titanic { +enum LoadMode { LOADMODE_AUDIO_BUFFER = 1, LOADMODE_SCUMMVM = 2 }; + class QSoundManager; class CWaveFile { private: - uint _size; + byte *_waveData; + int _waveSize; + int _dataSize; + int _headerSize; + int _rate; + byte _flags; + uint16 _wavType; + Audio::SeekableAudioStream *_audioStream; +private: + /** + * Handles setup of fields shared by the constructors + */ + void setup(); + + /** + * Gets passed the raw data for the wave file + */ + void load(byte *data, uint dataSize); public: - QSoundManager *_owner; - Audio::SeekableAudioStream *_stream; - Audio::SoundHandle _soundHandle; Audio::Mixer::SoundType _soundType; + + LoadMode _loadMode; + CAudioBuffer *_audioBuffer; + DisposeAfterUse::Flag _disposeAudioBuffer; + int _channel; public: CWaveFile(); CWaveFile(QSoundManager *owner); @@ -56,7 +77,12 @@ public: /** * Return the size of the wave file */ - uint size() const { return _size; } + uint size() const { return _dataSize; } + + /** + * Returns a ScummVM Audio Stream for playback purposes + */ + Audio::SeekableAudioStream *audioStream(); /** * Tries to load the specified wave file sound @@ -76,34 +102,34 @@ public: /** * Tries to load the specified audio buffer */ - bool loadMusic(CAudioBuffer *buffer); + bool loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse); /** * Returns true if the wave file has data loaded */ - bool isLoaded() const { return _stream != nullptr; } + bool isLoaded() const { + return _audioStream != nullptr || _waveData != nullptr; + } /** * Return the frequency of the loaded wave file */ - uint getFrequency() const; + uint getFrequency(); /** * Resets the music stream */ void reset(); - uint getSize() const; - /** * Lock sound data for access */ - const byte *lock(int val1, int val2); + const int16 *lock(); /** * Unlock sound data after a prior call to lock */ - void unlock(const byte *ptr); + void unlock(const int16 *ptr); }; } // End of namespace Titanic diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp index 4042088761..180b08175b 100644 --- a/graphics/macgui/mactext.cpp +++ b/graphics/macgui/mactext.cpp @@ -140,8 +140,6 @@ void MacText::splitString(Common::String &str) { if (text.size()) { for (uint i = 0; i < text.size(); i++) { - _text.push_back(text[i]); - _textLines[curLine].chunks[curChunk].text = text[i]; if ((text.size() > 1 || !nextChunk) && !(i == text.size() - 1 && nextChunk)) { @@ -189,12 +187,8 @@ void MacText::splitString(Common::String &str) { _textLines[curLine].chunks[curChunk].text = text[0]; - _text.push_back(text[0]); - if (text.size() > 1) { for (uint i = 1; i < text.size(); i++) { - _text.push_back(text[i]); - curLine++; _textLines.resize(curLine + 1); _textLines[curLine].chunks.push_back(_currentFormatting); @@ -304,6 +298,11 @@ int MacText::getLineHeight(int line) { return _textLines[line].height; } +void MacText::setInterLinear(int interLinear) { + _interLinear = interLinear; + recalcDims(); +} + void MacText::recalcDims() { int y = 0; _textMaxWidth = 0; @@ -315,7 +314,7 @@ void MacText::recalcDims() { _textMaxWidth = MAX(_textMaxWidth, getLineWidth(i, true)); } - _textMaxHeight = y; + _textMaxHeight = y - _interLinear; } void MacText::draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int yoff) { @@ -331,28 +330,28 @@ void MacText::draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int } void MacText::appendText(Common::String str) { - int oldLen = _text.size(); + int oldLen = _textLines.size(); // TODO: Recalc length splitString(str); recalcDims(); - render(oldLen + 1, _text.size()); + render(oldLen + 1, _textLines.size()); } void MacText::replaceLastLine(Common::String str) { - int oldLen = MAX<int>(0, _text.size() - 1); + int oldLen = MAX<int>(0, _textLines.size() - 1); // TODO: Recalc length, adapt to _textLines - if (_text.size()) - _text.pop_back(); + if (_textLines.size()) + _textLines.pop_back(); splitString(str); recalcDims(); - render(oldLen, _text.size()); + render(oldLen, _textLines.size()); } } // End of namespace Graphics diff --git a/graphics/macgui/mactext.h b/graphics/macgui/mactext.h index 2ce0c3065b..85c855950f 100644 --- a/graphics/macgui/mactext.h +++ b/graphics/macgui/mactext.h @@ -91,11 +91,12 @@ public: MacText(Common::String s, MacWindowManager *wm, const Graphics::Font *font, int fgcolor, int bgcolor, int maxWidth = -1, TextAlign textAlignment = kTextAlignLeft); - void setInterLinear(int interLinear) { _interLinear = interLinear; } + void setInterLinear(int interLinear); void draw(ManagedSurface *g, int x, int y, int w, int h, int xoff, int yoff); void appendText(Common::String str); void replaceLastLine(Common::String str); + int getLineCount() { return _textLines.size(); } void render(); Graphics::ManagedSurface *getSurface() { return _surface; } @@ -118,8 +119,6 @@ private: int _maxWidth; int _interLinear; - Common::Array<Common::String> _text; - int _textMaxWidth; int _textMaxHeight; diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat Binary files differindex 63d5b4c490..3c6f2db7ec 100644 --- a/gui/themes/translations.dat +++ b/gui/themes/translations.dat diff --git a/po/de_DE.po b/po/de_DE.po index 9e6218f07c..549b71a916 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -8,10 +8,10 @@ msgstr "" "Project-Id-Version: ScummVM 1.10.0git\n" "Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n" "POT-Creation-Date: 2017-01-31 18:17+0100\n" -"PO-Revision-Date: 2017-01-30 17:55+0000\n" +"PO-Revision-Date: 2017-02-08 21:48+0000\n" "Last-Translator: Lothar Serra Mari <rootfather@scummvm.org>\n" -"Language-Team: German <https://translations.scummvm.org/projects/scummvm/" -"scummvm/de/>\n" +"Language-Team: German " +"<https://translations.scummvm.org/projects/scummvm/scummvm/de/>\n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" @@ -27,7 +27,7 @@ msgstr "(erstellt am %s)" #: gui/about.cpp:101 msgid "Features compiled in:" -msgstr "Verwendete Funktionen:" +msgstr "Verfügbare Funktionen:" #: gui/about.cpp:110 msgid "Available engines:" diff --git a/test/common/span.h b/test/common/span.h index d9b1d3120e..55ef2c6bd2 100644 --- a/test/common/span.h +++ b/test/common/span.h @@ -496,6 +496,8 @@ public: TS_ASSERT(span.getStringAt(0) == data); TS_ASSERT(span.getStringAt(0, 2) == "he"); + TS_ASSERT(span.getStringAt(2) == "llo"); + TS_ASSERT(span.getStringAt(2, 3) == "llo"); span[3] = '\0'; TS_ASSERT(span.getStringAt(0) == "hel"); } |