diff options
48 files changed, 16456 insertions, 1418 deletions
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/engines/cryo/ResourceManager.cpp b/engines/cryo/ResourceManager.cpp new file mode 100644 index 0000000000..79218c598c --- /dev/null +++ b/engines/cryo/ResourceManager.cpp @@ -0,0 +1,122 @@ +/* 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 "ResourceManager.h" + +namespace Cryo { + +ResourceManager::ResourceManager() { +} + +ResourceManager::ResourceManager(const Common::String &datFileName) { + LoadDatFile(datFileName); +} + +ResourceManager::~ResourceManager() { +} + +bool ResourceManager::LoadDatFile(const Common::String &datFileName) { + if (_datFile.isOpen()) { + _datFile.close(); + _files.clear(); + } + + assert(_datFile.open(datFileName)); + + uint16 numFiles = _datFile.readUint16LE(); + + for (uint16 i = 0; i < numFiles; i++) { + DatFileEntry entry; + + _datFile.read(entry._name, sizeof(entry._name)); + entry._size = _datFile.readUint32LE(); + entry._offset = _datFile.readUint32LE(); + entry._flag = _datFile.readByte(); + + _files.push_back(entry); + } + + return true; +} + +Common::SeekableReadStream *ResourceManager::GetFile(const Common::String &resName, unsigned int hintIndex) { + // First, try raw disk file so we can support modding/patching + + if (Common::File::exists(resName)) { + debug("Loading %s from disk", resName); + + Common::File *resource = new Common::File(); + resource->open(resName); + return resource; + } + + // Look inside .dat file + + if (_datFile.isOpen()) { + for (unsigned int i = hintIndex; i < _files.size(); i++) { + if (!resName.compareToIgnoreCase(_files[i]._name)) { + debug("Loading %s from dat file", resName); + Common::SeekableSubReadStream *resource = new Common::SeekableSubReadStream(&_datFile, _files[i]._offset, _files[i]._offset + _files[i]._size); + return resource; + } + } + } + + debug("Unable to load %s - does't exists", resName); + return nullptr; +} + +Common::SeekableReadStream *ResourceManager::GetFile(unsigned int resIndex) { + if (_files.size() > resIndex) { + return GetFile(Common::String(_files[resIndex]._name), resIndex); + } + + return nullptr; +} + +void *ResourceManager::StreamToBuffer(Common::SeekableReadStream *stream, unsigned int *size) { + if (!stream) + return nullptr; + + unsigned int readSize = stream->size(); + byte *data = new byte[readSize + 1]; + readSize = stream->read(data, readSize); + + if (size) + *size = readSize; + return data; +} + +void *ResourceManager::GetData(const Common::String &resName, unsigned int *size) { + Common::SeekableReadStream *resource = GetFile(resName); + void *data = StreamToBuffer(resource, size); + delete resource; + return data; +} + +void *ResourceManager::GetData(int resIndex, unsigned int *size) { + Common::SeekableReadStream *resource = GetFile(resIndex); + void *data = StreamToBuffer(resource, size); + delete resource; + return data; +} +} diff --git a/engines/cryo/ResourceManager.h b/engines/cryo/ResourceManager.h new file mode 100644 index 0000000000..5a587fcaa3 --- /dev/null +++ b/engines/cryo/ResourceManager.h @@ -0,0 +1,92 @@ +/* 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 "common/array.h" +#include "common/file.h" +#include "common/fs.h" +#include "common/str.h" +#include "common/substream.h" +#include "common/debug.h" + +namespace Cryo { + +template<typename T> +class CryoArray { +private: + byte *_data; + bool _ownData; + uint16 ElementOffset(int num) { + assert(_data && num < Count()) + return (static_cast<uint16 *>_data)[num]; + } +public: + CryoArray(void *data, bool ownData) : _data(data), _ownData(ownData) { + } + ~CryoArray() { + if (_ownData) + delete data; + } + uint16 Count() { + return ElementOffset(0) / 2; + } + const T *operator[](int index) { + return static_cast<T *>(_data + ElementOffset(num)); + } +}; + +class ResourceManager { +private: + struct DatFileEntry { + char _name[16]; + unsigned int _size; + unsigned int _offset; + byte _flag; + }; + + Common::Array<DatFileEntry> _files; + Common::File _datFile; + + static void *StreamToBuffer(Common::SeekableReadStream *stream, unsigned int *size); + +public: + ResourceManager(const Common::String &datFileName); + ResourceManager(); + ~ResourceManager(); + + bool LoadDatFile(const Common::String &datFileName); + + // Load resource as a seekable stream + Common::SeekableReadStream *GetFile(const Common::String &resName, unsigned int hintIndex = 0); + Common::SeekableReadStream *GetFile(unsigned int resIndex); + + // Load resource as a buffer + void *GetData(const Common::String &resName, unsigned int *size = nullptr); + void *GetData(int resIndex, unsigned int *size = nullptr); + void *operator[](int resIndex) { + return GetData(resIndex); + } + +}; + +} diff --git a/engines/cryo/bugs.txt b/engines/cryo/bugs.txt new file mode 100644 index 0000000000..a69538a449 --- /dev/null +++ b/engines/cryo/bugs.txt @@ -0,0 +1,19 @@ + +1. Open menu and replay last dialog, then press stop. hover over buttons - hint text will be misplaced +2. During valley location change some junk appears in the bottom half of screen for a brief time (broken transition effect?) +3. Transitions often show a lot of red colors (bad palette fadein/out?) +4. After game load in some areas (White Arch) top bar and inventory not redrawn due to (DrawFlags?) initialized incorrectly +5. Mac reload feature uses hardcoded savefile from eden.dat +6. First time in Tau's cave, try to take knife. When Dina objects, click on her - Tau's dialog will start (maybe it's original bug?) +7. Mouse clipping may be lost during FMV scenes +8. Screen doubling feature probably doesn't work (not really needed, can be replaced with built-in SCUMMVM scaler) +9. Tons of debug messages spam when hover mouse over party icons or menu buttons +A. King's bread drawn over inventory bar +B. PC cursor clipped too agressively +C. PC logos and credits videos won't play because encoded in old HNM format +D. Eye blinking works incorrectly? +E. Bogus hitbox in upper right corner of mirror screen (under mini-map) +F. Wrong frescoes cursor on PC +G. Junk on a valley entrance screen on PC +H. On PC, no sound during first Mungo's dialogue, memory corruption after that +J. PC intro video is lagging behind of background voice 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..1538ee4110 --- /dev/null +++ b/engines/cryo/cryo.cpp @@ -0,0 +1,116 @@ +/* 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) { + // Put your engine in a sane state, but do nothing big yet; + // in particular, do not load data from files; rather, if you + // need to do such things, do them from run(). + + // Do not initialize graphics here + // Do not initialize audio devices here + + // However this is the place to specify all default directories +// const Common::FSNode gameDataDir(ConfMan.get("path")); +// SearchMan.addSubDirectoryMatching(gameDataDir, "sound"); + + // Here is the right place to set up the engine specific debug channels + DebugMan.addDebugChannel(kCryoDebugExample, "example", "this is just an example for a engine specific debug channel"); + DebugMan.addDebugChannel(kCryoDebugExample2, "example2", "also an example"); + + // Don't forget to register your random source + _rnd = new Common::RandomSource("cryo"); + _debugger = nullptr; + + _game = nullptr; + _video = nullptr; + _screenView = nullptr; + + _showHotspots = false; + + g_ed = this; +} + +CryoEngine::~CryoEngine() { + debug("CryoEngine::~CryoEngine"); + + // Dispose your resources here + delete _rnd; + delete _game; + delete _video; + delete _screenView; + delete _debugger; + + // Remove all of our debug levels here + 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()); + + // Additional setup. + debug("CryoEngine::init"); + + // Your main even loop should be (invoked from) here. + debug("CryoEngine::go: Hello, World!"); + + // This test will show up if -d1 and --debugflags=example are specified on the commandline + debugC(1, kCryoDebugExample, "Example debug call"); + + // This test will show up if --debugflags=example or --debugflags=example2 or both of them and -d3 are specified on the commandline + debugC(3, kCryoDebugExample | kCryoDebugExample2, "Example debug call two"); + + _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..08509e4c11 --- /dev/null +++ b/engines/cryo/eden.cpp @@ -0,0 +1,9364 @@ +/* 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 run; + *scr++ = fill; //TODO: wha? + *scr++ = fill; + ww -= 128 + 1; + for (run = 127; run--;) + *scr++ = fill; + } + } else { + byte fill = *pix++; + byte run = 255 - c + 2; + ww -= run; + if (fill == 0) + scr += run; + else + for (; run--;) + *scr++ = fill; + } + } else { + byte run = c + 1; + ww -= run; + for (; run--;) { + 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 run; + *scr++ = fill; //TODO: wha? + *scr++ = fill; + ww -= 128 + 1; + for (run = 127; run--;) + *scr++ = fill; + } else { + byte fill = *pix++; + byte run = 255 - c + 2; + ww -= run; + for (; run--;) + *scr++ = fill; + } + } else { + byte run = c + 1; + ww -= run; + for (; run--;) { + 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 run; + *scr++ = fill; //TODO: wha? + *scr++ = fill; + ww -= 128 + 1; + for (run = 127; run--;) + *scr++ = fill; + } + } else { + byte fill = *pix++; + byte run = 255 - c + 2; + ww -= run; + if (fill == 0) + scr += run; + else { + for (; run--;) + *scr++ = fill; + } + } + } else { + byte run = c + 1; + ww -= run; + for (; run--;) { + 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 = -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 != -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 != -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 run; + *scr++ = fill; //TODO: wha? + *scr++ = fill; + ww -= 128 + 1; + for (run = 127; run--;) + *scr++ = fill; + } + } else { + byte fill = *pix++; + byte run = 255 - c + 2; + ww -= run; + if (fill == 0) + scr += run; + else { + for (; run--;) + *scr++ = fill; + } + } + } else { + byte run = c + 1; + ww -= run; + for (; run--;) { + 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 ? stepLeft = 1 : -1; + int16 stepRight = _musicChannel->_volumeRight < volumeRight ? stepRight = 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 < 0 //TODO: never happens + || _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 (int 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..a470a566be --- /dev/null +++ b/engines/cryo/eden.h @@ -0,0 +1,742 @@ +/* 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 "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/gameflow.txt b/engines/cryo/gameflow.txt new file mode 100644 index 0000000000..c932fc86f2 --- /dev/null +++ b/engines/cryo/gameflow.txt @@ -0,0 +1,24 @@ + +game phases + + 0 - game start + 10 - enter throne room + 20 - heard talk of eloi and father + 30 - in prince's room + 40 - met dina + 41 - talking to tau room: 202 + 50 - tau died + 60 - talked to jabber + 70 - got a gift from jabber + 71 - part with dina at secret crypt + 80 - learned about fresques / got flute + 81 - convinced monk to help + 82 - enter throne room + 90 - got king's permission + A0 - met chong + A1 - chong joins party + B0 - on valley screen after citadel build complete + C0 - met ulan + D0 - build citadel in uluru + E0 - got gift from ulan + ... 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..81329fb190 --- /dev/null +++ b/engines/cryo/platdefs.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_PLATDEFS_H +#define CRYO_PLATDEFS_H + +#if 1 +#include "common/file.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; + +#endif + +} // End of namespace Cryo + +#endif diff --git a/engines/cryo/readme.txt b/engines/cryo/readme.txt new file mode 100644 index 0000000000..c0f023be0f --- /dev/null +++ b/engines/cryo/readme.txt @@ -0,0 +1,72 @@ +Citadel of Mo, the last remaining place where humans can be safe from army +of vicious Tyrannosaurus led by allmighty Morkus Rex. What awaits young Adam, +prince of Mo, who just came of age and want to travel across the world? +Will he be able to restore long lost friendship between dinosaurus and humans? + + +This is SCUMMVM reimplementation of Cryo's Lost Eden game engine. In order to +stay as close as possible to original game and minimize number of bugs +introduced during code reconstruction, in its current state this project is +a straight reverse-engineered game code hooked up to SCUMMVM framework. +Because of that, this code in no way represent the quality or coding practices +of SCUMMVM itself. Essentially, this is how the game was originally written. + +There are several Lost Eden game versions known to exists. + +- Non-interactive PC demo version. Basically, a number of video files played + in a loop with FM music in background. Google for "ANCIBUR2.HNM" file to + find it. + +- Interactive PC demo version. Allows to play through whole Citadel of Mo + then shows "Coming Soon" banner. + Can be found here: http://www.ag.ru/games/lost-eden/demos/2677 + Download is a self-extracting archive, unpack it with 7zip or similar tool. + +- PC version. Main version of the game. Written in assembly and partially based + on Dune's game code. + Runs in real-mode DOS environment, uses VGA 320x200 graphics and digitized + sounds/music. Allows to select several languages for in-game subtitles. It is + rumored that bootleg Russian translation also exists. Has 3 predefined slots + for game save/load. Uses two different video codecs for HNM files. + +- MAC version. Almost identical to PC version. Has slightly modified UI. Such + as exta spaces on the inventory bar, resized subtitles overlay and different + implementation of mouse cursor (which is worse than the original one). Looks + like screen transition effects are also changed / rearranged. Also comes with + updated game script. + This version has no limit on save game slots. Standard system file selection + dialogs are used instead. All screen hot-spots coordinates loaded from the + main resource file instead of hard-coded values used in PC version. + +- 3DO version. Uses completely different resource formats. + +- CDI version. Uses completely different resource formats. + +- CD32 version. Mentioned in PC demo version, but never released? + + +This reimplementation project is based on MAC version, since it's much easier +to work with than any other versions. + +At this moment Mac version of the game is fully playabe/completeable. List of +currently discovered bugs can be found in bugs.txt file. None of those are +critical or game-breaking. Only single game save/load slot is supported and +saves are not cross-platform compatible. Also, no game restart feature work +due to the way it's implemented. + +PC versions (Demo and Full) are supported as well, but have a number of more +severe glitches. + +Because of limited development environment, this code is only tested on +MSVS2013 32-bit compiler. There may be some issues with GCC/LLVM compilers +or on 64-bit platforms. As mentioned above, this code is neither pretty or +bug-free (aka it's a can of worms). Several original bugs, various oddities +and problematic areas are marked with TODO comment in the source code. There +are number of variables with non-descripitve names like byte_1234, those +purpose is yet to be clearly understood. To make code debugging easier, +some commands have been added in the debugger. Some parts, like image +drawing routines, can be simplified/generalized. + +Because parts of this code (mainly decompression and video playback) used +by other Cryo's games, it might be worthy to make them reusable by future +engines. 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..88326e647e --- /dev/null +++ b/engines/cryo/video.cpp @@ -0,0 +1,616 @@ +/* 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 + 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/director.cpp b/engines/director/director.cpp index 9417538f54..ab45e921cf 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")); @@ -146,8 +148,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 +229,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..882eb14495 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: @@ -109,6 +110,10 @@ public: int _machineType; bool _playbackPaused; + Common::String _nextMovie; + Common::String _nextMovieFrameS; + int _nextMovieFrameI; + protected: virtual Common::Error run(); diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp index 3b121e0121..68b1713f46 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) { @@ -575,8 +574,8 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { 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); @@ -670,14 +669,14 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uin int x = _sprites[spriteId]->_startPoint.x + rectLeft; int y = _sprites[spriteId]->_startPoint.y + rectTop; int height = button->initialRect.height(); // _sprites[spriteId]->_height; - int width = button->initialRect.width() + 3; //_sprites[spriteId]->_width; + 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. + // 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(); + // TODO: review all cases to confirm if we should use text height. + // height = textRect.height(); Common::Rect _rect; @@ -727,7 +726,7 @@ 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); @@ -891,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; @@ -906,9 +907,9 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo 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]); + // 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->_currentScore->_fontMap[textCast->fontId]); } Graphics::MacFont macFont = Graphics::MacFont(textCast->fontId, textCast->fontSize, textCast->textSlant); @@ -938,8 +939,8 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo height = textSurface->h; if (textSize != NULL) { - //TODO: this offset could be due to incorrect fonts loaded! - textSize->bottom = height + (mt.getLineCount() - 2); + // TODO: this offset could be due to incorrect fonts loaded! + textSize->bottom = height + mt.getLineCount(); } uint16 textX = 0, textY = 0; @@ -970,7 +971,9 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo textX--; } else { x++; - y += 3; + if (width % 2 != 0) + x++; + y += 2; } switch (textCast->textAlign) { 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 630d681dee..552030a155 100644 --- a/engines/director/lingo/lingo-builtins.cpp +++ b/engines/director/lingo/lingo-builtins.cpp @@ -56,50 +56,53 @@ static struct BuiltinProto { { "string", Lingo::b_string, 1, 1, true }, // D2 { "value", Lingo::b_value, 1, 1, true }, // D2 // 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 function + { "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 + { "abort", Lingo::b_abort, 0, 0, false }, // D4 c { "continue", Lingo::b_continue, 0, 0, false }, // D2 - { "dontPassEvent", Lingo::b_dontPassEvent, 0, 0, false }, // D2 + { "dontPassEvent", Lingo::b_dontPassEvent, 0, 0, false }, // D2 c { "delay", Lingo::b_delay, 1, 1, false }, // D2 { "do", Lingo::b_do, 1, 1, false }, // D2 - { "halt", Lingo::b_halt, 0, 0, false }, // D4 - { "nothing", Lingo::b_nothing, 0, 0, false }, // D2 + { "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 // play // D2 { "playAccel", Lingo::b_playAccel, -1,0, false }, // D2 @@ -116,16 +119,18 @@ static struct BuiltinProto { // 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 // Misc - { "alert", Lingo::b_alert, 1, 1, false }, // D2 - { "cursor", Lingo::b_cursor, 1, 1, false }, // D2 + { "alert", Lingo::b_alert, 1, 1, false }, // D2 c + { "cursor", Lingo::b_cursor, 1, 1, false }, // D2 c { "framesToHMS", Lingo::b_framesToHMS, 4, 4, false }, // D3 { "HMStoFrames", Lingo::b_HMStoFrames, 4, 4, false }, // D3 + { "param", Lingo::b_param, 1, 1, true }, // D4 f { "printFrom", Lingo::b_printFrom, -1,0, false }, // D2 // put // D2 // set // D2 @@ -134,27 +139,29 @@ static struct BuiltinProto { // Score { "constrainH", Lingo::b_constrainH, 2, 2, true }, // D2 { "constrainV", Lingo::b_constrainV, 2, 2, true }, // D2 - { "duplicate", Lingo::b_duplicate, 1, 2, false }, // D4 + { "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", Lingo::b_erase, 1, 1, false }, // D4 - { "findEmpty", Lingo::b_findEmpty, 1, 1, true }, // D4 + { "erase", Lingo::b_erase, 1, 1, false }, // D4 c + { "findEmpty", Lingo::b_findEmpty, 1, 1, true }, // D4 f // go // D2 - { "importFileInto", Lingo::b_importFileInto,2, 2, false }, // D4 - { "installMenu", Lingo::b_installMenu, 1, 1, false }, // D2 + { "importFileInto", Lingo::b_importFileInto,2, 2, false }, // D4 c + { "installMenu", Lingo::b_installMenu, 1, 1, false }, // D2 c + { "intersect", Lingo::b_intersect, 2, 2, false }, // D4 f { "label", Lingo::b_label, 1, 1, true }, // D2 { "marker", Lingo::b_marker, 1, 1, true }, // D2 - { "move", Lingo::b_move, 1, 2, false }, // D4 + { "move", Lingo::b_move, 1, 2, false }, // D4 c { "moveableSprite", Lingo::b_moveableSprite,0, 0, false }, // D2 - { "pasteClipBoardInto",Lingo::b_pasteClipBoardInto,1, 1, false }, // D4 + { "pasteClipBoardInto",Lingo::b_pasteClipBoardInto,1, 1, false }, // D4 c { "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 + { "rollOver", Lingo::b_rollOver, 1, 1, true }, // D2 f { "spriteBox", Lingo::b_spriteBox, -1,0, false }, // D2 - { "unLoad", Lingo::b_unLoad, 0, 2, false }, // D4 - { "unLoadCast", Lingo::b_unLoadCast, 0, 2, false }, // D4 + { "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 { "zoomBox", Lingo::b_zoomBox, -1,0, false }, // D2 // Point @@ -165,9 +172,15 @@ static struct BuiltinProto { { "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-playFile", Lingo::b_soundPlayFile, 2, 2, false }, // D3 c { "sound-stop", Lingo::b_soundStop, 1, 1, false }, // D3 - { "soundBusy", Lingo::b_soundBusy, 1, 1, true }, // D3 + { "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 { "backspace", Lingo::b_backspace, 0, 0, false }, // D2 { "empty", Lingo::b_empty, 0, 0, false }, // D2 @@ -179,9 +192,10 @@ static struct BuiltinProto { { "true", Lingo::b_true, 0, 0, false }, // D2 { "version", Lingo::b_version, 0, 0, false }, // D3 // References - { "cast", Lingo::b_cast, 1, 1, false }, // D4 - { "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 + { "window", Lingo::b_window, 1, 1, false }, // D4 f { 0, 0, 0, 0, false } }; @@ -195,7 +209,35 @@ static const char *twoWordBuiltins[] = { static const char *builtinFunctions[] = { "cast", + "count", "field", + "findEmpty", + "findPos", + "findPosNear", + "getaProp", + "getAt", + "getLast", + "getNthFileNameInFolder", + "getOne", + "getPos", + "getProp", + "getPropAt", + "ilk", + "inflate", + "integerp", + "intersect", + "list", + "listP", + "max", + "min", + "objectp", + "pictureP", + "rollOver", + "soundBusy", + "stringp", + "symbolp", + "window", + "xFactoryList", 0 }; @@ -216,8 +258,12 @@ void Lingo::initBuiltIns() { _functions[(void *)sym->u.s] = new FuncDesc(blt->name, ""); } - for (const char **b = builtinFunctions; *b; b++) + 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; @@ -629,6 +675,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(); @@ -659,6 +713,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"); } @@ -730,6 +790,12 @@ void Lingo::b_halt(int 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; @@ -770,6 +836,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); @@ -833,6 +905,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; @@ -904,6 +982,12 @@ void Lingo::b_constrainV(int nargs) { g_lingo->push(Datum(0)); } +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); @@ -939,6 +1023,14 @@ void Lingo::b_installMenu(int nargs) { warning("STUB: b_installMenu(%d)", d.u.i); } +void Lingo::b_intersect(int nargs) { + g_lingo->printSTUBWithArglist("b_intersect", nargs); + + g_lingo->dropStack(nargs); + + g_lingo->push(Datum(0)); +} + void Lingo::b_label(int nargs) { Datum d = g_lingo->pop(); d.toInt(); @@ -1040,6 +1132,41 @@ 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); +} + +void Lingo::b_window(int nargs) { + g_lingo->printSTUBWithArglist("b_window", nargs); + g_lingo->dropStack(nargs); + g_lingo->push(Datum(0)); +} + /////////////////// // Point diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp index 2a20e02b2e..7046fed979 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", "" }, @@ -946,6 +947,11 @@ void Lingo::c_whencode() { g_lingo->_pc = end; } +void Lingo::c_tellcode() { + warning("STUB: c_tellcode"); +} + + //************************ // Built-in functions //************************ diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp index ef19293d92..5ae58a9207 100644 --- a/engines/director/lingo/lingo-funcs.cpp +++ b/engines/director/lingo/lingo-funcs.cpp @@ -181,19 +181,24 @@ void Lingo::func_goto(Datum &frame, Datum &movie) { return; } - restartLingo(); + _vm->_nextMovie = *movie.u.s; + _vm->_currentScore->_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; } diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp index 56c0af2f63..e25e206024 100644 --- a/engines/director/lingo/lingo-gr.cpp +++ b/engines/director/lingo/lingo-gr.cpp @@ -145,8 +145,9 @@ tSPRITE = 334, tINTERSECTS = 335, tWITHIN = 336, - tON = 337, - tME = 338 + tTELL = 337, + tON = 338, + tME = 339 }; #endif /* Tokens. */ @@ -229,8 +230,9 @@ #define tSPRITE 334 #define tINTERSECTS 335 #define tWITHIN 336 -#define tON 337 -#define tME 338 +#define tTELL 337 +#define tON 338 +#define tME 339 @@ -298,7 +300,7 @@ typedef union YYSTYPE Common::Array<double> *arr; } /* Line 193 of yacc.c. */ -#line 302 "engines/director/lingo/lingo-gr.cpp" +#line 304 "engines/director/lingo/lingo-gr.cpp" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -311,7 +313,7 @@ typedef union YYSTYPE /* Line 216 of yacc.c. */ -#line 315 "engines/director/lingo/lingo-gr.cpp" +#line 317 "engines/director/lingo/lingo-gr.cpp" #ifdef short # undef short @@ -524,22 +526,22 @@ union yyalloc #endif /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 115 +#define YYFINAL 116 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 1612 +#define YYLAST 1602 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 99 +#define YYNTOKENS 100 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 42 /* YYNRULES -- Number of rules. */ -#define YYNRULES 154 +#define YYNRULES 155 /* YYNRULES -- Number of states. */ -#define YYNSTATES 337 +#define YYNSTATES 341 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 338 +#define YYMAXUTOK 339 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -548,15 +550,15 @@ union yyalloc static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 91, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 92, 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, 90, 85, 2, - 92, 93, 88, 86, 98, 87, 2, 89, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 91, 86, 2, + 93, 94, 89, 87, 99, 88, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 95, 84, 94, 2, 2, 2, 2, 2, 2, 2, + 96, 85, 95, 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, 96, 2, 97, 2, 2, 2, 2, 2, 2, + 2, 97, 2, 98, 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, @@ -580,7 +582,7 @@ 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, 81, 82, 83 + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84 }; #if YYDEBUG @@ -590,84 +592,85 @@ 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, 248, 253, 255, 257, 260, 262, 266, 270, 274, - 278, 282, 286, 290, 294, 298, 302, 306, 310, 313, - 317, 321, 325, 329, 332, 335, 339, 343, 348, 353, - 358, 365, 370, 377, 382, 389, 394, 401, 404, 406, - 408, 411, 413, 416, 419, 421, 424, 427, 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, 582, 585 + 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, 267, 269, 271, 274, 276, + 280, 284, 288, 292, 296, 300, 304, 308, 312, 316, + 320, 324, 327, 331, 335, 339, 343, 346, 349, 353, + 357, 362, 367, 372, 379, 384, 391, 396, 403, 408, + 415, 418, 420, 422, 425, 427, 430, 433, 435, 438, + 441, 443, 446, 451, 458, 463, 466, 470, 472, 476, + 478, 482, 485, 488, 491, 494, 498, 501, 504, 506, + 510, 513, 516, 519, 523, 526, 527, 531, 532, 541, + 544, 545, 554, 555, 556, 567, 568, 570, 574, 579, + 580, 583, 584, 586, 590, 592 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { - 100, 0, -1, 100, 101, 102, -1, 102, -1, 1, - 101, -1, 91, -1, -1, 130, -1, 137, -1, 105, - -1, 45, 121, 38, 24, -1, 45, 121, 70, 121, - -1, 45, 121, 71, 121, -1, 47, 24, 84, 121, - -1, 47, 12, 84, 121, -1, 47, 13, 121, 84, - 121, -1, 47, 24, 49, 121, -1, 47, 12, 49, - 121, -1, 47, 13, 121, 49, 121, -1, 121, -1, - 122, -1, 104, -1, 106, -1, 113, 92, 112, 93, - 119, 118, 28, -1, 114, 84, 121, 118, 49, 121, - 118, 119, 118, 28, -1, 114, 84, 121, 118, 30, - 49, 121, 118, 119, 118, 28, -1, 120, 121, 118, - -1, 115, 112, 48, 101, 119, 118, 28, -1, 115, - 112, 48, 101, 119, 118, 53, 119, 118, 28, -1, - 115, 112, 48, 101, 119, 118, 117, 108, 118, 28, - -1, 115, 112, 48, 117, 104, 118, -1, 115, 112, - 48, 117, 104, 118, 53, 117, 104, 118, -1, 115, - 112, 48, 117, 104, 118, 109, 118, 107, 118, -1, - -1, 53, 117, 104, -1, 108, 111, -1, 111, -1, - 109, 110, -1, 110, -1, 116, 112, 48, 117, 105, - 118, -1, 109, -1, 116, 112, 48, 117, 119, 118, - -1, 121, -1, 121, 84, 121, -1, 92, 112, 93, - -1, 46, 52, -1, 46, 51, 24, -1, 37, -1, - 32, -1, -1, -1, -1, 119, 101, -1, 119, 105, - -1, 50, 24, 48, -1, 11, -1, 14, -1, 27, - -1, 25, -1, 22, -1, 23, 121, -1, 24, 92, - 138, 93, -1, 24, -1, 12, -1, 13, 121, -1, - 103, -1, 121, 86, 121, -1, 121, 87, 121, -1, - 121, 88, 121, -1, 121, 89, 121, -1, 121, 69, - 121, -1, 121, 94, 121, -1, 121, 95, 121, -1, - 121, 65, 121, -1, 121, 60, 121, -1, 121, 61, - 121, -1, 121, 66, 121, -1, 121, 67, 121, -1, - 68, 121, -1, 121, 85, 121, -1, 121, 72, 121, - -1, 121, 73, 121, -1, 121, 74, 121, -1, 86, - 121, -1, 87, 121, -1, 92, 121, 93, -1, 96, - 138, 97, -1, 79, 121, 80, 121, -1, 79, 121, - 81, 121, -1, 75, 121, 43, 121, -1, 75, 121, - 49, 121, 43, 121, -1, 76, 121, 43, 121, -1, - 76, 121, 49, 121, 43, 121, -1, 77, 121, 43, - 121, -1, 77, 121, 49, 121, 43, 121, -1, 78, - 121, 43, 121, -1, 78, 121, 49, 121, 43, 121, - -1, 45, 121, -1, 125, -1, 128, -1, 33, 46, - -1, 33, -1, 35, 123, -1, 59, 124, -1, 16, - -1, 18, 121, -1, 17, 121, -1, 17, -1, 19, - 140, -1, 83, 92, 24, 93, -1, 83, 92, 24, - 98, 138, 93, -1, 56, 121, 51, 121, -1, 56, - 121, -1, 20, 24, 138, -1, 24, -1, 123, 98, - 24, -1, 24, -1, 124, 98, 24, -1, 36, 39, - -1, 36, 42, -1, 36, 44, -1, 36, 126, -1, - 36, 126, 127, -1, 36, 127, -1, 34, 121, -1, - 121, -1, 43, 41, 121, -1, 41, 121, -1, 57, - 58, -1, 57, 126, -1, 57, 126, 127, -1, 57, - 127, -1, -1, 29, 129, 138, -1, -1, 40, 24, - 131, 117, 135, 101, 136, 119, -1, 54, 24, -1, - -1, 55, 24, 132, 117, 135, 101, 136, 119, -1, - -1, -1, 82, 24, 133, 117, 134, 135, 101, 136, - 119, 28, -1, -1, 24, -1, 135, 98, 24, -1, - 135, 101, 98, 24, -1, -1, 24, 139, -1, -1, - 121, -1, 138, 98, 121, -1, 121, -1, 139, 98, - 121, -1, 121, 101, -1, 140, 98, 121, 101, -1 + 101, 0, -1, 101, 102, 103, -1, 103, -1, 1, + 102, -1, 92, -1, -1, 132, -1, 139, -1, 106, + -1, 45, 123, 38, 24, -1, 45, 123, 70, 123, + -1, 45, 123, 71, 123, -1, 47, 24, 85, 123, + -1, 47, 12, 85, 123, -1, 47, 13, 123, 85, + 123, -1, 47, 24, 49, 123, -1, 47, 12, 49, + 123, -1, 47, 13, 123, 49, 123, -1, 123, -1, + 124, -1, 105, -1, 107, -1, 114, 93, 113, 94, + 120, 119, 28, -1, 115, 85, 123, 119, 49, 123, + 119, 120, 119, 28, -1, 115, 85, 123, 119, 30, + 49, 123, 119, 120, 119, 28, -1, 121, 123, 119, + -1, 122, 123, 102, 120, 119, 28, -1, 122, 123, + 49, 123, -1, 116, 113, 48, 102, 120, 119, 28, + -1, 116, 113, 48, 102, 120, 119, 53, 120, 119, + 28, -1, 116, 113, 48, 102, 120, 119, 118, 109, + 119, 28, -1, 116, 113, 48, 118, 105, 119, -1, + 116, 113, 48, 118, 105, 119, 53, 118, 105, 119, + -1, 116, 113, 48, 118, 105, 119, 110, 119, 108, + 119, -1, -1, 53, 118, 105, -1, 109, 112, -1, + 112, -1, 110, 111, -1, 111, -1, 117, 113, 48, + 118, 106, 119, -1, 110, -1, 117, 113, 48, 118, + 120, 119, -1, 123, -1, 123, 85, 123, -1, 93, + 113, 94, -1, 46, 52, -1, 46, 51, 24, -1, + 37, -1, 32, -1, -1, -1, -1, 120, 102, -1, + 120, 106, -1, 50, 24, 48, -1, 82, -1, 11, + -1, 14, -1, 27, -1, 25, -1, 22, -1, 23, + 123, -1, 24, 93, 140, 94, -1, 24, -1, 12, + -1, 13, 123, -1, 104, -1, 123, 87, 123, -1, + 123, 88, 123, -1, 123, 89, 123, -1, 123, 90, + 123, -1, 123, 69, 123, -1, 123, 95, 123, -1, + 123, 96, 123, -1, 123, 65, 123, -1, 123, 60, + 123, -1, 123, 61, 123, -1, 123, 66, 123, -1, + 123, 67, 123, -1, 68, 123, -1, 123, 86, 123, + -1, 123, 72, 123, -1, 123, 73, 123, -1, 123, + 74, 123, -1, 87, 123, -1, 88, 123, -1, 93, + 123, 94, -1, 97, 140, 98, -1, 79, 123, 80, + 123, -1, 79, 123, 81, 123, -1, 75, 123, 43, + 123, -1, 75, 123, 49, 123, 43, 123, -1, 76, + 123, 43, 123, -1, 76, 123, 49, 123, 43, 123, + -1, 77, 123, 43, 123, -1, 77, 123, 49, 123, + 43, 123, -1, 78, 123, 43, 123, -1, 78, 123, + 49, 123, 43, 123, -1, 45, 123, -1, 127, -1, + 130, -1, 33, 46, -1, 33, -1, 35, 125, -1, + 59, 126, -1, 16, -1, 18, 123, -1, 17, 123, + -1, 17, -1, 19, 141, -1, 84, 93, 24, 94, + -1, 84, 93, 24, 99, 140, 94, -1, 56, 123, + 51, 123, -1, 56, 123, -1, 20, 24, 140, -1, + 24, -1, 125, 99, 24, -1, 24, -1, 126, 99, + 24, -1, 36, 39, -1, 36, 42, -1, 36, 44, + -1, 36, 128, -1, 36, 128, 129, -1, 36, 129, + -1, 34, 123, -1, 123, -1, 43, 41, 123, -1, + 41, 123, -1, 57, 58, -1, 57, 128, -1, 57, + 128, 129, -1, 57, 129, -1, -1, 29, 131, 140, + -1, -1, 40, 24, 133, 118, 137, 102, 138, 120, + -1, 54, 24, -1, -1, 55, 24, 134, 118, 137, + 102, 138, 120, -1, -1, -1, 83, 24, 135, 118, + 136, 137, 102, 138, 120, 28, -1, -1, 24, -1, + 137, 99, 24, -1, 137, 102, 99, 24, -1, -1, + 24, 141, -1, -1, 123, -1, 140, 99, 123, -1, + 123, -1, 141, 99, 123, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ @@ -675,20 +678,20 @@ static const yytype_uint16 yyrline[] = { 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, 251, 261, 273, - 285, 295, 305, 317, 318, 321, 322, 325, 326, 329, - 337, 338, 346, 347, 348, 351, 354, 361, 368, 376, - 379, 382, 383, 384, 387, 393, 394, 397, 400, 403, - 406, 409, 412, 416, 423, 429, 430, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, - 454, 455, 456, 457, 458, 459, 460, 463, 464, 465, - 466, 467, 469, 470, 471, 474, 477, 480, 483, 484, - 485, 486, 487, 488, 491, 492, 495, 496, 507, 508, - 509, 510, 513, 516, 521, 522, 525, 526, 529, 530, - 533, 536, 539, 539, 569, 569, 575, 578, 578, 583, - 584, 583, 594, 595, 596, 597, 600, 604, 612, 613, - 614, 617, 618, 621, 622 + 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, 422, 426, 433, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, + 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 473, 474, 475, 476, 477, 479, 480, 481, 484, 487, + 490, 493, 494, 495, 496, 497, 498, 501, 502, 505, + 506, 517, 518, 519, 520, 523, 526, 531, 532, 535, + 536, 539, 540, 543, 546, 549, 549, 579, 579, 585, + 588, 588, 593, 594, 593, 604, 605, 606, 607, 610, + 614, 622, 623, 624, 627, 628 }; #endif @@ -709,15 +712,15 @@ static const char *const yytname[] = "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", - "elseifstmtoneliner1", "elseifstmt1", "cond", "repeatwhile", - "repeatwith", "if", "elseif", "begin", "end", "stmtlist", "when", "expr", - "proc", "globallist", "instancelist", "gotofunc", "gotoframe", - "gotomovie", "playfunc", "@1", "defn", "@2", "@3", "@4", "@5", "argdef", - "argstore", "macro", "arglist", "nonemptyarglist", "nonemptyarglistnl", 0 + "tINTERSECTS", "tWITHIN", "tTELL", "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", "tell", "expr", "proc", "globallist", "instancelist", "gotofunc", + "gotoframe", "gotomovie", "playfunc", "@1", "defn", "@2", "@3", "@4", + "@5", "argdef", "argstore", "macro", "arglist", "nonemptyarglist", 0 }; #endif @@ -734,30 +737,30 @@ 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, 336, 337, 338, 61, 38, 43, 45, 42, 47, - 37, 10, 40, 41, 62, 60, 91, 93, 44 + 335, 336, 337, 338, 339, 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, 99, 100, 100, 100, 101, 102, 102, 102, 102, - 103, 103, 103, 103, 103, 103, 103, 103, 103, 104, - 104, 105, 105, 105, 105, 105, 105, 106, 106, 106, - 106, 106, 106, 107, 107, 108, 108, 109, 109, 110, - 111, 111, 112, 112, 112, 113, 114, 115, 116, 117, - 118, 119, 119, 119, 120, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 122, 122, 122, - 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 122, 122, 122, 122, 123, 123, 124, 124, 125, 125, - 125, 125, 125, 125, 126, 126, 127, 127, 128, 128, - 128, 128, 129, 128, 131, 130, 130, 132, 130, 133, - 134, 130, 135, 135, 135, 135, 136, 137, 138, 138, - 138, 139, 139, 140, 140 + 0, 100, 101, 101, 101, 102, 103, 103, 103, 103, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, + 105, 106, 106, 106, 106, 106, 106, 106, 106, 107, + 107, 107, 107, 107, 107, 108, 108, 109, 109, 110, + 110, 111, 112, 112, 113, 113, 113, 114, 115, 116, + 117, 118, 119, 120, 120, 120, 121, 122, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 125, 125, 126, + 126, 127, 127, 127, 127, 127, 127, 128, 128, 129, + 129, 130, 130, 130, 130, 131, 130, 133, 132, 132, + 134, 132, 135, 136, 132, 137, 137, 137, 137, 138, + 139, 140, 140, 140, 141, 141 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -765,20 +768,20 @@ 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, - 2, 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, 1, 2, 2, 1, 2, 4, - 6, 4, 2, 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, 1, 3, 2, 4 + 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, 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, 1, 2, 2, + 1, 2, 4, 6, 4, 2, 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, 1, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -786,101 +789,103 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 0, 55, 63, 0, 56, 104, 107, 0, 0, - 0, 59, 0, 62, 58, 57, 132, 101, 0, 0, - 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 58, 66, 0, 59, 107, 110, 0, 0, + 0, 62, 0, 65, 61, 60, 135, 104, 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, 151, 0, 3, 68, 21, 9, 22, + 0, 0, 0, 0, 0, 19, 20, 101, 102, 7, + 8, 5, 4, 65, 0, 67, 109, 108, 154, 111, + 151, 63, 151, 150, 151, 103, 117, 105, 0, 121, + 0, 122, 0, 123, 128, 124, 126, 137, 100, 0, + 47, 0, 0, 0, 0, 139, 140, 115, 131, 132, + 134, 119, 106, 81, 0, 0, 0, 0, 0, 142, + 0, 86, 87, 0, 152, 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, 0, 148, 0, 3, 65, 21, 9, 22, 0, - 0, 0, 0, 19, 20, 98, 99, 7, 8, 5, - 4, 62, 0, 64, 106, 105, 0, 108, 148, 60, - 148, 151, 147, 148, 100, 114, 102, 0, 118, 0, - 119, 0, 120, 125, 121, 123, 134, 97, 0, 45, - 0, 0, 0, 0, 136, 137, 112, 128, 129, 131, - 116, 103, 78, 0, 0, 0, 0, 0, 139, 0, - 83, 84, 0, 149, 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, 148, - 0, 153, 0, 113, 149, 0, 0, 133, 0, 124, - 127, 0, 122, 49, 0, 0, 0, 46, 0, 0, - 0, 0, 0, 54, 49, 0, 130, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, - 85, 86, 0, 2, 0, 50, 0, 0, 49, 0, - 26, 74, 75, 73, 76, 77, 70, 80, 81, 82, - 79, 66, 67, 68, 69, 71, 72, 0, 61, 152, - 115, 126, 142, 10, 11, 12, 17, 14, 0, 0, - 16, 13, 142, 111, 117, 89, 0, 91, 0, 93, - 0, 95, 0, 87, 88, 140, 109, 148, 150, 51, - 0, 44, 51, 0, 43, 154, 143, 0, 18, 15, - 0, 0, 0, 0, 0, 142, 0, 50, 0, 0, - 50, 50, 0, 146, 146, 90, 92, 94, 96, 0, - 110, 52, 53, 0, 0, 50, 49, 30, 144, 0, - 51, 51, 146, 23, 50, 51, 27, 51, 0, 48, - 49, 50, 38, 0, 145, 135, 138, 51, 51, 50, - 50, 50, 40, 36, 0, 0, 37, 33, 0, 0, - 50, 0, 0, 35, 0, 0, 50, 49, 50, 49, - 141, 0, 24, 28, 29, 49, 31, 0, 32, 0, - 25, 51, 34, 50, 50, 39, 41 + 0, 151, 0, 0, 116, 152, 0, 136, 0, 127, + 130, 0, 125, 51, 0, 0, 0, 48, 0, 0, + 0, 0, 0, 56, 51, 0, 133, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, + 88, 89, 0, 2, 0, 52, 0, 0, 51, 0, + 26, 0, 53, 77, 78, 76, 79, 80, 73, 83, + 84, 85, 82, 69, 70, 71, 72, 74, 75, 155, + 64, 118, 129, 145, 10, 11, 12, 17, 14, 0, + 0, 16, 13, 145, 114, 120, 92, 0, 94, 0, + 96, 0, 98, 0, 90, 91, 143, 112, 151, 153, + 53, 0, 46, 53, 0, 45, 28, 52, 146, 0, + 18, 15, 0, 0, 0, 0, 0, 145, 0, 52, + 0, 0, 52, 52, 54, 55, 0, 0, 149, 149, + 93, 95, 97, 99, 0, 113, 0, 0, 52, 51, + 32, 27, 147, 0, 53, 53, 149, 23, 52, 53, + 29, 53, 0, 50, 51, 52, 40, 0, 148, 138, + 141, 53, 53, 52, 52, 52, 42, 38, 0, 0, + 39, 35, 0, 0, 52, 0, 0, 37, 0, 0, + 52, 51, 52, 51, 144, 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, 43, 271, 44, 45, 46, 272, 48, 318, 301, - 302, 292, 303, 120, 49, 50, 51, 293, 212, 190, - 257, 52, 53, 54, 76, 101, 55, 84, 85, 56, - 73, 57, 153, 164, 178, 255, 247, 280, 58, 145, - 72, 67 + -1, 44, 264, 45, 46, 47, 265, 49, 322, 305, + 306, 296, 307, 121, 50, 51, 52, 297, 213, 190, + 247, 53, 54, 55, 56, 77, 102, 57, 85, 86, + 58, 74, 59, 153, 164, 178, 257, 249, 284, 60, + 146, 69 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -264 +#define YYPACT_NINF -278 static const yytype_int16 yypact[] = { - 297, -60, -264, -264, 907, -264, -264, 907, 907, 907, - 34, -264, 907, 984, -264, -264, -264, 29, 67, 804, - -264, 71, 907, 46, 55, 75, 76, 84, 907, 881, - 85, 907, 907, 907, 907, 907, 907, 89, 25, 907, - 907, 907, 907, 2, -264, -264, -264, -264, -264, 30, - 37, 1010, 907, 1517, -264, -264, -264, -264, -264, -264, - -264, 31, 907, 1517, 1517, 1517, 1423, 43, 907, 1517, - 907, 1517, 44, 907, -264, -264, 47, 907, -264, 907, - -264, 103, -264, 1517, -16, -264, -264, 1043, 122, -264, - -38, 907, -34, 100, -264, -264, 1330, -264, -16, -264, - -264, 51, -56, 1075, 1107, 1139, 1171, 1361, -264, 126, - -56, -56, 1455, 1517, 17, -264, 383, 1010, 907, 1010, - 105, 1486, 1517, 907, 907, 907, 907, 907, 907, 907, - 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, - 1043, -264, 907, 53, 1455, -32, 907, 53, 130, 1517, - 1517, 907, -264, -264, 131, 907, 907, -264, 907, 907, - 704, 907, 907, -264, -264, 907, -264, 137, 907, 907, - 907, 907, 907, 907, 907, 907, 907, 907, -264, -12, - -264, -264, 907, -264, 72, 1517, 74, 1392, -60, 907, - -264, 16, 16, 16, -56, -56, -56, 1517, 16, 16, - 120, 155, 155, -56, -56, 1517, 1517, 1423, -264, 1517, - -264, 1517, 140, -264, 1517, 1517, 1517, 1517, 907, 907, - 1517, 1517, 140, 1517, -264, 1517, 1203, 1517, 1235, 1517, - 1267, 1517, 1299, 1517, 1517, -264, -264, 907, 1517, -264, - -4, -264, -264, 727, 1517, -264, -264, -2, 1517, 1517, - -2, 907, 907, 907, 907, 140, 14, 555, 119, 907, - 555, -264, 157, 81, 81, 1517, 1517, 1517, 1517, -2, - -264, -264, -264, 156, 907, 1517, -6, -25, -264, 161, - -264, -264, 81, -264, 1517, -264, -264, -264, 162, -264, - -264, 162, -264, 1010, -264, 555, 555, -264, -264, 555, - 555, 162, 162, -264, 1010, 727, -264, 135, 145, 469, - 555, 167, 169, -264, 170, 152, -264, -264, -264, -264, - -264, 173, -264, -264, -264, -264, -264, 727, -264, 641, - -264, 641, -264, -264, 555, -264, -264 + 294, -76, -278, -278, 902, -278, -278, 902, 902, 902, + 32, -278, 902, 960, -278, -278, -278, -21, 40, 807, + -278, 48, 902, 45, 46, 50, 56, 66, 902, 865, + 74, 902, 902, 902, 902, 902, 902, -278, 75, -62, + 902, 902, 902, 902, 2, -278, -278, -278, -278, -278, + 8, 15, 997, 902, 902, 1506, -278, -278, -278, -278, + -278, -278, -278, 21, 902, 1506, 1506, 1506, 1506, 26, + 902, 1506, 902, 26, 902, -278, -278, 47, 902, -278, + 902, -278, 104, -278, 1506, 25, -278, -278, 1026, 125, + -278, -38, 902, -37, 102, -278, -278, 1346, -278, 25, + -278, -278, 52, -45, 1058, 1090, 1122, 1154, 1378, -278, + 130, -45, -45, 1442, 1506, 24, -278, 381, 997, 902, + 997, 107, 1474, 1506, 706, 902, 902, 902, 902, 902, + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + 902, 902, 1026, 902, 59, 1442, -77, 59, 137, 1506, + 1506, 902, -278, -278, 140, 902, 902, -278, 902, 902, + 1314, 902, 902, -278, -278, 902, -278, 141, 902, 902, + 902, 902, 902, 902, 902, 902, 902, 902, -278, 19, + -278, -278, 902, -278, 73, 1506, 85, 1410, -76, 902, + -278, 902, -278, 16, 16, 16, -45, -45, -45, 1506, + 16, 16, 20, 197, 197, -45, -45, 1506, 1506, 1506, + -278, -278, 1506, 157, -278, 1506, 1506, 1506, 1506, 902, + 902, 1506, 1506, 157, 1506, -278, 1506, 1186, 1506, 1218, + 1506, 1250, 1506, 1282, 1506, 1506, -278, -278, 902, 1506, + -278, 27, -278, -278, 729, 1506, 1506, 555, -278, -73, + 1506, 1506, -73, 902, 902, 902, 902, 157, 49, 555, + 133, 902, 555, -278, -278, -278, 160, 161, 90, 90, + 1506, 1506, 1506, 1506, -73, -278, 165, 902, 1506, -7, + 7, -278, -278, 170, -278, -278, 90, -278, 1506, -278, + -278, -278, 164, -278, -278, 164, -278, 997, -278, 555, + 555, -278, -278, 555, 555, 164, 164, -278, 997, 729, + -278, 146, 152, 468, 555, 176, 177, -278, 178, 159, + -278, -278, -278, -278, -278, 180, -278, -278, -278, -278, + -278, 729, -278, 642, -278, 642, -278, -278, 555, -278, + -278 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -264, -264, 11, 86, -264, -240, 0, -264, -264, -264, - -74, -243, -97, -113, -264, -264, -264, -237, -94, -27, - -225, -264, 1, -264, -264, -264, -264, 176, -8, -264, - -264, -264, -264, -264, -264, -264, -198, -263, -264, -24, - -264, -264 + -278, -278, 23, 92, -278, -240, 0, -278, -278, -278, + -70, -211, -93, -117, -278, -278, -278, -277, -126, -61, + -56, -278, -278, 1, -278, -278, -278, -278, 185, -22, + -278, -278, -278, -278, -278, -278, -278, -217, -208, -278, + -25, 202 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -890,334 +895,332 @@ static const yytype_int16 yypgoto[] = #define YYTABLE_NINF -7 static const yytype_int16 yytable[] = { - 47, 281, 115, 261, 184, 63, 186, 289, 64, 65, - 66, 158, 60, 69, 71, 161, 129, 260, 114, 297, - 83, 99, 286, 87, 250, 79, 258, 81, 290, 96, - 83, 59, 102, 103, 104, 105, 106, 107, 137, 138, - 110, 111, 112, 113, 143, 259, 159, 287, 306, 147, - 162, 304, 121, 122, 116, 295, 296, 269, 68, 306, - 299, 208, 300, 140, 304, 316, 182, 90, 91, 113, - 222, 144, 309, 310, 113, 74, 152, 141, 149, 92, - 150, 236, 126, 127, 235, 128, 237, 332, 129, 59, - 166, 75, 160, 59, 243, 86, 262, 88, 89, 93, - 94, 132, 133, 134, 135, 136, 334, 270, 95, 100, - 137, 138, 182, 108, 181, 182, 47, 109, 121, 185, - 187, 118, 117, 139, 191, 192, 193, 194, 195, 196, + 48, 184, 116, 186, 263, 65, 252, 100, 66, 67, + 68, 158, 161, 71, 68, 308, 61, 210, 115, 61, + 84, 290, 182, 88, 62, 75, 267, 131, 308, 97, + 84, 110, 103, 104, 105, 106, 107, 108, 223, 293, + 274, 111, 112, 113, 114, 144, 291, 159, 162, 147, + 139, 140, 236, 122, 123, 124, 70, 260, 91, 92, + 294, 285, 244, 152, 76, 142, 80, 117, 82, 320, + 93, 114, 87, 145, 94, 114, 261, 166, 301, 149, + 95, 150, 128, 129, 310, 130, 128, 129, 131, 130, + 96, 336, 131, 160, 61, 310, 89, 90, 101, 109, + 119, 118, 134, 135, 136, 137, 138, 135, 136, 137, + 138, 139, 140, 237, 141, 139, 140, 48, 238, 122, + 185, 187, 181, 182, 241, 143, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 113, 142, 146, 207, 151, 148, 157, 209, 163, 167, - 179, 182, 211, 188, 210, 213, 214, 215, 240, 216, - 217, 224, 220, 221, 246, 239, 223, 241, 274, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 279, - 308, 278, 288, 238, 283, 294, 126, 127, 317, 128, - 244, 315, 129, 319, 289, 322, 305, 323, 324, 242, - 325, 330, 183, 291, 313, 98, 133, 134, 135, 136, - 0, 0, 0, 256, 137, 138, 0, 0, 245, 248, - 249, 126, 127, 327, 128, 329, 0, 129, 0, 0, - 273, 331, 0, 276, 277, 0, 0, 0, 113, 0, - 0, 0, 0, 135, 136, 0, 0, 0, 285, 137, - 138, 0, 265, 266, 267, 268, 0, 298, 263, 0, - 275, 264, 0, 0, 307, 0, 0, 0, 0, 0, - 0, 0, 311, 312, 314, 284, 0, 0, 0, 0, - 282, 0, 0, 321, 0, 0, 0, 0, 0, 326, - 0, 328, 0, 0, 121, 0, 0, -6, 1, 0, - 0, 0, 0, 0, 0, 121, 335, 336, 2, 3, - 4, 5, 0, 6, 7, 8, 9, 10, 0, 11, - 12, 13, 14, 0, 15, 0, 16, 0, 0, 333, - 17, 333, 18, 19, 20, 0, 0, 21, 0, 0, - 0, 0, 22, 23, 24, 0, 0, 25, 0, 0, - 0, 26, 27, 28, 29, 0, 30, 0, 0, 0, - 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, - 0, 0, 32, 33, 34, 35, 36, 0, 0, 37, - 38, 0, 0, 39, 40, 0, 0, 0, -6, 41, - 0, 0, 0, 42, 2, 3, 4, 5, 0, 6, - 7, 8, 9, 10, 0, 11, 12, 13, 14, 0, - 15, 0, 16, 0, 0, 0, 17, 0, 18, 19, - 20, 0, 0, 21, 0, 0, 0, 0, 22, 23, - 24, 0, 0, 25, 0, 0, 0, 26, 27, 28, - 29, 0, 30, 0, 0, 0, 0, 0, 0, 0, - 0, 31, 0, 0, 0, 0, 0, 0, 32, 33, - 34, 35, 36, 0, 0, 37, 38, 0, 0, 39, - 40, 0, 0, 0, 0, 41, 0, 0, 0, 42, - 2, 3, 4, 5, 0, 6, 7, 8, 9, 10, - 0, 11, 12, 61, 14, 0, 15, 320, 16, 0, - 0, 0, 17, 0, 18, 19, 20, 0, 0, 0, - 0, 0, 0, 0, 22, 23, 24, 0, 0, 25, - 0, 0, 0, 0, 0, 28, 29, 0, 30, 0, - 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, - 0, 0, 0, 0, 32, 33, 34, 35, 36, 0, - 0, 0, 38, 0, 0, 39, 40, 0, 0, 0, - 59, 41, 0, 0, 0, 42, 2, 3, 4, 5, - 0, 6, 7, 8, 9, 10, 0, 11, 12, 61, + 207, 208, 114, 275, 209, 151, 148, 192, 182, 157, + 163, 167, 212, 292, 179, 188, 215, 216, 182, 217, + 218, 211, 221, 222, 214, 225, 224, 240, 309, 226, + 227, 228, 229, 230, 231, 232, 233, 234, 235, 242, + 312, 248, 277, 239, 259, 282, 266, 262, 281, 283, + 245, 319, 246, 287, 298, 331, 293, 333, 276, 321, + 323, 279, 280, 335, 326, 327, 328, 329, 334, 183, + 295, 243, 317, 258, 99, 73, 0, 289, 0, 0, + 250, 251, 0, 0, 0, 0, 0, 302, 299, 300, + 0, 0, 0, 303, 311, 304, 0, 0, 0, 114, + 0, 0, 315, 316, 318, 313, 314, 0, 0, 0, + 0, 0, 0, 325, 270, 271, 272, 273, 0, 330, + 0, 332, 278, 128, 129, 0, 130, 0, 0, 131, + 0, 0, 268, 0, 0, 269, 339, 340, 288, 338, + 0, 0, 0, 0, 0, 0, 137, 138, 0, 0, + 0, 0, 139, 140, -6, 1, 0, 286, 122, 0, + 0, 0, 0, 0, 0, 2, 3, 4, 5, 122, + 6, 7, 8, 9, 10, 0, 11, 12, 13, 14, + 0, 15, 0, 16, 0, 0, 0, 17, 0, 18, + 19, 20, 0, 337, 21, 337, 0, 0, 0, 22, + 23, 24, 0, 0, 25, 0, 0, 0, 26, 27, + 28, 29, 0, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 0, 0, 0, 0, 32, + 33, 34, 35, 36, 0, 0, 37, 38, 39, 0, + 0, 40, 41, 0, 0, 0, -6, 42, 0, 0, + 0, 43, 2, 3, 4, 5, 0, 6, 7, 8, + 9, 10, 0, 11, 12, 13, 14, 0, 15, 0, + 16, 0, 0, 0, 17, 0, 18, 19, 20, 0, + 0, 21, 0, 0, 0, 0, 22, 23, 24, 0, + 0, 25, 0, 0, 0, 26, 27, 28, 29, 0, + 30, 0, 0, 0, 0, 0, 0, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 32, 33, 34, 35, + 36, 0, 0, 37, 38, 39, 0, 0, 40, 41, + 0, 0, 0, 0, 42, 0, 0, 0, 43, 2, + 3, 4, 5, 0, 6, 7, 8, 9, 10, 0, + 11, 12, 63, 14, 0, 15, 324, 16, 0, 0, + 0, 17, 0, 18, 19, 20, 0, 0, 0, 0, + 0, 0, 0, 22, 23, 24, 0, 0, 25, 0, + 0, 0, 0, 0, 28, 29, 0, 30, 0, 0, + 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, + 0, 0, 0, 32, 33, 34, 35, 36, 0, 0, + 37, 0, 39, 0, 0, 40, 41, 0, 0, 0, + 61, 42, 0, 0, 0, 43, 2, 3, 4, 5, + 0, 6, 7, 8, 9, 10, 0, 11, 12, 63, 14, 0, 15, 0, 16, 0, 0, 0, 17, 0, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 22, 23, 24, 0, 0, 25, 0, 0, 0, 0, 0, 28, 29, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, - 32, 33, 34, 35, 36, 0, 0, 0, 38, 0, - 0, 39, 40, 0, 0, 0, 59, 41, 0, 0, - 0, 42, 2, 3, 4, 5, 0, 6, 7, 8, - 9, 10, 0, 11, 12, 61, 14, 0, 15, 0, - 16, 0, 0, 0, 17, 0, 18, 19, 20, 0, - 0, 0, 0, 0, 0, 0, 22, 23, 24, 0, - 0, 25, 0, 0, 0, 0, 0, 28, 29, 0, - 30, 0, 0, 0, 0, 0, 0, 0, 0, 31, - 0, 0, 0, 0, 0, 0, 32, 33, 34, 35, - 36, 0, 0, 0, 38, 0, 0, 39, 40, 0, - 0, 0, 0, 41, 0, 0, 0, 42, 2, 3, - 4, 5, 0, 6, 7, 8, 9, 10, 0, 11, - 12, 61, 14, 218, 15, 0, 16, 0, 0, 0, - 17, 0, 18, 19, 123, 124, 0, 0, 0, 125, - 126, 127, 22, 128, 24, 0, 129, 130, 131, 0, - 0, 0, 0, 28, 29, 0, 30, 0, 219, 132, - 133, 134, 135, 136, 0, 31, 0, 0, 137, 138, - 0, 0, 32, 33, 34, 35, 36, 0, 0, 0, - 38, 0, 0, 39, 40, 2, 3, 4, 5, 41, - 0, 0, 0, 42, 0, 0, 11, 12, 61, 14, - 0, 15, 0, 0, 0, 0, 0, 0, 77, 0, - 0, 0, 0, 78, 0, 79, 80, 81, 82, 62, - 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 33, 34, 35, 36, 0, 0, 37, 0, 39, + 0, 0, 40, 41, 0, 0, 0, 61, 42, 0, + 0, 0, 43, 2, 3, 4, 5, 0, 6, 7, + 8, 9, 10, 0, 11, 12, 63, 14, 0, 15, + 0, 16, 0, 0, 0, 17, 0, 18, 19, 20, + 0, 0, 0, 0, 0, 0, 0, 22, 23, 24, + 0, 0, 25, 0, 0, 0, 0, 0, 28, 29, + 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 0, 0, 0, 0, 0, 0, 32, 33, 34, + 35, 36, 0, 0, 37, 0, 39, 0, 0, 40, + 41, 0, 0, 0, 0, 42, 0, 0, 0, 43, + 2, 3, 4, 5, 0, 6, 7, 8, 9, 10, + 0, 11, 12, 63, 14, 191, 15, 0, 16, 0, + 0, 0, 17, 0, 18, 19, 125, 126, 0, 0, + 0, 127, 128, 129, 22, 130, 24, 0, 131, 132, + 133, 0, 0, 0, 0, 28, 29, 0, 30, 0, + 0, 0, 134, 135, 136, 137, 138, 31, 61, 0, + 0, 139, 140, 0, 32, 33, 34, 35, 36, 0, + 0, 0, 0, 39, 0, 0, 40, 41, 2, 3, + 4, 5, 42, 0, 0, 0, 43, 0, 0, 11, + 12, 63, 14, 0, 15, 0, 0, 0, 0, 0, + 0, 78, 0, 0, 0, 0, 79, 0, 80, 81, + 82, 83, 64, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 31, 0, 0, 0, 0, 0, 0, 32, - 33, 34, 35, 36, 0, 0, 0, 0, 0, 0, - 39, 40, 2, 3, 4, 5, 41, 0, 0, 0, - 42, 0, 0, 11, 12, 61, 14, 0, 15, 0, - 0, 0, 0, 0, 0, 77, 0, 0, 2, 3, - 4, 5, 79, 0, 81, 0, 62, 0, 24, 11, - 12, 61, 14, 0, 15, 0, 0, 0, 0, 97, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, - 0, 0, 62, 0, 24, 0, 32, 33, 34, 35, - 36, 0, 0, 0, 0, 0, 0, 39, 40, 0, - 0, 0, 0, 41, 0, 31, 0, 42, 0, 0, + 0, 0, 0, 0, 0, 31, 2, 3, 4, 5, + 0, 0, 32, 33, 34, 35, 36, 11, 12, 63, + 14, 0, 15, 0, 40, 41, 0, 0, 0, 78, + 42, 0, 0, 0, 43, 0, 80, 0, 82, 0, + 64, 0, 24, 2, 3, 4, 5, 0, 0, 0, + 0, 0, 0, 98, 11, 12, 63, 14, 0, 15, + 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, + 32, 33, 34, 35, 36, 0, 0, 64, 0, 24, + 0, 0, 40, 41, 0, 0, 0, 0, 42, 0, + 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, + 31, 2, 3, 4, 5, 0, 0, 32, 33, 34, + 35, 36, 11, 12, 63, 14, 0, 15, 0, 40, + 41, 0, 0, 0, 0, 42, 0, 0, 0, 43, + 0, 0, 0, 0, 0, 64, 0, 24, 2, 3, + 4, 5, 0, 0, 0, 0, 0, 0, 0, 11, + 12, 63, 14, 0, 15, 0, 0, 0, 31, 0, + 0, 0, 0, 0, 0, 32, 33, 34, 35, 36, + 0, 0, 64, 0, 24, 0, 0, 40, 41, 0, + 0, 0, 0, 72, 0, 0, 0, 43, 0, 0, + 0, 0, 0, 0, 154, 31, 0, 0, 0, 0, 0, 0, 32, 33, 34, 35, 36, 0, 0, 0, - 0, 0, 0, 39, 40, 2, 3, 4, 5, 41, - 0, 0, 0, 42, 0, 0, 11, 12, 61, 14, - 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 3, 4, 5, 0, 0, 0, 0, 62, - 0, 24, 11, 12, 61, 14, 0, 15, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 31, 0, 0, 62, 0, 24, 0, 32, - 33, 34, 35, 36, 0, 0, 0, 0, 0, 0, - 39, 40, 0, 0, 0, 0, 70, 0, 31, 0, - 42, 154, 0, 0, 0, 32, 33, 34, 35, 36, - 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, - 0, 0, 119, 123, 124, 0, 42, 0, 125, 126, - 127, 0, 128, 155, 156, 129, 130, 131, 168, 0, - 0, 0, 0, 0, 169, 0, 0, 0, 132, 133, - 134, 135, 136, 0, 0, 123, 124, 137, 138, 0, - 125, 126, 127, 0, 128, 0, 0, 129, 130, 131, - 170, 0, 0, 0, 0, 0, 171, 0, 0, 0, - 132, 133, 134, 135, 136, 0, 0, 123, 124, 137, - 138, 0, 125, 126, 127, 0, 128, 0, 0, 129, - 130, 131, 172, 0, 0, 0, 0, 0, 173, 0, - 0, 0, 132, 133, 134, 135, 136, 0, 0, 123, - 124, 137, 138, 0, 125, 126, 127, 0, 128, 0, - 0, 129, 130, 131, 174, 0, 0, 0, 0, 0, - 175, 0, 0, 0, 132, 133, 134, 135, 136, 0, - 0, 123, 124, 137, 138, 0, 125, 126, 127, 0, - 128, 0, 0, 129, 130, 131, 251, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 132, 133, 134, 135, - 136, 0, 0, 123, 124, 137, 138, 0, 125, 126, - 127, 0, 128, 0, 0, 129, 130, 131, 252, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 132, 133, - 134, 135, 136, 0, 0, 123, 124, 137, 138, 0, - 125, 126, 127, 0, 128, 0, 0, 129, 130, 131, - 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 132, 133, 134, 135, 136, 0, 0, 123, 124, 137, - 138, 0, 125, 126, 127, 0, 128, 0, 0, 129, - 130, 131, 254, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 132, 133, 134, 135, 136, 0, 0, 123, - 124, 137, 138, 0, 125, 126, 127, 0, 128, 0, - 0, 129, 130, 131, 0, 0, 0, 0, 0, 0, - 0, 165, 0, 0, 132, 133, 134, 135, 136, 0, - 123, 124, 0, 137, 138, 125, 126, 127, 0, 128, - 0, 0, 129, 130, 131, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 132, 133, 134, 135, 136, - 0, 123, 124, 0, 137, 138, 125, 126, 127, 0, - 128, 0, 0, 129, 130, 131, 0, 0, 0, 0, - 0, 176, 177, 0, 0, 0, 132, 133, 134, 135, - 136, 0, 123, 124, 0, 137, 138, 125, 126, 127, - 0, 128, 0, 0, 129, 130, 131, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 189, 132, 133, 134, - 135, 136, 0, 123, 124, 180, 137, 138, 125, 126, - 127, 0, 128, 0, 0, 129, 130, 131, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 132, 133, - 134, 135, 136, 0, 59, 123, 124, 137, 138, 0, - 125, 126, 127, 0, 128, 0, 0, 129, 130, 131, + 0, 0, 0, 0, 40, 41, 125, 126, 0, 0, + 120, 127, 128, 129, 43, 130, 155, 156, 131, 132, + 133, 168, 0, 0, 0, 0, 0, 169, 0, 0, + 0, 0, 134, 135, 136, 137, 138, 0, 125, 126, + 0, 139, 140, 127, 128, 129, 0, 130, 0, 0, + 131, 132, 133, 170, 0, 0, 0, 0, 0, 171, + 0, 0, 0, 0, 134, 135, 136, 137, 138, 0, + 125, 126, 0, 139, 140, 127, 128, 129, 0, 130, + 0, 0, 131, 132, 133, 172, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 134, 135, 136, 137, + 138, 0, 125, 126, 0, 139, 140, 127, 128, 129, + 0, 130, 0, 0, 131, 132, 133, 174, 0, 0, + 0, 0, 0, 175, 0, 0, 0, 0, 134, 135, + 136, 137, 138, 0, 125, 126, 0, 139, 140, 127, + 128, 129, 0, 130, 0, 0, 131, 132, 133, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 132, 133, 134, 135, 136, 0, 123, 124, 180, 137, - 138, 125, 126, 127, 0, 128, 0, 0, 129, 130, - 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 189, 132, 133, 134, 135, 136, 0, 123, 124, 0, - 137, 138, 125, 126, 127, 0, 128, 0, 0, 129, - 130, 131, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 132, 133, 134, 135, 136, 0, 0, 0, - 0, 137, 138 + 134, 135, 136, 137, 138, 0, 125, 126, 0, 139, + 140, 127, 128, 129, 0, 130, 0, 0, 131, 132, + 133, 254, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 134, 135, 136, 137, 138, 0, 125, 126, + 0, 139, 140, 127, 128, 129, 0, 130, 0, 0, + 131, 132, 133, 255, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 134, 135, 136, 137, 138, 0, + 125, 126, 0, 139, 140, 127, 128, 129, 0, 130, + 0, 0, 131, 132, 133, 256, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 134, 135, 136, 137, + 138, 0, 125, 126, 0, 139, 140, 127, 128, 129, + 0, 130, 0, 0, 131, 132, 133, 0, 0, 0, + 0, 0, 0, 219, 0, 0, 0, 0, 134, 135, + 136, 137, 138, 0, 125, 126, 0, 139, 140, 127, + 128, 129, 0, 130, 0, 0, 131, 132, 133, 0, + 0, 0, 0, 0, 0, 0, 0, 165, 0, 220, + 134, 135, 136, 137, 138, 0, 125, 126, 0, 139, + 140, 127, 128, 129, 0, 130, 0, 0, 131, 132, + 133, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 134, 135, 136, 137, 138, 0, 125, 126, + 0, 139, 140, 127, 128, 129, 0, 130, 0, 0, + 131, 132, 133, 0, 0, 0, 0, 0, 176, 177, + 0, 0, 0, 0, 134, 135, 136, 137, 138, 0, + 125, 126, 0, 139, 140, 127, 128, 129, 0, 130, + 0, 0, 131, 132, 133, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 189, 134, 135, 136, 137, + 138, 0, 125, 126, 180, 139, 140, 127, 128, 129, + 0, 130, 0, 0, 131, 132, 133, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 134, 135, + 136, 137, 138, 0, 125, 126, 180, 139, 140, 127, + 128, 129, 0, 130, 0, 0, 131, 132, 133, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, + 134, 135, 136, 137, 138, 0, 125, 126, 0, 139, + 140, 127, 128, 129, 0, 130, 0, 0, 131, 132, + 133, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 134, 135, 136, 137, 138, 0, 0, 0, + 0, 139, 140 }; static const yytype_int16 yycheck[] = { - 0, 264, 0, 243, 117, 4, 119, 32, 7, 8, - 9, 49, 1, 12, 13, 49, 72, 242, 42, 282, - 19, 29, 28, 22, 222, 41, 30, 43, 53, 28, - 29, 91, 31, 32, 33, 34, 35, 36, 94, 95, - 39, 40, 41, 42, 68, 49, 84, 53, 291, 73, - 84, 288, 51, 52, 43, 280, 281, 255, 24, 302, - 285, 93, 287, 62, 301, 305, 98, 12, 13, 68, - 164, 70, 297, 298, 73, 46, 84, 66, 77, 24, - 79, 93, 66, 67, 178, 69, 98, 327, 72, 91, - 98, 24, 91, 91, 188, 24, 98, 51, 52, 24, - 24, 85, 86, 87, 88, 89, 331, 93, 24, 24, - 94, 95, 98, 24, 97, 98, 116, 92, 117, 118, - 119, 84, 92, 92, 123, 124, 125, 126, 127, 128, + 0, 118, 0, 120, 244, 4, 223, 29, 7, 8, + 9, 49, 49, 12, 13, 292, 92, 94, 43, 92, + 19, 28, 99, 22, 1, 46, 99, 72, 305, 28, + 29, 93, 31, 32, 33, 34, 35, 36, 164, 32, + 257, 40, 41, 42, 43, 70, 53, 85, 85, 74, + 95, 96, 178, 52, 53, 54, 24, 30, 12, 13, + 53, 269, 188, 85, 24, 64, 41, 44, 43, 309, + 24, 70, 24, 72, 24, 74, 49, 99, 286, 78, + 24, 80, 66, 67, 295, 69, 66, 67, 72, 69, + 24, 331, 72, 92, 92, 306, 51, 52, 24, 24, + 85, 93, 86, 87, 88, 89, 90, 87, 88, 89, + 90, 95, 96, 94, 93, 95, 96, 117, 99, 118, + 119, 120, 98, 99, 185, 99, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 98, 98, 142, 41, 98, 24, 146, 48, 98, - 24, 98, 151, 48, 24, 24, 155, 156, 185, 158, - 159, 24, 161, 162, 24, 93, 165, 93, 49, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 98, - 293, 24, 276, 182, 28, 24, 66, 67, 53, 69, - 189, 304, 72, 48, 32, 28, 290, 28, 28, 188, - 48, 28, 116, 277, 301, 29, 86, 87, 88, 89, - -1, -1, -1, 237, 94, 95, -1, -1, 207, 218, - 219, 66, 67, 317, 69, 319, -1, 72, -1, -1, - 257, 325, -1, 260, 261, -1, -1, -1, 237, -1, - -1, -1, -1, 88, 89, -1, -1, -1, 275, 94, - 95, -1, 251, 252, 253, 254, -1, 284, 247, -1, - 259, 250, -1, -1, 291, -1, -1, -1, -1, -1, - -1, -1, 299, 300, 301, 274, -1, -1, -1, -1, - 269, -1, -1, 310, -1, -1, -1, -1, -1, 316, - -1, 318, -1, -1, 293, -1, -1, 0, 1, -1, - -1, -1, -1, -1, -1, 304, 333, 334, 11, 12, - 13, 14, -1, 16, 17, 18, 19, 20, -1, 22, - 23, 24, 25, -1, 27, -1, 29, -1, -1, 329, - 33, 331, 35, 36, 37, -1, -1, 40, -1, -1, - -1, -1, 45, 46, 47, -1, -1, 50, -1, -1, - -1, 54, 55, 56, 57, -1, 59, -1, -1, -1, - -1, -1, -1, -1, -1, 68, -1, -1, -1, -1, - -1, -1, 75, 76, 77, 78, 79, -1, -1, 82, - 83, -1, -1, 86, 87, -1, -1, -1, 91, 92, - -1, -1, -1, 96, 11, 12, 13, 14, -1, 16, - 17, 18, 19, 20, -1, 22, 23, 24, 25, -1, - 27, -1, 29, -1, -1, -1, 33, -1, 35, 36, - 37, -1, -1, 40, -1, -1, -1, -1, 45, 46, - 47, -1, -1, 50, -1, -1, -1, 54, 55, 56, - 57, -1, 59, -1, -1, -1, -1, -1, -1, -1, - -1, 68, -1, -1, -1, -1, -1, -1, 75, 76, - 77, 78, 79, -1, -1, 82, 83, -1, -1, 86, - 87, -1, -1, -1, -1, 92, -1, -1, -1, 96, - 11, 12, 13, 14, -1, 16, 17, 18, 19, 20, - -1, 22, 23, 24, 25, -1, 27, 28, 29, -1, - -1, -1, 33, -1, 35, 36, 37, -1, -1, -1, - -1, -1, -1, -1, 45, 46, 47, -1, -1, 50, - -1, -1, -1, -1, -1, 56, 57, -1, 59, -1, - -1, -1, -1, -1, -1, -1, -1, 68, -1, -1, - -1, -1, -1, -1, 75, 76, 77, 78, 79, -1, - -1, -1, 83, -1, -1, 86, 87, -1, -1, -1, - 91, 92, -1, -1, -1, 96, 11, 12, 13, 14, + 139, 140, 141, 94, 143, 41, 99, 124, 99, 24, + 48, 99, 151, 279, 24, 48, 155, 156, 99, 158, + 159, 24, 161, 162, 24, 24, 165, 94, 294, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 94, + 297, 24, 49, 182, 240, 24, 247, 243, 28, 99, + 189, 308, 191, 28, 24, 321, 32, 323, 259, 53, + 48, 262, 263, 329, 28, 28, 28, 48, 28, 117, + 280, 188, 305, 238, 29, 13, -1, 278, -1, -1, + 219, 220, -1, -1, -1, -1, -1, 288, 284, 285, + -1, -1, -1, 289, 295, 291, -1, -1, -1, 238, + -1, -1, 303, 304, 305, 301, 302, -1, -1, -1, + -1, -1, -1, 314, 253, 254, 255, 256, -1, 320, + -1, 322, 261, 66, 67, -1, 69, -1, -1, 72, + -1, -1, 249, -1, -1, 252, 337, 338, 277, 335, + -1, -1, -1, -1, -1, -1, 89, 90, -1, -1, + -1, -1, 95, 96, 0, 1, -1, 274, 297, -1, + -1, -1, -1, -1, -1, 11, 12, 13, 14, 308, + 16, 17, 18, 19, 20, -1, 22, 23, 24, 25, + -1, 27, -1, 29, -1, -1, -1, 33, -1, 35, + 36, 37, -1, 333, 40, 335, -1, -1, -1, 45, + 46, 47, -1, -1, 50, -1, -1, -1, 54, 55, + 56, 57, -1, 59, -1, -1, -1, -1, -1, -1, + -1, -1, 68, -1, -1, -1, -1, -1, -1, 75, + 76, 77, 78, 79, -1, -1, 82, 83, 84, -1, + -1, 87, 88, -1, -1, -1, 92, 93, -1, -1, + -1, 97, 11, 12, 13, 14, -1, 16, 17, 18, + 19, 20, -1, 22, 23, 24, 25, -1, 27, -1, + 29, -1, -1, -1, 33, -1, 35, 36, 37, -1, + -1, 40, -1, -1, -1, -1, 45, 46, 47, -1, + -1, 50, -1, -1, -1, 54, 55, 56, 57, -1, + 59, -1, -1, -1, -1, -1, -1, -1, -1, 68, + -1, -1, -1, -1, -1, -1, 75, 76, 77, 78, + 79, -1, -1, 82, 83, 84, -1, -1, 87, 88, + -1, -1, -1, -1, 93, -1, -1, -1, 97, 11, + 12, 13, 14, -1, 16, 17, 18, 19, 20, -1, + 22, 23, 24, 25, -1, 27, 28, 29, -1, -1, + -1, 33, -1, 35, 36, 37, -1, -1, -1, -1, + -1, -1, -1, 45, 46, 47, -1, -1, 50, -1, + -1, -1, -1, -1, 56, 57, -1, 59, -1, -1, + -1, -1, -1, -1, -1, -1, 68, -1, -1, -1, + -1, -1, -1, 75, 76, 77, 78, 79, -1, -1, + 82, -1, 84, -1, -1, 87, 88, -1, -1, -1, + 92, 93, -1, -1, -1, 97, 11, 12, 13, 14, -1, 16, 17, 18, 19, 20, -1, 22, 23, 24, 25, -1, 27, -1, 29, -1, -1, -1, 33, -1, 35, 36, 37, -1, -1, -1, -1, -1, -1, -1, 45, 46, 47, -1, -1, 50, -1, -1, -1, -1, -1, 56, 57, -1, 59, -1, -1, -1, -1, -1, -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, - 75, 76, 77, 78, 79, -1, -1, -1, 83, -1, - -1, 86, 87, -1, -1, -1, 91, 92, -1, -1, - -1, 96, 11, 12, 13, 14, -1, 16, 17, 18, - 19, 20, -1, 22, 23, 24, 25, -1, 27, -1, - 29, -1, -1, -1, 33, -1, 35, 36, 37, -1, - -1, -1, -1, -1, -1, -1, 45, 46, 47, -1, - -1, 50, -1, -1, -1, -1, -1, 56, 57, -1, - 59, -1, -1, -1, -1, -1, -1, -1, -1, 68, - -1, -1, -1, -1, -1, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, -1, -1, 86, 87, -1, - -1, -1, -1, 92, -1, -1, -1, 96, 11, 12, - 13, 14, -1, 16, 17, 18, 19, 20, -1, 22, - 23, 24, 25, 49, 27, -1, 29, -1, -1, -1, - 33, -1, 35, 36, 60, 61, -1, -1, -1, 65, - 66, 67, 45, 69, 47, -1, 72, 73, 74, -1, - -1, -1, -1, 56, 57, -1, 59, -1, 84, 85, - 86, 87, 88, 89, -1, 68, -1, -1, 94, 95, - -1, -1, 75, 76, 77, 78, 79, -1, -1, -1, - 83, -1, -1, 86, 87, 11, 12, 13, 14, 92, - -1, -1, -1, 96, -1, -1, 22, 23, 24, 25, - -1, 27, -1, -1, -1, -1, -1, -1, 34, -1, - -1, -1, -1, 39, -1, 41, 42, 43, 44, 45, - -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, + 75, 76, 77, 78, 79, -1, -1, 82, -1, 84, + -1, -1, 87, 88, -1, -1, -1, 92, 93, -1, + -1, -1, 97, 11, 12, 13, 14, -1, 16, 17, + 18, 19, 20, -1, 22, 23, 24, 25, -1, 27, + -1, 29, -1, -1, -1, 33, -1, 35, 36, 37, + -1, -1, -1, -1, -1, -1, -1, 45, 46, 47, + -1, -1, 50, -1, -1, -1, -1, -1, 56, 57, + -1, 59, -1, -1, -1, -1, -1, -1, -1, -1, + 68, -1, -1, -1, -1, -1, -1, 75, 76, 77, + 78, 79, -1, -1, 82, -1, 84, -1, -1, 87, + 88, -1, -1, -1, -1, 93, -1, -1, -1, 97, + 11, 12, 13, 14, -1, 16, 17, 18, 19, 20, + -1, 22, 23, 24, 25, 49, 27, -1, 29, -1, + -1, -1, 33, -1, 35, 36, 60, 61, -1, -1, + -1, 65, 66, 67, 45, 69, 47, -1, 72, 73, + 74, -1, -1, -1, -1, 56, 57, -1, 59, -1, + -1, -1, 86, 87, 88, 89, 90, 68, 92, -1, + -1, 95, 96, -1, 75, 76, 77, 78, 79, -1, + -1, -1, -1, 84, -1, -1, 87, 88, 11, 12, + 13, 14, 93, -1, -1, -1, 97, -1, -1, 22, + 23, 24, 25, -1, 27, -1, -1, -1, -1, -1, + -1, 34, -1, -1, -1, -1, 39, -1, 41, 42, + 43, 44, 45, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 68, -1, -1, -1, -1, -1, -1, 75, - 76, 77, 78, 79, -1, -1, -1, -1, -1, -1, - 86, 87, 11, 12, 13, 14, 92, -1, -1, -1, - 96, -1, -1, 22, 23, 24, 25, -1, 27, -1, - -1, -1, -1, -1, -1, 34, -1, -1, 11, 12, - 13, 14, 41, -1, 43, -1, 45, -1, 47, 22, - 23, 24, 25, -1, 27, -1, -1, -1, -1, 58, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 68, - -1, -1, 45, -1, 47, -1, 75, 76, 77, 78, - 79, -1, -1, -1, -1, -1, -1, 86, 87, -1, - -1, -1, -1, 92, -1, 68, -1, 96, -1, -1, + -1, -1, -1, -1, -1, 68, 11, 12, 13, 14, + -1, -1, 75, 76, 77, 78, 79, 22, 23, 24, + 25, -1, 27, -1, 87, 88, -1, -1, -1, 34, + 93, -1, -1, -1, 97, -1, 41, -1, 43, -1, + 45, -1, 47, 11, 12, 13, 14, -1, -1, -1, + -1, -1, -1, 58, 22, 23, 24, 25, -1, 27, + -1, -1, -1, 68, -1, -1, -1, -1, -1, -1, + 75, 76, 77, 78, 79, -1, -1, 45, -1, 47, + -1, -1, 87, 88, -1, -1, -1, -1, 93, -1, + -1, -1, 97, -1, -1, -1, -1, -1, -1, -1, + 68, 11, 12, 13, 14, -1, -1, 75, 76, 77, + 78, 79, 22, 23, 24, 25, -1, 27, -1, 87, + 88, -1, -1, -1, -1, 93, -1, -1, -1, 97, + -1, -1, -1, -1, -1, 45, -1, 47, 11, 12, + 13, 14, -1, -1, -1, -1, -1, -1, -1, 22, + 23, 24, 25, -1, 27, -1, -1, -1, 68, -1, + -1, -1, -1, -1, -1, 75, 76, 77, 78, 79, + -1, -1, 45, -1, 47, -1, -1, 87, 88, -1, + -1, -1, -1, 93, -1, -1, -1, 97, -1, -1, + -1, -1, -1, -1, 38, 68, -1, -1, -1, -1, -1, -1, 75, 76, 77, 78, 79, -1, -1, -1, - -1, -1, -1, 86, 87, 11, 12, 13, 14, 92, - -1, -1, -1, 96, -1, -1, 22, 23, 24, 25, - -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 11, 12, 13, 14, -1, -1, -1, -1, 45, - -1, 47, 22, 23, 24, 25, -1, 27, -1, -1, + -1, -1, -1, -1, 87, 88, 60, 61, -1, -1, + 93, 65, 66, 67, 97, 69, 70, 71, 72, 73, + 74, 43, -1, -1, -1, -1, -1, 49, -1, -1, + -1, -1, 86, 87, 88, 89, 90, -1, 60, 61, + -1, 95, 96, 65, 66, 67, -1, 69, -1, -1, + 72, 73, 74, 43, -1, -1, -1, -1, -1, 49, + -1, -1, -1, -1, 86, 87, 88, 89, 90, -1, + 60, 61, -1, 95, 96, 65, 66, 67, -1, 69, + -1, -1, 72, 73, 74, 43, -1, -1, -1, -1, + -1, 49, -1, -1, -1, -1, 86, 87, 88, 89, + 90, -1, 60, 61, -1, 95, 96, 65, 66, 67, + -1, 69, -1, -1, 72, 73, 74, 43, -1, -1, + -1, -1, -1, 49, -1, -1, -1, -1, 86, 87, + 88, 89, 90, -1, 60, 61, -1, 95, 96, 65, + 66, 67, -1, 69, -1, -1, 72, 73, 74, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 68, -1, -1, 45, -1, 47, -1, 75, - 76, 77, 78, 79, -1, -1, -1, -1, -1, -1, - 86, 87, -1, -1, -1, -1, 92, -1, 68, -1, - 96, 38, -1, -1, -1, 75, 76, 77, 78, 79, - -1, -1, -1, -1, -1, -1, 86, 87, -1, -1, - -1, -1, 92, 60, 61, -1, 96, -1, 65, 66, - 67, -1, 69, 70, 71, 72, 73, 74, 43, -1, - -1, -1, -1, -1, 49, -1, -1, -1, 85, 86, - 87, 88, 89, -1, -1, 60, 61, 94, 95, -1, - 65, 66, 67, -1, 69, -1, -1, 72, 73, 74, - 43, -1, -1, -1, -1, -1, 49, -1, -1, -1, - 85, 86, 87, 88, 89, -1, -1, 60, 61, 94, - 95, -1, 65, 66, 67, -1, 69, -1, -1, 72, - 73, 74, 43, -1, -1, -1, -1, -1, 49, -1, - -1, -1, 85, 86, 87, 88, 89, -1, -1, 60, - 61, 94, 95, -1, 65, 66, 67, -1, 69, -1, - -1, 72, 73, 74, 43, -1, -1, -1, -1, -1, - 49, -1, -1, -1, 85, 86, 87, 88, 89, -1, - -1, 60, 61, 94, 95, -1, 65, 66, 67, -1, - 69, -1, -1, 72, 73, 74, 43, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 85, 86, 87, 88, - 89, -1, -1, 60, 61, 94, 95, -1, 65, 66, - 67, -1, 69, -1, -1, 72, 73, 74, 43, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 85, 86, - 87, 88, 89, -1, -1, 60, 61, 94, 95, -1, - 65, 66, 67, -1, 69, -1, -1, 72, 73, 74, - 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 85, 86, 87, 88, 89, -1, -1, 60, 61, 94, - 95, -1, 65, 66, 67, -1, 69, -1, -1, 72, - 73, 74, 43, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 85, 86, 87, 88, 89, -1, -1, 60, - 61, 94, 95, -1, 65, 66, 67, -1, 69, -1, - -1, 72, 73, 74, -1, -1, -1, -1, -1, -1, - -1, 51, -1, -1, 85, 86, 87, 88, 89, -1, - 60, 61, -1, 94, 95, 65, 66, 67, -1, 69, + 86, 87, 88, 89, 90, -1, 60, 61, -1, 95, + 96, 65, 66, 67, -1, 69, -1, -1, 72, 73, + 74, 43, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 86, 87, 88, 89, 90, -1, 60, 61, + -1, 95, 96, 65, 66, 67, -1, 69, -1, -1, + 72, 73, 74, 43, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 86, 87, 88, 89, 90, -1, + 60, 61, -1, 95, 96, 65, 66, 67, -1, 69, + -1, -1, 72, 73, 74, 43, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 86, 87, 88, 89, + 90, -1, 60, 61, -1, 95, 96, 65, 66, 67, + -1, 69, -1, -1, 72, 73, 74, -1, -1, -1, + -1, -1, -1, 49, -1, -1, -1, -1, 86, 87, + 88, 89, 90, -1, 60, 61, -1, 95, 96, 65, + 66, 67, -1, 69, -1, -1, 72, 73, 74, -1, + -1, -1, -1, -1, -1, -1, -1, 51, -1, 85, + 86, 87, 88, 89, 90, -1, 60, 61, -1, 95, + 96, 65, 66, 67, -1, 69, -1, -1, 72, 73, + 74, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 86, 87, 88, 89, 90, -1, 60, 61, + -1, 95, 96, 65, 66, 67, -1, 69, -1, -1, + 72, 73, 74, -1, -1, -1, -1, -1, 80, 81, + -1, -1, -1, -1, 86, 87, 88, 89, 90, -1, + 60, 61, -1, 95, 96, 65, 66, 67, -1, 69, -1, -1, 72, 73, 74, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 85, 86, 87, 88, 89, - -1, 60, 61, -1, 94, 95, 65, 66, 67, -1, - 69, -1, -1, 72, 73, 74, -1, -1, -1, -1, - -1, 80, 81, -1, -1, -1, 85, 86, 87, 88, - 89, -1, 60, 61, -1, 94, 95, 65, 66, 67, + 90, -1, 60, 61, 94, 95, 96, 65, 66, 67, -1, 69, -1, -1, 72, 73, 74, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 84, 85, 86, 87, - 88, 89, -1, 60, 61, 93, 94, 95, 65, 66, - 67, -1, 69, -1, -1, 72, 73, 74, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 85, 86, - 87, 88, 89, -1, 91, 60, 61, 94, 95, -1, - 65, 66, 67, -1, 69, -1, -1, 72, 73, 74, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 85, 86, 87, 88, 89, -1, 60, 61, 93, 94, - 95, 65, 66, 67, -1, 69, -1, -1, 72, 73, + -1, -1, -1, -1, -1, -1, -1, -1, 86, 87, + 88, 89, 90, -1, 60, 61, 94, 95, 96, 65, + 66, 67, -1, 69, -1, -1, 72, 73, 74, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 85, + 86, 87, 88, 89, 90, -1, 60, 61, -1, 95, + 96, 65, 66, 67, -1, 69, -1, -1, 72, 73, 74, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 84, 85, 86, 87, 88, 89, -1, 60, 61, -1, - 94, 95, 65, 66, 67, -1, 69, -1, -1, 72, - 73, 74, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 85, 86, 87, 88, 89, -1, -1, -1, - -1, 94, 95 + -1, -1, 86, 87, 88, 89, 90, -1, -1, -1, + -1, 95, 96 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -1227,37 +1230,38 @@ static const yytype_uint8 yystos[] = 0, 1, 11, 12, 13, 14, 16, 17, 18, 19, 20, 22, 23, 24, 25, 27, 29, 33, 35, 36, 37, 40, 45, 46, 47, 50, 54, 55, 56, 57, - 59, 68, 75, 76, 77, 78, 79, 82, 83, 86, - 87, 92, 96, 100, 102, 103, 104, 105, 106, 113, - 114, 115, 120, 121, 122, 125, 128, 130, 137, 91, - 101, 24, 45, 121, 121, 121, 121, 140, 24, 121, - 92, 121, 139, 129, 46, 24, 123, 34, 39, 41, - 42, 43, 44, 121, 126, 127, 24, 121, 51, 52, - 12, 13, 24, 24, 24, 24, 121, 58, 126, 127, - 24, 124, 121, 121, 121, 121, 121, 121, 24, 92, - 121, 121, 121, 121, 138, 0, 101, 92, 84, 92, - 112, 121, 121, 60, 61, 65, 66, 67, 69, 72, - 73, 74, 85, 86, 87, 88, 89, 94, 95, 92, - 121, 101, 98, 138, 121, 138, 98, 138, 98, 121, - 121, 41, 127, 131, 38, 70, 71, 24, 49, 84, - 121, 49, 84, 48, 132, 51, 127, 98, 43, 49, - 43, 49, 43, 49, 43, 49, 80, 81, 133, 24, - 93, 97, 98, 102, 112, 121, 112, 121, 48, 84, - 118, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 121, 121, 121, 93, 121, - 24, 121, 117, 24, 121, 121, 121, 121, 49, 84, - 121, 121, 117, 121, 24, 121, 121, 121, 121, 121, - 121, 121, 121, 121, 121, 117, 93, 98, 121, 93, - 118, 93, 101, 117, 121, 101, 24, 135, 121, 121, - 135, 43, 43, 43, 43, 134, 138, 119, 30, 49, - 119, 104, 98, 101, 101, 121, 121, 121, 121, 135, - 93, 101, 105, 118, 49, 121, 118, 118, 24, 98, - 136, 136, 101, 28, 121, 118, 28, 53, 117, 32, - 53, 109, 110, 116, 24, 119, 119, 136, 118, 119, - 119, 108, 109, 111, 116, 117, 110, 118, 112, 119, - 119, 118, 118, 111, 118, 112, 104, 53, 107, 48, - 28, 118, 28, 28, 28, 48, 118, 117, 118, 117, - 28, 117, 104, 105, 119, 118, 118 + 59, 68, 75, 76, 77, 78, 79, 82, 83, 84, + 87, 88, 93, 97, 101, 103, 104, 105, 106, 107, + 114, 115, 116, 121, 122, 123, 124, 127, 130, 132, + 139, 92, 102, 24, 45, 123, 123, 123, 123, 141, + 24, 123, 93, 141, 131, 46, 24, 125, 34, 39, + 41, 42, 43, 44, 123, 128, 129, 24, 123, 51, + 52, 12, 13, 24, 24, 24, 24, 123, 58, 128, + 129, 24, 126, 123, 123, 123, 123, 123, 123, 24, + 93, 123, 123, 123, 123, 140, 0, 102, 93, 85, + 93, 113, 123, 123, 123, 60, 61, 65, 66, 67, + 69, 72, 73, 74, 86, 87, 88, 89, 90, 95, + 96, 93, 123, 99, 140, 123, 140, 140, 99, 123, + 123, 41, 129, 133, 38, 70, 71, 24, 49, 85, + 123, 49, 85, 48, 134, 51, 129, 99, 43, 49, + 43, 49, 43, 49, 43, 49, 80, 81, 135, 24, + 94, 98, 99, 103, 113, 123, 113, 123, 48, 85, + 119, 49, 102, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 94, 24, 123, 118, 24, 123, 123, 123, 123, 49, + 85, 123, 123, 118, 123, 24, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 118, 94, 99, 123, + 94, 119, 94, 102, 118, 123, 123, 120, 24, 137, + 123, 123, 137, 43, 43, 43, 43, 136, 140, 120, + 30, 49, 120, 105, 102, 106, 119, 99, 102, 102, + 123, 123, 123, 123, 137, 94, 119, 49, 123, 119, + 119, 28, 24, 99, 138, 138, 102, 28, 123, 119, + 28, 53, 118, 32, 53, 110, 111, 117, 24, 120, + 120, 138, 119, 120, 120, 109, 110, 112, 117, 118, + 111, 119, 113, 120, 120, 119, 119, 112, 119, 113, + 105, 53, 108, 48, 28, 119, 28, 28, 28, 48, + 119, 118, 119, 118, 28, 118, 105, 106, 120, 119, + 119 }; #define yyerrok (yyerrstatus = 0) @@ -2236,7 +2240,21 @@ yyreduce: break; case 27: -#line 251 "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)); @@ -2249,8 +2267,8 @@ yyreduce: g_lingo->processIf(0, 0); ;} break; - case 28: -#line 261 "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)); @@ -2265,8 +2283,8 @@ yyreduce: g_lingo->processIf(0, 0); ;} break; - case 29: -#line 273 "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)); @@ -2281,8 +2299,8 @@ yyreduce: g_lingo->processIf(0, (yyvsp[(9) - (10)].code)); ;} break; - case 30: -#line 285 "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)); @@ -2295,8 +2313,8 @@ yyreduce: g_lingo->processIf(0, 0); ;} break; - case 31: -#line 295 "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)); @@ -2309,8 +2327,8 @@ yyreduce: g_lingo->processIf(0, 0); ;} break; - case 32: -#line 305 "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)); @@ -2323,18 +2341,18 @@ yyreduce: g_lingo->processIf(0, (yyvsp[(10) - (10)].code)); ;} break; - case 33: -#line 317 "engines/director/lingo/lingo-gr.y" + case 35: +#line 323 "engines/director/lingo/lingo-gr.y" { (yyval.code) = 0; ;} break; - case 34: -#line 318 "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 329 "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)); @@ -2343,8 +2361,8 @@ yyreduce: g_lingo->codeLabel((yyvsp[(1) - (6)].code)); ;} break; - case 41: -#line 338 "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)); @@ -2353,23 +2371,23 @@ yyreduce: g_lingo->codeLabel((yyvsp[(1) - (6)].code)); ;} break; - case 42: -#line 346 "engines/director/lingo/lingo-gr.y" + case 44: +#line 352 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(STOP); ;} break; - case 43: -#line 347 "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 351 "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 354 "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); @@ -2377,8 +2395,8 @@ yyreduce: delete (yyvsp[(3) - (3)].s); ;} break; - case 47: -#line 361 "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); @@ -2386,8 +2404,8 @@ yyreduce: g_lingo->codeLabel(0); ;} break; - case 48: -#line 368 "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 @@ -2396,23 +2414,23 @@ yyreduce: g_lingo->code1(skipEnd); ;} break; - case 49: -#line 376 "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 379 "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 382 "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 387 "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); @@ -2420,63 +2438,70 @@ yyreduce: delete (yyvsp[(2) - (3)].s); ;} break; - case 55: -#line 393 "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 394 "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 397 "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 400 "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 403 "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); delete (yyvsp[(1) - (1)].s); ;} break; - case 60: -#line 406 "engines/director/lingo/lingo-gr.y" + case 63: +#line 416 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (2)].s)]->u.func); delete (yyvsp[(1) - (2)].s); ;} break; - case 61: -#line 409 "engines/director/lingo/lingo-gr.y" + case 64: +#line 419 "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 62: -#line 412 "engines/director/lingo/lingo-gr.y" + case 65: +#line 422 "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 63: -#line 416 "engines/director/lingo/lingo-gr.y" + case 66: +#line 426 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->codeConst(0); // Put dummy id g_lingo->code1(g_lingo->c_theentitypush); @@ -2486,8 +2511,8 @@ yyreduce: g_lingo->code2(e, f); ;} break; - case 64: -#line 423 "engines/director/lingo/lingo-gr.y" + case 67: +#line 433 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->code1(g_lingo->c_theentitypush); inst e = 0, f = 0; @@ -2496,336 +2521,336 @@ yyreduce: g_lingo->code2(e, f); ;} break; - case 66: -#line 430 "engines/director/lingo/lingo-gr.y" + case 69: +#line 440 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_add); ;} break; - case 67: -#line 431 "engines/director/lingo/lingo-gr.y" + case 70: +#line 441 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_sub); ;} break; - case 68: -#line 432 "engines/director/lingo/lingo-gr.y" + case 71: +#line 442 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_mul); ;} break; - case 69: -#line 433 "engines/director/lingo/lingo-gr.y" + case 72: +#line 443 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_div); ;} break; - case 70: -#line 434 "engines/director/lingo/lingo-gr.y" + case 73: +#line 444 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_mod); ;} break; - case 71: -#line 435 "engines/director/lingo/lingo-gr.y" + case 74: +#line 445 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_gt); ;} break; - case 72: -#line 436 "engines/director/lingo/lingo-gr.y" + case 75: +#line 446 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_lt); ;} break; - case 73: -#line 437 "engines/director/lingo/lingo-gr.y" + case 76: +#line 447 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_neq); ;} break; - case 74: -#line 438 "engines/director/lingo/lingo-gr.y" + case 77: +#line 448 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_ge); ;} break; - case 75: -#line 439 "engines/director/lingo/lingo-gr.y" + case 78: +#line 449 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_le); ;} break; - case 76: -#line 440 "engines/director/lingo/lingo-gr.y" + case 79: +#line 450 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_and); ;} break; - case 77: -#line 441 "engines/director/lingo/lingo-gr.y" + case 80: +#line 451 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_or); ;} break; - case 78: -#line 442 "engines/director/lingo/lingo-gr.y" + case 81: +#line 452 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_not); ;} break; - case 79: -#line 443 "engines/director/lingo/lingo-gr.y" + case 82: +#line 453 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_ampersand); ;} break; - case 80: -#line 444 "engines/director/lingo/lingo-gr.y" + case 83: +#line 454 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_concat); ;} break; - case 81: -#line 445 "engines/director/lingo/lingo-gr.y" + case 84: +#line 455 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_contains); ;} break; - case 82: -#line 446 "engines/director/lingo/lingo-gr.y" + case 85: +#line 456 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_starts); ;} break; - case 83: -#line 447 "engines/director/lingo/lingo-gr.y" + case 86: +#line 457 "engines/director/lingo/lingo-gr.y" { (yyval.code) = (yyvsp[(2) - (2)].code); ;} break; - case 84: -#line 448 "engines/director/lingo/lingo-gr.y" + case 87: +#line 458 "engines/director/lingo/lingo-gr.y" { (yyval.code) = (yyvsp[(2) - (2)].code); g_lingo->code1(g_lingo->c_negate); ;} break; - case 85: -#line 449 "engines/director/lingo/lingo-gr.y" + case 88: +#line 459 "engines/director/lingo/lingo-gr.y" { (yyval.code) = (yyvsp[(2) - (3)].code); ;} break; - case 86: -#line 450 "engines/director/lingo/lingo-gr.y" + case 89: +#line 460 "engines/director/lingo/lingo-gr.y" { (yyval.code) = g_lingo->codeArray((yyvsp[(2) - (3)].narg)); ;} break; - case 87: -#line 451 "engines/director/lingo/lingo-gr.y" + case 90: +#line 461 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_intersects); ;} break; - case 88: -#line 452 "engines/director/lingo/lingo-gr.y" + case 91: +#line 462 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_within); ;} break; - case 89: -#line 453 "engines/director/lingo/lingo-gr.y" + case 92: +#line 463 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_charOf); ;} break; - case 90: -#line 454 "engines/director/lingo/lingo-gr.y" + case 93: +#line 464 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_charToOf); ;} break; - case 91: -#line 455 "engines/director/lingo/lingo-gr.y" + case 94: +#line 465 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_itemOf); ;} break; - case 92: -#line 456 "engines/director/lingo/lingo-gr.y" + case 95: +#line 466 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_itemToOf); ;} break; - case 93: -#line 457 "engines/director/lingo/lingo-gr.y" + case 96: +#line 467 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_lineOf); ;} break; - case 94: -#line 458 "engines/director/lingo/lingo-gr.y" + case 97: +#line 468 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_lineToOf); ;} break; - case 95: -#line 459 "engines/director/lingo/lingo-gr.y" + case 98: +#line 469 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_wordOf); ;} break; - case 96: -#line 460 "engines/director/lingo/lingo-gr.y" + case 99: +#line 470 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_wordToOf); ;} break; - case 97: -#line 463 "engines/director/lingo/lingo-gr.y" + case 100: +#line 473 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_printtop); ;} break; - case 100: -#line 466 "engines/director/lingo/lingo-gr.y" + case 103: +#line 476 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_exitRepeat); ;} break; - case 101: -#line 467 "engines/director/lingo/lingo-gr.y" + case 104: +#line 477 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(0); // Push fake value on stack g_lingo->code1(g_lingo->c_procret); ;} break; - case 104: -#line 471 "engines/director/lingo/lingo-gr.y" + case 107: +#line 481 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (1)].s)]->u.func); delete (yyvsp[(1) - (1)].s); ;} break; - case 105: -#line 474 "engines/director/lingo/lingo-gr.y" + case 108: +#line 484 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (2)].s)]->u.func); delete (yyvsp[(1) - (2)].s); ;} break; - case 106: -#line 477 "engines/director/lingo/lingo-gr.y" + case 109: +#line 487 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (2)].s)]->u.func); delete (yyvsp[(1) - (2)].s); ;} break; - case 107: -#line 480 "engines/director/lingo/lingo-gr.y" + case 110: +#line 490 "engines/director/lingo/lingo-gr.y" { g_lingo->code2(g_lingo->c_voidpush, g_lingo->_builtins[*(yyvsp[(1) - (1)].s)]->u.func); delete (yyvsp[(1) - (1)].s); ;} break; - case 108: -#line 483 "engines/director/lingo/lingo-gr.y" + case 111: +#line 493 "engines/director/lingo/lingo-gr.y" { g_lingo->codeFunc((yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].narg)); ;} break; - case 109: -#line 484 "engines/director/lingo/lingo-gr.y" + case 112: +#line 494 "engines/director/lingo/lingo-gr.y" { g_lingo->codeMe((yyvsp[(3) - (4)].s), 0); ;} break; - case 110: -#line 485 "engines/director/lingo/lingo-gr.y" + case 113: +#line 495 "engines/director/lingo/lingo-gr.y" { g_lingo->codeMe((yyvsp[(3) - (6)].s), (yyvsp[(5) - (6)].narg)); ;} break; - case 111: -#line 486 "engines/director/lingo/lingo-gr.y" + case 114: +#line 496 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_open); ;} break; - case 112: -#line 487 "engines/director/lingo/lingo-gr.y" + case 115: +#line 497 "engines/director/lingo/lingo-gr.y" { g_lingo->code2(g_lingo->c_voidpush, g_lingo->c_open); ;} break; - case 113: -#line 488 "engines/director/lingo/lingo-gr.y" + case 116: +#line 498 "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 114: -#line 491 "engines/director/lingo/lingo-gr.y" + case 117: +#line 501 "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 115: -#line 492 "engines/director/lingo/lingo-gr.y" + case 118: +#line 502 "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 116: -#line 495 "engines/director/lingo/lingo-gr.y" + case 119: +#line 505 "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 117: -#line 496 "engines/director/lingo/lingo-gr.y" + case 120: +#line 506 "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 118: -#line 507 "engines/director/lingo/lingo-gr.y" + case 121: +#line 517 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_gotoloop); ;} break; - case 119: -#line 508 "engines/director/lingo/lingo-gr.y" + case 122: +#line 518 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_gotonext); ;} break; - case 120: -#line 509 "engines/director/lingo/lingo-gr.y" + case 123: +#line 519 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_gotoprevious); ;} break; - case 121: -#line 510 "engines/director/lingo/lingo-gr.y" + case 124: +#line 520 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(1); g_lingo->code1(g_lingo->c_goto); ;} break; - case 122: -#line 513 "engines/director/lingo/lingo-gr.y" + case 125: +#line 523 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(3); g_lingo->code1(g_lingo->c_goto); ;} break; - case 123: -#line 516 "engines/director/lingo/lingo-gr.y" + case 126: +#line 526 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(2); g_lingo->code1(g_lingo->c_goto); ;} break; - case 128: -#line 529 "engines/director/lingo/lingo-gr.y" + case 131: +#line 539 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_playdone); ;} break; - case 129: -#line 530 "engines/director/lingo/lingo-gr.y" + case 132: +#line 540 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(1); g_lingo->code1(g_lingo->c_play); ;} break; - case 130: -#line 533 "engines/director/lingo/lingo-gr.y" + case 133: +#line 543 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(3); g_lingo->code1(g_lingo->c_play); ;} break; - case 131: -#line 536 "engines/director/lingo/lingo-gr.y" + case 134: +#line 546 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(2); g_lingo->code1(g_lingo->c_play); ;} break; - case 132: -#line 539 "engines/director/lingo/lingo-gr.y" + case 135: +#line 549 "engines/director/lingo/lingo-gr.y" { g_lingo->codeSetImmediate(true); ;} break; - case 133: -#line 539 "engines/director/lingo/lingo-gr.y" + case 136: +#line 549 "engines/director/lingo/lingo-gr.y" { g_lingo->codeSetImmediate(false); g_lingo->codeFunc((yyvsp[(1) - (3)].s), (yyvsp[(3) - (3)].narg)); ;} break; - case 134: -#line 569 "engines/director/lingo/lingo-gr.y" + case 137: +#line 579 "engines/director/lingo/lingo-gr.y" { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); ;} break; - case 135: -#line 570 "engines/director/lingo/lingo-gr.y" + case 138: +#line 580 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(0); // Push fake value on stack g_lingo->code1(g_lingo->c_procret); @@ -2833,38 +2858,38 @@ yyreduce: g_lingo->_indef = false; ;} break; - case 136: -#line 575 "engines/director/lingo/lingo-gr.y" + case 139: +#line 585 "engines/director/lingo/lingo-gr.y" { g_lingo->codeFactory(*(yyvsp[(2) - (2)].s)); ;} break; - case 137: -#line 578 "engines/director/lingo/lingo-gr.y" + case 140: +#line 588 "engines/director/lingo/lingo-gr.y" { g_lingo->_indef = true; ;} break; - case 138: -#line 579 "engines/director/lingo/lingo-gr.y" + case 141: +#line 589 "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 139: -#line 583 "engines/director/lingo/lingo-gr.y" + case 142: +#line 593 "engines/director/lingo/lingo-gr.y" { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); ;} break; - case 140: -#line 584 "engines/director/lingo/lingo-gr.y" + case 143: +#line 594 "engines/director/lingo/lingo-gr.y" { g_lingo->_ignoreMe = true; ;} break; - case 141: -#line 584 "engines/director/lingo/lingo-gr.y" + case 144: +#line 594 "engines/director/lingo/lingo-gr.y" { g_lingo->codeConst(0); // Push fake value on stack g_lingo->code1(g_lingo->c_procret); @@ -2876,33 +2901,33 @@ yyreduce: ;} break; - case 142: -#line 594 "engines/director/lingo/lingo-gr.y" + case 145: +#line 604 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = 0; ;} break; - case 143: -#line 595 "engines/director/lingo/lingo-gr.y" + case 146: +#line 605 "engines/director/lingo/lingo-gr.y" { g_lingo->codeArg((yyvsp[(1) - (1)].s)); (yyval.narg) = 1; ;} break; - case 144: -#line 596 "engines/director/lingo/lingo-gr.y" + case 147: +#line 606 "engines/director/lingo/lingo-gr.y" { g_lingo->codeArg((yyvsp[(3) - (3)].s)); (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;} break; - case 145: -#line 597 "engines/director/lingo/lingo-gr.y" + case 148: +#line 607 "engines/director/lingo/lingo-gr.y" { g_lingo->codeArg((yyvsp[(4) - (4)].s)); (yyval.narg) = (yyvsp[(1) - (4)].narg) + 1; ;} break; - case 146: -#line 600 "engines/director/lingo/lingo-gr.y" + case 149: +#line 610 "engines/director/lingo/lingo-gr.y" { g_lingo->codeArgStore(); ;} break; - case 147: -#line 604 "engines/director/lingo/lingo-gr.y" + case 150: +#line 614 "engines/director/lingo/lingo-gr.y" { g_lingo->code1(g_lingo->c_call); g_lingo->codeString((yyvsp[(1) - (2)].s)->c_str()); @@ -2911,44 +2936,34 @@ yyreduce: g_lingo->code1(numpar); ;} break; - case 148: -#line 612 "engines/director/lingo/lingo-gr.y" + case 151: +#line 622 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = 0; ;} break; - case 149: -#line 613 "engines/director/lingo/lingo-gr.y" + case 152: +#line 623 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = 1; ;} break; - case 150: -#line 614 "engines/director/lingo/lingo-gr.y" + case 153: +#line 624 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;} break; - case 151: -#line 617 "engines/director/lingo/lingo-gr.y" + case 154: +#line 627 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = 1; ;} break; - case 152: -#line 618 "engines/director/lingo/lingo-gr.y" + case 155: +#line 628 "engines/director/lingo/lingo-gr.y" { (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;} break; - case 153: -#line 621 "engines/director/lingo/lingo-gr.y" - { (yyval.narg) = 1; ;} - break; - - case 154: -#line 622 "engines/director/lingo/lingo-gr.y" - { (yyval.narg) = (yyvsp[(1) - (4)].narg) + 1; ;} - break; - /* Line 1267 of yacc.c. */ -#line 2952 "engines/director/lingo/lingo-gr.cpp" +#line 2967 "engines/director/lingo/lingo-gr.cpp" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -3162,6 +3177,6 @@ yyreturn: } -#line 625 "engines/director/lingo/lingo-gr.y" +#line 631 "engines/director/lingo/lingo-gr.y" diff --git a/engines/director/lingo/lingo-gr.h b/engines/director/lingo/lingo-gr.h index 639ada7d9e..367837d2c6 100644 --- a/engines/director/lingo/lingo-gr.h +++ b/engines/director/lingo/lingo-gr.h @@ -118,8 +118,9 @@ tSPRITE = 334, tINTERSECTS = 335, tWITHIN = 336, - tON = 337, - tME = 338 + tTELL = 337, + tON = 338, + tME = 339 }; #endif /* Tokens. */ @@ -202,8 +203,9 @@ #define tSPRITE 334 #define tINTERSECTS 335 #define tWITHIN 336 -#define tON 337 -#define tME 338 +#define tTELL 337 +#define tON 338 +#define tME 339 @@ -221,7 +223,7 @@ typedef union YYSTYPE Common::Array<double> *arr; } /* Line 1529 of yacc.c. */ -#line 225 "engines/director/lingo/lingo-gr.hpp" +#line 227 "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 7e0f04681a..39cb8a2c0d 100644 --- a/engines/director/lingo/lingo-gr.y +++ b/engines/director/lingo/lingo-gr.y @@ -100,11 +100,11 @@ 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 %token tON tME -%type<code> asgn begin elseif elsestmtoneliner end expr if when repeatwhile repeatwith stmtlist -%type<narg> argdef arglist nonemptyarglist nonemptyarglistnl +%type<code> asgn begin elseif elsestmtoneliner end expr if when repeatwhile repeatwith stmtlist tell +%type<narg> argdef arglist nonemptyarglist %right '=' %left tLT tLE tGT tGE tNEQ tCONTAINS tSTARTS @@ -246,6 +246,12 @@ stmt: stmtoneliner 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 { @@ -390,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); @@ -480,7 +490,7 @@ proc: tPUT expr { g_lingo->code1(g_lingo->c_printtop); } | BLTINNOARGSORONE { g_lingo->code2(g_lingo->c_voidpush, g_lingo->_builtins[*$1]->u.func); delete $1; } - | BLTINARGLIST nonemptyarglistnl { g_lingo->codeFunc($1, $2); } + | BLTINARGLIST nonemptyarglist { g_lingo->codeFunc($1, $2); } | 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); } @@ -618,8 +628,4 @@ nonemptyarglist: expr { $$ = 1; } | nonemptyarglist ',' expr { $$ = $1 + 1; } ; -nonemptyarglistnl: expr nl { $$ = 1; } - | nonemptyarglistnl ',' expr nl { $$ = $1 + 1; } - ; - %% diff --git a/engines/director/lingo/lingo-lex.cpp b/engines/director/lingo/lingo-lex.cpp index e26eed1a81..829a423a01 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 70 +#define YY_END_OF_BUFFER 71 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -373,36 +373,36 @@ 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[256] = { 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, 71, 69, 3, 67, 67, 69, 69, 69, + 66, 66, 66, 65, 66, 66, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 2, 2, 3, 67, 0, 0, + 0, 0, 0, 68, 4, 62, 1, 64, 65, 61, + 59, 60, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 22, 12, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 35, 36, 63, 38, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 52, + 63, 63, 63, 2, 2, 0, 4, 1, 64, 63, + + 6, 63, 63, 63, 63, 63, 63, 16, 63, 63, + 63, 63, 0, 63, 63, 63, 63, 63, 63, 63, + 31, 63, 63, 34, 63, 63, 63, 42, 63, 44, + 63, 63, 63, 63, 63, 63, 63, 63, 0, 63, + 63, 8, 63, 10, 11, 15, 0, 16, 18, 63, + 63, 63, 0, 63, 63, 25, 26, 27, 28, 63, + 63, 63, 33, 37, 39, 63, 63, 63, 63, 46, + 0, 51, 56, 63, 54, 58, 14, 5, 63, 63, + 16, 16, 63, 19, 63, 21, 63, 63, 29, 63, + 32, 63, 63, 63, 63, 63, 50, 50, 57, 63, + + 0, 7, 63, 16, 63, 20, 63, 63, 30, 63, + 63, 43, 53, 45, 0, 0, 50, 55, 0, 63, + 17, 63, 63, 63, 63, 0, 0, 0, 0, 50, + 13, 9, 23, 63, 63, 41, 0, 0, 0, 50, + 63, 40, 0, 0, 0, 0, 24, 49, 48, 49, + 0, 0, 0, 47, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -448,73 +448,73 @@ 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[267] = { 0, - 0, 63, 160, 645, 67, 71, 75, 79, 140, 0, - 645, 133, 126, 54, 70, 94, 65, 67, 65, 61, + 0, 63, 159, 646, 67, 71, 75, 79, 147, 0, + 646, 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, 646, 216, 179, + 224, 119, 99, 646, 0, 646, 0, 88, 95, 646, + 646, 646, 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, 232, 222, 227, 232, 240, 237, 249, 259, 0, + 263, 248, 253, 290, 299, 256, 0, 0, 84, 275, + + 0, 268, 266, 271, 287, 282, 291, 184, 280, 281, + 289, 300, 322, 285, 304, 300, 305, 298, 298, 312, + 0, 313, 297, 0, 313, 305, 309, 0, 326, 0, + 323, 321, 332, 360, 331, 337, 325, 347, 347, 338, + 342, 0, 359, 0, 0, 0, 375, 0, 0, 349, + 361, 368, 357, 373, 361, 0, 0, 0, 0, 366, + 367, 370, 0, 0, 381, 375, 385, 369, 370, 0, + 404, 0, 0, 387, 387, 0, 412, 0, 398, 397, + 0, 0, 391, 0, 399, 646, 401, 397, 0, 412, + 0, 415, 406, 404, 419, 408, 441, 451, 0, 416, + + 447, 0, 429, 0, 424, 0, 448, 447, 0, 451, + 438, 0, 0, 0, 471, 451, 475, 0, 453, 444, + 0, 458, 465, 466, 447, 509, 473, 472, 474, 516, + 646, 0, 0, 454, 476, 0, 482, 518, 494, 526, + 495, 0, 512, 532, 514, 542, 0, 646, 538, 646, + 540, 526, 547, 552, 646, 601, 603, 606, 609, 615, + 620, 625, 628, 633, 635, 640 } ; -static yyconst flex_int16_t yy_def[264] = +static yyconst flex_int16_t yy_def[267] = { 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 + 255, 1, 255, 255, 255, 255, 255, 255, 256, 257, + 255, 255, 255, 255, 255, 255, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 255, 255, 255, 255, 255, 255, + 255, 255, 256, 255, 259, 255, 260, 255, 255, 255, + 255, 255, 258, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 255, 255, 255, 259, 260, 255, 258, + + 258, 258, 258, 258, 258, 258, 258, 261, 258, 258, + 258, 258, 255, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 255, 258, + 258, 258, 258, 258, 258, 258, 262, 263, 258, 258, + 258, 258, 255, 258, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, + 264, 258, 258, 258, 258, 258, 255, 258, 258, 258, + 265, 263, 258, 258, 258, 255, 258, 258, 258, 258, + 258, 258, 258, 258, 258, 258, 264, 264, 258, 258, + + 255, 258, 258, 265, 258, 258, 258, 258, 258, 258, + 258, 258, 258, 258, 255, 255, 264, 258, 255, 258, + 258, 258, 258, 258, 258, 255, 255, 255, 255, 264, + 255, 258, 258, 258, 258, 258, 255, 255, 255, 264, + 258, 258, 255, 266, 255, 255, 258, 255, 266, 255, + 255, 255, 255, 266, 0, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255 } ; -static yyconst flex_int16_t yy_nxt[710] = +static yyconst flex_int16_t yy_nxt[711] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 11, 13, 4, 14, 15, 11, 16, 17, 18, 19, 20, @@ -524,79 +524,79 @@ 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, 255, 255, + 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, 147, 255, 78, 147, 79, + 255, 80, 94, 38, 38, 95, 53, 104, 88, 42, + + 103, 89, 255, 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, 255, 114, 115, 116, 255, + 117, 118, 119, 125, 42, 121, 105, 120, 109, 123, + 124, 126, 127, 132, 112, 106, 128, 129, 110, 111, + 114, 115, 122, 116, 117, 118, 130, 119, 125, 42, + 121, 120, 131, 123, 124, 133, 126, 127, 132, 134, + 128, 129, 137, 135, 255, 138, 122, 136, 255, 139, + 130, 94, 38, 38, 95, 140, 131, 141, 142, 133, + + 95, 38, 38, 95, 134, 143, 137, 144, 135, 138, + 145, 146, 136, 139, 149, 150, 151, 152, 255, 154, + 140, 141, 142, 113, 155, 158, 113, 157, 159, 143, + 160, 163, 144, 156, 145, 161, 146, 162, 149, 150, + 151, 164, 152, 154, 165, 166, 167, 168, 175, 155, + 158, 157, 159, 169, 160, 163, 153, 156, 170, 173, + 161, 171, 162, 174, 171, 164, 176, 177, 165, 166, + 178, 167, 168, 175, 179, 180, 147, 169, 183, 147, + 153, 184, 170, 173, 185, 255, 186, 174, 172, 187, + 191, 176, 177, 188, 178, 189, 190, 192, 179, 193, + + 180, 194, 183, 195, 196, 171, 184, 199, 171, 185, + 186, 200, 172, 201, 187, 191, 201, 188, 202, 189, + 190, 203, 192, 205, 193, 206, 194, 195, 196, 207, + 208, 209, 199, 210, 255, 211, 200, 198, 212, 213, + 255, 214, 215, 202, 218, 215, 203, 205, 201, 206, + 216, 201, 215, 207, 208, 215, 209, 220, 210, 211, + 216, 198, 212, 221, 213, 214, 222, 223, 218, 224, + 227, 219, 226, 225, 231, 226, 215, 232, 233, 215, + 236, 220, 217, 234, 216, 229, 235, 221, 241, 237, + 227, 222, 223, 238, 224, 227, 219, 225, 239, 231, + + 228, 232, 242, 233, 236, 229, 217, 230, 234, 229, + 226, 235, 241, 226, 237, 227, 243, 215, 238, 244, + 215, 245, 244, 239, 228, 216, 242, 246, 247, 229, + 246, 230, 248, 244, 250, 216, 244, 255, 228, 255, + 243, 251, 255, 251, 251, 245, 251, 253, 254, 255, + 240, 254, 247, 254, 255, 255, 254, 248, 255, 250, + 255, 227, 228, 255, 255, 255, 255, 255, 255, 252, + 255, 252, 253, 255, 240, 255, 229, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 227, 255, 255, 255, + 255, 255, 255, 252, 255, 252, 255, 255, 255, 255, + + 229, 43, 43, 255, 43, 43, 43, 45, 45, 53, + 53, 53, 97, 97, 97, 98, 98, 255, 98, 98, + 98, 148, 255, 148, 148, 148, 181, 255, 255, 181, + 181, 182, 182, 182, 197, 255, 255, 197, 204, 204, + 204, 249, 255, 255, 249, 3, 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, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } ; -static yyconst flex_int16_t yy_chk[710] = +static yyconst flex_int16_t yy_chk[711] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -607,75 +607,75 @@ 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, 82, 87, 65, 59, 83, 84, 63, 64, + 68, 68, 74, 69, 70, 71, 85, 72, 79, 41, + 74, 73, 86, 75, 76, 88, 81, 82, 87, 89, + 83, 84, 92, 91, 0, 93, 74, 91, 0, 96, + 85, 94, 94, 94, 94, 100, 86, 102, 103, 88, + + 95, 95, 95, 95, 89, 104, 92, 105, 91, 93, + 106, 107, 91, 96, 109, 110, 111, 112, 0, 114, + 100, 102, 103, 113, 115, 117, 113, 116, 118, 104, + 119, 123, 105, 115, 106, 120, 107, 122, 109, 110, + 111, 125, 112, 114, 126, 127, 129, 131, 137, 115, + 117, 116, 118, 132, 119, 123, 113, 115, 133, 135, + 120, 134, 122, 136, 134, 125, 138, 139, 126, 127, + 140, 129, 131, 137, 141, 143, 147, 132, 150, 147, + 113, 151, 133, 135, 152, 0, 153, 136, 134, 154, + 162, 138, 139, 155, 140, 160, 161, 165, 141, 166, + + 143, 167, 150, 168, 169, 171, 151, 174, 171, 152, + 153, 175, 134, 177, 154, 162, 177, 155, 179, 160, + 161, 180, 165, 183, 166, 185, 167, 168, 169, 187, + 188, 190, 174, 192, 0, 193, 175, 171, 194, 195, + 0, 196, 197, 179, 200, 197, 180, 183, 201, 185, + 197, 201, 198, 187, 188, 198, 190, 203, 192, 193, + 198, 171, 194, 205, 195, 196, 207, 208, 200, 210, + 216, 201, 215, 211, 219, 215, 217, 220, 222, 217, + 225, 203, 198, 223, 217, 216, 224, 205, 234, 227, + 215, 207, 208, 228, 210, 216, 201, 211, 229, 219, + + 215, 220, 235, 222, 225, 215, 198, 217, 223, 216, + 226, 224, 234, 226, 227, 215, 237, 230, 228, 238, + 230, 239, 238, 229, 215, 230, 235, 240, 241, 215, + 240, 217, 243, 244, 245, 240, 244, 0, 226, 249, + 237, 251, 249, 246, 251, 239, 246, 252, 253, 0, + 230, 253, 241, 254, 0, 0, 254, 243, 0, 245, + 0, 246, 226, 0, 0, 0, 0, 0, 0, 251, + 0, 246, 252, 0, 230, 0, 246, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, + 0, 0, 0, 251, 0, 246, 0, 0, 0, 0, + + 246, 256, 256, 0, 256, 256, 256, 257, 257, 258, + 258, 258, 259, 259, 259, 260, 260, 0, 260, 260, + 260, 261, 0, 261, 261, 261, 262, 0, 0, 262, + 262, 263, 263, 263, 264, 0, 0, 264, 265, 265, + 265, 266, 0, 0, 266, 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, 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 } ; static yy_state_type yy_last_accepting_state; @@ -1000,13 +1000,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 >= 256 ) 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] != 646 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1270,21 +1270,32 @@ YY_RULE_SETUP case 46: YY_RULE_SETUP #line 141 "engines/director/lingo/lingo-lex.l" +{ count(); return tTELL; } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 142 "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 48: YY_RULE_SETUP -#line 149 "engines/director/lingo/lingo-lex.l" +#line 153 "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 +1334,15 @@ YY_RULE_SETUP warning("Unhandled the entity %s", ptr); } YY_BREAK -case 48: +case 49: YY_RULE_SETUP -#line 189 "engines/director/lingo/lingo-lex.l" +#line 196 "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 +1372,15 @@ YY_RULE_SETUP return THEENTITY; } YY_BREAK -case 49: +case 50: YY_RULE_SETUP -#line 220 "engines/director/lingo/lingo-lex.l" +#line 230 "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 +1398,76 @@ YY_RULE_SETUP warning("Unhandled the entity %s", ptr); } YY_BREAK -case 50: +case 51: YY_RULE_SETUP -#line 239 "engines/director/lingo/lingo-lex.l" +#line 252 "engines/director/lingo/lingo-lex.l" { count(); return tTHEN; } YY_BREAK -case 51: +case 52: YY_RULE_SETUP -#line 240 "engines/director/lingo/lingo-lex.l" +#line 253 "engines/director/lingo/lingo-lex.l" { count(); return tTO; } YY_BREAK -case 52: +case 53: YY_RULE_SETUP -#line 241 "engines/director/lingo/lingo-lex.l" +#line 254 "engines/director/lingo/lingo-lex.l" { count(); return tSPRITE; } YY_BREAK -case 53: +case 54: YY_RULE_SETUP -#line 242 "engines/director/lingo/lingo-lex.l" +#line 255 "engines/director/lingo/lingo-lex.l" { count(); return tWITH; } YY_BREAK -case 54: +case 55: YY_RULE_SETUP -#line 243 "engines/director/lingo/lingo-lex.l" +#line 256 "engines/director/lingo/lingo-lex.l" { count(); return tWITHIN; } YY_BREAK -case 55: +case 56: YY_RULE_SETUP -#line 244 "engines/director/lingo/lingo-lex.l" +#line 257 "engines/director/lingo/lingo-lex.l" { count(); return tWHEN; } YY_BREAK -case 56: +case 57: YY_RULE_SETUP -#line 245 "engines/director/lingo/lingo-lex.l" +#line 258 "engines/director/lingo/lingo-lex.l" { count(); return tWHILE; } YY_BREAK -case 57: +case 58: YY_RULE_SETUP -#line 246 "engines/director/lingo/lingo-lex.l" +#line 259 "engines/director/lingo/lingo-lex.l" { count(); return tWORD; } YY_BREAK -case 58: +case 59: YY_RULE_SETUP -#line 248 "engines/director/lingo/lingo-lex.l" +#line 261 "engines/director/lingo/lingo-lex.l" { count(); return tNEQ; } YY_BREAK -case 59: +case 60: YY_RULE_SETUP -#line 249 "engines/director/lingo/lingo-lex.l" +#line 262 "engines/director/lingo/lingo-lex.l" { count(); return tGE; } YY_BREAK -case 60: +case 61: YY_RULE_SETUP -#line 250 "engines/director/lingo/lingo-lex.l" +#line 263 "engines/director/lingo/lingo-lex.l" { count(); return tLE; } YY_BREAK -case 61: +case 62: YY_RULE_SETUP -#line 251 "engines/director/lingo/lingo-lex.l" +#line 264 "engines/director/lingo/lingo-lex.l" { count(); return tCONCAT; } YY_BREAK -case 62: +case 63: YY_RULE_SETUP -#line 253 "engines/director/lingo/lingo-lex.l" +#line 266 "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; @@ -1467,16 +1487,16 @@ YY_RULE_SETUP if (g_lingo->_builtins[yytext]->maxArgs == 0) return type == BLTIN ? BLTINNOARGS : FBLTINNOARGS; else if (g_lingo->_builtins[yytext]->maxArgs == 1) - return type == BLTINNOARGSORONE; + return BLTINNOARGSORONE; else - return type == BLTINARGLIST; + return BLTINARGLIST; } else if (g_lingo->_builtins[yytext]->nargs == 1 && g_lingo->_builtins[yytext]->maxArgs == 1) { return type == BLTIN ? BLTINONEARG : FBLTINONEARG; } else if (g_lingo->_builtins[yytext]->nargs == -1) { - return type == BLTINARGLIST; + return BLTINARGLIST; } else { - return type == BLTINARGLIST; + return BLTINARGLIST; } } } @@ -1484,43 +1504,43 @@ YY_RULE_SETUP return ID; } YY_BREAK -case 63: +case 64: YY_RULE_SETUP -#line 292 "engines/director/lingo/lingo-lex.l" +#line 308 "engines/director/lingo/lingo-lex.l" { count(); yylval.f = atof(yytext); return FLOAT; } YY_BREAK -case 64: +case 65: YY_RULE_SETUP -#line 293 "engines/director/lingo/lingo-lex.l" +#line 309 "engines/director/lingo/lingo-lex.l" { count(); yylval.i = strtol(yytext, NULL, 10); return INT; } YY_BREAK -case 65: +case 66: YY_RULE_SETUP -#line 294 "engines/director/lingo/lingo-lex.l" +#line 310 "engines/director/lingo/lingo-lex.l" { count(); return *yytext; } YY_BREAK -case 66: -/* rule 66 can match eol */ +case 67: +/* rule 67 can match eol */ YY_RULE_SETUP -#line 295 "engines/director/lingo/lingo-lex.l" +#line 311 "engines/director/lingo/lingo-lex.l" { return '\n'; } YY_BREAK -case 67: +case 68: YY_RULE_SETUP -#line 296 "engines/director/lingo/lingo-lex.l" +#line 312 "engines/director/lingo/lingo-lex.l" { count(); yylval.s = new Common::String(&yytext[1]); yylval.s->deleteLastChar(); return STRING; } YY_BREAK -case 68: +case 69: YY_RULE_SETUP -#line 297 "engines/director/lingo/lingo-lex.l" +#line 313 "engines/director/lingo/lingo-lex.l" YY_BREAK -case 69: +case 70: YY_RULE_SETUP -#line 299 "engines/director/lingo/lingo-lex.l" +#line 315 "engines/director/lingo/lingo-lex.l" ECHO; YY_BREAK -#line 1524 "engines/director/lingo/lingo-lex.cpp" +#line 1544 "engines/director/lingo/lingo-lex.cpp" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1813,7 +1833,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 >= 256 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1841,11 +1861,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 >= 256 ) 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 == 255); return yy_is_jam ? 0 : yy_current_state; } @@ -2483,7 +2503,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 299 "engines/director/lingo/lingo-lex.l" +#line 315 "engines/director/lingo/lingo-lex.l" diff --git a/engines/director/lingo/lingo-lex.l b/engines/director/lingo/lingo-lex.l index ec9d6319bd..d6bf59ad5d 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,41 @@ 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: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]+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 +153,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 +196,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 +230,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 +249,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; @@ -273,27 +289,27 @@ whitespace [\t ] if (g_lingo->_builtins[yytext]->maxArgs == 0) return type == BLTIN ? BLTINNOARGS : FBLTINNOARGS; else if (g_lingo->_builtins[yytext]->maxArgs == 1) - return type == BLTINNOARGSORONE; + return BLTINNOARGSORONE; else - return type == BLTINARGLIST; + return BLTINARGLIST; } else if (g_lingo->_builtins[yytext]->nargs == 1 && g_lingo->_builtins[yytext]->maxArgs == 1) { return type == BLTIN ? BLTINONEARG : FBLTINONEARG; } else if (g_lingo->_builtins[yytext]->nargs == -1) { - return type == BLTINARGLIST; + return BLTINARGLIST; } else { - return type == BLTINARGLIST; + return BLTINARGLIST; } } } 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 d606b76945..ec94d066f3 100644 --- a/engines/director/lingo/lingo-the.cpp +++ b/engines/director/lingo/lingo-the.cpp @@ -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 @@ -60,6 +61,7 @@ TheEntity entities[] = { { 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 { kTheLastClick, "lastClick", false }, // D2 f { kTheLastEvent, "lastEvent", false }, // D2 f @@ -85,16 +87,25 @@ TheEntity entities[] = { { kTheMouseV, "mouseV", false }, // D2 f { kTheMouseWord, "mouseWord", false }, // D3 f { kTheMovie, "movie", false }, // D2 f + { kTheMovieFileFreeSize,"movieFileFreeSize",false }, // D4 f + { kTheMovieFileSize, "movieFileSize", false }, // D4 f + { kTheMovieName, "movieName", false }, // D4 f + { kTheMoviePath, "moviePath", false }, // D4 f { kTheMultiSound, "multiSound", false }, { 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 }, + { kThePreLoadRAM, "preLoadRAM", false }, // D4 p + { kTheQuickTimePresent, "quickTimePresent", false }, // D4 f { kTheResult, "result", false }, // D2 f { kTheRightMouseDown, "rightMouseDown", false }, { kTheRightMouseUp, "rightMouseUp", false }, { kTheRomanLingo, "romanLingo", false }, + { 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 @@ -123,7 +134,9 @@ TheEntity entities[] = { { kTheTrace, "trace", false }, // D4 p { kTheTraceLoad, "traceLoad", false }, // D4 p { kTheTraceLogFile, "traceLogFile", false }, // D4 p - { kTheWindow, "window", false }, + { kTheUpdateMovieEnabled,"updateMovieEnabled",false }, // D4 p + { kTheWindow, "window", true }, // D4 + { kTheWindowList, "windowList", false }, // D4 p { kTheWords, "words", false }, // D3 { kTheNOEntity, NULL, false } }; @@ -145,25 +158,25 @@ TheEntityField fields[] = { { kTheSprite, "locH", kTheLocH }, // D2 p { kTheSprite, "locV", kTheLocV }, // D2 p { kTheSprite, "moveable", kTheMoveable }, - { kTheSprite, "movieRate", kTheMovieRate }, - { kTheSprite, "movieTime", kTheMovieTime }, + { 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 }, // D4 p - { kTheSprite, "startTime", kTheStartTime }, + { 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, "type", kTheType }, // D2 p { kTheSprite, "visible", kTheVisible }, - { kTheSprite, "volume", kTheVolume }, + { kTheSprite, "volume", kTheVolume }, // D4 p { kTheSprite, "width", kTheWidth }, // D2 p // Common cast fields { kTheCast, "castType", kTheCastType }, // D4 p - { kTheCast, "filename", kTheFilename }, // D4 p + { kTheCast, "filename", kTheFileName }, // D4 p { kTheCast, "height", kTheHeight }, // D4 p { kTheCast, "loaded", kTheLoaded }, // D4 p { kTheCast, "modified", kTheModified }, // D4 p @@ -179,13 +192,17 @@ TheEntityField fields[] = { { kTheCast, "foreColor", kTheForeColor }, // 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 }, @@ -205,10 +222,15 @@ TheEntityField fields[] = { { kTheField, "textSize", kTheTextSize }, // D3 p { kTheField, "textStyle", kTheTextStyle }, // D3 p - { kTheWindow, "drawRect", kTheDrawRect }, - { kTheWindow, "filename", kTheFilename }, + { 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 }, - { kTheWindow, "visible", kTheVisible }, + { kTheWindow, "visible", kTheVisible }, // D4 p + { kTheWindow, "windowType", kTheWindowType }, // D4 p { kTheMenuItem, "checkmark", kTheCheckMark }, // D3 p { kTheMenuItem, "enabled", kTheEnabled }, // D3 p @@ -632,7 +654,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; @@ -714,7 +736,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: diff --git a/engines/director/lingo/lingo-the.h b/engines/director/lingo/lingo-the.h index be501ba984..24f5e266a3 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, @@ -58,6 +59,7 @@ enum TheEntityType { kTheKey, kTheKeyCode, kTheKeyDownScript, + kTheKeyUpScript, kTheLabelList, kTheLastClick, kTheLastEvent, @@ -83,16 +85,25 @@ enum TheEntityType { kTheMouseV, kTheMouseWord, kTheMovie, + kTheMovieFileFreeSize, + kTheMovieFileSize, + kTheMovieName, + kTheMoviePath, kTheMultiSound, kTheOptionDown, + kTheParamCount, kThePathName, kThePauseState, kThePerFrameHook, kThePreloadEventAbort, + kThePreLoadRAM, + kTheQuickTimePresent, kTheResult, kTheRightMouseDown, kTheRightMouseUp, kTheRomanLingo, + kTheSearchCurrentFolder, + kTheSearchPath, kTheSelection, kTheSelEnd, kTheSelStart, @@ -121,80 +132,90 @@ enum TheEntityType { 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, kTheMovieRate, kTheMovieTime, - kTheNumber, kTheName, + kTheNumber, kThePalette, kThePattern, kThePausedAtStart, kThePicture, - kThePreload, + kThePreLoad, kThePuppet, kThePurgePriority, kTheRect, kTheRegPoint, kTheRight, - kTheShort, - kTheStopTime, - kTheStretch, - kTheStartTime, 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..f7eafda11b 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" }, diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h index b327853b39..afadef7a90 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, @@ -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(); @@ -368,6 +372,7 @@ 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); @@ -375,6 +380,7 @@ public: 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,12 +388,14 @@ public: static void b_constrainH(int nargs); static void b_constrainV(int nargs); + static void b_copyToClipBoard(int nargs); static void b_duplicate(int nargs); static void b_editableText(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_intersect(int nargs); static void b_label(int nargs); static void b_marker(int nargs); static void b_move(int nargs); @@ -412,6 +420,7 @@ public: 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); @@ -424,16 +433,25 @@ 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_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); @@ -518,8 +536,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 e499a2361a..561ecd3659 100644 --- a/engines/director/lingo/tests/builtin.lingo +++ b/engines/director/lingo/tests/builtin.lingo @@ -27,4 +27,4 @@ move cast 1, cast 3 move cast 3 put findEmpty(cast 10) pasteClipBoardInto cast 2 -put the width of the cast 3 +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/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp index e15c8f8da6..180b08175b 100644 --- a/graphics/macgui/mactext.cpp +++ b/graphics/macgui/mactext.cpp @@ -298,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; @@ -309,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) { diff --git a/graphics/macgui/mactext.h b/graphics/macgui/mactext.h index 4df4f1c3aa..85c855950f 100644 --- a/graphics/macgui/mactext.h +++ b/graphics/macgui/mactext.h @@ -91,7 +91,7 @@ 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); |